xref: /aosp_15_r20/external/google-fruit/tests/test_install.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 XAnnot1 = fruit::Annotated<Annotation1, X>;
26*a65addddSAndroid Build Coastguard Worker    '''
27*a65addddSAndroid Build Coastguard Worker
28*a65addddSAndroid Build Coastguard Workerclass TestInstall(parameterized.TestCase):
29*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
30*a65addddSAndroid Build Coastguard Worker        ('X', 'X'),
31*a65addddSAndroid Build Coastguard Worker        ('X', 'const X'),
32*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
33*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'),
34*a65addddSAndroid Build Coastguard Worker    ])
35*a65addddSAndroid Build Coastguard Worker    def test_success(self, XParamInChildComponent, XParamInRootComponent):
36*a65addddSAndroid Build Coastguard Worker        source = '''
37*a65addddSAndroid Build Coastguard Worker            struct X {
38*a65addddSAndroid Build Coastguard Worker              int n;
39*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
40*a65addddSAndroid Build Coastguard Worker            };
41*a65addddSAndroid Build Coastguard Worker
42*a65addddSAndroid Build Coastguard Worker            fruit::Component<XParamInChildComponent> getChildComponent() {
43*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
44*a65addddSAndroid Build Coastguard Worker                .registerProvider<XParamInChildComponent()>([]() { return X(5); });
45*a65addddSAndroid Build Coastguard Worker            }
46*a65addddSAndroid Build Coastguard Worker
47*a65addddSAndroid Build Coastguard Worker            fruit::Component<XParamInRootComponent> getRootComponent() {
48*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
49*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent);
50*a65addddSAndroid Build Coastguard Worker            }
51*a65addddSAndroid Build Coastguard Worker
52*a65addddSAndroid Build Coastguard Worker            int main() {
53*a65addddSAndroid Build Coastguard Worker              fruit::Injector<XParamInRootComponent> injector(getRootComponent);
54*a65addddSAndroid Build Coastguard Worker              X x = injector.get<XParamInRootComponent>();
55*a65addddSAndroid Build Coastguard Worker              Assert(x.n == 5);
56*a65addddSAndroid Build Coastguard Worker            }
57*a65addddSAndroid Build Coastguard Worker            '''
58*a65addddSAndroid Build Coastguard Worker        expect_success(
59*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
60*a65addddSAndroid Build Coastguard Worker            source,
61*a65addddSAndroid Build Coastguard Worker            locals())
62*a65addddSAndroid Build Coastguard Worker
63*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
64*a65addddSAndroid Build Coastguard Worker        ('const X', 'X'),
65*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'),
66*a65addddSAndroid Build Coastguard Worker    ])
67*a65addddSAndroid Build Coastguard Worker    def test_install_error_child_component_provides_const(self, XParamInChildComponent, XParamInRootComponent):
68*a65addddSAndroid Build Coastguard Worker        source = '''
69*a65addddSAndroid Build Coastguard Worker            struct X {};
70*a65addddSAndroid Build Coastguard Worker
71*a65addddSAndroid Build Coastguard Worker            fruit::Component<XParamInChildComponent> getChildComponent();
72*a65addddSAndroid Build Coastguard Worker
73*a65addddSAndroid Build Coastguard Worker            fruit::Component<XParamInRootComponent> getRootComponent() {
74*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
75*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent);
76*a65addddSAndroid Build Coastguard Worker            }
77*a65addddSAndroid Build Coastguard Worker            '''
78*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
79*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<XParamInRootComponent>',
80*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
81*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
82*a65addddSAndroid Build Coastguard Worker            source,
83*a65addddSAndroid Build Coastguard Worker            locals())
84*a65addddSAndroid Build Coastguard Worker
85*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
86*a65addddSAndroid Build Coastguard Worker        ('X', 'X'),
87*a65addddSAndroid Build Coastguard Worker        ('X', 'const X'),
88*a65addddSAndroid Build Coastguard Worker        ('const X', 'const X'),
89*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
90*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'),
91*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X>'),
92*a65addddSAndroid Build Coastguard Worker    ])
93*a65addddSAndroid Build Coastguard Worker    def test_with_requirements_success(self, ProvidedXParam, RequiredXParam):
94*a65addddSAndroid Build Coastguard Worker        ProvidedXParamWithoutConst = ProvidedXParam.replace('const ', '')
95*a65addddSAndroid Build Coastguard Worker        source = '''
96*a65addddSAndroid Build Coastguard Worker            struct X {
97*a65addddSAndroid Build Coastguard Worker              int n;
98*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
99*a65addddSAndroid Build Coastguard Worker            };
100*a65addddSAndroid Build Coastguard Worker
101*a65addddSAndroid Build Coastguard Worker            struct Y {
102*a65addddSAndroid Build Coastguard Worker              X x;
103*a65addddSAndroid Build Coastguard Worker              Y(X x): x(x) {}
104*a65addddSAndroid Build Coastguard Worker            };
105*a65addddSAndroid Build Coastguard Worker
106*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<RequiredXParam>, Y> getChildComponent1() {
107*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
108*a65addddSAndroid Build Coastguard Worker                .registerProvider<Y(RequiredXParam)>([](X x) { return Y(x); });
109*a65addddSAndroid Build Coastguard Worker            }
110*a65addddSAndroid Build Coastguard Worker
111*a65addddSAndroid Build Coastguard Worker            fruit::Component<ProvidedXParam> getChildComponent2() {
112*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
113*a65addddSAndroid Build Coastguard Worker                .registerProvider<ProvidedXParamWithoutConst()>([]() { return X(5); });
114*a65addddSAndroid Build Coastguard Worker            }
115*a65addddSAndroid Build Coastguard Worker
116*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y> getRootComponent() {
117*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
118*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent1)
119*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent2);
120*a65addddSAndroid Build Coastguard Worker            }
121*a65addddSAndroid Build Coastguard Worker
122*a65addddSAndroid Build Coastguard Worker            int main() {
123*a65addddSAndroid Build Coastguard Worker              fruit::Injector<Y> injector(getRootComponent);
124*a65addddSAndroid Build Coastguard Worker              Y y = injector.get<Y>();
125*a65addddSAndroid Build Coastguard Worker              Assert(y.x.n == 5);
126*a65addddSAndroid Build Coastguard Worker            }
127*a65addddSAndroid Build Coastguard Worker            '''
128*a65addddSAndroid Build Coastguard Worker        expect_success(
129*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
130*a65addddSAndroid Build Coastguard Worker            source,
131*a65addddSAndroid Build Coastguard Worker            locals())
132*a65addddSAndroid Build Coastguard Worker
133*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
134*a65addddSAndroid Build Coastguard Worker        ('const X', 'X'),
135*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'),
136*a65addddSAndroid Build Coastguard Worker    ])
137*a65addddSAndroid Build Coastguard Worker    def test_with_requirements_error_only_nonconst_provided(self, ProvidedXParam, RequiredXParam):
138*a65addddSAndroid Build Coastguard Worker        source = '''
139*a65addddSAndroid Build Coastguard Worker            struct X {};
140*a65addddSAndroid Build Coastguard Worker            struct Y {};
141*a65addddSAndroid Build Coastguard Worker
142*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<RequiredXParam>, Y> getChildComponent1();
143*a65addddSAndroid Build Coastguard Worker
144*a65addddSAndroid Build Coastguard Worker            fruit::Component<ProvidedXParam> getChildComponent2();
145*a65addddSAndroid Build Coastguard Worker
146*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y> getRootComponent() {
147*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
148*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent1)
149*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent2);
150*a65addddSAndroid Build Coastguard Worker            }
151*a65addddSAndroid Build Coastguard Worker            '''
152*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
153*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<RequiredXParam>',
154*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
155*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
156*a65addddSAndroid Build Coastguard Worker            source,
157*a65addddSAndroid Build Coastguard Worker            locals())
158*a65addddSAndroid Build Coastguard Worker
159*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
160*a65addddSAndroid Build Coastguard Worker        ('const X', 'X'),
161*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'),
162*a65addddSAndroid Build Coastguard Worker    ])
163*a65addddSAndroid Build Coastguard Worker    def test_with_requirements_error_only_nonconst_provided_reversed_install_order(self, ProvidedXParam, RequiredXParam):
164*a65addddSAndroid Build Coastguard Worker        source = '''
165*a65addddSAndroid Build Coastguard Worker            struct X {};
166*a65addddSAndroid Build Coastguard Worker            struct Y {};
167*a65addddSAndroid Build Coastguard Worker
168*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<RequiredXParam>, Y> getChildComponent1();
169*a65addddSAndroid Build Coastguard Worker
170*a65addddSAndroid Build Coastguard Worker            fruit::Component<ProvidedXParam> getChildComponent2();
171*a65addddSAndroid Build Coastguard Worker
172*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y> getRootComponent() {
173*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
174*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent2)
175*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent1);
176*a65addddSAndroid Build Coastguard Worker            }
177*a65addddSAndroid Build Coastguard Worker            '''
178*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
179*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<RequiredXParam>',
180*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
181*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
182*a65addddSAndroid Build Coastguard Worker            source,
183*a65addddSAndroid Build Coastguard Worker            locals())
184*a65addddSAndroid Build Coastguard Worker
185*a65addddSAndroid Build Coastguard Worker    def test_with_requirements_not_specified_in_child_component_error(self):
186*a65addddSAndroid Build Coastguard Worker        source = '''
187*a65addddSAndroid Build Coastguard Worker            struct X {
188*a65addddSAndroid Build Coastguard Worker              int n;
189*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
190*a65addddSAndroid Build Coastguard Worker            };
191*a65addddSAndroid Build Coastguard Worker
192*a65addddSAndroid Build Coastguard Worker            struct Y {
193*a65addddSAndroid Build Coastguard Worker              X x;
194*a65addddSAndroid Build Coastguard Worker              Y(X x): x(x) {}
195*a65addddSAndroid Build Coastguard Worker            };
196*a65addddSAndroid Build Coastguard Worker
197*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<X>, Y> getParentYComponent() {
198*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
199*a65addddSAndroid Build Coastguard Worker                .registerProvider([](X x) { return Y(x); });
200*a65addddSAndroid Build Coastguard Worker            }
201*a65addddSAndroid Build Coastguard Worker
202*a65addddSAndroid Build Coastguard Worker            // We intentionally don't have fruit::Required<X> here, we want to test that this results in an error.
203*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y> getYComponent() {
204*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
205*a65addddSAndroid Build Coastguard Worker                .install(getParentYComponent);
206*a65addddSAndroid Build Coastguard Worker            }
207*a65addddSAndroid Build Coastguard Worker            '''
208*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
209*a65addddSAndroid Build Coastguard Worker            'NoBindingFoundError<X>',
210*a65addddSAndroid Build Coastguard Worker            'No explicit binding nor C::Inject definition was found for T',
211*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
212*a65addddSAndroid Build Coastguard Worker            source)
213*a65addddSAndroid Build Coastguard Worker
214*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
215*a65addddSAndroid Build Coastguard Worker        ('X', 'const X'),
216*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'),
217*a65addddSAndroid Build Coastguard Worker    ])
218*a65addddSAndroid Build Coastguard Worker    def test_install_requiring_nonconst_then_install_requiring_const_ok(self, XAnnot, ConstXAnnot):
219*a65addddSAndroid Build Coastguard Worker        source = '''
220*a65addddSAndroid Build Coastguard Worker            struct X {};
221*a65addddSAndroid Build Coastguard Worker            struct Y {};
222*a65addddSAndroid Build Coastguard Worker            struct Z {};
223*a65addddSAndroid Build Coastguard Worker
224*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<XAnnot>, Y> getChildComponent1() {
225*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
226*a65addddSAndroid Build Coastguard Worker                  .registerConstructor<Y()>();
227*a65addddSAndroid Build Coastguard Worker            }
228*a65addddSAndroid Build Coastguard Worker
229*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<ConstXAnnot>, Z> getChildComponent2() {
230*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
231*a65addddSAndroid Build Coastguard Worker                  .registerConstructor<Z()>();
232*a65addddSAndroid Build Coastguard Worker            }
233*a65addddSAndroid Build Coastguard Worker
234*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y, Z> getRootComponent() {
235*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
236*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent1)
237*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent2)
238*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot()>();
239*a65addddSAndroid Build Coastguard Worker            }
240*a65addddSAndroid Build Coastguard Worker
241*a65addddSAndroid Build Coastguard Worker            int main() {
242*a65addddSAndroid Build Coastguard Worker              fruit::Injector<Y, Z> injector(getRootComponent);
243*a65addddSAndroid Build Coastguard Worker              injector.get<Y>();
244*a65addddSAndroid Build Coastguard Worker              injector.get<Z>();
245*a65addddSAndroid Build Coastguard Worker            }
246*a65addddSAndroid Build Coastguard Worker            '''
247*a65addddSAndroid Build Coastguard Worker        expect_success(
248*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
249*a65addddSAndroid Build Coastguard Worker            source,
250*a65addddSAndroid Build Coastguard Worker            locals())
251*a65addddSAndroid Build Coastguard Worker
252*a65addddSAndroid Build Coastguard Worker    def test_install_requiring_nonconst_then_install_requiring_const_declaring_const_requirement_error(self):
253*a65addddSAndroid Build Coastguard Worker        source = '''
254*a65addddSAndroid Build Coastguard Worker            struct X {};
255*a65addddSAndroid Build Coastguard Worker            struct Y {};
256*a65addddSAndroid Build Coastguard Worker            struct Z {};
257*a65addddSAndroid Build Coastguard Worker
258*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<X>, Y> getChildComponent1();
259*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const X>, Z> getChildComponent2();
260*a65addddSAndroid Build Coastguard Worker
261*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() {
262*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
263*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent1)
264*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent2);
265*a65addddSAndroid Build Coastguard Worker            }
266*a65addddSAndroid Build Coastguard Worker            '''
267*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
268*a65addddSAndroid Build Coastguard Worker            'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
269*a65addddSAndroid Build Coastguard Worker            'The type T was declared as a const Required type in the returned Component, however',
270*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
271*a65addddSAndroid Build Coastguard Worker            source,
272*a65addddSAndroid Build Coastguard Worker            locals())
273*a65addddSAndroid Build Coastguard Worker
274*a65addddSAndroid Build Coastguard Worker    def test_install_requiring_const_then_install_requiring_nonconst_ok(self):
275*a65addddSAndroid Build Coastguard Worker        source = '''
276*a65addddSAndroid Build Coastguard Worker            struct X {};
277*a65addddSAndroid Build Coastguard Worker            struct Y {};
278*a65addddSAndroid Build Coastguard Worker            struct Z {};
279*a65addddSAndroid Build Coastguard Worker
280*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const X>, Y> getChildComponent1() {
281*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
282*a65addddSAndroid Build Coastguard Worker                  .registerConstructor<Y()>();
283*a65addddSAndroid Build Coastguard Worker            }
284*a65addddSAndroid Build Coastguard Worker
285*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<X>, Z> getChildComponent2() {
286*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
287*a65addddSAndroid Build Coastguard Worker                  .registerConstructor<Z()>();
288*a65addddSAndroid Build Coastguard Worker            }
289*a65addddSAndroid Build Coastguard Worker
290*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y, Z> getRootComponent() {
291*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
292*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent1)
293*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent2)
294*a65addddSAndroid Build Coastguard Worker                .registerConstructor<X()>();
295*a65addddSAndroid Build Coastguard Worker            }
296*a65addddSAndroid Build Coastguard Worker
297*a65addddSAndroid Build Coastguard Worker            int main() {
298*a65addddSAndroid Build Coastguard Worker              fruit::Injector<Y, Z> injector(getRootComponent);
299*a65addddSAndroid Build Coastguard Worker              injector.get<Y>();
300*a65addddSAndroid Build Coastguard Worker              injector.get<Z>();
301*a65addddSAndroid Build Coastguard Worker            }
302*a65addddSAndroid Build Coastguard Worker            '''
303*a65addddSAndroid Build Coastguard Worker        expect_success(
304*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
305*a65addddSAndroid Build Coastguard Worker            source,
306*a65addddSAndroid Build Coastguard Worker            locals())
307*a65addddSAndroid Build Coastguard Worker
308*a65addddSAndroid Build Coastguard Worker    def test_install_requiring_const_then_install_requiring_nonconst_declaring_const_requirement_error(self):
309*a65addddSAndroid Build Coastguard Worker        source = '''
310*a65addddSAndroid Build Coastguard Worker            struct X {};
311*a65addddSAndroid Build Coastguard Worker            struct Y {};
312*a65addddSAndroid Build Coastguard Worker            struct Z {};
313*a65addddSAndroid Build Coastguard Worker
314*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const X>, Y> getChildComponent1();
315*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<X>, Z> getChildComponent2();
316*a65addddSAndroid Build Coastguard Worker
317*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() {
318*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
319*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent1)
320*a65addddSAndroid Build Coastguard Worker                .install(getChildComponent2);
321*a65addddSAndroid Build Coastguard Worker            }
322*a65addddSAndroid Build Coastguard Worker            '''
323*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
324*a65addddSAndroid Build Coastguard Worker            'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
325*a65addddSAndroid Build Coastguard Worker            'The type T was declared as a const Required type in the returned Component, however',
326*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
327*a65addddSAndroid Build Coastguard Worker            source,
328*a65addddSAndroid Build Coastguard Worker            locals())
329*a65addddSAndroid Build Coastguard Worker
330*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_success(self):
331*a65addddSAndroid Build Coastguard Worker        source = '''
332*a65addddSAndroid Build Coastguard Worker            struct X {
333*a65addddSAndroid Build Coastguard Worker              int n;
334*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
335*a65addddSAndroid Build Coastguard Worker            };
336*a65addddSAndroid Build Coastguard Worker
337*a65addddSAndroid Build Coastguard Worker            struct Arg {
338*a65addddSAndroid Build Coastguard Worker              Arg(int) {}
339*a65addddSAndroid Build Coastguard Worker              Arg() = default;
340*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
341*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
342*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
343*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
344*a65addddSAndroid Build Coastguard Worker            };
345*a65addddSAndroid Build Coastguard Worker
346*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&) {
347*a65addddSAndroid Build Coastguard Worker              return true;
348*a65addddSAndroid Build Coastguard Worker            }
349*a65addddSAndroid Build Coastguard Worker
350*a65addddSAndroid Build Coastguard Worker            namespace std {
351*a65addddSAndroid Build Coastguard Worker              template <>
352*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
353*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&) {
354*a65addddSAndroid Build Coastguard Worker                  return 0;
355*a65addddSAndroid Build Coastguard Worker                }
356*a65addddSAndroid Build Coastguard Worker              };
357*a65addddSAndroid Build Coastguard Worker            }
358*a65addddSAndroid Build Coastguard Worker
359*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg, Arg) {
360*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
361*a65addddSAndroid Build Coastguard Worker                .registerProvider([]() { return X(5); });
362*a65addddSAndroid Build Coastguard Worker            }
363*a65addddSAndroid Build Coastguard Worker
364*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
365*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
366*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), Arg{}, 15);
367*a65addddSAndroid Build Coastguard Worker            }
368*a65addddSAndroid Build Coastguard Worker
369*a65addddSAndroid Build Coastguard Worker            int main() {
370*a65addddSAndroid Build Coastguard Worker              fruit::Injector<X> injector(getComponent);
371*a65addddSAndroid Build Coastguard Worker              X x = injector.get<X>();
372*a65addddSAndroid Build Coastguard Worker              Assert(x.n == 5);
373*a65addddSAndroid Build Coastguard Worker            }
374*a65addddSAndroid Build Coastguard Worker            '''
375*a65addddSAndroid Build Coastguard Worker        expect_success(COMMON_DEFINITIONS, source)
376*a65addddSAndroid Build Coastguard Worker
377*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_move_constructible(self):
378*a65addddSAndroid Build Coastguard Worker        source = '''
379*a65addddSAndroid Build Coastguard Worker            struct Arg {
380*a65addddSAndroid Build Coastguard Worker              Arg() = default;
381*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
382*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = delete;
383*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
384*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
385*a65addddSAndroid Build Coastguard Worker            };
386*a65addddSAndroid Build Coastguard Worker
387*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
388*a65addddSAndroid Build Coastguard Worker
389*a65addddSAndroid Build Coastguard Worker            namespace std {
390*a65addddSAndroid Build Coastguard Worker              template <>
391*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
392*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
393*a65addddSAndroid Build Coastguard Worker              };
394*a65addddSAndroid Build Coastguard Worker            }
395*a65addddSAndroid Build Coastguard Worker
396*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
397*a65addddSAndroid Build Coastguard Worker
398*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
399*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
400*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), Arg{});
401*a65addddSAndroid Build Coastguard Worker            }
402*a65addddSAndroid Build Coastguard Worker            '''
403*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
404*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .Arg::Arg\(Arg&&\).'
405*a65addddSAndroid Build Coastguard Worker            r'|error: call to deleted constructor of .Arg.'
406*a65addddSAndroid Build Coastguard Worker            r'|.Arg::Arg\(const Arg &\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.'
407*a65addddSAndroid Build Coastguard Worker            r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.',
408*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
409*a65addddSAndroid Build Coastguard Worker            source)
410*a65addddSAndroid Build Coastguard Worker
411*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_move_constructible_with_conversion(self):
412*a65addddSAndroid Build Coastguard Worker        source = '''
413*a65addddSAndroid Build Coastguard Worker            struct Arg {
414*a65addddSAndroid Build Coastguard Worker              Arg(int) {}
415*a65addddSAndroid Build Coastguard Worker              Arg() = default;
416*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
417*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = delete;
418*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
419*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
420*a65addddSAndroid Build Coastguard Worker            };
421*a65addddSAndroid Build Coastguard Worker
422*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
423*a65addddSAndroid Build Coastguard Worker
424*a65addddSAndroid Build Coastguard Worker            namespace std {
425*a65addddSAndroid Build Coastguard Worker              template <>
426*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
427*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
428*a65addddSAndroid Build Coastguard Worker              };
429*a65addddSAndroid Build Coastguard Worker            }
430*a65addddSAndroid Build Coastguard Worker
431*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
432*a65addddSAndroid Build Coastguard Worker
433*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
434*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
435*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), 15);
436*a65addddSAndroid Build Coastguard Worker            }
437*a65addddSAndroid Build Coastguard Worker            '''
438*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
439*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .Arg::Arg\(Arg&&\).'
440*a65addddSAndroid Build Coastguard Worker            r'|error: call to deleted constructor of .Arg.'
441*a65addddSAndroid Build Coastguard Worker            r'|.Arg::Arg\((int|Arg &&)\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.',
442*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
443*a65addddSAndroid Build Coastguard Worker            source)
444*a65addddSAndroid Build Coastguard Worker
445*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_copy_constructible(self):
446*a65addddSAndroid Build Coastguard Worker        source = '''
447*a65addddSAndroid Build Coastguard Worker            struct X {
448*a65addddSAndroid Build Coastguard Worker              int n;
449*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
450*a65addddSAndroid Build Coastguard Worker            };
451*a65addddSAndroid Build Coastguard Worker
452*a65addddSAndroid Build Coastguard Worker            struct Arg {
453*a65addddSAndroid Build Coastguard Worker              Arg() = default;
454*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = delete;
455*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
456*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
457*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
458*a65addddSAndroid Build Coastguard Worker            };
459*a65addddSAndroid Build Coastguard Worker
460*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
461*a65addddSAndroid Build Coastguard Worker
462*a65addddSAndroid Build Coastguard Worker            namespace std {
463*a65addddSAndroid Build Coastguard Worker              template <>
464*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
465*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
466*a65addddSAndroid Build Coastguard Worker              };
467*a65addddSAndroid Build Coastguard Worker            }
468*a65addddSAndroid Build Coastguard Worker
469*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
470*a65addddSAndroid Build Coastguard Worker
471*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
472*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
473*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), Arg{});
474*a65addddSAndroid Build Coastguard Worker            }
475*a65addddSAndroid Build Coastguard Worker            '''
476*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
477*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .Arg::Arg\(const Arg&\).'
478*a65addddSAndroid Build Coastguard Worker            r'|error: call to deleted constructor of .Arg.'
479*a65addddSAndroid Build Coastguard Worker            r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function',
480*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
481*a65addddSAndroid Build Coastguard Worker            source)
482*a65addddSAndroid Build Coastguard Worker
483*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_copy_constructible_with_conversion(self):
484*a65addddSAndroid Build Coastguard Worker        source = '''
485*a65addddSAndroid Build Coastguard Worker            struct X {
486*a65addddSAndroid Build Coastguard Worker              int n;
487*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
488*a65addddSAndroid Build Coastguard Worker            };
489*a65addddSAndroid Build Coastguard Worker
490*a65addddSAndroid Build Coastguard Worker            struct Arg {
491*a65addddSAndroid Build Coastguard Worker              Arg(int) {}
492*a65addddSAndroid Build Coastguard Worker              Arg() = default;
493*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = delete;
494*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
495*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
496*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
497*a65addddSAndroid Build Coastguard Worker            };
498*a65addddSAndroid Build Coastguard Worker
499*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
500*a65addddSAndroid Build Coastguard Worker
501*a65addddSAndroid Build Coastguard Worker            namespace std {
502*a65addddSAndroid Build Coastguard Worker              template <>
503*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
504*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
505*a65addddSAndroid Build Coastguard Worker              };
506*a65addddSAndroid Build Coastguard Worker            }
507*a65addddSAndroid Build Coastguard Worker
508*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
509*a65addddSAndroid Build Coastguard Worker
510*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
511*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
512*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), 15);
513*a65addddSAndroid Build Coastguard Worker            }
514*a65addddSAndroid Build Coastguard Worker            '''
515*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
516*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .Arg::Arg\(const Arg&\).'
517*a65addddSAndroid Build Coastguard Worker            r'|error: call to deleted constructor of .Arg.'
518*a65addddSAndroid Build Coastguard Worker            r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function',
519*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
520*a65addddSAndroid Build Coastguard Worker            source)
521*a65addddSAndroid Build Coastguard Worker
522*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_move_assignable(self):
523*a65addddSAndroid Build Coastguard Worker        source = '''
524*a65addddSAndroid Build Coastguard Worker            struct Arg {
525*a65addddSAndroid Build Coastguard Worker              Arg() = default;
526*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
527*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
528*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
529*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = delete;
530*a65addddSAndroid Build Coastguard Worker            };
531*a65addddSAndroid Build Coastguard Worker
532*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
533*a65addddSAndroid Build Coastguard Worker
534*a65addddSAndroid Build Coastguard Worker            namespace std {
535*a65addddSAndroid Build Coastguard Worker              template <>
536*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
537*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
538*a65addddSAndroid Build Coastguard Worker              };
539*a65addddSAndroid Build Coastguard Worker            }
540*a65addddSAndroid Build Coastguard Worker
541*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
542*a65addddSAndroid Build Coastguard Worker
543*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
544*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
545*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), Arg{});
546*a65addddSAndroid Build Coastguard Worker            }
547*a65addddSAndroid Build Coastguard Worker            '''
548*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
549*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).'
550*a65addddSAndroid Build Coastguard Worker            r'|error: overload resolution selected deleted operator .=.'
551*a65addddSAndroid Build Coastguard Worker            r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function',
552*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
553*a65addddSAndroid Build Coastguard Worker            source)
554*a65addddSAndroid Build Coastguard Worker
555*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_move_assignable_with_conversion(self):
556*a65addddSAndroid Build Coastguard Worker        source = '''
557*a65addddSAndroid Build Coastguard Worker            struct Arg {
558*a65addddSAndroid Build Coastguard Worker              Arg(int) {}
559*a65addddSAndroid Build Coastguard Worker              Arg() = default;
560*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
561*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
562*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
563*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = delete;
564*a65addddSAndroid Build Coastguard Worker            };
565*a65addddSAndroid Build Coastguard Worker
566*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
567*a65addddSAndroid Build Coastguard Worker
568*a65addddSAndroid Build Coastguard Worker            namespace std {
569*a65addddSAndroid Build Coastguard Worker              template <>
570*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
571*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
572*a65addddSAndroid Build Coastguard Worker              };
573*a65addddSAndroid Build Coastguard Worker            }
574*a65addddSAndroid Build Coastguard Worker
575*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
576*a65addddSAndroid Build Coastguard Worker
577*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
578*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
579*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), 15);
580*a65addddSAndroid Build Coastguard Worker            }
581*a65addddSAndroid Build Coastguard Worker            '''
582*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
583*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).'
584*a65addddSAndroid Build Coastguard Worker            r'|error: overload resolution selected deleted operator .=.'
585*a65addddSAndroid Build Coastguard Worker            r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function',
586*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
587*a65addddSAndroid Build Coastguard Worker            source)
588*a65addddSAndroid Build Coastguard Worker
589*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_copy_assignable(self):
590*a65addddSAndroid Build Coastguard Worker        source = '''
591*a65addddSAndroid Build Coastguard Worker            struct X {
592*a65addddSAndroid Build Coastguard Worker              int n;
593*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
594*a65addddSAndroid Build Coastguard Worker            };
595*a65addddSAndroid Build Coastguard Worker
596*a65addddSAndroid Build Coastguard Worker            struct Arg {
597*a65addddSAndroid Build Coastguard Worker              Arg() = default;
598*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
599*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
600*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = delete;
601*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
602*a65addddSAndroid Build Coastguard Worker            };
603*a65addddSAndroid Build Coastguard Worker
604*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
605*a65addddSAndroid Build Coastguard Worker
606*a65addddSAndroid Build Coastguard Worker            namespace std {
607*a65addddSAndroid Build Coastguard Worker              template <>
608*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
609*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
610*a65addddSAndroid Build Coastguard Worker              };
611*a65addddSAndroid Build Coastguard Worker            }
612*a65addddSAndroid Build Coastguard Worker
613*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
614*a65addddSAndroid Build Coastguard Worker
615*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
616*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
617*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), Arg{});
618*a65addddSAndroid Build Coastguard Worker            }
619*a65addddSAndroid Build Coastguard Worker            '''
620*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
621*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).'
622*a65addddSAndroid Build Coastguard Worker            r'|error: overload resolution selected deleted operator .=.'
623*a65addddSAndroid Build Coastguard Worker            r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function',
624*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
625*a65addddSAndroid Build Coastguard Worker            source)
626*a65addddSAndroid Build Coastguard Worker
627*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_copy_assignable_with_conversion(self):
628*a65addddSAndroid Build Coastguard Worker        source = '''
629*a65addddSAndroid Build Coastguard Worker            struct X {
630*a65addddSAndroid Build Coastguard Worker              int n;
631*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
632*a65addddSAndroid Build Coastguard Worker            };
633*a65addddSAndroid Build Coastguard Worker
634*a65addddSAndroid Build Coastguard Worker            struct Arg {
635*a65addddSAndroid Build Coastguard Worker              Arg(int) {}
636*a65addddSAndroid Build Coastguard Worker              Arg() = default;
637*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
638*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
639*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = delete;
640*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
641*a65addddSAndroid Build Coastguard Worker            };
642*a65addddSAndroid Build Coastguard Worker
643*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
644*a65addddSAndroid Build Coastguard Worker
645*a65addddSAndroid Build Coastguard Worker            namespace std {
646*a65addddSAndroid Build Coastguard Worker              template <>
647*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
648*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
649*a65addddSAndroid Build Coastguard Worker              };
650*a65addddSAndroid Build Coastguard Worker            }
651*a65addddSAndroid Build Coastguard Worker
652*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
653*a65addddSAndroid Build Coastguard Worker
654*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
655*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
656*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), 15);
657*a65addddSAndroid Build Coastguard Worker            }
658*a65addddSAndroid Build Coastguard Worker            '''
659*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
660*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).'
661*a65addddSAndroid Build Coastguard Worker            r'|error: overload resolution selected deleted operator .=.'
662*a65addddSAndroid Build Coastguard Worker            r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function',
663*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
664*a65addddSAndroid Build Coastguard Worker            source)
665*a65addddSAndroid Build Coastguard Worker
666*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_equality_comparable(self):
667*a65addddSAndroid Build Coastguard Worker        source = '''
668*a65addddSAndroid Build Coastguard Worker            struct X {
669*a65addddSAndroid Build Coastguard Worker              int n;
670*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
671*a65addddSAndroid Build Coastguard Worker            };
672*a65addddSAndroid Build Coastguard Worker
673*a65addddSAndroid Build Coastguard Worker            struct Arg {
674*a65addddSAndroid Build Coastguard Worker              Arg() = default;
675*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
676*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
677*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
678*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
679*a65addddSAndroid Build Coastguard Worker            };
680*a65addddSAndroid Build Coastguard Worker
681*a65addddSAndroid Build Coastguard Worker            namespace std {
682*a65addddSAndroid Build Coastguard Worker              template <>
683*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
684*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
685*a65addddSAndroid Build Coastguard Worker              };
686*a65addddSAndroid Build Coastguard Worker            }
687*a65addddSAndroid Build Coastguard Worker
688*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
689*a65addddSAndroid Build Coastguard Worker
690*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
691*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
692*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), Arg{});
693*a65addddSAndroid Build Coastguard Worker            }
694*a65addddSAndroid Build Coastguard Worker            '''
695*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
696*a65addddSAndroid Build Coastguard Worker            r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)'
697*a65addddSAndroid Build Coastguard Worker            r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)'
698*a65addddSAndroid Build Coastguard Worker            r'|error C2676: binary .==.: .const Arg. does not define this operator',
699*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
700*a65addddSAndroid Build Coastguard Worker            source)
701*a65addddSAndroid Build Coastguard Worker
702*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_equality_comparable_with_conversion(self):
703*a65addddSAndroid Build Coastguard Worker        source = '''
704*a65addddSAndroid Build Coastguard Worker            struct X {
705*a65addddSAndroid Build Coastguard Worker              int n;
706*a65addddSAndroid Build Coastguard Worker              X(int n) : n(n) {}
707*a65addddSAndroid Build Coastguard Worker            };
708*a65addddSAndroid Build Coastguard Worker
709*a65addddSAndroid Build Coastguard Worker            struct Arg {
710*a65addddSAndroid Build Coastguard Worker              Arg(int) {}
711*a65addddSAndroid Build Coastguard Worker              Arg() = default;
712*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
713*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
714*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
715*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
716*a65addddSAndroid Build Coastguard Worker            };
717*a65addddSAndroid Build Coastguard Worker
718*a65addddSAndroid Build Coastguard Worker            namespace std {
719*a65addddSAndroid Build Coastguard Worker              template <>
720*a65addddSAndroid Build Coastguard Worker              struct hash<Arg> {
721*a65addddSAndroid Build Coastguard Worker                size_t operator()(const Arg&);
722*a65addddSAndroid Build Coastguard Worker              };
723*a65addddSAndroid Build Coastguard Worker            }
724*a65addddSAndroid Build Coastguard Worker
725*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
726*a65addddSAndroid Build Coastguard Worker
727*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
728*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
729*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), 15);
730*a65addddSAndroid Build Coastguard Worker            }
731*a65addddSAndroid Build Coastguard Worker            '''
732*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
733*a65addddSAndroid Build Coastguard Worker            r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)'
734*a65addddSAndroid Build Coastguard Worker            r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)'
735*a65addddSAndroid Build Coastguard Worker            r'|error C2676: binary .==.: .const Arg. does not define this operator',
736*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
737*a65addddSAndroid Build Coastguard Worker            source)
738*a65addddSAndroid Build Coastguard Worker
739*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_hashable(self):
740*a65addddSAndroid Build Coastguard Worker        source = '''
741*a65addddSAndroid Build Coastguard Worker            struct Arg {
742*a65addddSAndroid Build Coastguard Worker              Arg() = default;
743*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
744*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
745*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
746*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
747*a65addddSAndroid Build Coastguard Worker            };
748*a65addddSAndroid Build Coastguard Worker
749*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
750*a65addddSAndroid Build Coastguard Worker
751*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
752*a65addddSAndroid Build Coastguard Worker
753*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
754*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
755*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), Arg{});
756*a65addddSAndroid Build Coastguard Worker            }
757*a65addddSAndroid Build Coastguard Worker            '''
758*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
759*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .std::hash<Arg>::hash\(\).'
760*a65addddSAndroid Build Coastguard Worker            r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.'
761*a65addddSAndroid Build Coastguard Worker            r'|error: invalid use of incomplete type .struct std::hash<Arg>.'
762*a65addddSAndroid Build Coastguard Worker            r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.'
763*a65addddSAndroid Build Coastguard Worker            r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.'
764*a65addddSAndroid Build Coastguard Worker            r'|error C2064: term does not evaluate to a function taking 1 arguments',
765*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
766*a65addddSAndroid Build Coastguard Worker            source)
767*a65addddSAndroid Build Coastguard Worker
768*a65addddSAndroid Build Coastguard Worker    def test_install_with_args_error_not_hashable_with_conversion(self):
769*a65addddSAndroid Build Coastguard Worker        source = '''
770*a65addddSAndroid Build Coastguard Worker            struct Arg {
771*a65addddSAndroid Build Coastguard Worker              Arg(int) {}
772*a65addddSAndroid Build Coastguard Worker              Arg() = default;
773*a65addddSAndroid Build Coastguard Worker              Arg(const Arg&) = default;
774*a65addddSAndroid Build Coastguard Worker              Arg(Arg&&) = default;
775*a65addddSAndroid Build Coastguard Worker              Arg& operator=(const Arg&) = default;
776*a65addddSAndroid Build Coastguard Worker              Arg& operator=(Arg&&) = default;
777*a65addddSAndroid Build Coastguard Worker            };
778*a65addddSAndroid Build Coastguard Worker
779*a65addddSAndroid Build Coastguard Worker            bool operator==(const Arg&, const Arg&);
780*a65addddSAndroid Build Coastguard Worker
781*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getParentComponent(int, std::string, Arg);
782*a65addddSAndroid Build Coastguard Worker
783*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
784*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
785*a65addddSAndroid Build Coastguard Worker                .install(getParentComponent, 5, std::string("Hello"), 15);
786*a65addddSAndroid Build Coastguard Worker            }
787*a65addddSAndroid Build Coastguard Worker            '''
788*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
789*a65addddSAndroid Build Coastguard Worker            r'error: use of deleted function .std::hash<Arg>::hash\(\).'
790*a65addddSAndroid Build Coastguard Worker            r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.'
791*a65addddSAndroid Build Coastguard Worker            r'|error: invalid use of incomplete type .struct std::hash<Arg>.'
792*a65addddSAndroid Build Coastguard Worker            r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.'
793*a65addddSAndroid Build Coastguard Worker            r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.'
794*a65addddSAndroid Build Coastguard Worker            r'|error C2064: term does not evaluate to a function taking 1 arguments',
795*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
796*a65addddSAndroid Build Coastguard Worker            source)
797*a65addddSAndroid Build Coastguard Worker
798*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
799*a65addddSAndroid Build Coastguard Worker        'X',
800*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
801*a65addddSAndroid Build Coastguard Worker    ])
802*a65addddSAndroid Build Coastguard Worker    def test_install_component_functions_deduped(self, XAnnot):
803*a65addddSAndroid Build Coastguard Worker        source = '''
804*a65addddSAndroid Build Coastguard Worker            struct X {};
805*a65addddSAndroid Build Coastguard Worker
806*a65addddSAndroid Build Coastguard Worker            X x;
807*a65addddSAndroid Build Coastguard Worker
808*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
809*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
810*a65addddSAndroid Build Coastguard Worker                .addInstanceMultibinding<XAnnot, X>(x);
811*a65addddSAndroid Build Coastguard Worker            }
812*a65addddSAndroid Build Coastguard Worker
813*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent2() {
814*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
815*a65addddSAndroid Build Coastguard Worker                .install(getComponent);
816*a65addddSAndroid Build Coastguard Worker            }
817*a65addddSAndroid Build Coastguard Worker
818*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent3() {
819*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
820*a65addddSAndroid Build Coastguard Worker                .install(getComponent);
821*a65addddSAndroid Build Coastguard Worker            }
822*a65addddSAndroid Build Coastguard Worker
823*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent4() {
824*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
825*a65addddSAndroid Build Coastguard Worker                .install(getComponent2)
826*a65addddSAndroid Build Coastguard Worker                .install(getComponent3);
827*a65addddSAndroid Build Coastguard Worker            }
828*a65addddSAndroid Build Coastguard Worker
829*a65addddSAndroid Build Coastguard Worker            int main() {
830*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent4);
831*a65addddSAndroid Build Coastguard Worker
832*a65addddSAndroid Build Coastguard Worker              // We test multibindings because the effect on other bindings is not user-visible (that only affects
833*a65addddSAndroid Build Coastguard Worker              // performance).
834*a65addddSAndroid Build Coastguard Worker              std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
835*a65addddSAndroid Build Coastguard Worker              Assert(multibindings.size() == 1);
836*a65addddSAndroid Build Coastguard Worker              Assert(multibindings[0] == &x);
837*a65addddSAndroid Build Coastguard Worker            }
838*a65addddSAndroid Build Coastguard Worker            '''
839*a65addddSAndroid Build Coastguard Worker        expect_success(
840*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
841*a65addddSAndroid Build Coastguard Worker            source,
842*a65addddSAndroid Build Coastguard Worker            locals())
843*a65addddSAndroid Build Coastguard Worker
844*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
845*a65addddSAndroid Build Coastguard Worker        'X',
846*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
847*a65addddSAndroid Build Coastguard Worker    ])
848*a65addddSAndroid Build Coastguard Worker    def test_install_component_functions_deduped_across_normalized_component(self, XAnnot):
849*a65addddSAndroid Build Coastguard Worker        source = '''
850*a65addddSAndroid Build Coastguard Worker            struct X {};
851*a65addddSAndroid Build Coastguard Worker
852*a65addddSAndroid Build Coastguard Worker            X x;
853*a65addddSAndroid Build Coastguard Worker
854*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
855*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
856*a65addddSAndroid Build Coastguard Worker                .addInstanceMultibinding<XAnnot, X>(x);
857*a65addddSAndroid Build Coastguard Worker            }
858*a65addddSAndroid Build Coastguard Worker
859*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent2() {
860*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
861*a65addddSAndroid Build Coastguard Worker                .install(getComponent);
862*a65addddSAndroid Build Coastguard Worker            }
863*a65addddSAndroid Build Coastguard Worker
864*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent3() {
865*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
866*a65addddSAndroid Build Coastguard Worker                .install(getComponent);
867*a65addddSAndroid Build Coastguard Worker            }
868*a65addddSAndroid Build Coastguard Worker
869*a65addddSAndroid Build Coastguard Worker            int main() {
870*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<> normalizedComponent(getComponent2);
871*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(normalizedComponent, getComponent3);
872*a65addddSAndroid Build Coastguard Worker
873*a65addddSAndroid Build Coastguard Worker              // We test multibindings because the effect on other bindings is not user-visible (that only affects
874*a65addddSAndroid Build Coastguard Worker              // performance).
875*a65addddSAndroid Build Coastguard Worker              std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
876*a65addddSAndroid Build Coastguard Worker              Assert(multibindings.size() == 1);
877*a65addddSAndroid Build Coastguard Worker              Assert(multibindings[0] == &x);
878*a65addddSAndroid Build Coastguard Worker            }
879*a65addddSAndroid Build Coastguard Worker            '''
880*a65addddSAndroid Build Coastguard Worker        expect_success(
881*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
882*a65addddSAndroid Build Coastguard Worker            source,
883*a65addddSAndroid Build Coastguard Worker            locals())
884*a65addddSAndroid Build Coastguard Worker
885*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
886*a65addddSAndroid Build Coastguard Worker        'X',
887*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
888*a65addddSAndroid Build Coastguard Worker    ])
889*a65addddSAndroid Build Coastguard Worker    def test_install_component_functions_with_args_deduped(self, XAnnot):
890*a65addddSAndroid Build Coastguard Worker        source = '''
891*a65addddSAndroid Build Coastguard Worker            struct X {};
892*a65addddSAndroid Build Coastguard Worker
893*a65addddSAndroid Build Coastguard Worker            X x;
894*a65addddSAndroid Build Coastguard Worker
895*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent(int) {
896*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
897*a65addddSAndroid Build Coastguard Worker                .addInstanceMultibinding<XAnnot, X>(x);
898*a65addddSAndroid Build Coastguard Worker            }
899*a65addddSAndroid Build Coastguard Worker
900*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent2() {
901*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
902*a65addddSAndroid Build Coastguard Worker                .install(getComponent, 1);
903*a65addddSAndroid Build Coastguard Worker            }
904*a65addddSAndroid Build Coastguard Worker
905*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent3() {
906*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
907*a65addddSAndroid Build Coastguard Worker                .install(getComponent, 1);
908*a65addddSAndroid Build Coastguard Worker            }
909*a65addddSAndroid Build Coastguard Worker
910*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent4() {
911*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
912*a65addddSAndroid Build Coastguard Worker                .install(getComponent2)
913*a65addddSAndroid Build Coastguard Worker                .install(getComponent3);
914*a65addddSAndroid Build Coastguard Worker            }
915*a65addddSAndroid Build Coastguard Worker
916*a65addddSAndroid Build Coastguard Worker            int main() {
917*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent4);
918*a65addddSAndroid Build Coastguard Worker
919*a65addddSAndroid Build Coastguard Worker              // We test multibindings because the effect on other bindings is not user-visible (that only affects
920*a65addddSAndroid Build Coastguard Worker              // performance).
921*a65addddSAndroid Build Coastguard Worker              std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
922*a65addddSAndroid Build Coastguard Worker              Assert(multibindings.size() == 1);
923*a65addddSAndroid Build Coastguard Worker              Assert(multibindings[0] == &x);
924*a65addddSAndroid Build Coastguard Worker            }
925*a65addddSAndroid Build Coastguard Worker            '''
926*a65addddSAndroid Build Coastguard Worker        expect_success(
927*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
928*a65addddSAndroid Build Coastguard Worker            source,
929*a65addddSAndroid Build Coastguard Worker            locals())
930*a65addddSAndroid Build Coastguard Worker
931*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
932*a65addddSAndroid Build Coastguard Worker        'X',
933*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
934*a65addddSAndroid Build Coastguard Worker    ])
935*a65addddSAndroid Build Coastguard Worker    def test_install_component_functions_different_args_not_deduped(self, XAnnot):
936*a65addddSAndroid Build Coastguard Worker        source = '''
937*a65addddSAndroid Build Coastguard Worker            struct X {};
938*a65addddSAndroid Build Coastguard Worker
939*a65addddSAndroid Build Coastguard Worker            X x;
940*a65addddSAndroid Build Coastguard Worker
941*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent(int) {
942*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
943*a65addddSAndroid Build Coastguard Worker                .addInstanceMultibinding<XAnnot, X>(x);
944*a65addddSAndroid Build Coastguard Worker            }
945*a65addddSAndroid Build Coastguard Worker
946*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent2() {
947*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
948*a65addddSAndroid Build Coastguard Worker                .install(getComponent, 1);
949*a65addddSAndroid Build Coastguard Worker            }
950*a65addddSAndroid Build Coastguard Worker
951*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent3() {
952*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
953*a65addddSAndroid Build Coastguard Worker                .install(getComponent, 2);
954*a65addddSAndroid Build Coastguard Worker            }
955*a65addddSAndroid Build Coastguard Worker
956*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent4() {
957*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
958*a65addddSAndroid Build Coastguard Worker                .install(getComponent2)
959*a65addddSAndroid Build Coastguard Worker                .install(getComponent3);
960*a65addddSAndroid Build Coastguard Worker            }
961*a65addddSAndroid Build Coastguard Worker
962*a65addddSAndroid Build Coastguard Worker            int main() {
963*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent4);
964*a65addddSAndroid Build Coastguard Worker
965*a65addddSAndroid Build Coastguard Worker              // We test multibindings because the effect on other bindings is not user-visible (it only affects
966*a65addddSAndroid Build Coastguard Worker              // performance).
967*a65addddSAndroid Build Coastguard Worker              std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
968*a65addddSAndroid Build Coastguard Worker              Assert(multibindings.size() == 2);
969*a65addddSAndroid Build Coastguard Worker              Assert(multibindings[0] == &x);
970*a65addddSAndroid Build Coastguard Worker              Assert(multibindings[1] == &x);
971*a65addddSAndroid Build Coastguard Worker            }
972*a65addddSAndroid Build Coastguard Worker            '''
973*a65addddSAndroid Build Coastguard Worker        expect_success(
974*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
975*a65addddSAndroid Build Coastguard Worker            source,
976*a65addddSAndroid Build Coastguard Worker            locals())
977*a65addddSAndroid Build Coastguard Worker
978*a65addddSAndroid Build Coastguard Worker    def test_install_component_functions_loop(self):
979*a65addddSAndroid Build Coastguard Worker        source = '''
980*a65addddSAndroid Build Coastguard Worker            struct X {};
981*a65addddSAndroid Build Coastguard Worker            struct Y {};
982*a65addddSAndroid Build Coastguard Worker            struct Z {};
983*a65addddSAndroid Build Coastguard Worker
984*a65addddSAndroid Build Coastguard Worker            // X -> Y -> Z -> Y
985*a65addddSAndroid Build Coastguard Worker
986*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getXComponent();
987*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y> getYComponent();
988*a65addddSAndroid Build Coastguard Worker            fruit::Component<Z> getZComponent();
989*a65addddSAndroid Build Coastguard Worker
990*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getXComponent() {
991*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
992*a65addddSAndroid Build Coastguard Worker                  .registerConstructor<X()>()
993*a65addddSAndroid Build Coastguard Worker                  .install(getYComponent);
994*a65addddSAndroid Build Coastguard Worker            }
995*a65addddSAndroid Build Coastguard Worker
996*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y> getYComponent() {
997*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
998*a65addddSAndroid Build Coastguard Worker                  .registerConstructor<Y()>()
999*a65addddSAndroid Build Coastguard Worker                  .install(getZComponent);
1000*a65addddSAndroid Build Coastguard Worker            }
1001*a65addddSAndroid Build Coastguard Worker
1002*a65addddSAndroid Build Coastguard Worker            fruit::Component<Z> getZComponent() {
1003*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
1004*a65addddSAndroid Build Coastguard Worker                  .registerConstructor<Z()>()
1005*a65addddSAndroid Build Coastguard Worker                  .install(getYComponent);
1006*a65addddSAndroid Build Coastguard Worker            }
1007*a65addddSAndroid Build Coastguard Worker
1008*a65addddSAndroid Build Coastguard Worker            int main() {
1009*a65addddSAndroid Build Coastguard Worker              fruit::Injector<X> injector(getXComponent);
1010*a65addddSAndroid Build Coastguard Worker              (void)injector;
1011*a65addddSAndroid Build Coastguard Worker            }
1012*a65addddSAndroid Build Coastguard Worker            '''
1013*a65addddSAndroid Build Coastguard Worker        expect_runtime_error(
1014*a65addddSAndroid Build Coastguard Worker            r'Component installation trace \(from top-level to the most deeply-nested\):\n'
1015*a65addddSAndroid Build Coastguard Worker            r'(class )?fruit::Component<(struct )?X> ?\((__cdecl)?\*\)\((void)?\)\n'
1016*a65addddSAndroid Build Coastguard Worker            r'<-- The loop starts here\n'
1017*a65addddSAndroid Build Coastguard Worker            r'(class )?fruit::Component<(struct )?Y> ?\((__cdecl)?\*\)\((void)?\)\n'
1018*a65addddSAndroid Build Coastguard Worker            r'(class )?fruit::Component<(struct )?Z> ?\((__cdecl)?\*\)\((void)?\)\n'
1019*a65addddSAndroid Build Coastguard Worker            r'(class )?fruit::Component<(struct )?Y> ?\((__cdecl)?\*\)\((void)?\)\n',
1020*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
1021*a65addddSAndroid Build Coastguard Worker            source,
1022*a65addddSAndroid Build Coastguard Worker            locals())
1023*a65addddSAndroid Build Coastguard Worker
1024*a65addddSAndroid Build Coastguard Worker    def test_install_component_functions_different_arguments_loop_not_reported(self):
1025*a65addddSAndroid Build Coastguard Worker        source = '''
1026*a65addddSAndroid Build Coastguard Worker            struct X {};
1027*a65addddSAndroid Build Coastguard Worker            struct Y {};
1028*a65addddSAndroid Build Coastguard Worker            struct Z {};
1029*a65addddSAndroid Build Coastguard Worker
1030*a65addddSAndroid Build Coastguard Worker            // X -> Y(1) -> Z -> Y(2)
1031*a65addddSAndroid Build Coastguard Worker
1032*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getXComponent();
1033*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y> getYComponent(int);
1034*a65addddSAndroid Build Coastguard Worker            fruit::Component<Z> getZComponent();
1035*a65addddSAndroid Build Coastguard Worker
1036*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getXComponent() {
1037*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
1038*a65addddSAndroid Build Coastguard Worker                  .registerConstructor<X()>()
1039*a65addddSAndroid Build Coastguard Worker                  .install(getYComponent, 1);
1040*a65addddSAndroid Build Coastguard Worker            }
1041*a65addddSAndroid Build Coastguard Worker
1042*a65addddSAndroid Build Coastguard Worker            fruit::Component<Y> getYComponent(int n) {
1043*a65addddSAndroid Build Coastguard Worker                if (n == 1) {
1044*a65addddSAndroid Build Coastguard Worker                    return fruit::createComponent()
1045*a65addddSAndroid Build Coastguard Worker                        .registerConstructor<Y()>()
1046*a65addddSAndroid Build Coastguard Worker                        .install(getZComponent);
1047*a65addddSAndroid Build Coastguard Worker                } else {
1048*a65addddSAndroid Build Coastguard Worker                    return fruit::createComponent()
1049*a65addddSAndroid Build Coastguard Worker                        .registerConstructor<Y()>();
1050*a65addddSAndroid Build Coastguard Worker                }
1051*a65addddSAndroid Build Coastguard Worker            }
1052*a65addddSAndroid Build Coastguard Worker
1053*a65addddSAndroid Build Coastguard Worker            fruit::Component<Z> getZComponent() {
1054*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
1055*a65addddSAndroid Build Coastguard Worker                  .registerConstructor<Z()>()
1056*a65addddSAndroid Build Coastguard Worker                  .install(getYComponent, 2);
1057*a65addddSAndroid Build Coastguard Worker            }
1058*a65addddSAndroid Build Coastguard Worker
1059*a65addddSAndroid Build Coastguard Worker            int main() {
1060*a65addddSAndroid Build Coastguard Worker              fruit::Injector<X> injector(getXComponent);
1061*a65addddSAndroid Build Coastguard Worker              injector.get<X>();
1062*a65addddSAndroid Build Coastguard Worker            }
1063*a65addddSAndroid Build Coastguard Worker            '''
1064*a65addddSAndroid Build Coastguard Worker        expect_success(
1065*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
1066*a65addddSAndroid Build Coastguard Worker            source,
1067*a65addddSAndroid Build Coastguard Worker            locals())
1068*a65addddSAndroid Build Coastguard Worker
1069*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__':
1070*a65addddSAndroid Build Coastguard Worker    absltest.main()
1071