xref: /aosp_15_r20/external/google-fruit/tests/test_bind_interface.py (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
1*a65addddSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*a65addddSAndroid Build Coastguard Worker#  Copyright 2016 Google Inc. All Rights Reserved.
3*a65addddSAndroid Build Coastguard Worker#
4*a65addddSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker#
8*a65addddSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker#
10*a65addddSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS-IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker# limitations under the License.
15*a65addddSAndroid Build Coastguard Worker
16*a65addddSAndroid Build Coastguard Workerfrom absl.testing import parameterized
17*a65addddSAndroid Build Coastguard Workerfrom fruit_test_common import *
18*a65addddSAndroid Build Coastguard Worker
19*a65addddSAndroid Build Coastguard WorkerCOMMON_DEFINITIONS = '''
20*a65addddSAndroid Build Coastguard Worker    #include "test_common.h"
21*a65addddSAndroid Build Coastguard Worker
22*a65addddSAndroid Build Coastguard Worker    struct Annotation1 {};
23*a65addddSAndroid Build Coastguard Worker    struct Annotation2 {};
24*a65addddSAndroid Build Coastguard Worker    '''
25*a65addddSAndroid Build Coastguard Worker
26*a65addddSAndroid Build Coastguard Workerclass TestBindInstance(parameterized.TestCase):
27*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
28*a65addddSAndroid Build Coastguard Worker        ('X', 'X', 'const X&', 'Y'),
29*a65addddSAndroid Build Coastguard Worker        ('X', 'const X', 'const X&', 'Y'),
30*a65addddSAndroid Build Coastguard Worker        ('X', 'X', 'const X&', 'fruit::Annotated<Annotation1, Y>'),
31*a65addddSAndroid Build Coastguard Worker        ('X', 'const X', 'const X&', 'fruit::Annotated<Annotation1, Y>'),
32*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X&>', 'Y'),
33*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X&>', 'Y'),
34*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X&>', 'fruit::Annotated<Annotation1, Y>'),
35*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X&>', 'fruit::Annotated<Annotation1, Y>'),
36*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X&>', 'fruit::Annotated<Annotation2, Y>'),
37*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X&>', 'fruit::Annotated<Annotation2, Y>'),
38*a65addddSAndroid Build Coastguard Worker    ])
39*a65addddSAndroid Build Coastguard Worker    def test_bind_interface(self, XAnnot, MaybeConstXAnnot, XConstRefAnnot, YAnnot):
40*a65addddSAndroid Build Coastguard Worker        source = '''
41*a65addddSAndroid Build Coastguard Worker            struct X {
42*a65addddSAndroid Build Coastguard Worker              virtual void f() const = 0;
43*a65addddSAndroid Build Coastguard Worker            };
44*a65addddSAndroid Build Coastguard Worker
45*a65addddSAndroid Build Coastguard Worker            struct Y : public X {
46*a65addddSAndroid Build Coastguard Worker              INJECT(Y()) = default;
47*a65addddSAndroid Build Coastguard Worker
48*a65addddSAndroid Build Coastguard Worker              void f() const override {
49*a65addddSAndroid Build Coastguard Worker              }
50*a65addddSAndroid Build Coastguard Worker            };
51*a65addddSAndroid Build Coastguard Worker
52*a65addddSAndroid Build Coastguard Worker            fruit::Component<MaybeConstXAnnot> getComponent() {
53*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
54*a65addddSAndroid Build Coastguard Worker                .bind<XAnnot, YAnnot>();
55*a65addddSAndroid Build Coastguard Worker            }
56*a65addddSAndroid Build Coastguard Worker
57*a65addddSAndroid Build Coastguard Worker            int main() {
58*a65addddSAndroid Build Coastguard Worker              fruit::Injector<MaybeConstXAnnot> injector(getComponent);
59*a65addddSAndroid Build Coastguard Worker              const X& x = injector.get<XConstRefAnnot>();
60*a65addddSAndroid Build Coastguard Worker              x.f();
61*a65addddSAndroid Build Coastguard Worker            }
62*a65addddSAndroid Build Coastguard Worker        '''
63*a65addddSAndroid Build Coastguard Worker        expect_success(
64*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
65*a65addddSAndroid Build Coastguard Worker            source,
66*a65addddSAndroid Build Coastguard Worker            locals())
67*a65addddSAndroid Build Coastguard Worker
68*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
69*a65addddSAndroid Build Coastguard Worker        ('X', 'const X', 'const X&', 'Y'),
70*a65addddSAndroid Build Coastguard Worker        ('X', 'const X', 'const X&', 'fruit::Annotated<Annotation1, Y>'),
71*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X&>', 'Y'),
72*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X&>', 'fruit::Annotated<Annotation1, Y>'),
73*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X&>', 'fruit::Annotated<Annotation2, Y>'),
74*a65addddSAndroid Build Coastguard Worker    ])
75*a65addddSAndroid Build Coastguard Worker    def test_bind_interface_to_constant(self, XAnnot, ConstXAnnot, XConstRefAnnot, YAnnot):
76*a65addddSAndroid Build Coastguard Worker        source = '''
77*a65addddSAndroid Build Coastguard Worker            struct X {
78*a65addddSAndroid Build Coastguard Worker              virtual void f() const = 0;
79*a65addddSAndroid Build Coastguard Worker            };
80*a65addddSAndroid Build Coastguard Worker
81*a65addddSAndroid Build Coastguard Worker            struct Y : public X {
82*a65addddSAndroid Build Coastguard Worker              void f() const override {
83*a65addddSAndroid Build Coastguard Worker              }
84*a65addddSAndroid Build Coastguard Worker            };
85*a65addddSAndroid Build Coastguard Worker
86*a65addddSAndroid Build Coastguard Worker            const Y y{};
87*a65addddSAndroid Build Coastguard Worker
88*a65addddSAndroid Build Coastguard Worker            fruit::Component<ConstXAnnot> getComponent() {
89*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
90*a65addddSAndroid Build Coastguard Worker                .bindInstance<YAnnot, Y>(y)
91*a65addddSAndroid Build Coastguard Worker                .bind<XAnnot, YAnnot>();
92*a65addddSAndroid Build Coastguard Worker            }
93*a65addddSAndroid Build Coastguard Worker
94*a65addddSAndroid Build Coastguard Worker            int main() {
95*a65addddSAndroid Build Coastguard Worker              fruit::Injector<ConstXAnnot> injector(getComponent);
96*a65addddSAndroid Build Coastguard Worker              const X& x = injector.get<XConstRefAnnot>();
97*a65addddSAndroid Build Coastguard Worker              x.f();
98*a65addddSAndroid Build Coastguard Worker            }
99*a65addddSAndroid Build Coastguard Worker        '''
100*a65addddSAndroid Build Coastguard Worker        expect_success(
101*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
102*a65addddSAndroid Build Coastguard Worker            source,
103*a65addddSAndroid Build Coastguard Worker            locals())
104*a65addddSAndroid Build Coastguard Worker
105*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
106*a65addddSAndroid Build Coastguard Worker        ('X', 'X&', 'Y'),
107*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X&>', 'fruit::Annotated<Annotation2, Y>'),
108*a65addddSAndroid Build Coastguard Worker    ])
109*a65addddSAndroid Build Coastguard Worker    def test_bind_interface_target_bound_in_other_component(self, XAnnot, XRefAnnot, YAnnot):
110*a65addddSAndroid Build Coastguard Worker        source = '''
111*a65addddSAndroid Build Coastguard Worker            struct X {
112*a65addddSAndroid Build Coastguard Worker              virtual void f() = 0;
113*a65addddSAndroid Build Coastguard Worker            };
114*a65addddSAndroid Build Coastguard Worker
115*a65addddSAndroid Build Coastguard Worker            struct Y : public X {
116*a65addddSAndroid Build Coastguard Worker              void f() override {
117*a65addddSAndroid Build Coastguard Worker              }
118*a65addddSAndroid Build Coastguard Worker            };
119*a65addddSAndroid Build Coastguard Worker
120*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<YAnnot>, XAnnot> getComponent() {
121*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
122*a65addddSAndroid Build Coastguard Worker                .bind<XAnnot, YAnnot>();
123*a65addddSAndroid Build Coastguard Worker            }
124*a65addddSAndroid Build Coastguard Worker
125*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getRootComponent() {
126*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
127*a65addddSAndroid Build Coastguard Worker                .registerConstructor<YAnnot()>()
128*a65addddSAndroid Build Coastguard Worker                .install(getComponent);
129*a65addddSAndroid Build Coastguard Worker            }
130*a65addddSAndroid Build Coastguard Worker
131*a65addddSAndroid Build Coastguard Worker            int main() {
132*a65addddSAndroid Build Coastguard Worker              fruit::Injector<XAnnot> injector(getRootComponent);
133*a65addddSAndroid Build Coastguard Worker              X& x = injector.get<XRefAnnot>();
134*a65addddSAndroid Build Coastguard Worker              x.f();
135*a65addddSAndroid Build Coastguard Worker            }
136*a65addddSAndroid Build Coastguard Worker        '''
137*a65addddSAndroid Build Coastguard Worker        expect_success(
138*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
139*a65addddSAndroid Build Coastguard Worker            source,
140*a65addddSAndroid Build Coastguard Worker            locals())
141*a65addddSAndroid Build Coastguard Worker
142*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
143*a65addddSAndroid Build Coastguard Worker        ('X', 'X&', 'Y'),
144*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X&>', 'fruit::Annotated<Annotation2, Y>'),
145*a65addddSAndroid Build Coastguard Worker    ])
146*a65addddSAndroid Build Coastguard Worker    def test_bind_nonconst_interface_requires_nonconst_target(self, XAnnot, XRefAnnot, YAnnot):
147*a65addddSAndroid Build Coastguard Worker        source = '''
148*a65addddSAndroid Build Coastguard Worker            struct X {
149*a65addddSAndroid Build Coastguard Worker              virtual void f() = 0;
150*a65addddSAndroid Build Coastguard Worker            };
151*a65addddSAndroid Build Coastguard Worker
152*a65addddSAndroid Build Coastguard Worker            struct Y : public X {
153*a65addddSAndroid Build Coastguard Worker              void f() override {
154*a65addddSAndroid Build Coastguard Worker              }
155*a65addddSAndroid Build Coastguard Worker            };
156*a65addddSAndroid Build Coastguard Worker
157*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const YAnnot>, XAnnot> getComponent() {
158*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
159*a65addddSAndroid Build Coastguard Worker                .bind<XAnnot, YAnnot>();
160*a65addddSAndroid Build Coastguard Worker            }
161*a65addddSAndroid Build Coastguard Worker        '''
162*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
163*a65addddSAndroid Build Coastguard Worker            'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<YAnnot>',
164*a65addddSAndroid Build Coastguard Worker            'The type T was declared as a const Required type in the returned Component, however a non-const binding',
165*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
166*a65addddSAndroid Build Coastguard Worker            source,
167*a65addddSAndroid Build Coastguard Worker            locals())
168*a65addddSAndroid Build Coastguard Worker
169*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
170*a65addddSAndroid Build Coastguard Worker        ('X', 'Y'),
171*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, Y>'),
172*a65addddSAndroid Build Coastguard Worker    ])
173*a65addddSAndroid Build Coastguard Worker    def test_bind_interface_to_constant_nonconst_required_const_bound_error(self, XAnnot, YAnnot):
174*a65addddSAndroid Build Coastguard Worker        source = '''
175*a65addddSAndroid Build Coastguard Worker            struct X {
176*a65addddSAndroid Build Coastguard Worker              virtual void f() const = 0;
177*a65addddSAndroid Build Coastguard Worker            };
178*a65addddSAndroid Build Coastguard Worker
179*a65addddSAndroid Build Coastguard Worker            struct Y : public X {
180*a65addddSAndroid Build Coastguard Worker              void f() const override {
181*a65addddSAndroid Build Coastguard Worker              }
182*a65addddSAndroid Build Coastguard Worker            };
183*a65addddSAndroid Build Coastguard Worker
184*a65addddSAndroid Build Coastguard Worker            const Y y{};
185*a65addddSAndroid Build Coastguard Worker
186*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getComponent() {
187*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
188*a65addddSAndroid Build Coastguard Worker                .bindInstance<YAnnot, Y>(y)
189*a65addddSAndroid Build Coastguard Worker                .bind<XAnnot, YAnnot>();
190*a65addddSAndroid Build Coastguard Worker            }
191*a65addddSAndroid Build Coastguard Worker        '''
192*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
193*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<YAnnot>',
194*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
195*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
196*a65addddSAndroid Build Coastguard Worker            source,
197*a65addddSAndroid Build Coastguard Worker            locals())
198*a65addddSAndroid Build Coastguard Worker
199*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
200*a65addddSAndroid Build Coastguard Worker        ('X', 'X&', 'Y'),
201*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X&>', 'fruit::Annotated<Annotation2, Y>'),
202*a65addddSAndroid Build Coastguard Worker    ])
203*a65addddSAndroid Build Coastguard Worker    def test_bind_nonconst_interface_requires_nonconst_target_abstract(self, XAnnot, XRefAnnot, YAnnot):
204*a65addddSAndroid Build Coastguard Worker        source = '''
205*a65addddSAndroid Build Coastguard Worker            struct X {
206*a65addddSAndroid Build Coastguard Worker              virtual void f() = 0;
207*a65addddSAndroid Build Coastguard Worker            };
208*a65addddSAndroid Build Coastguard Worker
209*a65addddSAndroid Build Coastguard Worker            struct Y : public X {};
210*a65addddSAndroid Build Coastguard Worker
211*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const YAnnot>, XAnnot> getComponent() {
212*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
213*a65addddSAndroid Build Coastguard Worker                .bind<XAnnot, YAnnot>();
214*a65addddSAndroid Build Coastguard Worker            }
215*a65addddSAndroid Build Coastguard Worker        '''
216*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
217*a65addddSAndroid Build Coastguard Worker            'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<YAnnot>',
218*a65addddSAndroid Build Coastguard Worker            'The type T was declared as a const Required type in the returned Component, however a non-const binding',
219*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
220*a65addddSAndroid Build Coastguard Worker            source,
221*a65addddSAndroid Build Coastguard Worker            locals())
222*a65addddSAndroid Build Coastguard Worker
223*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
224*a65addddSAndroid Build Coastguard Worker        ('X', 'int'),
225*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, int>'),
226*a65addddSAndroid Build Coastguard Worker    ])
227*a65addddSAndroid Build Coastguard Worker    def test_error_not_base(self, XAnnot, intAnnot):
228*a65addddSAndroid Build Coastguard Worker        source = '''
229*a65addddSAndroid Build Coastguard Worker            struct X {};
230*a65addddSAndroid Build Coastguard Worker
231*a65addddSAndroid Build Coastguard Worker            fruit::Component<intAnnot> getComponent() {
232*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
233*a65addddSAndroid Build Coastguard Worker                .bind<XAnnot, intAnnot>();
234*a65addddSAndroid Build Coastguard Worker            }
235*a65addddSAndroid Build Coastguard Worker            '''
236*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
237*a65addddSAndroid Build Coastguard Worker            'NotABaseClassOfError<X,int>',
238*a65addddSAndroid Build Coastguard Worker            'I is not a base class of C.',
239*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
240*a65addddSAndroid Build Coastguard Worker            source,
241*a65addddSAndroid Build Coastguard Worker            locals())
242*a65addddSAndroid Build Coastguard Worker
243*a65addddSAndroid Build Coastguard Worker    # TODO: maybe the error should include the annotation here.
244*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
245*a65addddSAndroid Build Coastguard Worker        'X',
246*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
247*a65addddSAndroid Build Coastguard Worker    ])
248*a65addddSAndroid Build Coastguard Worker    def test_error_bound_to_itself(self, XAnnot):
249*a65addddSAndroid Build Coastguard Worker        source = '''
250*a65addddSAndroid Build Coastguard Worker            struct X {};
251*a65addddSAndroid Build Coastguard Worker
252*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
253*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
254*a65addddSAndroid Build Coastguard Worker                .bind<XAnnot, XAnnot>();
255*a65addddSAndroid Build Coastguard Worker            }
256*a65addddSAndroid Build Coastguard Worker            '''
257*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
258*a65addddSAndroid Build Coastguard Worker            'InterfaceBindingToSelfError<X>',
259*a65addddSAndroid Build Coastguard Worker            'The type C was bound to itself.',
260*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
261*a65addddSAndroid Build Coastguard Worker            source,
262*a65addddSAndroid Build Coastguard Worker            locals())
263*a65addddSAndroid Build Coastguard Worker
264*a65addddSAndroid Build Coastguard Worker    def test_bound_to_itself_with_annotation_error(self):
265*a65addddSAndroid Build Coastguard Worker        source = '''
266*a65addddSAndroid Build Coastguard Worker            struct X {};
267*a65addddSAndroid Build Coastguard Worker
268*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
269*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
270*a65addddSAndroid Build Coastguard Worker                .registerConstructor<X()>()
271*a65addddSAndroid Build Coastguard Worker                .bind<fruit::Annotated<Annotation1, X>, X>();
272*a65addddSAndroid Build Coastguard Worker            }
273*a65addddSAndroid Build Coastguard Worker            '''
274*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
275*a65addddSAndroid Build Coastguard Worker            'InterfaceBindingToSelfError<X>',
276*a65addddSAndroid Build Coastguard Worker            'The type C was bound to itself.',
277*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
278*a65addddSAndroid Build Coastguard Worker            source)
279*a65addddSAndroid Build Coastguard Worker
280*a65addddSAndroid Build Coastguard Worker    def test_bound_chain_ok(self):
281*a65addddSAndroid Build Coastguard Worker        source = '''
282*a65addddSAndroid Build Coastguard Worker            struct X {
283*a65addddSAndroid Build Coastguard Worker              virtual void f() = 0;
284*a65addddSAndroid Build Coastguard Worker            };
285*a65addddSAndroid Build Coastguard Worker
286*a65addddSAndroid Build Coastguard Worker            struct Y : public X {};
287*a65addddSAndroid Build Coastguard Worker
288*a65addddSAndroid Build Coastguard Worker            struct Z : public Y {
289*a65addddSAndroid Build Coastguard Worker              INJECT(Z()) = default;
290*a65addddSAndroid Build Coastguard Worker              void f() override {
291*a65addddSAndroid Build Coastguard Worker              }
292*a65addddSAndroid Build Coastguard Worker            };
293*a65addddSAndroid Build Coastguard Worker
294*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> getComponent() {
295*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
296*a65addddSAndroid Build Coastguard Worker                .bind<X, Y>()
297*a65addddSAndroid Build Coastguard Worker                .bind<Y, Z>();
298*a65addddSAndroid Build Coastguard Worker            }
299*a65addddSAndroid Build Coastguard Worker
300*a65addddSAndroid Build Coastguard Worker            int main() {
301*a65addddSAndroid Build Coastguard Worker              fruit::Injector<X> injector(getComponent);
302*a65addddSAndroid Build Coastguard Worker              X& x = injector.get<X&>();
303*a65addddSAndroid Build Coastguard Worker              x.f();
304*a65addddSAndroid Build Coastguard Worker            }
305*a65addddSAndroid Build Coastguard Worker        '''
306*a65addddSAndroid Build Coastguard Worker        expect_success(COMMON_DEFINITIONS, source)
307*a65addddSAndroid Build Coastguard Worker
308*a65addddSAndroid Build Coastguard Worker    def test_bind_non_normalized_types_error(self):
309*a65addddSAndroid Build Coastguard Worker        source = '''
310*a65addddSAndroid Build Coastguard Worker            struct X {};
311*a65addddSAndroid Build Coastguard Worker
312*a65addddSAndroid Build Coastguard Worker            struct Y : public std::shared_ptr<X> {};
313*a65addddSAndroid Build Coastguard Worker
314*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
315*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
316*a65addddSAndroid Build Coastguard Worker                .bind<std::shared_ptr<X>, Y>();
317*a65addddSAndroid Build Coastguard Worker            }
318*a65addddSAndroid Build Coastguard Worker            '''
319*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
320*a65addddSAndroid Build Coastguard Worker            'NonClassTypeError<std::shared_ptr<X>,X>',
321*a65addddSAndroid Build Coastguard Worker            'A non-class type T was specified. Use C instead',
322*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
323*a65addddSAndroid Build Coastguard Worker            source)
324*a65addddSAndroid Build Coastguard Worker
325*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__':
326*a65addddSAndroid Build Coastguard Worker    absltest.main()
327