xref: /aosp_15_r20/external/google-fruit/tests/test_multibindings_bind_provider.py (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
1*a65addddSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*a65addddSAndroid Build Coastguard Worker#  Copyright 2016 Google Inc. All Rights Reserved.
3*a65addddSAndroid Build Coastguard Worker#
4*a65addddSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker#
8*a65addddSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker#
10*a65addddSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS-IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker# limitations under the License.
15*a65addddSAndroid Build Coastguard Worker
16*a65addddSAndroid Build Coastguard Workerfrom absl.testing import parameterized
17*a65addddSAndroid Build Coastguard Workerfrom fruit_test_common import *
18*a65addddSAndroid Build Coastguard Worker
19*a65addddSAndroid Build Coastguard WorkerCOMMON_DEFINITIONS = '''
20*a65addddSAndroid Build Coastguard Worker    #include "test_common.h"
21*a65addddSAndroid Build Coastguard Worker
22*a65addddSAndroid Build Coastguard Worker    struct Annotation1 {};
23*a65addddSAndroid Build Coastguard Worker    struct Annotation2 {};
24*a65addddSAndroid Build Coastguard Worker
25*a65addddSAndroid Build Coastguard Worker    template <typename T>
26*a65addddSAndroid Build Coastguard Worker    using WithNoAnnot = T;
27*a65addddSAndroid Build Coastguard Worker
28*a65addddSAndroid Build Coastguard Worker    template <typename T>
29*a65addddSAndroid Build Coastguard Worker    using WithAnnot1 = fruit::Annotated<Annotation1, T>;
30*a65addddSAndroid Build Coastguard Worker    '''
31*a65addddSAndroid Build Coastguard Worker
32*a65addddSAndroid Build Coastguard Workerclass TestMultibindingsBindProvider(parameterized.TestCase):
33*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
34*a65addddSAndroid Build Coastguard Worker        'X()',
35*a65addddSAndroid Build Coastguard Worker        'new X()',
36*a65addddSAndroid Build Coastguard Worker    ])
37*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_success(self, ConstructX):
38*a65addddSAndroid Build Coastguard Worker        source = '''
39*a65addddSAndroid Build Coastguard Worker            struct X : public ConstructionTracker<X> {
40*a65addddSAndroid Build Coastguard Worker              INJECT(X()) = default;
41*a65addddSAndroid Build Coastguard Worker            };
42*a65addddSAndroid Build Coastguard Worker
43*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
44*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
45*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider([](){return ConstructX;});
46*a65addddSAndroid Build Coastguard Worker            }
47*a65addddSAndroid Build Coastguard Worker
48*a65addddSAndroid Build Coastguard Worker            int main() {
49*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent);
50*a65addddSAndroid Build Coastguard Worker
51*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 0);
52*a65addddSAndroid Build Coastguard Worker              Assert(injector.getMultibindings<X>().size() == 1);
53*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 1);
54*a65addddSAndroid Build Coastguard Worker            }
55*a65addddSAndroid Build Coastguard Worker            '''
56*a65addddSAndroid Build Coastguard Worker        expect_success(
57*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
58*a65addddSAndroid Build Coastguard Worker            source,
59*a65addddSAndroid Build Coastguard Worker            locals())
60*a65addddSAndroid Build Coastguard Worker
61*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
62*a65addddSAndroid Build Coastguard Worker        'WithNoAnnot',
63*a65addddSAndroid Build Coastguard Worker        'WithAnnot1',
64*a65addddSAndroid Build Coastguard Worker    ])
65*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_abstract_class_success(self, WithAnnot):
66*a65addddSAndroid Build Coastguard Worker        source = '''
67*a65addddSAndroid Build Coastguard Worker            struct I {
68*a65addddSAndroid Build Coastguard Worker              virtual int foo() = 0;
69*a65addddSAndroid Build Coastguard Worker              virtual ~I() = default;
70*a65addddSAndroid Build Coastguard Worker            };
71*a65addddSAndroid Build Coastguard Worker
72*a65addddSAndroid Build Coastguard Worker            struct X : public I {
73*a65addddSAndroid Build Coastguard Worker              int foo() override {
74*a65addddSAndroid Build Coastguard Worker                return 5;
75*a65addddSAndroid Build Coastguard Worker              }
76*a65addddSAndroid Build Coastguard Worker            };
77*a65addddSAndroid Build Coastguard Worker
78*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
79*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
80*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<WithAnnot<I*>()>([](){return static_cast<I*>(new X());});
81*a65addddSAndroid Build Coastguard Worker            }
82*a65addddSAndroid Build Coastguard Worker
83*a65addddSAndroid Build Coastguard Worker            int main() {
84*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent);
85*a65addddSAndroid Build Coastguard Worker
86*a65addddSAndroid Build Coastguard Worker              Assert(injector.getMultibindings<WithAnnot<I>>().size() == 1);
87*a65addddSAndroid Build Coastguard Worker              Assert(injector.getMultibindings<WithAnnot<I>>()[0]->foo() == 5);
88*a65addddSAndroid Build Coastguard Worker            }
89*a65addddSAndroid Build Coastguard Worker            '''
90*a65addddSAndroid Build Coastguard Worker        expect_success(
91*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
92*a65addddSAndroid Build Coastguard Worker            source,
93*a65addddSAndroid Build Coastguard Worker            locals())
94*a65addddSAndroid Build Coastguard Worker
95*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
96*a65addddSAndroid Build Coastguard Worker        'WithNoAnnot',
97*a65addddSAndroid Build Coastguard Worker        'WithAnnot1',
98*a65addddSAndroid Build Coastguard Worker    ])
99*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_abstract_class_with_no_virtual_destructor_error(self, WithAnnot):
100*a65addddSAndroid Build Coastguard Worker        source = '''
101*a65addddSAndroid Build Coastguard Worker            struct I {
102*a65addddSAndroid Build Coastguard Worker              virtual int foo() = 0;
103*a65addddSAndroid Build Coastguard Worker            };
104*a65addddSAndroid Build Coastguard Worker
105*a65addddSAndroid Build Coastguard Worker            struct X : public I {
106*a65addddSAndroid Build Coastguard Worker              int foo() override {
107*a65addddSAndroid Build Coastguard Worker                return 5;
108*a65addddSAndroid Build Coastguard Worker              }
109*a65addddSAndroid Build Coastguard Worker            };
110*a65addddSAndroid Build Coastguard Worker
111*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
112*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
113*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<WithAnnot<I*>()>([](){return static_cast<I*>(new X());});
114*a65addddSAndroid Build Coastguard Worker            }
115*a65addddSAndroid Build Coastguard Worker            '''
116*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
117*a65addddSAndroid Build Coastguard Worker            'MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorError<I>',
118*a65addddSAndroid Build Coastguard Worker            r'registerMultibindingProvider\(\) was called with a lambda that returns a pointer to T, but T is an abstract class with no virtual destructor',
119*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
120*a65addddSAndroid Build Coastguard Worker            source,
121*a65addddSAndroid Build Coastguard Worker            locals())
122*a65addddSAndroid Build Coastguard Worker
123*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
124*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
125*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
126*a65addddSAndroid Build Coastguard Worker    ], [
127*a65addddSAndroid Build Coastguard Worker        'WithNoAnnot',
128*a65addddSAndroid Build Coastguard Worker        'WithAnnot1',
129*a65addddSAndroid Build Coastguard Worker    ], [
130*a65addddSAndroid Build Coastguard Worker        'Y',
131*a65addddSAndroid Build Coastguard Worker        'const Y',
132*a65addddSAndroid Build Coastguard Worker        'Y*',
133*a65addddSAndroid Build Coastguard Worker        'const Y*',
134*a65addddSAndroid Build Coastguard Worker        'Y&',
135*a65addddSAndroid Build Coastguard Worker        'const Y&',
136*a65addddSAndroid Build Coastguard Worker        'std::shared_ptr<Y>',
137*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<Y>',
138*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<const Y>',
139*a65addddSAndroid Build Coastguard Worker    ])
140*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_with_param_success(self, ConstructX, XPtr, WithAnnot, YVariant):
141*a65addddSAndroid Build Coastguard Worker        source = '''
142*a65addddSAndroid Build Coastguard Worker            struct Y {};
143*a65addddSAndroid Build Coastguard Worker
144*a65addddSAndroid Build Coastguard Worker            struct X : public ConstructionTracker<X> {};
145*a65addddSAndroid Build Coastguard Worker
146*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<Y>> getYComponent() {
147*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
148*a65addddSAndroid Build Coastguard Worker                .registerConstructor<WithAnnot<Y>()>();
149*a65addddSAndroid Build Coastguard Worker            }
150*a65addddSAndroid Build Coastguard Worker
151*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
152*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
153*a65addddSAndroid Build Coastguard Worker                .install(getYComponent)
154*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; });
155*a65addddSAndroid Build Coastguard Worker            }
156*a65addddSAndroid Build Coastguard Worker
157*a65addddSAndroid Build Coastguard Worker            int main() {
158*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent);
159*a65addddSAndroid Build Coastguard Worker
160*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 0);
161*a65addddSAndroid Build Coastguard Worker              Assert(injector.getMultibindings<X>().size() == 1);
162*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 1);
163*a65addddSAndroid Build Coastguard Worker            }
164*a65addddSAndroid Build Coastguard Worker            '''
165*a65addddSAndroid Build Coastguard Worker        expect_success(
166*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
167*a65addddSAndroid Build Coastguard Worker            source,
168*a65addddSAndroid Build Coastguard Worker            locals())
169*a65addddSAndroid Build Coastguard Worker
170*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
171*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
172*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
173*a65addddSAndroid Build Coastguard Worker    ], [
174*a65addddSAndroid Build Coastguard Worker        'WithNoAnnot',
175*a65addddSAndroid Build Coastguard Worker        'WithAnnot1',
176*a65addddSAndroid Build Coastguard Worker    ], [
177*a65addddSAndroid Build Coastguard Worker        'Y',
178*a65addddSAndroid Build Coastguard Worker        'const Y',
179*a65addddSAndroid Build Coastguard Worker        'const Y*',
180*a65addddSAndroid Build Coastguard Worker        'const Y&',
181*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<const Y>',
182*a65addddSAndroid Build Coastguard Worker    ])
183*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_with_param_const_binding_success(self, ConstructX, XPtr, WithAnnot, YVariant):
184*a65addddSAndroid Build Coastguard Worker        source = '''
185*a65addddSAndroid Build Coastguard Worker            struct Y {};
186*a65addddSAndroid Build Coastguard Worker
187*a65addddSAndroid Build Coastguard Worker            struct X : public ConstructionTracker<X> {};
188*a65addddSAndroid Build Coastguard Worker
189*a65addddSAndroid Build Coastguard Worker            const Y y{};
190*a65addddSAndroid Build Coastguard Worker
191*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<const Y>> getYComponent() {
192*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
193*a65addddSAndroid Build Coastguard Worker                .bindInstance<WithAnnot<Y>, Y>(y);
194*a65addddSAndroid Build Coastguard Worker            }
195*a65addddSAndroid Build Coastguard Worker
196*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
197*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
198*a65addddSAndroid Build Coastguard Worker                .install(getYComponent)
199*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; });
200*a65addddSAndroid Build Coastguard Worker            }
201*a65addddSAndroid Build Coastguard Worker
202*a65addddSAndroid Build Coastguard Worker            int main() {
203*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent);
204*a65addddSAndroid Build Coastguard Worker
205*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 0);
206*a65addddSAndroid Build Coastguard Worker              Assert(injector.getMultibindings<X>().size() == 1);
207*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 1);
208*a65addddSAndroid Build Coastguard Worker            }
209*a65addddSAndroid Build Coastguard Worker            '''
210*a65addddSAndroid Build Coastguard Worker        expect_success(
211*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
212*a65addddSAndroid Build Coastguard Worker            source,
213*a65addddSAndroid Build Coastguard Worker            locals())
214*a65addddSAndroid Build Coastguard Worker
215*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
216*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
217*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
218*a65addddSAndroid Build Coastguard Worker    ], [
219*a65addddSAndroid Build Coastguard Worker        ('WithNoAnnot', 'Y'),
220*a65addddSAndroid Build Coastguard Worker        ('WithAnnot1', 'fruit::Annotated<Annotation1, Y>'),
221*a65addddSAndroid Build Coastguard Worker    ], [
222*a65addddSAndroid Build Coastguard Worker        'Y*',
223*a65addddSAndroid Build Coastguard Worker        'Y&',
224*a65addddSAndroid Build Coastguard Worker        'std::shared_ptr<Y>',
225*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<Y>',
226*a65addddSAndroid Build Coastguard Worker    ])
227*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_with_param_error_nonconst_param_required(self, ConstructX, XPtr, WithAnnot, YAnnotRegex, YVariant):
228*a65addddSAndroid Build Coastguard Worker        source = '''
229*a65addddSAndroid Build Coastguard Worker            struct Y {};
230*a65addddSAndroid Build Coastguard Worker            struct X {};
231*a65addddSAndroid Build Coastguard Worker
232*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<const Y>> getYComponent();
233*a65addddSAndroid Build Coastguard Worker
234*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
235*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
236*a65addddSAndroid Build Coastguard Worker                .install(getYComponent)
237*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; });
238*a65addddSAndroid Build Coastguard Worker            }
239*a65addddSAndroid Build Coastguard Worker            '''
240*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
241*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>',
242*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
243*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
244*a65addddSAndroid Build Coastguard Worker            source,
245*a65addddSAndroid Build Coastguard Worker            locals())
246*a65addddSAndroid Build Coastguard Worker
247*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
248*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
249*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
250*a65addddSAndroid Build Coastguard Worker    ], [
251*a65addddSAndroid Build Coastguard Worker        ('WithNoAnnot', 'Y'),
252*a65addddSAndroid Build Coastguard Worker        ('WithAnnot1', 'fruit::Annotated<Annotation1, Y>'),
253*a65addddSAndroid Build Coastguard Worker    ], [
254*a65addddSAndroid Build Coastguard Worker        'Y*',
255*a65addddSAndroid Build Coastguard Worker        'Y&',
256*a65addddSAndroid Build Coastguard Worker        'std::shared_ptr<Y>',
257*a65addddSAndroid Build Coastguard Worker        'fruit::Provider<Y>',
258*a65addddSAndroid Build Coastguard Worker    ])
259*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_with_param_error_nonconst_param_required_install_after(self, ConstructX, XPtr, WithAnnot, YAnnotRegex, YVariant):
260*a65addddSAndroid Build Coastguard Worker        source = '''
261*a65addddSAndroid Build Coastguard Worker            struct Y {};
262*a65addddSAndroid Build Coastguard Worker            struct X {};
263*a65addddSAndroid Build Coastguard Worker
264*a65addddSAndroid Build Coastguard Worker            fruit::Component<WithAnnot<const Y>> getYComponent();
265*a65addddSAndroid Build Coastguard Worker
266*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
267*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
268*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; })
269*a65addddSAndroid Build Coastguard Worker                .install(getYComponent);
270*a65addddSAndroid Build Coastguard Worker            }
271*a65addddSAndroid Build Coastguard Worker            '''
272*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
273*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>',
274*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
275*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
276*a65addddSAndroid Build Coastguard Worker            source,
277*a65addddSAndroid Build Coastguard Worker            locals())
278*a65addddSAndroid Build Coastguard Worker
279*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_requiring_nonconst_then_requiring_const_ok(self):
280*a65addddSAndroid Build Coastguard Worker        source = '''
281*a65addddSAndroid Build Coastguard Worker            struct X {};
282*a65addddSAndroid Build Coastguard Worker            struct Y {};
283*a65addddSAndroid Build Coastguard Worker
284*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getRootComponent() {
285*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
286*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider([](X&) { return Y(); })
287*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider([](const X&) { return Y(); })
288*a65addddSAndroid Build Coastguard Worker                .registerConstructor<X()>();
289*a65addddSAndroid Build Coastguard Worker            }
290*a65addddSAndroid Build Coastguard Worker
291*a65addddSAndroid Build Coastguard Worker            int main() {
292*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getRootComponent);
293*a65addddSAndroid Build Coastguard Worker              injector.getMultibindings<Y>();
294*a65addddSAndroid Build Coastguard Worker            }
295*a65addddSAndroid Build Coastguard Worker            '''
296*a65addddSAndroid Build Coastguard Worker        expect_success(
297*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
298*a65addddSAndroid Build Coastguard Worker            source,
299*a65addddSAndroid Build Coastguard Worker            locals())
300*a65addddSAndroid Build Coastguard Worker
301*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_requiring_nonconst_then_requiring_const_declaring_const_requirement_error(self):
302*a65addddSAndroid Build Coastguard Worker        source = '''
303*a65addddSAndroid Build Coastguard Worker            struct X {};
304*a65addddSAndroid Build Coastguard Worker            struct Y {};
305*a65addddSAndroid Build Coastguard Worker
306*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const X>> getRootComponent() {
307*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
308*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider([](X&) { return Y(); })
309*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider([](const X&) { return Y(); });
310*a65addddSAndroid Build Coastguard Worker            }
311*a65addddSAndroid Build Coastguard Worker            '''
312*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
313*a65addddSAndroid Build Coastguard Worker            'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
314*a65addddSAndroid Build Coastguard Worker            'The type T was declared as a const Required type in the returned Component, however',
315*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
316*a65addddSAndroid Build Coastguard Worker            source,
317*a65addddSAndroid Build Coastguard Worker            locals())
318*a65addddSAndroid Build Coastguard Worker
319*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_requiring_const_then_requiring_nonconst_ok(self):
320*a65addddSAndroid Build Coastguard Worker        source = '''
321*a65addddSAndroid Build Coastguard Worker            struct X {};
322*a65addddSAndroid Build Coastguard Worker            struct Y {};
323*a65addddSAndroid Build Coastguard Worker
324*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getRootComponent() {
325*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
326*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider([](const X&) { return Y(); })
327*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider([](X&) { return Y(); })
328*a65addddSAndroid Build Coastguard Worker                .registerConstructor<X()>();
329*a65addddSAndroid Build Coastguard Worker            }
330*a65addddSAndroid Build Coastguard Worker
331*a65addddSAndroid Build Coastguard Worker            int main() {
332*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getRootComponent);
333*a65addddSAndroid Build Coastguard Worker              injector.getMultibindings<Y>();
334*a65addddSAndroid Build Coastguard Worker            }
335*a65addddSAndroid Build Coastguard Worker            '''
336*a65addddSAndroid Build Coastguard Worker        expect_success(
337*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
338*a65addddSAndroid Build Coastguard Worker            source,
339*a65addddSAndroid Build Coastguard Worker            locals())
340*a65addddSAndroid Build Coastguard Worker
341*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_requiring_const_then_requiring_nonconst_declaring_const_requirement_error(self):
342*a65addddSAndroid Build Coastguard Worker        source = '''
343*a65addddSAndroid Build Coastguard Worker            struct X {};
344*a65addddSAndroid Build Coastguard Worker            struct Y {};
345*a65addddSAndroid Build Coastguard Worker
346*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<const X>> getRootComponent() {
347*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
348*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider([](const X&) { return Y(); })
349*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider([](X&) { return Y(); });
350*a65addddSAndroid Build Coastguard Worker            }
351*a65addddSAndroid Build Coastguard Worker            '''
352*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
353*a65addddSAndroid Build Coastguard Worker            'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
354*a65addddSAndroid Build Coastguard Worker            'The type T was declared as a const Required type in the returned Component, however',
355*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
356*a65addddSAndroid Build Coastguard Worker            source,
357*a65addddSAndroid Build Coastguard Worker            locals())
358*a65addddSAndroid Build Coastguard Worker
359*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
360*a65addddSAndroid Build Coastguard Worker        ('X()', 'X'),
361*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X*'),
362*a65addddSAndroid Build Coastguard Worker    ], [
363*a65addddSAndroid Build Coastguard Worker        ('Y', 'Y', 'Y**', r'Y\*\*'),
364*a65addddSAndroid Build Coastguard Worker        ('Y', 'Y', 'std::shared_ptr<Y>*', r'std::shared_ptr<Y>\*'),
365*a65addddSAndroid Build Coastguard Worker        ('Y', 'const Y', 'Y**', r'Y\*\*'),
366*a65addddSAndroid Build Coastguard Worker        ('Y', 'const Y', 'std::shared_ptr<Y>*', r'std::shared_ptr<Y>\*'),
367*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, Y>', 'fruit::Annotated<Annotation1, Y>', 'Y**', r'Y\*\*'),
368*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, Y>', 'fruit::Annotated<Annotation1, const Y>', 'Y**', r'Y\*\*'),
369*a65addddSAndroid Build Coastguard Worker    ])
370*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_with_param_error_type_not_injectable(self, ConstructX, XPtr, YAnnot, ConstYAnnot, YVariant, YVariantRegex):
371*a65addddSAndroid Build Coastguard Worker        source = '''
372*a65addddSAndroid Build Coastguard Worker            struct Y {};
373*a65addddSAndroid Build Coastguard Worker            struct X {};
374*a65addddSAndroid Build Coastguard Worker
375*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
376*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
377*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XPtr(YVariant)>([](YVariant){ return ConstructX; });
378*a65addddSAndroid Build Coastguard Worker            }
379*a65addddSAndroid Build Coastguard Worker            '''
380*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
381*a65addddSAndroid Build Coastguard Worker            'NonInjectableTypeError<YVariantRegex>',
382*a65addddSAndroid Build Coastguard Worker            'The type T is not injectable.',
383*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
384*a65addddSAndroid Build Coastguard Worker            source,
385*a65addddSAndroid Build Coastguard Worker            locals())
386*a65addddSAndroid Build Coastguard Worker
387*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
388*a65addddSAndroid Build Coastguard Worker        ('X()', 'X', 'X'),
389*a65addddSAndroid Build Coastguard Worker        ('X()', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
390*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X', 'X*'),
391*a65addddSAndroid Build Coastguard Worker        ('new X()', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X*>'),
392*a65addddSAndroid Build Coastguard Worker    ])
393*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_explicit_signature_success(self, ConstructX, XAnnot, XPtrAnnot):
394*a65addddSAndroid Build Coastguard Worker        source = '''
395*a65addddSAndroid Build Coastguard Worker            struct X : public ConstructionTracker<X> {
396*a65addddSAndroid Build Coastguard Worker              INJECT(X()) = default;
397*a65addddSAndroid Build Coastguard Worker
398*a65addddSAndroid Build Coastguard Worker              static bool constructed;
399*a65addddSAndroid Build Coastguard Worker            };
400*a65addddSAndroid Build Coastguard Worker
401*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
402*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
403*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XPtrAnnot()>([](){return ConstructX;});
404*a65addddSAndroid Build Coastguard Worker            }
405*a65addddSAndroid Build Coastguard Worker
406*a65addddSAndroid Build Coastguard Worker            int main() {
407*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent);
408*a65addddSAndroid Build Coastguard Worker
409*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 0);
410*a65addddSAndroid Build Coastguard Worker              Assert(injector.getMultibindings<XAnnot>().size() == 1);
411*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 1);
412*a65addddSAndroid Build Coastguard Worker            }
413*a65addddSAndroid Build Coastguard Worker            '''
414*a65addddSAndroid Build Coastguard Worker        expect_success(
415*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
416*a65addddSAndroid Build Coastguard Worker            source,
417*a65addddSAndroid Build Coastguard Worker            locals())
418*a65addddSAndroid Build Coastguard Worker
419*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
420*a65addddSAndroid Build Coastguard Worker        ('X()', 'X', 'X'),
421*a65addddSAndroid Build Coastguard Worker        ('X()', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
422*a65addddSAndroid Build Coastguard Worker        ('new X()', 'X', 'X*'),
423*a65addddSAndroid Build Coastguard Worker        ('new X()', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X*>'),
424*a65addddSAndroid Build Coastguard Worker    ])
425*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_explicit_signature_with_normalized_component_success(self, ConstructX, XAnnot, XPtrAnnot):
426*a65addddSAndroid Build Coastguard Worker        source = '''
427*a65addddSAndroid Build Coastguard Worker            struct X : public ConstructionTracker<X> {
428*a65addddSAndroid Build Coastguard Worker              INJECT(X()) = default;
429*a65addddSAndroid Build Coastguard Worker
430*a65addddSAndroid Build Coastguard Worker              static bool constructed;
431*a65addddSAndroid Build Coastguard Worker            };
432*a65addddSAndroid Build Coastguard Worker
433*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
434*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
435*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XPtrAnnot()>([](){return ConstructX;});
436*a65addddSAndroid Build Coastguard Worker            }
437*a65addddSAndroid Build Coastguard Worker
438*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getEmptyComponent() {
439*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent();
440*a65addddSAndroid Build Coastguard Worker            }
441*a65addddSAndroid Build Coastguard Worker
442*a65addddSAndroid Build Coastguard Worker            int main() {
443*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<> normalizedComponent(getComponent);
444*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(normalizedComponent, getEmptyComponent);
445*a65addddSAndroid Build Coastguard Worker
446*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 0);
447*a65addddSAndroid Build Coastguard Worker              Assert(injector.getMultibindings<XAnnot>().size() == 1);
448*a65addddSAndroid Build Coastguard Worker              Assert(X::num_objects_constructed == 1);
449*a65addddSAndroid Build Coastguard Worker            }
450*a65addddSAndroid Build Coastguard Worker            '''
451*a65addddSAndroid Build Coastguard Worker        expect_success(
452*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
453*a65addddSAndroid Build Coastguard Worker            source,
454*a65addddSAndroid Build Coastguard Worker            locals())
455*a65addddSAndroid Build Coastguard Worker
456*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
457*a65addddSAndroid Build Coastguard Worker        ('X', 'X*', 'int'),
458*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X*>', 'fruit::Annotated<Annotation2, int>'),
459*a65addddSAndroid Build Coastguard Worker    ])
460*a65addddSAndroid Build Coastguard Worker    def test_multiple_providers(self, XAnnot, XPtrAnnot, intAnnot):
461*a65addddSAndroid Build Coastguard Worker        source = '''
462*a65addddSAndroid Build Coastguard Worker            struct X {};
463*a65addddSAndroid Build Coastguard Worker
464*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
465*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
466*a65addddSAndroid Build Coastguard Worker                .registerProvider<intAnnot()>([](){return 42;})
467*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XAnnot(intAnnot)>([](int){return X();})
468*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XPtrAnnot(intAnnot)>([](int){return new X();});
469*a65addddSAndroid Build Coastguard Worker            }
470*a65addddSAndroid Build Coastguard Worker
471*a65addddSAndroid Build Coastguard Worker            int main() {
472*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent);
473*a65addddSAndroid Build Coastguard Worker
474*a65addddSAndroid Build Coastguard Worker              std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
475*a65addddSAndroid Build Coastguard Worker              Assert(multibindings.size() == 2);
476*a65addddSAndroid Build Coastguard Worker            }
477*a65addddSAndroid Build Coastguard Worker            '''
478*a65addddSAndroid Build Coastguard Worker        expect_success(
479*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
480*a65addddSAndroid Build Coastguard Worker            source,
481*a65addddSAndroid Build Coastguard Worker            locals())
482*a65addddSAndroid Build Coastguard Worker
483*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
484*a65addddSAndroid Build Coastguard Worker        'X()',
485*a65addddSAndroid Build Coastguard Worker        'new X()',
486*a65addddSAndroid Build Coastguard Worker    ], [
487*a65addddSAndroid Build Coastguard Worker        'X',
488*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
489*a65addddSAndroid Build Coastguard Worker    ])
490*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_malformed_signature(self, ConstructX, XAnnot):
491*a65addddSAndroid Build Coastguard Worker        source = '''
492*a65addddSAndroid Build Coastguard Worker            struct X {};
493*a65addddSAndroid Build Coastguard Worker
494*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
495*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
496*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XAnnot>([](){return ConstructX;});
497*a65addddSAndroid Build Coastguard Worker            }
498*a65addddSAndroid Build Coastguard Worker            '''
499*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
500*a65addddSAndroid Build Coastguard Worker            'NotASignatureError<XAnnot>',
501*a65addddSAndroid Build Coastguard Worker            'CandidateSignature was specified as parameter, but it.s not a signature.',
502*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
503*a65addddSAndroid Build Coastguard Worker            source,
504*a65addddSAndroid Build Coastguard Worker            locals())
505*a65addddSAndroid Build Coastguard Worker
506*a65addddSAndroid Build Coastguard Worker    @multiple_parameters([
507*a65addddSAndroid Build Coastguard Worker        'X(n)',
508*a65addddSAndroid Build Coastguard Worker        'new X(n)',
509*a65addddSAndroid Build Coastguard Worker    ], [
510*a65addddSAndroid Build Coastguard Worker        'X',
511*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
512*a65addddSAndroid Build Coastguard Worker    ])
513*a65addddSAndroid Build Coastguard Worker    def test_bind_multibinding_provider_lambda_with_captures_error(self, ConstructX, XAnnot):
514*a65addddSAndroid Build Coastguard Worker        source = '''
515*a65addddSAndroid Build Coastguard Worker            struct X {
516*a65addddSAndroid Build Coastguard Worker              X(int) {}
517*a65addddSAndroid Build Coastguard Worker            };
518*a65addddSAndroid Build Coastguard Worker
519*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
520*a65addddSAndroid Build Coastguard Worker              int n = 3;
521*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
522*a65addddSAndroid Build Coastguard Worker                .addMultibindingProvider<XAnnot()>([=]{return ConstructX;});
523*a65addddSAndroid Build Coastguard Worker            }
524*a65addddSAndroid Build Coastguard Worker            '''
525*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
526*a65addddSAndroid Build Coastguard Worker            'FunctorUsedAsProviderError<.*>',
527*a65addddSAndroid Build Coastguard Worker            'A stateful lambda or a non-lambda functor was used as provider',
528*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
529*a65addddSAndroid Build Coastguard Worker            source,
530*a65addddSAndroid Build Coastguard Worker            locals())
531*a65addddSAndroid Build Coastguard Worker
532*a65addddSAndroid Build Coastguard Worker    # TODO: should XPtrAnnot be just XAnnot in the signature?
533*a65addddSAndroid Build Coastguard Worker    # Make sure the behavior here is consistent with registerProvider() and registerFactory().
534*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
535*a65addddSAndroid Build Coastguard Worker        ('X', 'X*', '(struct )?X'),
536*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X*>', '(struct )?fruit::Annotated<(struct )?Annotation1, ?(struct )?X>'),
537*a65addddSAndroid Build Coastguard Worker    ])
538*a65addddSAndroid Build Coastguard Worker    def test_provider_returns_nullptr_error(self, XAnnot, XPtrAnnot, XAnnotRegex):
539*a65addddSAndroid Build Coastguard Worker        source = '''
540*a65addddSAndroid Build Coastguard Worker            struct X {};
541*a65addddSAndroid Build Coastguard Worker
542*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
543*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
544*a65addddSAndroid Build Coastguard Worker                  .addMultibindingProvider<XPtrAnnot()>([](){return (X*)nullptr;});
545*a65addddSAndroid Build Coastguard Worker            }
546*a65addddSAndroid Build Coastguard Worker
547*a65addddSAndroid Build Coastguard Worker            int main() {
548*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent);
549*a65addddSAndroid Build Coastguard Worker              injector.getMultibindings<XAnnot>();
550*a65addddSAndroid Build Coastguard Worker            }
551*a65addddSAndroid Build Coastguard Worker            '''
552*a65addddSAndroid Build Coastguard Worker        expect_runtime_error(
553*a65addddSAndroid Build Coastguard Worker            'Fatal injection error: attempting to get an instance for the type XAnnotRegex but the provider returned nullptr',
554*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
555*a65addddSAndroid Build Coastguard Worker            source,
556*a65addddSAndroid Build Coastguard Worker            locals())
557*a65addddSAndroid Build Coastguard Worker
558*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__':
559*a65addddSAndroid Build Coastguard Worker    absltest.main()
560