xref: /aosp_15_r20/external/google-fruit/tests/test_binding_clash.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    struct Y;
24*a65addddSAndroid Build Coastguard Worker    struct Z;
25*a65addddSAndroid Build Coastguard Worker
26*a65addddSAndroid Build Coastguard Worker    struct Annotation1 {};
27*a65addddSAndroid Build Coastguard Worker    using XAnnot1 = fruit::Annotated<Annotation1, X>;
28*a65addddSAndroid Build Coastguard Worker    using YAnnot1 = fruit::Annotated<Annotation1, Y>;
29*a65addddSAndroid Build Coastguard Worker    using ZAnnot1 = fruit::Annotated<Annotation1, Z>;
30*a65addddSAndroid Build Coastguard Worker    using ConstXAnnot1 = fruit::Annotated<Annotation1, const X>;
31*a65addddSAndroid Build Coastguard Worker    using ConstYAnnot1 = fruit::Annotated<Annotation1, const Y>;
32*a65addddSAndroid Build Coastguard Worker    using ConstZAnnot1 = fruit::Annotated<Annotation1, const Z>;
33*a65addddSAndroid Build Coastguard Worker
34*a65addddSAndroid Build Coastguard Worker    struct Annotation2 {};
35*a65addddSAndroid Build Coastguard Worker    using XAnnot2 = fruit::Annotated<Annotation2, X>;
36*a65addddSAndroid Build Coastguard Worker    using YAnnot2 = fruit::Annotated<Annotation2, Y>;
37*a65addddSAndroid Build Coastguard Worker    using ZAnnot2 = fruit::Annotated<Annotation2, Z>;
38*a65addddSAndroid Build Coastguard Worker    using ConstXAnnot2 = fruit::Annotated<Annotation2, const X>;
39*a65addddSAndroid Build Coastguard Worker    using ConstYAnnot2 = fruit::Annotated<Annotation2, const Y>;
40*a65addddSAndroid Build Coastguard Worker    using ConstZAnnot2 = fruit::Annotated<Annotation2, const Z>;
41*a65addddSAndroid Build Coastguard Worker
42*a65addddSAndroid Build Coastguard Worker    struct Annotation3 {};
43*a65addddSAndroid Build Coastguard Worker    '''
44*a65addddSAndroid Build Coastguard Worker
45*a65addddSAndroid Build Coastguard WorkerCONSTRUCTOR_BINDING = (
46*a65addddSAndroid Build Coastguard Worker    '',
47*a65addddSAndroid Build Coastguard Worker    '.registerConstructor<XAnnot()>()')
48*a65addddSAndroid Build Coastguard WorkerINTERFACE_BINDING = (
49*a65addddSAndroid Build Coastguard Worker    '''
50*a65addddSAndroid Build Coastguard Worker        struct Y : public X {};
51*a65addddSAndroid Build Coastguard Worker    ''',
52*a65addddSAndroid Build Coastguard Worker    '''
53*a65addddSAndroid Build Coastguard Worker        .bind<XAnnot, YAnnot>()
54*a65addddSAndroid Build Coastguard Worker        .registerConstructor<YAnnot()>()
55*a65addddSAndroid Build Coastguard Worker    ''')
56*a65addddSAndroid Build Coastguard WorkerINTERFACE_BINDING2 = (
57*a65addddSAndroid Build Coastguard Worker    '''
58*a65addddSAndroid Build Coastguard Worker        struct Y2 : public X {};
59*a65addddSAndroid Build Coastguard Worker    ''',
60*a65addddSAndroid Build Coastguard Worker    '''
61*a65addddSAndroid Build Coastguard Worker        .bind<XAnnot, Y2Annot>()
62*a65addddSAndroid Build Coastguard Worker        .registerConstructor<Y2Annot()>()
63*a65addddSAndroid Build Coastguard Worker    ''')
64*a65addddSAndroid Build Coastguard WorkerINSTALL = (
65*a65addddSAndroid Build Coastguard Worker    '''
66*a65addddSAndroid Build Coastguard Worker        fruit::Component<XAnnot> getParentComponent() {
67*a65addddSAndroid Build Coastguard Worker          return fruit::createComponent()
68*a65addddSAndroid Build Coastguard Worker            .registerConstructor<XAnnot()>();
69*a65addddSAndroid Build Coastguard Worker        }
70*a65addddSAndroid Build Coastguard Worker    ''',
71*a65addddSAndroid Build Coastguard Worker    '.install(getParentComponent)')
72*a65addddSAndroid Build Coastguard WorkerINSTALL2 = (
73*a65addddSAndroid Build Coastguard Worker    '''
74*a65addddSAndroid Build Coastguard Worker        fruit::Component<XAnnot> getParentComponent2() {
75*a65addddSAndroid Build Coastguard Worker          return fruit::createComponent()
76*a65addddSAndroid Build Coastguard Worker            .registerConstructor<XAnnot()>();
77*a65addddSAndroid Build Coastguard Worker        }
78*a65addddSAndroid Build Coastguard Worker    ''',
79*a65addddSAndroid Build Coastguard Worker    '.install(getParentComponent2)')
80*a65addddSAndroid Build Coastguard WorkerCONST_BINDING_FROM_INSTALL = (
81*a65addddSAndroid Build Coastguard Worker    '''
82*a65addddSAndroid Build Coastguard Worker        fruit::Component<const XAnnot> getParentComponent() {
83*a65addddSAndroid Build Coastguard Worker          return fruit::createComponent()
84*a65addddSAndroid Build Coastguard Worker            .registerConstructor<XAnnot()>();
85*a65addddSAndroid Build Coastguard Worker        }
86*a65addddSAndroid Build Coastguard Worker    ''',
87*a65addddSAndroid Build Coastguard Worker    '.install(getParentComponent)')
88*a65addddSAndroid Build Coastguard WorkerCONST_BINDING_FROM_INSTALL2 = (
89*a65addddSAndroid Build Coastguard Worker    '''
90*a65addddSAndroid Build Coastguard Worker        fruit::Component<const XAnnot> getParentComponent2() {
91*a65addddSAndroid Build Coastguard Worker          return fruit::createComponent()
92*a65addddSAndroid Build Coastguard Worker            .registerConstructor<XAnnot()>();
93*a65addddSAndroid Build Coastguard Worker        }
94*a65addddSAndroid Build Coastguard Worker    ''',
95*a65addddSAndroid Build Coastguard Worker    '.install(getParentComponent2)')
96*a65addddSAndroid Build Coastguard WorkerCONST_BINDING = (
97*a65addddSAndroid Build Coastguard Worker    '''
98*a65addddSAndroid Build Coastguard Worker        const X x{};
99*a65addddSAndroid Build Coastguard Worker    ''',
100*a65addddSAndroid Build Coastguard Worker    '.bindInstance<XAnnot, X>(x)')
101*a65addddSAndroid Build Coastguard WorkerCONST_BINDING2 = (
102*a65addddSAndroid Build Coastguard Worker    '''
103*a65addddSAndroid Build Coastguard Worker        const X x2{};
104*a65addddSAndroid Build Coastguard Worker    ''',
105*a65addddSAndroid Build Coastguard Worker    '.bindInstance<XAnnot, X>(x2)')
106*a65addddSAndroid Build Coastguard Worker
107*a65addddSAndroid Build Coastguard Workerclass TestBindingClash(parameterized.TestCase):
108*a65addddSAndroid Build Coastguard Worker    @multiple_named_parameters([
109*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING + INSTALL',) + CONSTRUCTOR_BINDING + INSTALL,
110*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING + INSTALL',) + INTERFACE_BINDING + INSTALL,
111*a65addddSAndroid Build Coastguard Worker        ('INSTALL + INSTALL2',) + INSTALL + INSTALL2,
112*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING + CONST_BINDING_FROM_INSTALL',) + CONSTRUCTOR_BINDING + CONST_BINDING_FROM_INSTALL,
113*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING + CONST_BINDING_FROM_INSTALL',) + INTERFACE_BINDING + CONST_BINDING_FROM_INSTALL,
114*a65addddSAndroid Build Coastguard Worker        ('INSTALL2 + CONST_BINDING_FROM_INSTALL',) + INSTALL2 + CONST_BINDING_FROM_INSTALL,
115*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_FROM_INSTALL + INSTALL2',) + CONST_BINDING_FROM_INSTALL + INSTALL2,
116*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING + INSTALL2',) + CONST_BINDING + INSTALL2,
117*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_FROM_INSTALL + CONST_BINDING_FROM_INSTALL2',) + CONST_BINDING_FROM_INSTALL + CONST_BINDING_FROM_INSTALL2,
118*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING + CONST_BINDING_FROM_INSTALL',) + CONST_BINDING + CONST_BINDING_FROM_INSTALL,
119*a65addddSAndroid Build Coastguard Worker    ], [
120*a65addddSAndroid Build Coastguard Worker        ('No annotation', 'X', 'Y', 'Y2'),
121*a65addddSAndroid Build Coastguard Worker        ('With annotation', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, Y>', 'fruit::Annotated<Annotation3, Y2>'),
122*a65addddSAndroid Build Coastguard Worker    ])
123*a65addddSAndroid Build Coastguard Worker    def test_clash_with_install(self,
124*a65addddSAndroid Build Coastguard Worker            binding1_preparation, binding1, binding2_preparation, binding2, XAnnot, YAnnot, Y2Annot):
125*a65addddSAndroid Build Coastguard Worker        source = '''
126*a65addddSAndroid Build Coastguard Worker            struct X{};
127*a65addddSAndroid Build Coastguard Worker
128*a65addddSAndroid Build Coastguard Worker            %s
129*a65addddSAndroid Build Coastguard Worker            %s
130*a65addddSAndroid Build Coastguard Worker
131*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getComponent() {
132*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
133*a65addddSAndroid Build Coastguard Worker                  %s
134*a65addddSAndroid Build Coastguard Worker                  %s;
135*a65addddSAndroid Build Coastguard Worker            }
136*a65addddSAndroid Build Coastguard Worker            ''' % (binding1_preparation, binding2_preparation, binding1, binding2)
137*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
138*a65addddSAndroid Build Coastguard Worker            'DuplicateTypesInComponentError<XAnnot>',
139*a65addddSAndroid Build Coastguard Worker            'The installed component provides some types that are already provided by the current component.',
140*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
141*a65addddSAndroid Build Coastguard Worker            source,
142*a65addddSAndroid Build Coastguard Worker            locals())
143*a65addddSAndroid Build Coastguard Worker
144*a65addddSAndroid Build Coastguard Worker    @multiple_named_parameters([
145*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING + CONSTRUCTOR_BINDING',) + CONSTRUCTOR_BINDING + CONSTRUCTOR_BINDING,
146*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING + INTERFACE_BINDING',) + CONSTRUCTOR_BINDING + INTERFACE_BINDING,
147*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING + CONSTRUCTOR_BINDING',) + INTERFACE_BINDING + CONSTRUCTOR_BINDING,
148*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING + INTERFACE_BINDING2',) + INTERFACE_BINDING + INTERFACE_BINDING2,
149*a65addddSAndroid Build Coastguard Worker        ('INSTALL + CONSTRUCTOR_BINDING',) + INSTALL + CONSTRUCTOR_BINDING,
150*a65addddSAndroid Build Coastguard Worker        ('INSTALL + INTERFACE_BINDING',) + INSTALL + INTERFACE_BINDING,
151*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_FROM_INSTALL + CONSTRUCTOR_BINDING',) + CONST_BINDING_FROM_INSTALL + CONSTRUCTOR_BINDING,
152*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_FROM_INSTALL + INTERFACE_BINDING',) + CONST_BINDING_FROM_INSTALL + INTERFACE_BINDING,
153*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING + CONSTRUCTOR_BINDING',) + CONST_BINDING + CONSTRUCTOR_BINDING,
154*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING + INTERFACE_BINDING',) + CONST_BINDING + INTERFACE_BINDING,
155*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING + CONST_BINDING',) + CONSTRUCTOR_BINDING + CONST_BINDING,
156*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING + CONST_BINDING',) + INTERFACE_BINDING + CONST_BINDING,
157*a65addddSAndroid Build Coastguard Worker        ('INSTALL2 + CONST_BINDING',) + INSTALL2 + CONST_BINDING,
158*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_FROM_INSTALL + CONST_BINDING',) + CONST_BINDING_FROM_INSTALL + CONST_BINDING,
159*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING + CONST_BINDING2',) + CONST_BINDING + CONST_BINDING2,
160*a65addddSAndroid Build Coastguard Worker    ], [
161*a65addddSAndroid Build Coastguard Worker        ('No annotation', 'X', 'Y', 'Y2'),
162*a65addddSAndroid Build Coastguard Worker        ('With annotation', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, Y>', 'fruit::Annotated<Annotation3, Y2>'),
163*a65addddSAndroid Build Coastguard Worker    ])
164*a65addddSAndroid Build Coastguard Worker    def test_clash_with_binding(self, binding1_preparation, binding1, binding2_preparation, binding2, XAnnot, YAnnot, Y2Annot):
165*a65addddSAndroid Build Coastguard Worker        source = '''
166*a65addddSAndroid Build Coastguard Worker            struct X{};
167*a65addddSAndroid Build Coastguard Worker
168*a65addddSAndroid Build Coastguard Worker            %s
169*a65addddSAndroid Build Coastguard Worker            %s
170*a65addddSAndroid Build Coastguard Worker
171*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getComponent() {
172*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
173*a65addddSAndroid Build Coastguard Worker                  %s
174*a65addddSAndroid Build Coastguard Worker                  %s;
175*a65addddSAndroid Build Coastguard Worker            }
176*a65addddSAndroid Build Coastguard Worker
177*a65addddSAndroid Build Coastguard Worker            ''' % (binding1_preparation, binding2_preparation, binding1, binding2)
178*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
179*a65addddSAndroid Build Coastguard Worker            'TypeAlreadyBoundError<XAnnot>',
180*a65addddSAndroid Build Coastguard Worker            'Trying to bind C but it is already bound.',
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    CONSTRUCTOR_BINDING_ANNOT1 = (
186*a65addddSAndroid Build Coastguard Worker        '',
187*a65addddSAndroid Build Coastguard Worker        '.registerConstructor<XAnnot1()>()')
188*a65addddSAndroid Build Coastguard Worker    CONSTRUCTOR_BINDING_ANNOT2 = (
189*a65addddSAndroid Build Coastguard Worker        '',
190*a65addddSAndroid Build Coastguard Worker        '.registerConstructor<XAnnot2()>()')
191*a65addddSAndroid Build Coastguard Worker    INTERFACE_BINDING_ANNOT1 = (
192*a65addddSAndroid Build Coastguard Worker        '''
193*a65addddSAndroid Build Coastguard Worker            struct Y : public X {};
194*a65addddSAndroid Build Coastguard Worker        ''',
195*a65addddSAndroid Build Coastguard Worker        '''
196*a65addddSAndroid Build Coastguard Worker            .bind<XAnnot1, YAnnot1>()
197*a65addddSAndroid Build Coastguard Worker            .registerConstructor<YAnnot1()>()
198*a65addddSAndroid Build Coastguard Worker        ''')
199*a65addddSAndroid Build Coastguard Worker    INTERFACE_BINDING_ANNOT2 = (
200*a65addddSAndroid Build Coastguard Worker        '''
201*a65addddSAndroid Build Coastguard Worker            struct Z : public X {};
202*a65addddSAndroid Build Coastguard Worker        ''',
203*a65addddSAndroid Build Coastguard Worker        '''
204*a65addddSAndroid Build Coastguard Worker            .bind<XAnnot2, ZAnnot2>()
205*a65addddSAndroid Build Coastguard Worker            .registerConstructor<ZAnnot2()>()
206*a65addddSAndroid Build Coastguard Worker        ''')
207*a65addddSAndroid Build Coastguard Worker    INSTALL_ANNOT1 = (
208*a65addddSAndroid Build Coastguard Worker        '''
209*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot1> getParentComponent1() {
210*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
211*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot1()>();
212*a65addddSAndroid Build Coastguard Worker            }
213*a65addddSAndroid Build Coastguard Worker        ''',
214*a65addddSAndroid Build Coastguard Worker        '.install(getParentComponent1)')
215*a65addddSAndroid Build Coastguard Worker    INSTALL_ANNOT2 = (
216*a65addddSAndroid Build Coastguard Worker        '''
217*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot2> getParentComponent2() {
218*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
219*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot2()>();
220*a65addddSAndroid Build Coastguard Worker            }
221*a65addddSAndroid Build Coastguard Worker        ''',
222*a65addddSAndroid Build Coastguard Worker        '.install(getParentComponent2)')
223*a65addddSAndroid Build Coastguard Worker    CONST_BINDING_FROM_INSTALL_ANNOT1 = (
224*a65addddSAndroid Build Coastguard Worker        '''
225*a65addddSAndroid Build Coastguard Worker            fruit::Component<ConstXAnnot1> getParentComponent1() {
226*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
227*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot1()>();
228*a65addddSAndroid Build Coastguard Worker            }
229*a65addddSAndroid Build Coastguard Worker        ''',
230*a65addddSAndroid Build Coastguard Worker        '.install(getParentComponent1)')
231*a65addddSAndroid Build Coastguard Worker    CONST_BINDING_FROM_INSTALL_ANNOT2 = (
232*a65addddSAndroid Build Coastguard Worker        '''
233*a65addddSAndroid Build Coastguard Worker            fruit::Component<ConstXAnnot2> getParentComponent2() {
234*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
235*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot2()>();
236*a65addddSAndroid Build Coastguard Worker            }
237*a65addddSAndroid Build Coastguard Worker        ''',
238*a65addddSAndroid Build Coastguard Worker        '.install(getParentComponent2)')
239*a65addddSAndroid Build Coastguard Worker    CONST_BINDING_ANNOT1 = (
240*a65addddSAndroid Build Coastguard Worker        '''
241*a65addddSAndroid Build Coastguard Worker            const X x1{};
242*a65addddSAndroid Build Coastguard Worker        ''',
243*a65addddSAndroid Build Coastguard Worker        '.bindInstance<XAnnot1, X>(x1)')
244*a65addddSAndroid Build Coastguard Worker    CONST_BINDING_ANNOT2 = (
245*a65addddSAndroid Build Coastguard Worker        '''
246*a65addddSAndroid Build Coastguard Worker            const X x2{};
247*a65addddSAndroid Build Coastguard Worker        ''',
248*a65addddSAndroid Build Coastguard Worker        '.bindInstance<XAnnot2, X>(x2)')
249*a65addddSAndroid Build Coastguard Worker
250*a65addddSAndroid Build Coastguard Worker    @parameterized.named_parameters([
251*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2',) + CONSTRUCTOR_BINDING_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2,
252*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING_ANNOT1 + INTERFACE_BINDING_ANNOT2',) + CONSTRUCTOR_BINDING_ANNOT1 + INTERFACE_BINDING_ANNOT2,
253*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2',) + INTERFACE_BINDING_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2,
254*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING_ANNOT1 + INTERFACE_BINDING_ANNOT2',) + INTERFACE_BINDING_ANNOT1 + INTERFACE_BINDING_ANNOT2,
255*a65addddSAndroid Build Coastguard Worker        ('INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2',) + INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2,
256*a65addddSAndroid Build Coastguard Worker        ('INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2',) + INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2,
257*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_FROM_INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2',) + CONST_BINDING_FROM_INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2,
258*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2',) + CONST_BINDING_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2,
259*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_FROM_INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2',) + CONST_BINDING_FROM_INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2,
260*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_ANNOT1 + INTERFACE_BINDING_ANNOT2',) + CONST_BINDING_ANNOT1 + INTERFACE_BINDING_ANNOT2,
261*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING_ANNOT1 + INSTALL_ANNOT2',) + CONSTRUCTOR_BINDING_ANNOT1 + INSTALL_ANNOT2,
262*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING_ANNOT1 + INSTALL_ANNOT2',) + INTERFACE_BINDING_ANNOT1 + INSTALL_ANNOT2,
263*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2',) + CONSTRUCTOR_BINDING_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2,
264*a65addddSAndroid Build Coastguard Worker        ('CONSTRUCTOR_BINDING_ANNOT1 + CONST_BINDING_ANNOT2',) + CONSTRUCTOR_BINDING_ANNOT1 + CONST_BINDING_ANNOT2,
265*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2',) + INTERFACE_BINDING_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2,
266*a65addddSAndroid Build Coastguard Worker        ('INTERFACE_BINDING_ANNOT1 + CONST_BINDING_ANNOT2',) + INTERFACE_BINDING_ANNOT1 + CONST_BINDING_ANNOT2,
267*a65addddSAndroid Build Coastguard Worker        ('INSTALL_ANNOT1 + INSTALL_ANNOT2',) + INSTALL_ANNOT1 + INSTALL_ANNOT2,
268*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_FROM_INSTALL_ANNOT1 + INSTALL_ANNOT2',) + CONST_BINDING_FROM_INSTALL_ANNOT1 + INSTALL_ANNOT2,
269*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_ANNOT1 + INSTALL_ANNOT2',) + CONST_BINDING_ANNOT1 + INSTALL_ANNOT2,
270*a65addddSAndroid Build Coastguard Worker        ('INSTALL_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2',) + INSTALL_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2,
271*a65addddSAndroid Build Coastguard Worker        ('INSTALL_ANNOT1 + CONST_BINDING_ANNOT2',) + INSTALL_ANNOT1 + CONST_BINDING_ANNOT2,
272*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_FROM_INSTALL_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2',) + CONST_BINDING_FROM_INSTALL_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2,
273*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_ANNOT1 + CONST_BINDING_ANNOT2',) + CONST_BINDING_ANNOT1 + CONST_BINDING_ANNOT2,
274*a65addddSAndroid Build Coastguard Worker        ('CONST_BINDING_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2',) + CONST_BINDING_ANNOT1 + CONST_BINDING_FROM_INSTALL_ANNOT2,
275*a65addddSAndroid Build Coastguard Worker    ])
276*a65addddSAndroid Build Coastguard Worker    def test_no_clash_with_different_annotations(self, binding1_preparation, binding1, binding2_preparation, binding2):
277*a65addddSAndroid Build Coastguard Worker        source = '''
278*a65addddSAndroid Build Coastguard Worker            struct X {};
279*a65addddSAndroid Build Coastguard Worker
280*a65addddSAndroid Build Coastguard Worker            %s
281*a65addddSAndroid Build Coastguard Worker            %s
282*a65addddSAndroid Build Coastguard Worker
283*a65addddSAndroid Build Coastguard Worker            fruit::Component<const XAnnot1, const XAnnot2> getComponent() {
284*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
285*a65addddSAndroid Build Coastguard Worker                  %s
286*a65addddSAndroid Build Coastguard Worker                  %s;
287*a65addddSAndroid Build Coastguard Worker            }
288*a65addddSAndroid Build Coastguard Worker
289*a65addddSAndroid Build Coastguard Worker            int main() {
290*a65addddSAndroid Build Coastguard Worker                fruit::Injector<const XAnnot1, const XAnnot2> injector(getComponent);
291*a65addddSAndroid Build Coastguard Worker                injector.get<XAnnot1>();
292*a65addddSAndroid Build Coastguard Worker                injector.get<XAnnot2>();
293*a65addddSAndroid Build Coastguard Worker            }
294*a65addddSAndroid Build Coastguard Worker            ''' % (binding1_preparation, binding2_preparation, binding1, binding2)
295*a65addddSAndroid Build Coastguard Worker        expect_success(
296*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
297*a65addddSAndroid Build Coastguard Worker            source)
298*a65addddSAndroid Build Coastguard Worker
299*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
300*a65addddSAndroid Build Coastguard Worker        ('X', 'X', 'X'),
301*a65addddSAndroid Build Coastguard Worker        ('const X', 'X', 'X'),
302*a65addddSAndroid Build Coastguard Worker        ('X', 'const X', 'X'),
303*a65addddSAndroid Build Coastguard Worker        ('const X', 'const X', 'X'),
304*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
305*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
306*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'),
307*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'),
308*a65addddSAndroid Build Coastguard Worker    ])
309*a65addddSAndroid Build Coastguard Worker    def test_during_component_merge(self, NormalizedComponentXAnnot, ComponentXAnnot, XAnnot):
310*a65addddSAndroid Build Coastguard Worker        source = '''
311*a65addddSAndroid Build Coastguard Worker            struct X {};
312*a65addddSAndroid Build Coastguard Worker
313*a65addddSAndroid Build Coastguard Worker            fruit::Component<NormalizedComponentXAnnot> getComponent1() {
314*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
315*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot()>();
316*a65addddSAndroid Build Coastguard Worker            }
317*a65addddSAndroid Build Coastguard Worker
318*a65addddSAndroid Build Coastguard Worker            fruit::Component<ComponentXAnnot> getComponent2() {
319*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
320*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot()>();
321*a65addddSAndroid Build Coastguard Worker            }
322*a65addddSAndroid Build Coastguard Worker
323*a65addddSAndroid Build Coastguard Worker            void f() {
324*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<NormalizedComponentXAnnot> nc(getComponent1);
325*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(nc, getComponent2);
326*a65addddSAndroid Build Coastguard Worker              (void) injector;
327*a65addddSAndroid Build Coastguard Worker            }
328*a65addddSAndroid Build Coastguard Worker            '''
329*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
330*a65addddSAndroid Build Coastguard Worker            'DuplicateTypesInComponentError<XAnnot>',
331*a65addddSAndroid Build Coastguard Worker            'The installed component provides some types that are already provided',
332*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
333*a65addddSAndroid Build Coastguard Worker            source,
334*a65addddSAndroid Build Coastguard Worker            locals())
335*a65addddSAndroid Build Coastguard Worker
336*a65addddSAndroid Build Coastguard Worker    def test_during_component_merge_with_different_annotation_ok(self):
337*a65addddSAndroid Build Coastguard Worker        source = '''
338*a65addddSAndroid Build Coastguard Worker            struct X {};
339*a65addddSAndroid Build Coastguard Worker
340*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot1> getComponent1() {
341*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
342*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot1()>();
343*a65addddSAndroid Build Coastguard Worker            }
344*a65addddSAndroid Build Coastguard Worker
345*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot2> getComponent2() {
346*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
347*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot2()>();
348*a65addddSAndroid Build Coastguard Worker            }
349*a65addddSAndroid Build Coastguard Worker
350*a65addddSAndroid Build Coastguard Worker            int main() {
351*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<XAnnot1> nc(getComponent1);
352*a65addddSAndroid Build Coastguard Worker              fruit::Injector<XAnnot1, XAnnot2> injector(nc, getComponent2);
353*a65addddSAndroid Build Coastguard Worker              injector.get<XAnnot1>();
354*a65addddSAndroid Build Coastguard Worker              injector.get<XAnnot2>();
355*a65addddSAndroid Build Coastguard Worker            }
356*a65addddSAndroid Build Coastguard Worker            '''
357*a65addddSAndroid Build Coastguard Worker        expect_success(
358*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
359*a65addddSAndroid Build Coastguard Worker            source)
360*a65addddSAndroid Build Coastguard Worker
361*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
362*a65addddSAndroid Build Coastguard Worker        ('X', '(struct )?X'),
363*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', '(struct )?fruit::Annotated<(struct )?Annotation1, ?(struct )?X>'),
364*a65addddSAndroid Build Coastguard Worker    ])
365*a65addddSAndroid Build Coastguard Worker    def test_bind_instance_and_bind_instance_runtime(self, XAnnot, XAnnotRegex):
366*a65addddSAndroid Build Coastguard Worker        source = '''
367*a65addddSAndroid Build Coastguard Worker            struct X {};
368*a65addddSAndroid Build Coastguard Worker
369*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponentForInstanceHelper() {
370*a65addddSAndroid Build Coastguard Worker              // Note: don't do this in real code, leaks memory.
371*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
372*a65addddSAndroid Build Coastguard Worker                .bindInstance<XAnnot, X>(*(new X()));
373*a65addddSAndroid Build Coastguard Worker            }
374*a65addddSAndroid Build Coastguard Worker
375*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getComponentForInstance() {
376*a65addddSAndroid Build Coastguard Worker              // Note: don't do this in real code, leaks memory.
377*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
378*a65addddSAndroid Build Coastguard Worker                .install(getComponentForInstanceHelper)
379*a65addddSAndroid Build Coastguard Worker                .bindInstance<XAnnot, X>(*(new X()));
380*a65addddSAndroid Build Coastguard Worker            }
381*a65addddSAndroid Build Coastguard Worker
382*a65addddSAndroid Build Coastguard Worker            int main() {
383*a65addddSAndroid Build Coastguard Worker              fruit::Injector<XAnnot> injector(getComponentForInstance);
384*a65addddSAndroid Build Coastguard Worker              injector.get<XAnnot>();
385*a65addddSAndroid Build Coastguard Worker            }
386*a65addddSAndroid Build Coastguard Worker            '''
387*a65addddSAndroid Build Coastguard Worker        expect_runtime_error(
388*a65addddSAndroid Build Coastguard Worker            'Fatal injection error: the type XAnnotRegex was provided more than once, with different bindings.',
389*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
390*a65addddSAndroid Build Coastguard Worker            source,
391*a65addddSAndroid Build Coastguard Worker            locals())
392*a65addddSAndroid Build Coastguard Worker
393*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
394*a65addddSAndroid Build Coastguard Worker        ('X', '(struct )?X'),
395*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', '(struct )?fruit::Annotated<(struct )?Annotation1, ?(struct )?X>'),
396*a65addddSAndroid Build Coastguard Worker    ])
397*a65addddSAndroid Build Coastguard Worker    def test_bind_instance_and_binding_runtime(self, XAnnot, XAnnotRegex):
398*a65addddSAndroid Build Coastguard Worker        source = '''
399*a65addddSAndroid Build Coastguard Worker            struct X {};
400*a65addddSAndroid Build Coastguard Worker
401*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponentForInstanceHelper(X* x) {
402*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
403*a65addddSAndroid Build Coastguard Worker                .bindInstance<XAnnot, X>(*x);
404*a65addddSAndroid Build Coastguard Worker            }
405*a65addddSAndroid Build Coastguard Worker
406*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getComponentForInstance(X* x) {
407*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
408*a65addddSAndroid Build Coastguard Worker                .install(getComponentForInstanceHelper, x)
409*a65addddSAndroid Build Coastguard Worker                .registerConstructor<XAnnot()>();
410*a65addddSAndroid Build Coastguard Worker            }
411*a65addddSAndroid Build Coastguard Worker
412*a65addddSAndroid Build Coastguard Worker            int main() {
413*a65addddSAndroid Build Coastguard Worker              X x;
414*a65addddSAndroid Build Coastguard Worker              fruit::Injector<XAnnot> injector(getComponentForInstance, &x);
415*a65addddSAndroid Build Coastguard Worker              injector.get<XAnnot>();
416*a65addddSAndroid Build Coastguard Worker            }
417*a65addddSAndroid Build Coastguard Worker            '''
418*a65addddSAndroid Build Coastguard Worker        expect_runtime_error(
419*a65addddSAndroid Build Coastguard Worker            'Fatal injection error: the type XAnnotRegex was provided more than once, with different bindings.',
420*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
421*a65addddSAndroid Build Coastguard Worker            source,
422*a65addddSAndroid Build Coastguard Worker            locals())
423*a65addddSAndroid Build Coastguard Worker
424*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
425*a65addddSAndroid Build Coastguard Worker        'X',
426*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
427*a65addddSAndroid Build Coastguard Worker    ])
428*a65addddSAndroid Build Coastguard Worker    def test_during_component_merge_consistent_ok(self, XAnnot):
429*a65addddSAndroid Build Coastguard Worker        source = '''
430*a65addddSAndroid Build Coastguard Worker            struct X : public ConstructionTracker<X> {
431*a65addddSAndroid Build Coastguard Worker              using Inject = X();
432*a65addddSAndroid Build Coastguard Worker            };
433*a65addddSAndroid Build Coastguard Worker
434*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getComponent() {
435*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent();
436*a65addddSAndroid Build Coastguard Worker            }
437*a65addddSAndroid Build Coastguard Worker
438*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getRootComponent() {
439*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
440*a65addddSAndroid Build Coastguard Worker                  .install(getComponent);
441*a65addddSAndroid Build Coastguard Worker            }
442*a65addddSAndroid Build Coastguard Worker
443*a65addddSAndroid Build Coastguard Worker            int main() {
444*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<> normalizedComponent(getRootComponent);
445*a65addddSAndroid Build Coastguard Worker              fruit::Injector<XAnnot> injector(normalizedComponent, getComponent);
446*a65addddSAndroid Build Coastguard Worker
447*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 0);
448*a65addddSAndroid Build Coastguard Worker              injector.get<XAnnot>();
449*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 1);
450*a65addddSAndroid Build Coastguard Worker            }
451*a65addddSAndroid Build Coastguard Worker            '''
452*a65addddSAndroid Build Coastguard Worker        expect_success(
453*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
454*a65addddSAndroid Build Coastguard Worker            source,
455*a65addddSAndroid Build Coastguard Worker            locals())
456*a65addddSAndroid Build Coastguard Worker
457*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__':
458*a65addddSAndroid Build Coastguard Worker    absltest.main()
459