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 Worker 16*a65addddSAndroid Build Coastguard Workerfrom absl.testing import parameterized 17*a65addddSAndroid Build Coastguard Workerfrom fruit_test_common import * 18*a65addddSAndroid Build Coastguard Worker 19*a65addddSAndroid Build Coastguard WorkerCOMMON_DEFINITIONS = ''' 20*a65addddSAndroid Build Coastguard Worker #include "test_common.h" 21*a65addddSAndroid Build Coastguard Worker 22*a65addddSAndroid Build Coastguard Worker struct X; 23*a65addddSAndroid Build Coastguard Worker 24*a65addddSAndroid Build Coastguard Worker struct Annotation1 {}; 25*a65addddSAndroid Build Coastguard Worker using XAnnot = fruit::Annotated<Annotation1, X>; 26*a65addddSAndroid Build Coastguard Worker 27*a65addddSAndroid Build Coastguard Worker struct Annotation2 {}; 28*a65addddSAndroid Build Coastguard Worker 29*a65addddSAndroid Build Coastguard Worker struct Annotation3 {}; 30*a65addddSAndroid Build Coastguard Worker 31*a65addddSAndroid Build Coastguard Worker template <typename T> 32*a65addddSAndroid Build Coastguard Worker using WithNoAnnotation = T; 33*a65addddSAndroid Build Coastguard Worker 34*a65addddSAndroid Build Coastguard Worker template <typename T> 35*a65addddSAndroid Build Coastguard Worker using WithAnnotation1 = fruit::Annotated<Annotation1, T>; 36*a65addddSAndroid Build Coastguard Worker ''' 37*a65addddSAndroid Build Coastguard Worker 38*a65addddSAndroid Build Coastguard Workerclass TestRegisterConstructor(parameterized.TestCase): 39*a65addddSAndroid Build Coastguard Worker 40*a65addddSAndroid Build Coastguard Worker def test_register_constructor_success_copyable_and_movable(self): 41*a65addddSAndroid Build Coastguard Worker source = ''' 42*a65addddSAndroid Build Coastguard Worker struct X { 43*a65addddSAndroid Build Coastguard Worker INJECT(X()) = default; 44*a65addddSAndroid Build Coastguard Worker X(X&&) = default; 45*a65addddSAndroid Build Coastguard Worker X(const X&) = default; 46*a65addddSAndroid Build Coastguard Worker }; 47*a65addddSAndroid Build Coastguard Worker 48*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 49*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 50*a65addddSAndroid Build Coastguard Worker } 51*a65addddSAndroid Build Coastguard Worker 52*a65addddSAndroid Build Coastguard Worker int main() { 53*a65addddSAndroid Build Coastguard Worker fruit::Injector<X> injector(getComponent); 54*a65addddSAndroid Build Coastguard Worker injector.get<X*>(); 55*a65addddSAndroid Build Coastguard Worker } 56*a65addddSAndroid Build Coastguard Worker ''' 57*a65addddSAndroid Build Coastguard Worker expect_success( 58*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 59*a65addddSAndroid Build Coastguard Worker source) 60*a65addddSAndroid Build Coastguard Worker 61*a65addddSAndroid Build Coastguard Worker def test_register_constructor_success_movable_only(self): 62*a65addddSAndroid Build Coastguard Worker source = ''' 63*a65addddSAndroid Build Coastguard Worker struct X { 64*a65addddSAndroid Build Coastguard Worker INJECT(X()) = default; 65*a65addddSAndroid Build Coastguard Worker X(X&&) = default; 66*a65addddSAndroid Build Coastguard Worker X(const X&) = delete; 67*a65addddSAndroid Build Coastguard Worker }; 68*a65addddSAndroid Build Coastguard Worker 69*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 70*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 71*a65addddSAndroid Build Coastguard Worker } 72*a65addddSAndroid Build Coastguard Worker 73*a65addddSAndroid Build Coastguard Worker int main() { 74*a65addddSAndroid Build Coastguard Worker fruit::Injector<X> injector(getComponent); 75*a65addddSAndroid Build Coastguard Worker injector.get<X*>(); 76*a65addddSAndroid Build Coastguard Worker } 77*a65addddSAndroid Build Coastguard Worker ''' 78*a65addddSAndroid Build Coastguard Worker expect_success( 79*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 80*a65addddSAndroid Build Coastguard Worker source) 81*a65addddSAndroid Build Coastguard Worker 82*a65addddSAndroid Build Coastguard Worker def test_register_constructor_success_not_movable(self): 83*a65addddSAndroid Build Coastguard Worker source = ''' 84*a65addddSAndroid Build Coastguard Worker struct X { 85*a65addddSAndroid Build Coastguard Worker INJECT(X()) = default; 86*a65addddSAndroid Build Coastguard Worker X(X&&) = delete; 87*a65addddSAndroid Build Coastguard Worker X(const X&) = delete; 88*a65addddSAndroid Build Coastguard Worker }; 89*a65addddSAndroid Build Coastguard Worker 90*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 91*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 92*a65addddSAndroid Build Coastguard Worker } 93*a65addddSAndroid Build Coastguard Worker 94*a65addddSAndroid Build Coastguard Worker int main() { 95*a65addddSAndroid Build Coastguard Worker fruit::Injector<X> injector(getComponent); 96*a65addddSAndroid Build Coastguard Worker injector.get<X*>(); 97*a65addddSAndroid Build Coastguard Worker } 98*a65addddSAndroid Build Coastguard Worker ''' 99*a65addddSAndroid Build Coastguard Worker expect_success( 100*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 101*a65addddSAndroid Build Coastguard Worker source) 102*a65addddSAndroid Build Coastguard Worker 103*a65addddSAndroid Build Coastguard Worker # TODO: consider moving to test_normalized_component.py 104*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 105*a65addddSAndroid Build Coastguard Worker ('X', 'Y', 'Y', 'Z'), 106*a65addddSAndroid Build Coastguard Worker ('X', 'Y', 'const Y', 'Z'), 107*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, Y>', 'fruit::Annotated<Annotation2, const Y>', 'fruit::Annotated<Annotation3, Z>'), 108*a65addddSAndroid Build Coastguard Worker ]) 109*a65addddSAndroid Build Coastguard Worker def test_autoinject_with_annotation_success(self, XAnnot, YAnnot, MaybeConstYAnnot, ZAnnot): 110*a65addddSAndroid Build Coastguard Worker source = ''' 111*a65addddSAndroid Build Coastguard Worker struct X { 112*a65addddSAndroid Build Coastguard Worker using Inject = X(); 113*a65addddSAndroid Build Coastguard Worker }; 114*a65addddSAndroid Build Coastguard Worker 115*a65addddSAndroid Build Coastguard Worker struct Y : public ConstructionTracker<Y> { 116*a65addddSAndroid Build Coastguard Worker using Inject = Y(); 117*a65addddSAndroid Build Coastguard Worker }; 118*a65addddSAndroid Build Coastguard Worker 119*a65addddSAndroid Build Coastguard Worker struct Z { 120*a65addddSAndroid Build Coastguard Worker using Inject = Z(); 121*a65addddSAndroid Build Coastguard Worker }; 122*a65addddSAndroid Build Coastguard Worker 123*a65addddSAndroid Build Coastguard Worker fruit::Component<ZAnnot, MaybeConstYAnnot, XAnnot> getComponent() { 124*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 125*a65addddSAndroid Build Coastguard Worker } 126*a65addddSAndroid Build Coastguard Worker 127*a65addddSAndroid Build Coastguard Worker fruit::Component<> getEmptyComponent() { 128*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 129*a65addddSAndroid Build Coastguard Worker } 130*a65addddSAndroid Build Coastguard Worker 131*a65addddSAndroid Build Coastguard Worker int main() { 132*a65addddSAndroid Build Coastguard Worker fruit::NormalizedComponent<> normalizedComponent(getEmptyComponent); 133*a65addddSAndroid Build Coastguard Worker fruit::Injector<MaybeConstYAnnot> injector(normalizedComponent, getComponent); 134*a65addddSAndroid Build Coastguard Worker 135*a65addddSAndroid Build Coastguard Worker Assert(Y::num_objects_constructed == 0); 136*a65addddSAndroid Build Coastguard Worker injector.get<YAnnot>(); 137*a65addddSAndroid Build Coastguard Worker Assert(Y::num_objects_constructed == 1); 138*a65addddSAndroid Build Coastguard Worker } 139*a65addddSAndroid Build Coastguard Worker ''' 140*a65addddSAndroid Build Coastguard Worker expect_success( 141*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 142*a65addddSAndroid Build Coastguard Worker source, 143*a65addddSAndroid Build Coastguard Worker locals()) 144*a65addddSAndroid Build Coastguard Worker 145*a65addddSAndroid Build Coastguard Worker def test_autoinject_annotation_in_signature_return_type(self): 146*a65addddSAndroid Build Coastguard Worker source = ''' 147*a65addddSAndroid Build Coastguard Worker struct X { 148*a65addddSAndroid Build Coastguard Worker using Inject = XAnnot(); 149*a65addddSAndroid Build Coastguard Worker }; 150*a65addddSAndroid Build Coastguard Worker 151*a65addddSAndroid Build Coastguard Worker fruit::Component<XAnnot> getComponent() { 152*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 153*a65addddSAndroid Build Coastguard Worker } 154*a65addddSAndroid Build Coastguard Worker ''' 155*a65addddSAndroid Build Coastguard Worker expect_compile_error( 156*a65addddSAndroid Build Coastguard Worker 'InjectTypedefWithAnnotationError<X>', 157*a65addddSAndroid Build Coastguard Worker 'C::Inject is a signature that returns an annotated type', 158*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 159*a65addddSAndroid Build Coastguard Worker source) 160*a65addddSAndroid Build Coastguard Worker 161*a65addddSAndroid Build Coastguard Worker def test_autoinject_wrong_class_in_typedef(self): 162*a65addddSAndroid Build Coastguard Worker source = ''' 163*a65addddSAndroid Build Coastguard Worker struct X { 164*a65addddSAndroid Build Coastguard Worker using Inject = X(); 165*a65addddSAndroid Build Coastguard Worker }; 166*a65addddSAndroid Build Coastguard Worker 167*a65addddSAndroid Build Coastguard Worker struct Y : public X { 168*a65addddSAndroid Build Coastguard Worker }; 169*a65addddSAndroid Build Coastguard Worker 170*a65addddSAndroid Build Coastguard Worker fruit::Component<Y> getComponent() { 171*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 172*a65addddSAndroid Build Coastguard Worker } 173*a65addddSAndroid Build Coastguard Worker ''' 174*a65addddSAndroid Build Coastguard Worker expect_compile_error( 175*a65addddSAndroid Build Coastguard Worker 'InjectTypedefForWrongClassError<Y,X>', 176*a65addddSAndroid Build Coastguard Worker 'C::Inject is a signature, but does not return a C. Maybe the class C has no Inject typedef and', 177*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 178*a65addddSAndroid Build Coastguard Worker source) 179*a65addddSAndroid Build Coastguard Worker 180*a65addddSAndroid Build Coastguard Worker def test_register_constructor_error_abstract_class(self): 181*a65addddSAndroid Build Coastguard Worker if re.search('MSVC', CXX_COMPILER_NAME) is not None: 182*a65addddSAndroid Build Coastguard Worker # MSVC allows to construct the type X(int*) but SignatureType<Type<X(int*)>> doesn't find the 183*a65addddSAndroid Build Coastguard Worker # specialization. 184*a65addddSAndroid Build Coastguard Worker return 185*a65addddSAndroid Build Coastguard Worker source = ''' 186*a65addddSAndroid Build Coastguard Worker struct X { 187*a65addddSAndroid Build Coastguard Worker X(int*) {} 188*a65addddSAndroid Build Coastguard Worker 189*a65addddSAndroid Build Coastguard Worker virtual void foo() = 0; 190*a65addddSAndroid Build Coastguard Worker }; 191*a65addddSAndroid Build Coastguard Worker 192*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 193*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 194*a65addddSAndroid Build Coastguard Worker .registerConstructor<fruit::Annotated<Annotation1, X>(int*)>(); 195*a65addddSAndroid Build Coastguard Worker } 196*a65addddSAndroid Build Coastguard Worker ''' 197*a65addddSAndroid Build Coastguard Worker # Some compilers give a generic compile error, some don't and then Fruit reports the error. 198*a65addddSAndroid Build Coastguard Worker try: 199*a65addddSAndroid Build Coastguard Worker expect_generic_compile_error( 200*a65addddSAndroid Build Coastguard Worker 'invalid abstract return type' 201*a65addddSAndroid Build Coastguard Worker '|.X.: cannot instantiate abstract class', 202*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 203*a65addddSAndroid Build Coastguard Worker source) 204*a65addddSAndroid Build Coastguard Worker except: 205*a65addddSAndroid Build Coastguard Worker expect_compile_error( 206*a65addddSAndroid Build Coastguard Worker 'CannotConstructAbstractClassError<X>', 207*a65addddSAndroid Build Coastguard Worker 'The specified class can.t be constructed because it.s an abstract class', 208*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 209*a65addddSAndroid Build Coastguard Worker source) 210*a65addddSAndroid Build Coastguard Worker 211*a65addddSAndroid Build Coastguard Worker def test_register_constructor_error_malformed_signature(self): 212*a65addddSAndroid Build Coastguard Worker source = ''' 213*a65addddSAndroid Build Coastguard Worker struct X { 214*a65addddSAndroid Build Coastguard Worker X(int) {} 215*a65addddSAndroid Build Coastguard Worker }; 216*a65addddSAndroid Build Coastguard Worker 217*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 218*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 219*a65addddSAndroid Build Coastguard Worker .registerConstructor<X[]>(); 220*a65addddSAndroid Build Coastguard Worker } 221*a65addddSAndroid Build Coastguard Worker ''' 222*a65addddSAndroid Build Coastguard Worker expect_compile_error( 223*a65addddSAndroid Build Coastguard Worker r'NotASignatureError<X\[\]>', 224*a65addddSAndroid Build Coastguard Worker r'CandidateSignature was specified as parameter, but it.s not a signature. Signatures are of the form', 225*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 226*a65addddSAndroid Build Coastguard Worker source) 227*a65addddSAndroid Build Coastguard Worker 228*a65addddSAndroid Build Coastguard Worker def test_register_constructor_error_malformed_signature_autoinject(self): 229*a65addddSAndroid Build Coastguard Worker source = ''' 230*a65addddSAndroid Build Coastguard Worker struct X { 231*a65addddSAndroid Build Coastguard Worker using Inject = X[]; 232*a65addddSAndroid Build Coastguard Worker X(int) {} 233*a65addddSAndroid Build Coastguard Worker }; 234*a65addddSAndroid Build Coastguard Worker 235*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 236*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 237*a65addddSAndroid Build Coastguard Worker } 238*a65addddSAndroid Build Coastguard Worker ''' 239*a65addddSAndroid Build Coastguard Worker expect_compile_error( 240*a65addddSAndroid Build Coastguard Worker r'InjectTypedefNotASignatureError<X,X\[\]>', 241*a65addddSAndroid Build Coastguard Worker r'C::Inject should be a typedef to a signature', 242*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 243*a65addddSAndroid Build Coastguard Worker source) 244*a65addddSAndroid Build Coastguard Worker 245*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 246*a65addddSAndroid Build Coastguard Worker 'char*', 247*a65addddSAndroid Build Coastguard Worker 'fruit::Annotated<Annotation1, char*>', 248*a65addddSAndroid Build Coastguard Worker ]) 249*a65addddSAndroid Build Coastguard Worker def test_register_constructor_does_not_exist_error(self, charPtrAnnot): 250*a65addddSAndroid Build Coastguard Worker source = ''' 251*a65addddSAndroid Build Coastguard Worker struct X { 252*a65addddSAndroid Build Coastguard Worker X(int*) {} 253*a65addddSAndroid Build Coastguard Worker }; 254*a65addddSAndroid Build Coastguard Worker 255*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 256*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 257*a65addddSAndroid Build Coastguard Worker .registerConstructor<X(charPtrAnnot)>(); 258*a65addddSAndroid Build Coastguard Worker } 259*a65addddSAndroid Build Coastguard Worker ''' 260*a65addddSAndroid Build Coastguard Worker expect_compile_error( 261*a65addddSAndroid Build Coastguard Worker r'NoConstructorMatchingInjectSignatureError<X,X\(char\*\)>', 262*a65addddSAndroid Build Coastguard Worker r'contains an Inject typedef but it.s not constructible with the specified types', 263*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 264*a65addddSAndroid Build Coastguard Worker source, 265*a65addddSAndroid Build Coastguard Worker locals()) 266*a65addddSAndroid Build Coastguard Worker 267*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 268*a65addddSAndroid Build Coastguard Worker 'char*', 269*a65addddSAndroid Build Coastguard Worker 'fruit::Annotated<Annotation1, char*>', 270*a65addddSAndroid Build Coastguard Worker ]) 271*a65addddSAndroid Build Coastguard Worker def test_autoinject_constructor_does_not_exist_error(self, charPtrAnnot): 272*a65addddSAndroid Build Coastguard Worker source = ''' 273*a65addddSAndroid Build Coastguard Worker struct X { 274*a65addddSAndroid Build Coastguard Worker using Inject = X(charPtrAnnot); 275*a65addddSAndroid Build Coastguard Worker X(int*) {} 276*a65addddSAndroid Build Coastguard Worker }; 277*a65addddSAndroid Build Coastguard Worker 278*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 279*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 280*a65addddSAndroid Build Coastguard Worker } 281*a65addddSAndroid Build Coastguard Worker ''' 282*a65addddSAndroid Build Coastguard Worker expect_compile_error( 283*a65addddSAndroid Build Coastguard Worker r'NoConstructorMatchingInjectSignatureError<X,X\(char\*\)>', 284*a65addddSAndroid Build Coastguard Worker r'contains an Inject typedef but it.s not constructible with the specified types', 285*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 286*a65addddSAndroid Build Coastguard Worker source, 287*a65addddSAndroid Build Coastguard Worker locals()) 288*a65addddSAndroid Build Coastguard Worker 289*a65addddSAndroid Build Coastguard Worker def test_autoinject_abstract_class_error(self): 290*a65addddSAndroid Build Coastguard Worker source = ''' 291*a65addddSAndroid Build Coastguard Worker struct X { 292*a65addddSAndroid Build Coastguard Worker using Inject = fruit::Annotated<Annotation1, X>(); 293*a65addddSAndroid Build Coastguard Worker 294*a65addddSAndroid Build Coastguard Worker virtual void scale() = 0; 295*a65addddSAndroid Build Coastguard Worker // Note: here we "forgot" to implement scale() (on purpose, for this test) so X is an abstract class. 296*a65addddSAndroid Build Coastguard Worker }; 297*a65addddSAndroid Build Coastguard Worker 298*a65addddSAndroid Build Coastguard Worker fruit::Component<fruit::Annotated<Annotation1, X>> getComponent() { 299*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 300*a65addddSAndroid Build Coastguard Worker } 301*a65addddSAndroid Build Coastguard Worker ''' 302*a65addddSAndroid Build Coastguard Worker expect_compile_error( 303*a65addddSAndroid Build Coastguard Worker 'CannotConstructAbstractClassError<X>', 304*a65addddSAndroid Build Coastguard Worker 'The specified class can.t be constructed because it.s an abstract class.', 305*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 306*a65addddSAndroid Build Coastguard Worker source) 307*a65addddSAndroid Build Coastguard Worker 308*a65addddSAndroid Build Coastguard Worker @multiple_parameters([ 309*a65addddSAndroid Build Coastguard Worker 'WithNoAnnotation', 310*a65addddSAndroid Build Coastguard Worker 'WithAnnotation1', 311*a65addddSAndroid Build Coastguard Worker ], [ 312*a65addddSAndroid Build Coastguard Worker 'Y', 313*a65addddSAndroid Build Coastguard Worker 'const Y', 314*a65addddSAndroid Build Coastguard Worker 'Y*', 315*a65addddSAndroid Build Coastguard Worker 'const Y*', 316*a65addddSAndroid Build Coastguard Worker 'Y&', 317*a65addddSAndroid Build Coastguard Worker 'const Y&', 318*a65addddSAndroid Build Coastguard Worker 'std::shared_ptr<Y>', 319*a65addddSAndroid Build Coastguard Worker 'fruit::Provider<Y>', 320*a65addddSAndroid Build Coastguard Worker 'fruit::Provider<const Y>', 321*a65addddSAndroid Build Coastguard Worker ]) 322*a65addddSAndroid Build Coastguard Worker def test_register_constructor_with_param_success(self, WithAnnotation, YVariant): 323*a65addddSAndroid Build Coastguard Worker source = ''' 324*a65addddSAndroid Build Coastguard Worker struct Y {}; 325*a65addddSAndroid Build Coastguard Worker struct X { 326*a65addddSAndroid Build Coastguard Worker X(YVariant) { 327*a65addddSAndroid Build Coastguard Worker } 328*a65addddSAndroid Build Coastguard Worker }; 329*a65addddSAndroid Build Coastguard Worker 330*a65addddSAndroid Build Coastguard Worker fruit::Component<WithAnnotation<Y>> getYComponent() { 331*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 332*a65addddSAndroid Build Coastguard Worker .registerConstructor<WithAnnotation<Y>()>(); 333*a65addddSAndroid Build Coastguard Worker } 334*a65addddSAndroid Build Coastguard Worker 335*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 336*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 337*a65addddSAndroid Build Coastguard Worker .install(getYComponent) 338*a65addddSAndroid Build Coastguard Worker .registerConstructor<X(WithAnnotation<YVariant>)>(); 339*a65addddSAndroid Build Coastguard Worker } 340*a65addddSAndroid Build Coastguard Worker 341*a65addddSAndroid Build Coastguard Worker int main() { 342*a65addddSAndroid Build Coastguard Worker fruit::Injector<X> injector(getComponent); 343*a65addddSAndroid Build Coastguard Worker injector.get<X>(); 344*a65addddSAndroid Build Coastguard Worker } 345*a65addddSAndroid Build Coastguard Worker ''' 346*a65addddSAndroid Build Coastguard Worker expect_success( 347*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 348*a65addddSAndroid Build Coastguard Worker source, 349*a65addddSAndroid Build Coastguard Worker locals()) 350*a65addddSAndroid Build Coastguard Worker 351*a65addddSAndroid Build Coastguard Worker @multiple_parameters([ 352*a65addddSAndroid Build Coastguard Worker 'WithNoAnnotation', 353*a65addddSAndroid Build Coastguard Worker 'WithAnnotation1', 354*a65addddSAndroid Build Coastguard Worker ], [ 355*a65addddSAndroid Build Coastguard Worker 'Y', 356*a65addddSAndroid Build Coastguard Worker 'const Y', 357*a65addddSAndroid Build Coastguard Worker 'const Y*', 358*a65addddSAndroid Build Coastguard Worker 'const Y&', 359*a65addddSAndroid Build Coastguard Worker 'fruit::Provider<const Y>', 360*a65addddSAndroid Build Coastguard Worker ]) 361*a65addddSAndroid Build Coastguard Worker def test_register_constructor_with_param_const_binding_success(self, WithAnnotation, YVariant): 362*a65addddSAndroid Build Coastguard Worker source = ''' 363*a65addddSAndroid Build Coastguard Worker struct Y {}; 364*a65addddSAndroid Build Coastguard Worker struct X { 365*a65addddSAndroid Build Coastguard Worker X(YVariant) { 366*a65addddSAndroid Build Coastguard Worker } 367*a65addddSAndroid Build Coastguard Worker }; 368*a65addddSAndroid Build Coastguard Worker 369*a65addddSAndroid Build Coastguard Worker const Y y{}; 370*a65addddSAndroid Build Coastguard Worker 371*a65addddSAndroid Build Coastguard Worker fruit::Component<WithAnnotation<const Y>> getYComponent() { 372*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 373*a65addddSAndroid Build Coastguard Worker .bindInstance<WithAnnotation<Y>, Y>(y); 374*a65addddSAndroid Build Coastguard Worker } 375*a65addddSAndroid Build Coastguard Worker 376*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 377*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 378*a65addddSAndroid Build Coastguard Worker .install(getYComponent) 379*a65addddSAndroid Build Coastguard Worker .registerConstructor<X(WithAnnotation<YVariant>)>(); 380*a65addddSAndroid Build Coastguard Worker } 381*a65addddSAndroid Build Coastguard Worker 382*a65addddSAndroid Build Coastguard Worker int main() { 383*a65addddSAndroid Build Coastguard Worker fruit::Injector<X> injector(getComponent); 384*a65addddSAndroid Build Coastguard Worker injector.get<X>(); 385*a65addddSAndroid Build Coastguard Worker } 386*a65addddSAndroid Build Coastguard Worker ''' 387*a65addddSAndroid Build Coastguard Worker expect_success( 388*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 389*a65addddSAndroid Build Coastguard Worker source, 390*a65addddSAndroid Build Coastguard Worker locals()) 391*a65addddSAndroid Build Coastguard Worker 392*a65addddSAndroid Build Coastguard Worker @multiple_parameters([ 393*a65addddSAndroid Build Coastguard Worker ('WithNoAnnotation', 'Y'), 394*a65addddSAndroid Build Coastguard Worker ('WithAnnotation1', 'fruit::Annotated<Annotation1,Y>'), 395*a65addddSAndroid Build Coastguard Worker ], [ 396*a65addddSAndroid Build Coastguard Worker 'Y*', 397*a65addddSAndroid Build Coastguard Worker 'Y&', 398*a65addddSAndroid Build Coastguard Worker 'std::shared_ptr<Y>', 399*a65addddSAndroid Build Coastguard Worker 'fruit::Provider<Y>', 400*a65addddSAndroid Build Coastguard Worker ]) 401*a65addddSAndroid Build Coastguard Worker def test_register_constructor_with_param_error_nonconst_param_required(self, WithAnnotation, YAnnotRegex, YVariant): 402*a65addddSAndroid Build Coastguard Worker source = ''' 403*a65addddSAndroid Build Coastguard Worker struct Y {}; 404*a65addddSAndroid Build Coastguard Worker struct X { 405*a65addddSAndroid Build Coastguard Worker X(YVariant); 406*a65addddSAndroid Build Coastguard Worker }; 407*a65addddSAndroid Build Coastguard Worker 408*a65addddSAndroid Build Coastguard Worker fruit::Component<WithAnnotation<const Y>> getYComponent(); 409*a65addddSAndroid Build Coastguard Worker 410*a65addddSAndroid Build Coastguard Worker fruit::Component<> getComponent() { 411*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 412*a65addddSAndroid Build Coastguard Worker .install(getYComponent) 413*a65addddSAndroid Build Coastguard Worker .registerConstructor<X(WithAnnotation<YVariant>)>(); 414*a65addddSAndroid Build Coastguard Worker } 415*a65addddSAndroid Build Coastguard Worker ''' 416*a65addddSAndroid Build Coastguard Worker expect_compile_error( 417*a65addddSAndroid Build Coastguard Worker 'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>', 418*a65addddSAndroid Build Coastguard Worker 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 419*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 420*a65addddSAndroid Build Coastguard Worker source, 421*a65addddSAndroid Build Coastguard Worker locals()) 422*a65addddSAndroid Build Coastguard Worker 423*a65addddSAndroid Build Coastguard Worker @multiple_parameters([ 424*a65addddSAndroid Build Coastguard Worker ('WithNoAnnotation', 'Y'), 425*a65addddSAndroid Build Coastguard Worker ('WithAnnotation1', 'fruit::Annotated<Annotation1, Y>'), 426*a65addddSAndroid Build Coastguard Worker ], [ 427*a65addddSAndroid Build Coastguard Worker 'Y*', 428*a65addddSAndroid Build Coastguard Worker 'Y&', 429*a65addddSAndroid Build Coastguard Worker 'std::shared_ptr<Y>', 430*a65addddSAndroid Build Coastguard Worker 'fruit::Provider<Y>', 431*a65addddSAndroid Build Coastguard Worker ]) 432*a65addddSAndroid Build Coastguard Worker def test_register_constructor_with_param_error_nonconst_param_required_install_after(self, WithAnnotation, YAnnotRegex, YVariant): 433*a65addddSAndroid Build Coastguard Worker source = ''' 434*a65addddSAndroid Build Coastguard Worker struct Y {}; 435*a65addddSAndroid Build Coastguard Worker struct X { 436*a65addddSAndroid Build Coastguard Worker X(YVariant); 437*a65addddSAndroid Build Coastguard Worker }; 438*a65addddSAndroid Build Coastguard Worker 439*a65addddSAndroid Build Coastguard Worker fruit::Component<WithAnnotation<const Y>> getYComponent(); 440*a65addddSAndroid Build Coastguard Worker 441*a65addddSAndroid Build Coastguard Worker fruit::Component<> getComponent() { 442*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 443*a65addddSAndroid Build Coastguard Worker .registerConstructor<X(WithAnnotation<YVariant>)>() 444*a65addddSAndroid Build Coastguard Worker .install(getYComponent); 445*a65addddSAndroid Build Coastguard Worker } 446*a65addddSAndroid Build Coastguard Worker ''' 447*a65addddSAndroid Build Coastguard Worker expect_compile_error( 448*a65addddSAndroid Build Coastguard Worker 'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>', 449*a65addddSAndroid Build Coastguard Worker 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 450*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 451*a65addddSAndroid Build Coastguard Worker source, 452*a65addddSAndroid Build Coastguard Worker locals()) 453*a65addddSAndroid Build Coastguard Worker 454*a65addddSAndroid Build Coastguard Worker def test_register_constructor_requiring_nonconst_then_requiring_const_ok(self): 455*a65addddSAndroid Build Coastguard Worker source = ''' 456*a65addddSAndroid Build Coastguard Worker struct X {}; 457*a65addddSAndroid Build Coastguard Worker 458*a65addddSAndroid Build Coastguard Worker struct Y { 459*a65addddSAndroid Build Coastguard Worker Y(X&) {} 460*a65addddSAndroid Build Coastguard Worker }; 461*a65addddSAndroid Build Coastguard Worker 462*a65addddSAndroid Build Coastguard Worker struct Z { 463*a65addddSAndroid Build Coastguard Worker Z(const X&) {} 464*a65addddSAndroid Build Coastguard Worker }; 465*a65addddSAndroid Build Coastguard Worker 466*a65addddSAndroid Build Coastguard Worker fruit::Component<Y, Z> getRootComponent() { 467*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 468*a65addddSAndroid Build Coastguard Worker .registerConstructor<Y(X&)>() 469*a65addddSAndroid Build Coastguard Worker .registerConstructor<Z(const X&)>() 470*a65addddSAndroid Build Coastguard Worker .registerConstructor<X()>(); 471*a65addddSAndroid Build Coastguard Worker } 472*a65addddSAndroid Build Coastguard Worker 473*a65addddSAndroid Build Coastguard Worker int main() { 474*a65addddSAndroid Build Coastguard Worker fruit::Injector<Y, Z> injector(getRootComponent); 475*a65addddSAndroid Build Coastguard Worker injector.get<Y>(); 476*a65addddSAndroid Build Coastguard Worker injector.get<Z>(); 477*a65addddSAndroid Build Coastguard Worker } 478*a65addddSAndroid Build Coastguard Worker ''' 479*a65addddSAndroid Build Coastguard Worker expect_success( 480*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 481*a65addddSAndroid Build Coastguard Worker source, 482*a65addddSAndroid Build Coastguard Worker locals()) 483*a65addddSAndroid Build Coastguard Worker 484*a65addddSAndroid Build Coastguard Worker def test_register_constructor_requiring_nonconst_then_requiring_const_declaring_const_requirement_error(self): 485*a65addddSAndroid Build Coastguard Worker source = ''' 486*a65addddSAndroid Build Coastguard Worker struct X {}; 487*a65addddSAndroid Build Coastguard Worker 488*a65addddSAndroid Build Coastguard Worker struct Y { 489*a65addddSAndroid Build Coastguard Worker Y(X&) {} 490*a65addddSAndroid Build Coastguard Worker }; 491*a65addddSAndroid Build Coastguard Worker 492*a65addddSAndroid Build Coastguard Worker struct Z { 493*a65addddSAndroid Build Coastguard Worker Z(const X&) {} 494*a65addddSAndroid Build Coastguard Worker }; 495*a65addddSAndroid Build Coastguard Worker 496*a65addddSAndroid Build Coastguard Worker fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() { 497*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 498*a65addddSAndroid Build Coastguard Worker .registerConstructor<Y(X&)>() 499*a65addddSAndroid Build Coastguard Worker .registerConstructor<Z(const X&)>(); 500*a65addddSAndroid Build Coastguard Worker } 501*a65addddSAndroid Build Coastguard Worker ''' 502*a65addddSAndroid Build Coastguard Worker expect_compile_error( 503*a65addddSAndroid Build Coastguard Worker 'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>', 504*a65addddSAndroid Build Coastguard Worker 'The type T was declared as a const Required type in the returned Component, however', 505*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 506*a65addddSAndroid Build Coastguard Worker source, 507*a65addddSAndroid Build Coastguard Worker locals()) 508*a65addddSAndroid Build Coastguard Worker 509*a65addddSAndroid Build Coastguard Worker def test_register_constructor_requiring_const_then_requiring_nonconst_ok(self): 510*a65addddSAndroid Build Coastguard Worker source = ''' 511*a65addddSAndroid Build Coastguard Worker struct X {}; 512*a65addddSAndroid Build Coastguard Worker 513*a65addddSAndroid Build Coastguard Worker struct Y { 514*a65addddSAndroid Build Coastguard Worker Y(const X&) {} 515*a65addddSAndroid Build Coastguard Worker }; 516*a65addddSAndroid Build Coastguard Worker 517*a65addddSAndroid Build Coastguard Worker struct Z { 518*a65addddSAndroid Build Coastguard Worker Z(X&) {} 519*a65addddSAndroid Build Coastguard Worker }; 520*a65addddSAndroid Build Coastguard Worker 521*a65addddSAndroid Build Coastguard Worker fruit::Component<Y, Z> getRootComponent() { 522*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 523*a65addddSAndroid Build Coastguard Worker .registerConstructor<Y(const X&)>() 524*a65addddSAndroid Build Coastguard Worker .registerConstructor<Z(X&)>() 525*a65addddSAndroid Build Coastguard Worker .registerConstructor<X()>(); 526*a65addddSAndroid Build Coastguard Worker } 527*a65addddSAndroid Build Coastguard Worker 528*a65addddSAndroid Build Coastguard Worker int main() { 529*a65addddSAndroid Build Coastguard Worker fruit::Injector<Y, Z> injector(getRootComponent); 530*a65addddSAndroid Build Coastguard Worker injector.get<Y>(); 531*a65addddSAndroid Build Coastguard Worker injector.get<Z>(); 532*a65addddSAndroid Build Coastguard Worker } 533*a65addddSAndroid Build Coastguard Worker ''' 534*a65addddSAndroid Build Coastguard Worker expect_success( 535*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 536*a65addddSAndroid Build Coastguard Worker source, 537*a65addddSAndroid Build Coastguard Worker locals()) 538*a65addddSAndroid Build Coastguard Worker 539*a65addddSAndroid Build Coastguard Worker def test_register_constructor_requiring_const_then_requiring_nonconst_declaring_const_requirement_error(self): 540*a65addddSAndroid Build Coastguard Worker source = ''' 541*a65addddSAndroid Build Coastguard Worker struct X {}; 542*a65addddSAndroid Build Coastguard Worker 543*a65addddSAndroid Build Coastguard Worker struct Y { 544*a65addddSAndroid Build Coastguard Worker Y(const X&) {} 545*a65addddSAndroid Build Coastguard Worker }; 546*a65addddSAndroid Build Coastguard Worker 547*a65addddSAndroid Build Coastguard Worker struct Z { 548*a65addddSAndroid Build Coastguard Worker Z(X&) {} 549*a65addddSAndroid Build Coastguard Worker }; 550*a65addddSAndroid Build Coastguard Worker 551*a65addddSAndroid Build Coastguard Worker fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() { 552*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 553*a65addddSAndroid Build Coastguard Worker .registerConstructor<Y(const X&)>() 554*a65addddSAndroid Build Coastguard Worker .registerConstructor<Z(X&)>(); 555*a65addddSAndroid Build Coastguard Worker } 556*a65addddSAndroid Build Coastguard Worker ''' 557*a65addddSAndroid Build Coastguard Worker expect_compile_error( 558*a65addddSAndroid Build Coastguard Worker 'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>', 559*a65addddSAndroid Build Coastguard Worker 'The type T was declared as a const Required type in the returned Component, however', 560*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 561*a65addddSAndroid Build Coastguard Worker source, 562*a65addddSAndroid Build Coastguard Worker locals()) 563*a65addddSAndroid Build Coastguard Worker 564*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 565*a65addddSAndroid Build Coastguard Worker ('Y**', r'Y\*\*'), 566*a65addddSAndroid Build Coastguard Worker ('std::shared_ptr<Y>*', r'std::shared_ptr<Y>\*'), 567*a65addddSAndroid Build Coastguard Worker ('std::nullptr_t', r'(std::)?nullptr(_t)?'), 568*a65addddSAndroid Build Coastguard Worker ('Y*&', r'Y\*&'), 569*a65addddSAndroid Build Coastguard Worker ('Y(*)()', r'Y(\((__cdecl)?\*\))?\((void)?\)'), 570*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, Y**>', r'Y\*\*'), 571*a65addddSAndroid Build Coastguard Worker ]) 572*a65addddSAndroid Build Coastguard Worker def test_register_constructor_with_param_error_type_not_injectable(self, YVariant, YVariantRegex): 573*a65addddSAndroid Build Coastguard Worker source = ''' 574*a65addddSAndroid Build Coastguard Worker struct Y {}; 575*a65addddSAndroid Build Coastguard Worker struct X { 576*a65addddSAndroid Build Coastguard Worker X(YVariant); 577*a65addddSAndroid Build Coastguard Worker }; 578*a65addddSAndroid Build Coastguard Worker 579*a65addddSAndroid Build Coastguard Worker fruit::Component<> getComponent() { 580*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 581*a65addddSAndroid Build Coastguard Worker .registerConstructor<X(YVariant)>(); 582*a65addddSAndroid Build Coastguard Worker } 583*a65addddSAndroid Build Coastguard Worker ''' 584*a65addddSAndroid Build Coastguard Worker expect_compile_error( 585*a65addddSAndroid Build Coastguard Worker 'NonInjectableTypeError<YVariantRegex>', 586*a65addddSAndroid Build Coastguard Worker 'The type T is not injectable.', 587*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 588*a65addddSAndroid Build Coastguard Worker source, 589*a65addddSAndroid Build Coastguard Worker locals()) 590*a65addddSAndroid Build Coastguard Worker 591*a65addddSAndroid Build Coastguard Worker def test_register_constructor_error_assisted_param(self): 592*a65addddSAndroid Build Coastguard Worker source = ''' 593*a65addddSAndroid Build Coastguard Worker struct X { 594*a65addddSAndroid Build Coastguard Worker INJECT(X(ASSISTED(double) factor)) { 595*a65addddSAndroid Build Coastguard Worker (void) factor; 596*a65addddSAndroid Build Coastguard Worker } 597*a65addddSAndroid Build Coastguard Worker }; 598*a65addddSAndroid Build Coastguard Worker 599*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 600*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 601*a65addddSAndroid Build Coastguard Worker .registerConstructor<X(fruit::Assisted<double>)>(); 602*a65addddSAndroid Build Coastguard Worker } 603*a65addddSAndroid Build Coastguard Worker ''' 604*a65addddSAndroid Build Coastguard Worker expect_compile_error( 605*a65addddSAndroid Build Coastguard Worker 'AssistedParamInRegisterConstructorSignatureError<X\\(fruit::Assisted<double>\\)>', 606*a65addddSAndroid Build Coastguard Worker 'CandidateSignature was used as signature for a registerConstructor.* but it contains an assisted parameter.', 607*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 608*a65addddSAndroid Build Coastguard Worker source, 609*a65addddSAndroid Build Coastguard Worker locals()) 610*a65addddSAndroid Build Coastguard Worker 611*a65addddSAndroid Build Coastguard Worker def test_implicit_register_constructor_error_assisted_param(self): 612*a65addddSAndroid Build Coastguard Worker source = ''' 613*a65addddSAndroid Build Coastguard Worker struct X { 614*a65addddSAndroid Build Coastguard Worker INJECT(X(ASSISTED(double) factor)) { 615*a65addddSAndroid Build Coastguard Worker (void) factor; 616*a65addddSAndroid Build Coastguard Worker } 617*a65addddSAndroid Build Coastguard Worker }; 618*a65addddSAndroid Build Coastguard Worker 619*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 620*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 621*a65addddSAndroid Build Coastguard Worker } 622*a65addddSAndroid Build Coastguard Worker ''' 623*a65addddSAndroid Build Coastguard Worker expect_compile_error( 624*a65addddSAndroid Build Coastguard Worker 'AssistedParamInRegisterConstructorSignatureError<X\\(fruit::Assisted<double>\\)>', 625*a65addddSAndroid Build Coastguard Worker 'CandidateSignature was used as signature for a registerConstructor.* but it contains an assisted parameter.', 626*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 627*a65addddSAndroid Build Coastguard Worker source, 628*a65addddSAndroid Build Coastguard Worker locals()) 629*a65addddSAndroid Build Coastguard Worker 630*a65addddSAndroid Build Coastguard Worker 631*a65addddSAndroid Build Coastguard Worker 632*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__': 633*a65addddSAndroid Build Coastguard Worker absltest.main() 634