xref: /aosp_15_r20/external/google-fruit/tests/test_register_provider.py (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
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 Annotation1 {};
23*a65addddSAndroid Build Coastguard Worker
24*a65addddSAndroid Build Coastguard Worker    template <typename T>
25*a65addddSAndroid Build Coastguard Worker    using WithNoAnnot = T;
26*a65addddSAndroid Build Coastguard Worker
27*a65addddSAndroid Build Coastguard Worker    template <typename T>
28*a65addddSAndroid Build Coastguard Worker    using WithAnnot1 = fruit::Annotated<Annotation1, T>;
29*a65addddSAndroid Build Coastguard Worker    '''
30*a65addddSAndroid Build Coastguard Worker
31*a65addddSAndroid Build Coastguard Workerclass TestRegisterProvider(parameterized.TestCase):
32*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
33*a65addddSAndroid Build Coastguard Worker        'WithNoAnnot',
34*a65addddSAndroid Build Coastguard Worker        'WithAnnot1',
35*a65addddSAndroid Build Coastguard Worker    ], [
36*a65addddSAndroid Build Coastguard Worker       ('X()', 'X'),
37*a65addddSAndroid Build Coastguard Worker       ('new X()', 'X*'),
38*a65addddSAndroid Build Coastguard Worker    ])
39*a65addddSAndroid Build Coastguard Worker    def test_register_provider_success(self, WithAnnot, ConstructX, XPtr):
40*a65addddSAndroid Build Coastguard Worker        source = '''
41*a65addddSAndroid Build Coastguard Worker            struct X : public ConstructionTracker<X> {
42*a65addddSAndroid Build Coastguard Worker              int value = 5;
43*a65addddSAndroid Build Coastguard Worker            };
44*a65addddSAndroid Build Coastguard Worker
45*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<X>> getComponent() {
46*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
47*a65addddSAndroid Build Coastguard Worker                .registerProvider<WithAnnot<XPtr>()>([](){return ConstructX;});
48*a65addddSAndroid Build Coastguard Worker            }
49*a65addddSAndroid Build Coastguard Worker
50*a65addddSAndroid Build Coastguard Worker            int main() {
51*a65addddSAndroid Build Coastguard Worker              fruit::Injector<WithAnnot<X>> injector(getComponent);
52*a65addddSAndroid Build Coastguard Worker
53*a65addddSAndroid Build Coastguard Worker              Assert((injector.get<WithAnnot<X                 >>(). value == 5));
54*a65addddSAndroid Build Coastguard Worker              Assert((injector.get<WithAnnot<X*                >>()->value == 5));
55*a65addddSAndroid Build Coastguard Worker              Assert((injector.get<WithAnnot<X&                >>(). value == 5));
56*a65addddSAndroid Build Coastguard Worker              Assert((injector.get<WithAnnot<const X           >>(). value == 5));
57*a65addddSAndroid Build Coastguard Worker              Assert((injector.get<WithAnnot<const X*          >>()->value == 5));
58*a65addddSAndroid Build Coastguard Worker              Assert((injector.get<WithAnnot<const X&          >>(). value == 5));
59*a65addddSAndroid Build Coastguard Worker              Assert((injector.get<WithAnnot<std::shared_ptr<X>>>()->value == 5));
60*a65addddSAndroid Build Coastguard Worker
61*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 1);
62*a65addddSAndroid Build Coastguard Worker            }
63*a65addddSAndroid Build Coastguard Worker            '''
64*a65addddSAndroid Build Coastguard Worker        expect_success(
65*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
66*a65addddSAndroid Build Coastguard Worker            source,
67*a65addddSAndroid Build Coastguard Worker            locals())
68*a65addddSAndroid Build Coastguard Worker
69*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
70*a65addddSAndroid Build Coastguard Worker        'WithNoAnnot',
71*a65addddSAndroid Build Coastguard Worker        'WithAnnot1',
72*a65addddSAndroid Build Coastguard Worker    ])
73*a65addddSAndroid Build Coastguard Worker    def test_register_provider_abstract_class_ok(self, WithAnnot):
74*a65addddSAndroid Build Coastguard Worker        source = '''
75*a65addddSAndroid Build Coastguard Worker            struct I {
76*a65addddSAndroid Build Coastguard Worker              virtual int foo() = 0;
77*a65addddSAndroid Build Coastguard Worker              virtual ~I() = default;
78*a65addddSAndroid Build Coastguard Worker            };
79*a65addddSAndroid Build Coastguard Worker
80*a65addddSAndroid Build Coastguard Worker            struct X : public I {
81*a65addddSAndroid Build Coastguard Worker              int foo() override {
82*a65addddSAndroid Build Coastguard Worker                return 5;
83*a65addddSAndroid Build Coastguard Worker              }
84*a65addddSAndroid Build Coastguard Worker            };
85*a65addddSAndroid Build Coastguard Worker
86*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<I>> getComponent() {
87*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
88*a65addddSAndroid Build Coastguard Worker                .registerProvider<WithAnnot<I*>()>([](){return static_cast<I*>(new X());});
89*a65addddSAndroid Build Coastguard Worker            }
90*a65addddSAndroid Build Coastguard Worker
91*a65addddSAndroid Build Coastguard Worker            int main() {
92*a65addddSAndroid Build Coastguard Worker              fruit::Injector<WithAnnot<I>> injector(getComponent);
93*a65addddSAndroid Build Coastguard Worker
94*a65addddSAndroid Build Coastguard Worker              Assert(injector.get<WithAnnot<I*>>()->foo() == 5);
95*a65addddSAndroid Build Coastguard Worker            }
96*a65addddSAndroid Build Coastguard Worker            '''
97*a65addddSAndroid Build Coastguard Worker        expect_success(
98*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
99*a65addddSAndroid Build Coastguard Worker            source,
100*a65addddSAndroid Build Coastguard Worker            locals())
101*a65addddSAndroid Build Coastguard Worker
102*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
103*a65addddSAndroid Build Coastguard Worker        'WithNoAnnot',
104*a65addddSAndroid Build Coastguard Worker        'WithAnnot1',
105*a65addddSAndroid Build Coastguard Worker    ])
106*a65addddSAndroid Build Coastguard Worker    def test_register_provider_abstract_class_with_no_virtual_destructor_error(self, WithAnnot):
107*a65addddSAndroid Build Coastguard Worker        source = '''
108*a65addddSAndroid Build Coastguard Worker            struct I {
109*a65addddSAndroid Build Coastguard Worker              virtual int foo() = 0;
110*a65addddSAndroid Build Coastguard Worker            };
111*a65addddSAndroid Build Coastguard Worker
112*a65addddSAndroid Build Coastguard Worker            struct X : public I {
113*a65addddSAndroid Build Coastguard Worker              int foo() override {
114*a65addddSAndroid Build Coastguard Worker                return 5;
115*a65addddSAndroid Build Coastguard Worker              }
116*a65addddSAndroid Build Coastguard Worker            };
117*a65addddSAndroid Build Coastguard Worker
118*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<I>> getComponent() {
119*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
120*a65addddSAndroid Build Coastguard Worker                .registerProvider<WithAnnot<I*>()>([](){return static_cast<I*>(new X());});
121*a65addddSAndroid Build Coastguard Worker            }
122*a65addddSAndroid Build Coastguard Worker            '''
123*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
124*a65addddSAndroid Build Coastguard Worker            r'ProviderReturningPointerToAbstractClassWithNoVirtualDestructorError<I>',
125*a65addddSAndroid Build Coastguard Worker            r'registerProvider\(\) was called with a lambda that returns a pointer to T, but T is an abstract class',
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()',
132*a65addddSAndroid Build Coastguard Worker        'new X()',
133*a65addddSAndroid Build Coastguard Worker    ])
134*a65addddSAndroid Build Coastguard Worker    def test_register_provider_not_copyable_success(self, ConstructX):
135*a65addddSAndroid Build Coastguard Worker        source = '''
136*a65addddSAndroid Build Coastguard Worker            struct X {
137*a65addddSAndroid Build Coastguard Worker              X() = default;
138*a65addddSAndroid Build Coastguard Worker              X(X&&) = default;
139*a65addddSAndroid Build Coastguard Worker              X(const X&) = delete;
140*a65addddSAndroid Build Coastguard Worker            };
141*a65addddSAndroid Build Coastguard Worker
142*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
143*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
144*a65addddSAndroid Build Coastguard Worker                .registerProvider([](){return ConstructX;});
145*a65addddSAndroid Build Coastguard Worker            }
146*a65addddSAndroid Build Coastguard Worker
147*a65addddSAndroid Build Coastguard Worker            int main() {
148*a65addddSAndroid Build Coastguard Worker              fruit::Injector<X> injector(getComponent);
149*a65addddSAndroid Build Coastguard Worker              injector.get<X*>();
150*a65addddSAndroid Build Coastguard Worker            }
151*a65addddSAndroid Build Coastguard Worker            '''
152*a65addddSAndroid Build Coastguard Worker        expect_success(
153*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
154*a65addddSAndroid Build Coastguard Worker            source,
155*a65addddSAndroid Build Coastguard Worker            locals())
156*a65addddSAndroid Build Coastguard Worker
157*a65addddSAndroid Build Coastguard Worker    def test_register_provider_not_movable_returning_pointer_success(self):
158*a65addddSAndroid Build Coastguard Worker        source = '''
159*a65addddSAndroid Build Coastguard Worker            struct X {
160*a65addddSAndroid Build Coastguard Worker              X() = default;
161*a65addddSAndroid Build Coastguard Worker              X(X&&) = delete;
162*a65addddSAndroid Build Coastguard Worker              X(const X&) = delete;
163*a65addddSAndroid Build Coastguard Worker            };
164*a65addddSAndroid Build Coastguard Worker
165*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
166*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
167*a65addddSAndroid Build Coastguard Worker                .registerProvider([](){return new X();});
168*a65addddSAndroid Build Coastguard Worker            }
169*a65addddSAndroid Build Coastguard Worker
170*a65addddSAndroid Build Coastguard Worker            int main() {
171*a65addddSAndroid Build Coastguard Worker              fruit::Injector<X> injector(getComponent);
172*a65addddSAndroid Build Coastguard Worker              injector.get<X*>();
173*a65addddSAndroid Build Coastguard Worker            }
174*a65addddSAndroid Build Coastguard Worker            '''
175*a65addddSAndroid Build Coastguard Worker        expect_success(
176*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
177*a65addddSAndroid Build Coastguard Worker            source)
178*a65addddSAndroid Build Coastguard Worker
179*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
180*a65addddSAndroid Build Coastguard Worker        'X',
181*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
182*a65addddSAndroid Build Coastguard Worker    ])
183*a65addddSAndroid Build Coastguard Worker    def test_register_provider_error_not_function(self, XAnnot):
184*a65addddSAndroid Build Coastguard Worker        source = '''
185*a65addddSAndroid Build Coastguard Worker            struct X {
186*a65addddSAndroid Build Coastguard Worker              X(int) {}
187*a65addddSAndroid Build Coastguard Worker            };
188*a65addddSAndroid Build Coastguard Worker
189*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getComponent() {
190*a65addddSAndroid Build Coastguard Worker              int n = 3;
191*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
192*a65addddSAndroid Build Coastguard Worker                .registerProvider<XAnnot()>([=]{return X(n);});
193*a65addddSAndroid Build Coastguard Worker            }
194*a65addddSAndroid Build Coastguard Worker            '''
195*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
196*a65addddSAndroid Build Coastguard Worker            'FunctorUsedAsProviderError<.*>',
197*a65addddSAndroid Build Coastguard Worker            'A stateful lambda or a non-lambda functor was used as provider',
198*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
199*a65addddSAndroid Build Coastguard Worker            source,
200*a65addddSAndroid Build Coastguard Worker            locals())
201*a65addddSAndroid Build Coastguard Worker
202*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
203*a65addddSAndroid Build Coastguard Worker        'int',
204*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, int>',
205*a65addddSAndroid Build Coastguard Worker    ])
206*a65addddSAndroid Build Coastguard Worker    def test_register_provider_error_malformed_signature(self, intAnnot):
207*a65addddSAndroid Build Coastguard Worker        source = '''
208*a65addddSAndroid Build Coastguard Worker            fruit::Component<intAnnot> getComponent() {
209*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
210*a65addddSAndroid Build Coastguard Worker                .registerProvider<intAnnot>([](){return 42;});
211*a65addddSAndroid Build Coastguard Worker            }
212*a65addddSAndroid Build Coastguard Worker            '''
213*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
214*a65addddSAndroid Build Coastguard Worker            'NotASignatureError<intAnnot>',
215*a65addddSAndroid Build Coastguard Worker            'CandidateSignature was specified as parameter, but it.s not a signature. Signatures are of the form',
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', 'X*', '(struct )?X'),
222*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X*>', '(struct )?fruit::Annotated<(struct )?Annotation1, ?(struct )?X>'),
223*a65addddSAndroid Build Coastguard Worker    ])
224*a65addddSAndroid Build Coastguard Worker    def test_register_provider_error_returned_nullptr(self, XAnnot, XPtrAnnot, XAnnotRegex):
225*a65addddSAndroid Build Coastguard Worker        source = '''
226*a65addddSAndroid Build Coastguard Worker            struct X {};
227*a65addddSAndroid Build Coastguard Worker
228*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getComponent() {
229*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
230*a65addddSAndroid Build Coastguard Worker                  .registerProvider<XPtrAnnot()>([](){return (X*)nullptr;});
231*a65addddSAndroid Build Coastguard Worker            }
232*a65addddSAndroid Build Coastguard Worker
233*a65addddSAndroid Build Coastguard Worker            int main() {
234*a65addddSAndroid Build Coastguard Worker              fruit::Injector<XAnnot> injector(getComponent);
235*a65addddSAndroid Build Coastguard Worker              injector.get<XAnnot>();
236*a65addddSAndroid Build Coastguard Worker            }
237*a65addddSAndroid Build Coastguard Worker            '''
238*a65addddSAndroid Build Coastguard Worker        expect_runtime_error(
239*a65addddSAndroid Build Coastguard Worker            'Fatal injection error: attempting to get an instance for the type XAnnotRegex but the provider returned nullptr',
240*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
241*a65addddSAndroid Build Coastguard Worker            source,
242*a65addddSAndroid Build Coastguard Worker            locals())
243*a65addddSAndroid Build Coastguard Worker
244*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
245*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
246*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
247*a65addddSAndroid Build Coastguard Worker    ], [
248*a65addddSAndroid Build Coastguard Worker        'WithNoAnnot',
249*a65addddSAndroid Build Coastguard Worker        'WithAnnot1',
250*a65addddSAndroid Build Coastguard Worker    ], [
251*a65addddSAndroid Build Coastguard Worker        'Y',
252*a65addddSAndroid Build Coastguard Worker        'const Y',
253*a65addddSAndroid Build Coastguard Worker        'Y*',
254*a65addddSAndroid Build Coastguard Worker        'const Y*',
255*a65addddSAndroid Build Coastguard Worker        'Y&',
256*a65addddSAndroid Build Coastguard Worker        'const Y&',
257*a65addddSAndroid Build Coastguard Worker        'std::shared_ptr<Y>',
258*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<Y>',
259*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<const Y>',
260*a65addddSAndroid Build Coastguard Worker    ])
261*a65addddSAndroid Build Coastguard Worker    def test_register_provider_with_param_success(self, ConstructX, XPtr, WithAnnot, YVariant):
262*a65addddSAndroid Build Coastguard Worker        source = '''
263*a65addddSAndroid Build Coastguard Worker            struct Y {};
264*a65addddSAndroid Build Coastguard Worker            struct X {};
265*a65addddSAndroid Build Coastguard Worker
266*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<Y>> getYComponent() {
267*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
268*a65addddSAndroid Build Coastguard Worker                .registerConstructor<WithAnnot<Y>()>();
269*a65addddSAndroid Build Coastguard Worker            }
270*a65addddSAndroid Build Coastguard Worker
271*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
272*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
273*a65addddSAndroid Build Coastguard Worker                .install(getYComponent)
274*a65addddSAndroid Build Coastguard Worker                .registerProvider<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; });
275*a65addddSAndroid Build Coastguard Worker            }
276*a65addddSAndroid Build Coastguard Worker
277*a65addddSAndroid Build Coastguard Worker            int main() {
278*a65addddSAndroid Build Coastguard Worker              fruit::Injector<X> injector(getComponent);
279*a65addddSAndroid Build Coastguard Worker              injector.get<X>();
280*a65addddSAndroid Build Coastguard Worker            }
281*a65addddSAndroid Build Coastguard Worker            '''
282*a65addddSAndroid Build Coastguard Worker        expect_success(
283*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
284*a65addddSAndroid Build Coastguard Worker            source,
285*a65addddSAndroid Build Coastguard Worker            locals())
286*a65addddSAndroid Build Coastguard Worker
287*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
288*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
289*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
290*a65addddSAndroid Build Coastguard Worker    ], [
291*a65addddSAndroid Build Coastguard Worker        'WithNoAnnot',
292*a65addddSAndroid Build Coastguard Worker        'WithAnnot1',
293*a65addddSAndroid Build Coastguard Worker    ], [
294*a65addddSAndroid Build Coastguard Worker        'Y',
295*a65addddSAndroid Build Coastguard Worker        'const Y',
296*a65addddSAndroid Build Coastguard Worker        'const Y*',
297*a65addddSAndroid Build Coastguard Worker        'const Y&',
298*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<const Y>',
299*a65addddSAndroid Build Coastguard Worker    ])
300*a65addddSAndroid Build Coastguard Worker    def test_register_provider_with_param_const_binding_success(self, ConstructX, XPtr, WithAnnot, YVariant):
301*a65addddSAndroid Build Coastguard Worker        source = '''
302*a65addddSAndroid Build Coastguard Worker            struct Y {};
303*a65addddSAndroid Build Coastguard Worker            struct X {};
304*a65addddSAndroid Build Coastguard Worker
305*a65addddSAndroid Build Coastguard Worker            const Y y{};
306*a65addddSAndroid Build Coastguard Worker
307*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<const Y>> getYComponent() {
308*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
309*a65addddSAndroid Build Coastguard Worker                .bindInstance<WithAnnot<Y>, Y>(y);
310*a65addddSAndroid Build Coastguard Worker            }
311*a65addddSAndroid Build Coastguard Worker
312*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
313*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
314*a65addddSAndroid Build Coastguard Worker                .install(getYComponent)
315*a65addddSAndroid Build Coastguard Worker                .registerProvider<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; });
316*a65addddSAndroid Build Coastguard Worker            }
317*a65addddSAndroid Build Coastguard Worker
318*a65addddSAndroid Build Coastguard Worker            int main() {
319*a65addddSAndroid Build Coastguard Worker              fruit::Injector<X> injector(getComponent);
320*a65addddSAndroid Build Coastguard Worker              injector.get<X>();
321*a65addddSAndroid Build Coastguard Worker            }
322*a65addddSAndroid Build Coastguard Worker            '''
323*a65addddSAndroid Build Coastguard Worker        expect_success(
324*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
325*a65addddSAndroid Build Coastguard Worker            source,
326*a65addddSAndroid Build Coastguard Worker            locals())
327*a65addddSAndroid Build Coastguard Worker
328*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
329*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
330*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
331*a65addddSAndroid Build Coastguard Worker    ], [
332*a65addddSAndroid Build Coastguard Worker        ('WithNoAnnot', 'Y'),
333*a65addddSAndroid Build Coastguard Worker        ('WithAnnot1', 'fruit::Annotated<Annotation1, Y>'),
334*a65addddSAndroid Build Coastguard Worker    ], [
335*a65addddSAndroid Build Coastguard Worker        'Y*',
336*a65addddSAndroid Build Coastguard Worker        'Y&',
337*a65addddSAndroid Build Coastguard Worker        'std::shared_ptr<Y>',
338*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<Y>',
339*a65addddSAndroid Build Coastguard Worker    ])
340*a65addddSAndroid Build Coastguard Worker    def test_register_provider_with_param_error_nonconst_param_required(self, ConstructX, XPtr, WithAnnot, YAnnotRegex, YVariant):
341*a65addddSAndroid Build Coastguard Worker        source = '''
342*a65addddSAndroid Build Coastguard Worker            struct Y {};
343*a65addddSAndroid Build Coastguard Worker            struct X {};
344*a65addddSAndroid Build Coastguard Worker
345*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<const Y>> getYComponent();
346*a65addddSAndroid Build Coastguard Worker
347*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
348*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
349*a65addddSAndroid Build Coastguard Worker                .install(getYComponent)
350*a65addddSAndroid Build Coastguard Worker                .registerProvider<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; });
351*a65addddSAndroid Build Coastguard Worker            }
352*a65addddSAndroid Build Coastguard Worker            '''
353*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
354*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>',
355*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
356*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
357*a65addddSAndroid Build Coastguard Worker            source,
358*a65addddSAndroid Build Coastguard Worker            locals())
359*a65addddSAndroid Build Coastguard Worker
360*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
361*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
362*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
363*a65addddSAndroid Build Coastguard Worker    ], [
364*a65addddSAndroid Build Coastguard Worker        ('WithNoAnnot', 'Y'),
365*a65addddSAndroid Build Coastguard Worker        ('WithAnnot1', 'fruit::Annotated<Annotation1, Y>'),
366*a65addddSAndroid Build Coastguard Worker    ], [
367*a65addddSAndroid Build Coastguard Worker        'Y*',
368*a65addddSAndroid Build Coastguard Worker        'Y&',
369*a65addddSAndroid Build Coastguard Worker        'std::shared_ptr<Y>',
370*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<Y>',
371*a65addddSAndroid Build Coastguard Worker    ])
372*a65addddSAndroid Build Coastguard Worker    def test_register_provider_with_param_error_nonconst_param_required_install_after(self, ConstructX, XPtr, WithAnnot, YAnnotRegex, YVariant):
373*a65addddSAndroid Build Coastguard Worker        source = '''
374*a65addddSAndroid Build Coastguard Worker            struct Y {};
375*a65addddSAndroid Build Coastguard Worker            struct X {};
376*a65addddSAndroid Build Coastguard Worker
377*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<const Y>> getYComponent();
378*a65addddSAndroid Build Coastguard Worker
379*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
380*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
381*a65addddSAndroid Build Coastguard Worker                .registerProvider<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; })
382*a65addddSAndroid Build Coastguard Worker                .install(getYComponent);
383*a65addddSAndroid Build Coastguard Worker            }
384*a65addddSAndroid Build Coastguard Worker            '''
385*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
386*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>',
387*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
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    def test_register_provider_requiring_nonconst_then_requiring_const_ok(self):
393*a65addddSAndroid Build Coastguard Worker        source = '''
394*a65addddSAndroid Build Coastguard Worker            struct X {};
395*a65addddSAndroid Build Coastguard Worker            struct Y {};
396*a65addddSAndroid Build Coastguard Worker            struct Z {};
397*a65addddSAndroid Build Coastguard Worker
398*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y, Z> getRootComponent() {
399*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
400*a65addddSAndroid Build Coastguard Worker                .registerProvider([](X&) { return Y();})
401*a65addddSAndroid Build Coastguard Worker                .registerProvider([](const X&) { return Z();})
402*a65addddSAndroid Build Coastguard Worker                .registerConstructor<X()>();
403*a65addddSAndroid Build Coastguard Worker            }
404*a65addddSAndroid Build Coastguard Worker
405*a65addddSAndroid Build Coastguard Worker            int main() {
406*a65addddSAndroid Build Coastguard Worker              fruit::Injector<Y, Z> injector(getRootComponent);
407*a65addddSAndroid Build Coastguard Worker              injector.get<Y>();
408*a65addddSAndroid Build Coastguard Worker              injector.get<Z>();
409*a65addddSAndroid Build Coastguard Worker            }
410*a65addddSAndroid Build Coastguard Worker            '''
411*a65addddSAndroid Build Coastguard Worker        expect_success(
412*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
413*a65addddSAndroid Build Coastguard Worker            source,
414*a65addddSAndroid Build Coastguard Worker            locals())
415*a65addddSAndroid Build Coastguard Worker
416*a65addddSAndroid Build Coastguard Worker    def test_register_provider_requiring_nonconst_then_requiring_const_declaring_const_requirement_error(self):
417*a65addddSAndroid Build Coastguard Worker        source = '''
418*a65addddSAndroid Build Coastguard Worker            struct X {};
419*a65addddSAndroid Build Coastguard Worker            struct Y {};
420*a65addddSAndroid Build Coastguard Worker            struct Z {};
421*a65addddSAndroid Build Coastguard Worker
422*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() {
423*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
424*a65addddSAndroid Build Coastguard Worker                .registerProvider([](X&) { return Y();})
425*a65addddSAndroid Build Coastguard Worker                .registerProvider([](const X&) { return Z();});
426*a65addddSAndroid Build Coastguard Worker            }
427*a65addddSAndroid Build Coastguard Worker            '''
428*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
429*a65addddSAndroid Build Coastguard Worker            'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
430*a65addddSAndroid Build Coastguard Worker            'The type T was declared as a const Required type in the returned Component, however',
431*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
432*a65addddSAndroid Build Coastguard Worker            source,
433*a65addddSAndroid Build Coastguard Worker            locals())
434*a65addddSAndroid Build Coastguard Worker
435*a65addddSAndroid Build Coastguard Worker    def test_register_provider_requiring_const_then_requiring_nonconst_ok(self):
436*a65addddSAndroid Build Coastguard Worker        source = '''
437*a65addddSAndroid Build Coastguard Worker            struct X {};
438*a65addddSAndroid Build Coastguard Worker            struct Y {};
439*a65addddSAndroid Build Coastguard Worker            struct Z {};
440*a65addddSAndroid Build Coastguard Worker
441*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y, Z> getRootComponent() {
442*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
443*a65addddSAndroid Build Coastguard Worker                .registerProvider([](const X&) { return Y();})
444*a65addddSAndroid Build Coastguard Worker                .registerProvider([](X&) { return Z();})
445*a65addddSAndroid Build Coastguard Worker                .registerConstructor<X()>();
446*a65addddSAndroid Build Coastguard Worker            }
447*a65addddSAndroid Build Coastguard Worker
448*a65addddSAndroid Build Coastguard Worker            int main() {
449*a65addddSAndroid Build Coastguard Worker              fruit::Injector<Y, Z> injector(getRootComponent);
450*a65addddSAndroid Build Coastguard Worker              injector.get<Y>();
451*a65addddSAndroid Build Coastguard Worker              injector.get<Z>();
452*a65addddSAndroid Build Coastguard Worker            }
453*a65addddSAndroid Build Coastguard Worker            '''
454*a65addddSAndroid Build Coastguard Worker        expect_success(
455*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
456*a65addddSAndroid Build Coastguard Worker            source,
457*a65addddSAndroid Build Coastguard Worker            locals())
458*a65addddSAndroid Build Coastguard Worker
459*a65addddSAndroid Build Coastguard Worker    def test_register_provider_requiring_const_then_requiring_nonconst_declaring_const_requirement_error(self):
460*a65addddSAndroid Build Coastguard Worker        source = '''
461*a65addddSAndroid Build Coastguard Worker            struct X {};
462*a65addddSAndroid Build Coastguard Worker            struct Y {};
463*a65addddSAndroid Build Coastguard Worker            struct Z {};
464*a65addddSAndroid Build Coastguard Worker
465*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() {
466*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
467*a65addddSAndroid Build Coastguard Worker                .registerProvider([](const X&) { return Y();})
468*a65addddSAndroid Build Coastguard Worker                .registerProvider([](X&) { return Z();});
469*a65addddSAndroid Build Coastguard Worker            }
470*a65addddSAndroid Build Coastguard Worker            '''
471*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
472*a65addddSAndroid Build Coastguard Worker            'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
473*a65addddSAndroid Build Coastguard Worker            'The type T was declared as a const Required type in the returned Component, however',
474*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
475*a65addddSAndroid Build Coastguard Worker            source,
476*a65addddSAndroid Build Coastguard Worker            locals())
477*a65addddSAndroid Build Coastguard Worker
478*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
479*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
480*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
481*a65addddSAndroid Build Coastguard Worker    ], [
482*a65addddSAndroid Build Coastguard Worker        ('Y**', r'Y\*\*'),
483*a65addddSAndroid Build Coastguard Worker        ('std::shared_ptr<Y>*', r'std::shared_ptr<Y>\*'),
484*a65addddSAndroid Build Coastguard Worker        ('std::nullptr_t', r'(std::)?nullptr(_t)?'),
485*a65addddSAndroid Build Coastguard Worker        ('Y*&', r'Y\*&'),
486*a65addddSAndroid Build Coastguard Worker        ('Y(*)()', r'Y(\((__cdecl)?\*\))?\((void)?\)'),
487*a65addddSAndroid Build Coastguard Worker    ])
488*a65addddSAndroid Build Coastguard Worker    def test_register_provider_with_param_error_type_not_injectable(self, ConstructX, XPtr, YVariant, YVariantRegex):
489*a65addddSAndroid Build Coastguard Worker        source = '''
490*a65addddSAndroid Build Coastguard Worker            struct Y {};
491*a65addddSAndroid Build Coastguard Worker            struct X {};
492*a65addddSAndroid Build Coastguard Worker
493*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
494*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
495*a65addddSAndroid Build Coastguard Worker                .registerProvider<XPtr(YVariant)>([](YVariant){ return ConstructX; });
496*a65addddSAndroid Build Coastguard Worker            }
497*a65addddSAndroid Build Coastguard Worker            '''
498*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
499*a65addddSAndroid Build Coastguard Worker            'NonInjectableTypeError<YVariantRegex>',
500*a65addddSAndroid Build Coastguard Worker            'The type T is not injectable.',
501*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
502*a65addddSAndroid Build Coastguard Worker            source,
503*a65addddSAndroid Build Coastguard Worker            locals())
504*a65addddSAndroid Build Coastguard Worker
505*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__':
506*a65addddSAndroid Build Coastguard Worker    absltest.main()
507