xref: /aosp_15_r20/external/google-fruit/tests/test_register_constructor.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 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