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 30*a65addddSAndroid Build Coastguard Workerclass TestInjectedProvider(parameterized.TestCase): 31*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 32*a65addddSAndroid Build Coastguard Worker ('X*', r'X\*'), 33*a65addddSAndroid Build Coastguard Worker ('const X*', r'const X\*'), 34*a65addddSAndroid Build Coastguard Worker ('X&', r'X&'), 35*a65addddSAndroid Build Coastguard Worker ('const X&', r'const X&'), 36*a65addddSAndroid Build Coastguard Worker ('std::shared_ptr<X>', r'std::shared_ptr<X>'), 37*a65addddSAndroid Build Coastguard Worker ]) 38*a65addddSAndroid Build Coastguard Worker def test_error_non_class_type_parameter(self, XVariant, XVariantRegexp): 39*a65addddSAndroid Build Coastguard Worker source = ''' 40*a65addddSAndroid Build Coastguard Worker struct X {}; 41*a65addddSAndroid Build Coastguard Worker 42*a65addddSAndroid Build Coastguard Worker fruit::Provider<XVariant> provider; 43*a65addddSAndroid Build Coastguard Worker ''' 44*a65addddSAndroid Build Coastguard Worker expect_compile_error( 45*a65addddSAndroid Build Coastguard Worker 'NonClassTypeError<XVariantRegexp,X>', 46*a65addddSAndroid Build Coastguard Worker 'A non-class type T was specified. Use C instead', 47*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 48*a65addddSAndroid Build Coastguard Worker source, 49*a65addddSAndroid Build Coastguard Worker locals()) 50*a65addddSAndroid Build Coastguard Worker 51*a65addddSAndroid Build Coastguard Worker def test_error_annotated_type_parameter(self): 52*a65addddSAndroid Build Coastguard Worker source = ''' 53*a65addddSAndroid Build Coastguard Worker struct X {}; 54*a65addddSAndroid Build Coastguard Worker 55*a65addddSAndroid Build Coastguard Worker fruit::Provider<XAnnot> provider; 56*a65addddSAndroid Build Coastguard Worker ''' 57*a65addddSAndroid Build Coastguard Worker expect_compile_error( 58*a65addddSAndroid Build Coastguard Worker 'AnnotatedTypeError<fruit::Annotated<Annotation1,X>,X>', 59*a65addddSAndroid Build Coastguard Worker 'An annotated type was specified where a non-annotated type was expected.', 60*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 61*a65addddSAndroid Build Coastguard Worker source) 62*a65addddSAndroid Build Coastguard Worker 63*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 64*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Provider<X>', 'X', 'X'), 65*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Provider<X>', 'X', 'const X&'), 66*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Provider<X>', 'X', 'const X*'), 67*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Provider<X>', 'X', 'X&'), 68*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Provider<X>', 'X', 'X*'), 69*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Provider<X>', 'X', 'std::shared_ptr<X>'), 70*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Provider<X>', 'X', 'fruit::Provider<X>'), 71*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Provider<X>', 'X', 'fruit::Provider<const X>'), 72*a65addddSAndroid Build Coastguard Worker ('X', 'fruit::Provider<const X>', 'const X', 'const X&'), 73*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, fruit::Provider<X>>', 'X', 'const X&'), 74*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, fruit::Provider<const X>>', 'const X', 'const X&'), 75*a65addddSAndroid Build Coastguard Worker ]) 76*a65addddSAndroid Build Coastguard Worker def test_provider_get_ok(self, XBindingInInjector, XProviderAnnot, XParamInProvider, XProviderGetParam): 77*a65addddSAndroid Build Coastguard Worker source = ''' 78*a65addddSAndroid Build Coastguard Worker struct X { 79*a65addddSAndroid Build Coastguard Worker using Inject = X(); 80*a65addddSAndroid Build Coastguard Worker }; 81*a65addddSAndroid Build Coastguard Worker 82*a65addddSAndroid Build Coastguard Worker fruit::Component<XBindingInInjector> getComponent() { 83*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 84*a65addddSAndroid Build Coastguard Worker } 85*a65addddSAndroid Build Coastguard Worker 86*a65addddSAndroid Build Coastguard Worker int main() { 87*a65addddSAndroid Build Coastguard Worker fruit::Injector<XBindingInInjector> injector(getComponent); 88*a65addddSAndroid Build Coastguard Worker fruit::Provider<XParamInProvider> provider = injector.get<XProviderAnnot>(); 89*a65addddSAndroid Build Coastguard Worker 90*a65addddSAndroid Build Coastguard Worker XProviderGetParam x = provider.get<XProviderGetParam>(); 91*a65addddSAndroid Build Coastguard Worker (void)x; 92*a65addddSAndroid Build Coastguard Worker } 93*a65addddSAndroid Build Coastguard Worker ''' 94*a65addddSAndroid Build Coastguard Worker expect_success( 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 ('const X', 'fruit::Provider<const X>', 'const X', 'X'), 101*a65addddSAndroid Build Coastguard Worker ('const X', 'fruit::Provider<const X>', 'const X', 'const X&'), 102*a65addddSAndroid Build Coastguard Worker ('const X', 'fruit::Provider<const X>', 'const X', 'const X*'), 103*a65addddSAndroid Build Coastguard Worker ('const X', 'fruit::Provider<const X>', 'const X', 'fruit::Provider<const X>'), 104*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, fruit::Provider<const X>>', 'const X', 'const X&'), 105*a65addddSAndroid Build Coastguard Worker ]) 106*a65addddSAndroid Build Coastguard Worker def test_provider_get_const_binding_ok(self, XBindingInInjector, XProviderAnnot, XParamInProvider, XProviderGetParam): 107*a65addddSAndroid Build Coastguard Worker XBindingInInjectorWithoutConst = XBindingInInjector.replace('const ', '') 108*a65addddSAndroid Build Coastguard Worker source = ''' 109*a65addddSAndroid Build Coastguard Worker struct X {}; 110*a65addddSAndroid Build Coastguard Worker 111*a65addddSAndroid Build Coastguard Worker const X x{}; 112*a65addddSAndroid Build Coastguard Worker 113*a65addddSAndroid Build Coastguard Worker fruit::Component<XBindingInInjector> getComponent() { 114*a65addddSAndroid Build Coastguard Worker return fruit::createComponent() 115*a65addddSAndroid Build Coastguard Worker .bindInstance<XBindingInInjectorWithoutConst, X>(x); 116*a65addddSAndroid Build Coastguard Worker } 117*a65addddSAndroid Build Coastguard Worker 118*a65addddSAndroid Build Coastguard Worker int main() { 119*a65addddSAndroid Build Coastguard Worker fruit::Injector<XBindingInInjector> injector(getComponent); 120*a65addddSAndroid Build Coastguard Worker fruit::Provider<XParamInProvider> provider = injector.get<XProviderAnnot>(); 121*a65addddSAndroid Build Coastguard Worker 122*a65addddSAndroid Build Coastguard Worker XProviderGetParam x = provider.get<XProviderGetParam>(); 123*a65addddSAndroid Build Coastguard Worker (void)x; 124*a65addddSAndroid Build Coastguard Worker } 125*a65addddSAndroid Build Coastguard Worker ''' 126*a65addddSAndroid Build Coastguard Worker expect_success( 127*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 128*a65addddSAndroid Build Coastguard Worker source, 129*a65addddSAndroid Build Coastguard Worker locals()) 130*a65addddSAndroid Build Coastguard Worker 131*a65addddSAndroid Build Coastguard Worker def test_provider_get_during_injection_ok(self): 132*a65addddSAndroid Build Coastguard Worker source = ''' 133*a65addddSAndroid Build Coastguard Worker struct X { 134*a65addddSAndroid Build Coastguard Worker INJECT(X()) = default; 135*a65addddSAndroid Build Coastguard Worker void foo() { 136*a65addddSAndroid Build Coastguard Worker } 137*a65addddSAndroid Build Coastguard Worker }; 138*a65addddSAndroid Build Coastguard Worker 139*a65addddSAndroid Build Coastguard Worker struct Y { 140*a65addddSAndroid Build Coastguard Worker X x; 141*a65addddSAndroid Build Coastguard Worker INJECT(Y(fruit::Provider<X> xProvider)) 142*a65addddSAndroid Build Coastguard Worker : x(xProvider.get<X>()) { 143*a65addddSAndroid Build Coastguard Worker } 144*a65addddSAndroid Build Coastguard Worker 145*a65addddSAndroid Build Coastguard Worker void foo() { 146*a65addddSAndroid Build Coastguard Worker x.foo(); 147*a65addddSAndroid Build Coastguard Worker } 148*a65addddSAndroid Build Coastguard Worker }; 149*a65addddSAndroid Build Coastguard Worker 150*a65addddSAndroid Build Coastguard Worker struct Z { 151*a65addddSAndroid Build Coastguard Worker Y y; 152*a65addddSAndroid Build Coastguard Worker INJECT(Z(fruit::Provider<Y> yProvider)) 153*a65addddSAndroid Build Coastguard Worker : y(yProvider.get<Y>()) { 154*a65addddSAndroid Build Coastguard Worker } 155*a65addddSAndroid Build Coastguard Worker 156*a65addddSAndroid Build Coastguard Worker void foo() { 157*a65addddSAndroid Build Coastguard Worker y.foo(); 158*a65addddSAndroid Build Coastguard Worker } 159*a65addddSAndroid Build Coastguard Worker }; 160*a65addddSAndroid Build Coastguard Worker 161*a65addddSAndroid Build Coastguard Worker fruit::Component<Z> getZComponent() { 162*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 163*a65addddSAndroid Build Coastguard Worker } 164*a65addddSAndroid Build Coastguard Worker 165*a65addddSAndroid Build Coastguard Worker int main() { 166*a65addddSAndroid Build Coastguard Worker fruit::Injector<Z> injector(getZComponent); 167*a65addddSAndroid Build Coastguard Worker fruit::Provider<Z> provider(injector); 168*a65addddSAndroid Build Coastguard Worker // During provider.get<Z>(), yProvider.get() is called, and during that xProvider.get() 169*a65addddSAndroid Build Coastguard Worker // is called. 170*a65addddSAndroid Build Coastguard Worker Z z = provider.get<Z>(); 171*a65addddSAndroid Build Coastguard Worker z.foo(); 172*a65addddSAndroid Build Coastguard Worker } 173*a65addddSAndroid Build Coastguard Worker ''' 174*a65addddSAndroid Build Coastguard Worker expect_success( 175*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 176*a65addddSAndroid Build Coastguard Worker source) 177*a65addddSAndroid Build Coastguard Worker 178*a65addddSAndroid Build Coastguard Worker def test_provider_get_error_type_not_provided(self): 179*a65addddSAndroid Build Coastguard Worker source = ''' 180*a65addddSAndroid Build Coastguard Worker struct X {}; 181*a65addddSAndroid Build Coastguard Worker struct Y {}; 182*a65addddSAndroid Build Coastguard Worker 183*a65addddSAndroid Build Coastguard Worker void f(fruit::Provider<X> provider) { 184*a65addddSAndroid Build Coastguard Worker provider.get<Y>(); 185*a65addddSAndroid Build Coastguard Worker } 186*a65addddSAndroid Build Coastguard Worker ''' 187*a65addddSAndroid Build Coastguard Worker expect_compile_error( 188*a65addddSAndroid Build Coastguard Worker 'TypeNotProvidedError<Y>', 189*a65addddSAndroid Build Coastguard Worker 'Trying to get an instance of T, but it is not provided by this Provider/Injector.', 190*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 191*a65addddSAndroid Build Coastguard Worker source) 192*a65addddSAndroid Build Coastguard Worker 193*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 194*a65addddSAndroid Build Coastguard Worker ('X**', r'X\*\*'), 195*a65addddSAndroid Build Coastguard Worker ('std::shared_ptr<X>*', r'std::shared_ptr<X>\*'), 196*a65addddSAndroid Build Coastguard Worker ('const std::shared_ptr<X>', r'const std::shared_ptr<X>'), 197*a65addddSAndroid Build Coastguard Worker ('X* const', r'X\* const'), 198*a65addddSAndroid Build Coastguard Worker ('const X* const', r'const X\* const'), 199*a65addddSAndroid Build Coastguard Worker ('std::nullptr_t', r'(std::)?nullptr(_t)?'), 200*a65addddSAndroid Build Coastguard Worker ('X*&', r'X\*&'), 201*a65addddSAndroid Build Coastguard Worker ('X(*)()', r'X(\((__cdecl)?\*\))?\((void)?\)'), 202*a65addddSAndroid Build Coastguard Worker ('void', r'void'), 203*a65addddSAndroid Build Coastguard Worker ('fruit::Annotated<Annotation1, fruit::Annotated<Annotation1, X>>', r'fruit::Annotated<Annotation1, X>'), 204*a65addddSAndroid Build Coastguard Worker ]) 205*a65addddSAndroid Build Coastguard Worker def test_provider_get_error_type_not_injectable(self, XVariant, XVariantRegex): 206*a65addddSAndroid Build Coastguard Worker source = ''' 207*a65addddSAndroid Build Coastguard Worker struct X {}; 208*a65addddSAndroid Build Coastguard Worker 209*a65addddSAndroid Build Coastguard Worker void f(fruit::Provider<X> provider) { 210*a65addddSAndroid Build Coastguard Worker provider.get<XVariant>(); 211*a65addddSAndroid Build Coastguard Worker } 212*a65addddSAndroid Build Coastguard Worker ''' 213*a65addddSAndroid Build Coastguard Worker expect_compile_error( 214*a65addddSAndroid Build Coastguard Worker 'NonInjectableTypeError<XVariantRegex>', 215*a65addddSAndroid Build Coastguard Worker 'The type T is not injectable', 216*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 217*a65addddSAndroid Build Coastguard Worker source, 218*a65addddSAndroid Build Coastguard Worker locals()) 219*a65addddSAndroid Build Coastguard Worker 220*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 221*a65addddSAndroid Build Coastguard Worker ('X&', r'X&'), 222*a65addddSAndroid Build Coastguard Worker ('X*', r'X\*'), 223*a65addddSAndroid Build Coastguard Worker ('std::shared_ptr<X>', r'std::shared_ptr<X>'), 224*a65addddSAndroid Build Coastguard Worker ('fruit::Provider<X>', r'fruit::Provider<X>'), 225*a65addddSAndroid Build Coastguard Worker ]) 226*a65addddSAndroid Build Coastguard Worker def test_const_provider_get_does_not_allow_injecting_nonconst_variants(self, XProviderGetParam, XProviderGetParamRegex): 227*a65addddSAndroid Build Coastguard Worker source = ''' 228*a65addddSAndroid Build Coastguard Worker void f(fruit::Provider<const X> provider) { 229*a65addddSAndroid Build Coastguard Worker provider.get<XProviderGetParam>(); 230*a65addddSAndroid Build Coastguard Worker } 231*a65addddSAndroid Build Coastguard Worker ''' 232*a65addddSAndroid Build Coastguard Worker expect_compile_error( 233*a65addddSAndroid Build Coastguard Worker 'TypeProvidedAsConstOnlyError<XProviderGetParamRegex>', 234*a65addddSAndroid Build Coastguard Worker 'Trying to get an instance of T, but it is only provided as a constant by this Provider/Injector', 235*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 236*a65addddSAndroid Build Coastguard Worker source, 237*a65addddSAndroid Build Coastguard Worker locals()) 238*a65addddSAndroid Build Coastguard Worker 239*a65addddSAndroid Build Coastguard Worker @parameterized.parameters([ 240*a65addddSAndroid Build Coastguard Worker ('fruit::Provider<Y>'), 241*a65addddSAndroid Build Coastguard Worker ('ANNOTATED(Annotation1, fruit::Provider<Y>)'), 242*a65addddSAndroid Build Coastguard Worker ]) 243*a65addddSAndroid Build Coastguard Worker def test_lazy_injection_with_annotations(self, Y_PROVIDER_ANNOT): 244*a65addddSAndroid Build Coastguard Worker source = ''' 245*a65addddSAndroid Build Coastguard Worker struct Y : public ConstructionTracker<Y> { 246*a65addddSAndroid Build Coastguard Worker using Inject = Y(); 247*a65addddSAndroid Build Coastguard Worker }; 248*a65addddSAndroid Build Coastguard Worker 249*a65addddSAndroid Build Coastguard Worker struct X : public ConstructionTracker<X> { 250*a65addddSAndroid Build Coastguard Worker INJECT(X(Y_PROVIDER_ANNOT provider)) : provider(provider) { 251*a65addddSAndroid Build Coastguard Worker } 252*a65addddSAndroid Build Coastguard Worker 253*a65addddSAndroid Build Coastguard Worker void run() { 254*a65addddSAndroid Build Coastguard Worker Y* y(provider); 255*a65addddSAndroid Build Coastguard Worker (void) y; 256*a65addddSAndroid Build Coastguard Worker } 257*a65addddSAndroid Build Coastguard Worker 258*a65addddSAndroid Build Coastguard Worker fruit::Provider<Y> provider; 259*a65addddSAndroid Build Coastguard Worker }; 260*a65addddSAndroid Build Coastguard Worker 261*a65addddSAndroid Build Coastguard Worker fruit::Component<X> getComponent() { 262*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 263*a65addddSAndroid Build Coastguard Worker } 264*a65addddSAndroid Build Coastguard Worker 265*a65addddSAndroid Build Coastguard Worker fruit::Component<> getEmptyComponent() { 266*a65addddSAndroid Build Coastguard Worker return fruit::createComponent(); 267*a65addddSAndroid Build Coastguard Worker } 268*a65addddSAndroid Build Coastguard Worker 269*a65addddSAndroid Build Coastguard Worker int main() { 270*a65addddSAndroid Build Coastguard Worker fruit::NormalizedComponent<> normalizedComponent(getEmptyComponent); 271*a65addddSAndroid Build Coastguard Worker fruit::Injector<X> injector(normalizedComponent, getComponent); 272*a65addddSAndroid Build Coastguard Worker 273*a65addddSAndroid Build Coastguard Worker Assert(X::num_objects_constructed == 0); 274*a65addddSAndroid Build Coastguard Worker Assert(Y::num_objects_constructed == 0); 275*a65addddSAndroid Build Coastguard Worker 276*a65addddSAndroid Build Coastguard Worker X* x(injector); 277*a65addddSAndroid Build Coastguard Worker 278*a65addddSAndroid Build Coastguard Worker Assert(X::num_objects_constructed == 1); 279*a65addddSAndroid Build Coastguard Worker Assert(Y::num_objects_constructed == 0); 280*a65addddSAndroid Build Coastguard Worker 281*a65addddSAndroid Build Coastguard Worker x->run(); 282*a65addddSAndroid Build Coastguard Worker 283*a65addddSAndroid Build Coastguard Worker Assert(X::num_objects_constructed == 1); 284*a65addddSAndroid Build Coastguard Worker Assert(Y::num_objects_constructed == 1); 285*a65addddSAndroid Build Coastguard Worker } 286*a65addddSAndroid Build Coastguard Worker ''' 287*a65addddSAndroid Build Coastguard Worker expect_success( 288*a65addddSAndroid Build Coastguard Worker COMMON_DEFINITIONS, 289*a65addddSAndroid Build Coastguard Worker source, 290*a65addddSAndroid Build Coastguard Worker locals()) 291*a65addddSAndroid Build Coastguard Worker 292*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__': 293*a65addddSAndroid Build Coastguard Worker absltest.main() 294