1*a65addddSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*a65addddSAndroid Build Coastguard Worker# Copyright 2016 Google Inc. All Rights Reserved. 3*a65addddSAndroid Build Coastguard Worker# 4*a65addddSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*a65addddSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*a65addddSAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*a65addddSAndroid Build Coastguard Worker# 8*a65addddSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*a65addddSAndroid Build Coastguard Worker# 10*a65addddSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*a65addddSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS-IS" BASIS, 12*a65addddSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*a65addddSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*a65addddSAndroid Build Coastguard Worker# limitations under the License. 15*a65addddSAndroid Build Coastguard Workerimport pytest 16*a65addddSAndroid Build Coastguard Workerfrom absl.testing import parameterized 17*a65addddSAndroid Build Coastguard Workerfrom fruit_test_common import * 18*a65addddSAndroid Build Coastguard Workerfrom fruit_test_config import CXX_COMPILER_NAME 19*a65addddSAndroid Build Coastguard Workerimport re 20*a65addddSAndroid Build Coastguard Worker 21*a65addddSAndroid Build Coastguard WorkerCOMMON_DEFINITIONS = ''' 22*a65addddSAndroid Build Coastguard Worker #include "test_common.h" 23*a65addddSAndroid Build Coastguard Worker 24*a65addddSAndroid Build Coastguard Worker struct Annotation {}; 25*a65addddSAndroid Build Coastguard Worker struct Annotation1 {}; 26*a65addddSAndroid Build Coastguard Worker struct Annotation2 {}; 27*a65addddSAndroid Build Coastguard Worker ''' 28*a65addddSAndroid Build Coastguard Worker 29*a65addddSAndroid Build Coastguard Workerclass TestMultibindingsBindInterface(parameterized.TestCase): 30*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 31*a65addddSAndroid Build Coastguard Worker ('X', 'XImpl'), 32*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Annotated<Annotation2, XImpl>'), 33*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, X>', 'XImpl'), 34*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, XImpl>'), 35*a65addddSAndroid Build Coastguard Worker ]) 36*a65addddSAndroid Build Coastguard Worker def test_add_interface_multibinding_success(self, XAnnot, XImplAnnot): 37*a65addddSAndroid Build Coastguard Worker source = ''' 38*a65addddSAndroid Build Coastguard Worker struct X { 39*a65addddSAndroid Build Coastguard Worker virtual int foo() = 0; 40*a65addddSAndroid Build Coastguard Worker }; 41*a65addddSAndroid Build Coastguard Worker 42*a65addddSAndroid Build Coastguard Worker struct XImpl : public X { 43*a65addddSAndroid Build Coastguard Worker INJECT(XImpl()) = default; 44*a65addddSAndroid Build Coastguard Worker 45*a65addddSAndroid Build Coastguard Worker int foo() override { 46*a65addddSAndroid Build Coastguard Worker return 5; 47*a65addddSAndroid Build Coastguard Worker } 48*a65addddSAndroid Build Coastguard Worker }; 49*a65addddSAndroid Build Coastguard Worker 50*a65addddSAndroid Build Coastguard Worker fruit::Component<> getComponent() { 51*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 52*a65addddSAndroid Build Coastguard Worker .addMultibinding<XAnnot, XImplAnnot>(); 53*a65addddSAndroid Build Coastguard Worker } 54*a65addddSAndroid Build Coastguard Worker 55*a65addddSAndroid Build Coastguard Worker int main() { 56*a65addddSAndroid Build Coastguard Worker fruit::Injector<> injector(getComponent); 57*a65addddSAndroid Build Coastguard Worker 58*a65addddSAndroid Build Coastguard Worker std::vector<X*> multibindings = injector.getMultibindings<XAnnot>(); 59*a65addddSAndroid Build Coastguard Worker Assert(multibindings.size() == 1); 60*a65addddSAndroid Build Coastguard Worker Assert(multibindings[0]->foo() == 5); 61*a65addddSAndroid Build Coastguard Worker } 62*a65addddSAndroid Build Coastguard Worker ''' 63*a65addddSAndroid Build Coastguard Worker expect_success( 64*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 65*a65addddSAndroid Build Coastguard Worker source, 66*a65addddSAndroid Build Coastguard Worker locals()) 67*a65addddSAndroid Build Coastguard Worker 68*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 69*a65addddSAndroid Build Coastguard Worker ('X', 'XImpl', 'const XImpl'), 70*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Annotated<Annotation2, XImpl>', 'fruit::Annotated<Annotation2, const XImpl>'), 71*a65addddSAndroid Build Coastguard Worker ]) 72*a65addddSAndroid Build Coastguard Worker def test_add_interface_multibinding_const_target_error_install_first(self, XAnnot, XImplAnnot, ConstXImplAnnot): 73*a65addddSAndroid Build Coastguard Worker source = ''' 74*a65addddSAndroid Build Coastguard Worker struct X { 75*a65addddSAndroid Build Coastguard Worker virtual int foo() = 0; 76*a65addddSAndroid Build Coastguard Worker }; 77*a65addddSAndroid Build Coastguard Worker 78*a65addddSAndroid Build Coastguard Worker struct XImpl : public X { 79*a65addddSAndroid Build Coastguard Worker int foo() override { 80*a65addddSAndroid Build Coastguard Worker return 5; 81*a65addddSAndroid Build Coastguard Worker } 82*a65addddSAndroid Build Coastguard Worker }; 83*a65addddSAndroid Build Coastguard Worker 84*a65addddSAndroid Build Coastguard Worker fruit::Component<ConstXImplAnnot> getXImplComponent(); 85*a65addddSAndroid Build Coastguard Worker 86*a65addddSAndroid Build Coastguard Worker fruit::Component<> getComponent() { 87*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 88*a65addddSAndroid Build Coastguard Worker .install(getXImplComponent) 89*a65addddSAndroid Build Coastguard Worker .addMultibinding<XAnnot, XImplAnnot>(); 90*a65addddSAndroid Build Coastguard Worker } 91*a65addddSAndroid Build Coastguard Worker ''' 92*a65addddSAndroid Build Coastguard Worker expect_compile_error( 93*a65addddSAndroid Build Coastguard Worker 'NonConstBindingRequiredButConstBindingProvidedError<XImplAnnot>', 94*a65addddSAndroid Build Coastguard Worker 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 95*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 96*a65addddSAndroid Build Coastguard Worker source, 97*a65addddSAndroid Build Coastguard Worker locals()) 98*a65addddSAndroid Build Coastguard Worker 99*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 100*a65addddSAndroid Build Coastguard Worker ('X', 'XImpl', 'const XImpl'), 101*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Annotated<Annotation2, XImpl>', 'fruit::Annotated<Annotation2, const XImpl>'), 102*a65addddSAndroid Build Coastguard Worker ]) 103*a65addddSAndroid Build Coastguard Worker def test_add_interface_multibinding_const_target_error_binding_first(self, XAnnot, XImplAnnot, ConstXImplAnnot): 104*a65addddSAndroid Build Coastguard Worker source = ''' 105*a65addddSAndroid Build Coastguard Worker struct X { 106*a65addddSAndroid Build Coastguard Worker virtual int foo() = 0; 107*a65addddSAndroid Build Coastguard Worker }; 108*a65addddSAndroid Build Coastguard Worker 109*a65addddSAndroid Build Coastguard Worker struct XImpl : public X { 110*a65addddSAndroid Build Coastguard Worker int foo() override { 111*a65addddSAndroid Build Coastguard Worker return 5; 112*a65addddSAndroid Build Coastguard Worker } 113*a65addddSAndroid Build Coastguard Worker }; 114*a65addddSAndroid Build Coastguard Worker 115*a65addddSAndroid Build Coastguard Worker fruit::Component<ConstXImplAnnot> getXImplComponent(); 116*a65addddSAndroid Build Coastguard Worker 117*a65addddSAndroid Build Coastguard Worker fruit::Component<> getComponent() { 118*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 119*a65addddSAndroid Build Coastguard Worker .addMultibinding<XAnnot, XImplAnnot>() 120*a65addddSAndroid Build Coastguard Worker .install(getXImplComponent); 121*a65addddSAndroid Build Coastguard Worker } 122*a65addddSAndroid Build Coastguard Worker ''' 123*a65addddSAndroid Build Coastguard Worker expect_compile_error( 124*a65addddSAndroid Build Coastguard Worker 'NonConstBindingRequiredButConstBindingProvidedError<XImplAnnot>', 125*a65addddSAndroid Build Coastguard Worker 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 126*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 127*a65addddSAndroid Build Coastguard Worker source, 128*a65addddSAndroid Build Coastguard Worker locals()) 129*a65addddSAndroid Build Coastguard Worker 130*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 131*a65addddSAndroid Build Coastguard Worker ('X', 'int'), 132*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, int>'), 133*a65addddSAndroid Build Coastguard Worker ]) 134*a65addddSAndroid Build Coastguard Worker def test_error_not_base(self, XAnnot, intAnnot): 135*a65addddSAndroid Build Coastguard Worker source = ''' 136*a65addddSAndroid Build Coastguard Worker struct X {}; 137*a65addddSAndroid Build Coastguard Worker 138*a65addddSAndroid Build Coastguard Worker fruit::Component<> getComponent() { 139*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 140*a65addddSAndroid Build Coastguard Worker .addMultibinding<XAnnot, intAnnot>(); 141*a65addddSAndroid Build Coastguard Worker } 142*a65addddSAndroid Build Coastguard Worker ''' 143*a65addddSAndroid Build Coastguard Worker expect_compile_error( 144*a65addddSAndroid Build Coastguard Worker 'NotABaseClassOfError<X,int>', 145*a65addddSAndroid Build Coastguard Worker 'I is not a base class of C.', 146*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 147*a65addddSAndroid Build Coastguard Worker source, 148*a65addddSAndroid Build Coastguard Worker locals()) 149*a65addddSAndroid Build Coastguard Worker 150*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 151*a65addddSAndroid Build Coastguard Worker ('Scaler', 'ScalerImpl'), 152*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, Scaler>', 'fruit::Annotated<Annotation2, ScalerImpl>'), 153*a65addddSAndroid Build Coastguard Worker ]) 154*a65addddSAndroid Build Coastguard Worker def test_error_abstract_class(self, ScalerAnnot, ScalerImplAnnot): 155*a65addddSAndroid Build Coastguard Worker source = ''' 156*a65addddSAndroid Build Coastguard Worker struct Scaler { 157*a65addddSAndroid Build Coastguard Worker virtual double scale(double x) = 0; 158*a65addddSAndroid Build Coastguard Worker }; 159*a65addddSAndroid Build Coastguard Worker 160*a65addddSAndroid Build Coastguard Worker struct ScalerImpl : public Scaler { 161*a65addddSAndroid Build Coastguard Worker // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class. 162*a65addddSAndroid Build Coastguard Worker }; 163*a65addddSAndroid Build Coastguard Worker 164*a65addddSAndroid Build Coastguard Worker fruit::Component<> getComponent() { 165*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 166*a65addddSAndroid Build Coastguard Worker .addMultibinding<ScalerAnnot, ScalerImplAnnot>(); 167*a65addddSAndroid Build Coastguard Worker } 168*a65addddSAndroid Build Coastguard Worker ''' 169*a65addddSAndroid Build Coastguard Worker expect_compile_error( 170*a65addddSAndroid Build Coastguard Worker 'NoBindingFoundForAbstractClassError<ScalerImplAnnot,ScalerImpl>', 171*a65addddSAndroid Build Coastguard Worker 'No explicit binding was found for T, and note that C is an abstract class', 172*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 173*a65addddSAndroid Build Coastguard Worker source, 174*a65addddSAndroid Build Coastguard Worker locals()) 175*a65addddSAndroid Build Coastguard Worker 176*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 177*a65addddSAndroid Build Coastguard Worker ('Scaler', 'ScalerImpl'), 178*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, Scaler>', 'fruit::Annotated<Annotation2, ScalerImpl>'), 179*a65addddSAndroid Build Coastguard Worker ]) 180*a65addddSAndroid Build Coastguard Worker def test_error_abstract_class_clang(self, ScalerAnnot, ScalerImplAnnot): 181*a65addddSAndroid Build Coastguard Worker if re.search('Clang', CXX_COMPILER_NAME) is None: 182*a65addddSAndroid Build Coastguard Worker # This is Clang-only because GCC >=4.9 refuses to even mention the type C() when C is an abstract class, 183*a65addddSAndroid Build Coastguard Worker # while Clang allows to mention the type (but of course there can be no functions with this type) 184*a65addddSAndroid Build Coastguard Worker return 185*a65addddSAndroid Build Coastguard Worker source = ''' 186*a65addddSAndroid Build Coastguard Worker struct Scaler { 187*a65addddSAndroid Build Coastguard Worker virtual double scale(double x) = 0; 188*a65addddSAndroid Build Coastguard Worker }; 189*a65addddSAndroid Build Coastguard Worker 190*a65addddSAndroid Build Coastguard Worker struct ScalerImpl : public Scaler { 191*a65addddSAndroid Build Coastguard Worker INJECT(ScalerImpl()) = default; 192*a65addddSAndroid Build Coastguard Worker 193*a65addddSAndroid Build Coastguard Worker // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class. 194*a65addddSAndroid Build Coastguard Worker }; 195*a65addddSAndroid Build Coastguard Worker 196*a65addddSAndroid Build Coastguard Worker fruit::Component<> getComponent() { 197*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 198*a65addddSAndroid Build Coastguard Worker .addMultibinding<ScalerAnnot, ScalerImplAnnot>(); 199*a65addddSAndroid Build Coastguard Worker } 200*a65addddSAndroid Build Coastguard Worker ''' 201*a65addddSAndroid Build Coastguard Worker expect_compile_error( 202*a65addddSAndroid Build Coastguard Worker 'CannotConstructAbstractClassError<ScalerImpl>', 203*a65addddSAndroid Build Coastguard Worker 'The specified class can.t be constructed because it.s an abstract class.', 204*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 205*a65addddSAndroid Build Coastguard Worker source, 206*a65addddSAndroid Build Coastguard Worker locals()) 207*a65addddSAndroid Build Coastguard Worker 208*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__': 209*a65addddSAndroid Build Coastguard Worker absltest.main() 210