xref: /aosp_15_r20/external/google-fruit/tests/test_multibindings_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 Workerimport pytest
16*a65addddSAndroid Build Coastguard Workerfrom absl.testing import parameterized
17*a65addddSAndroid Build Coastguard Workerfrom fruit_test_common import *
18*a65addddSAndroid Build Coastguard Workerfrom fruit_test_config import CXX_COMPILER_NAME
19*a65addddSAndroid Build Coastguard Workerimport re
20*a65addddSAndroid Build Coastguard Worker
21*a65addddSAndroid Build Coastguard WorkerCOMMON_DEFINITIONS = '''
22*a65addddSAndroid Build Coastguard Worker    #include "test_common.h"
23*a65addddSAndroid Build Coastguard Worker
24*a65addddSAndroid Build Coastguard Worker    struct Annotation {};
25*a65addddSAndroid Build Coastguard Worker    struct Annotation1 {};
26*a65addddSAndroid Build Coastguard Worker    struct Annotation2 {};
27*a65addddSAndroid Build Coastguard Worker    '''
28*a65addddSAndroid Build Coastguard Worker
29*a65addddSAndroid Build Coastguard Workerclass TestMultibindingsBindInterface(parameterized.TestCase):
30*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
31*a65addddSAndroid Build Coastguard Worker        ('X', 'XImpl'),
32*a65addddSAndroid Build Coastguard Worker        ('X', 'fruit::Annotated<Annotation2, XImpl>'),
33*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'XImpl'),
34*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, XImpl>'),
35*a65addddSAndroid Build Coastguard Worker    ])
36*a65addddSAndroid Build Coastguard Worker    def test_add_interface_multibinding_success(self, XAnnot, XImplAnnot):
37*a65addddSAndroid Build Coastguard Worker        source = '''
38*a65addddSAndroid Build Coastguard Worker            struct X {
39*a65addddSAndroid Build Coastguard Worker              virtual int foo() = 0;
40*a65addddSAndroid Build Coastguard Worker            };
41*a65addddSAndroid Build Coastguard Worker
42*a65addddSAndroid Build Coastguard Worker            struct XImpl : public X {
43*a65addddSAndroid Build Coastguard Worker              INJECT(XImpl()) = default;
44*a65addddSAndroid Build Coastguard Worker
45*a65addddSAndroid Build Coastguard Worker              int foo() override {
46*a65addddSAndroid Build Coastguard Worker                return 5;
47*a65addddSAndroid Build Coastguard Worker              }
48*a65addddSAndroid Build Coastguard Worker            };
49*a65addddSAndroid Build Coastguard Worker
50*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
51*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
52*a65addddSAndroid Build Coastguard Worker                .addMultibinding<XAnnot, XImplAnnot>();
53*a65addddSAndroid Build Coastguard Worker            }
54*a65addddSAndroid Build Coastguard Worker
55*a65addddSAndroid Build Coastguard Worker            int main() {
56*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(getComponent);
57*a65addddSAndroid Build Coastguard Worker
58*a65addddSAndroid Build Coastguard Worker              std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
59*a65addddSAndroid Build Coastguard Worker              Assert(multibindings.size() == 1);
60*a65addddSAndroid Build Coastguard Worker              Assert(multibindings[0]->foo() == 5);
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', 'XImpl', 'const XImpl'),
70*a65addddSAndroid Build Coastguard Worker        ('X', 'fruit::Annotated<Annotation2, XImpl>', 'fruit::Annotated<Annotation2, const XImpl>'),
71*a65addddSAndroid Build Coastguard Worker    ])
72*a65addddSAndroid Build Coastguard Worker    def test_add_interface_multibinding_const_target_error_install_first(self, XAnnot, XImplAnnot, ConstXImplAnnot):
73*a65addddSAndroid Build Coastguard Worker        source = '''
74*a65addddSAndroid Build Coastguard Worker            struct X {
75*a65addddSAndroid Build Coastguard Worker              virtual int foo() = 0;
76*a65addddSAndroid Build Coastguard Worker            };
77*a65addddSAndroid Build Coastguard Worker
78*a65addddSAndroid Build Coastguard Worker            struct XImpl : public X {
79*a65addddSAndroid Build Coastguard Worker              int foo() override {
80*a65addddSAndroid Build Coastguard Worker                return 5;
81*a65addddSAndroid Build Coastguard Worker              }
82*a65addddSAndroid Build Coastguard Worker            };
83*a65addddSAndroid Build Coastguard Worker
84*a65addddSAndroid Build Coastguard Worker            fruit::Component<ConstXImplAnnot> getXImplComponent();
85*a65addddSAndroid Build Coastguard Worker
86*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
87*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
88*a65addddSAndroid Build Coastguard Worker                .install(getXImplComponent)
89*a65addddSAndroid Build Coastguard Worker                .addMultibinding<XAnnot, XImplAnnot>();
90*a65addddSAndroid Build Coastguard Worker            }
91*a65addddSAndroid Build Coastguard Worker            '''
92*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
93*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<XImplAnnot>',
94*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
95*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
96*a65addddSAndroid Build Coastguard Worker            source,
97*a65addddSAndroid Build Coastguard Worker            locals())
98*a65addddSAndroid Build Coastguard Worker
99*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
100*a65addddSAndroid Build Coastguard Worker        ('X', 'XImpl', 'const XImpl'),
101*a65addddSAndroid Build Coastguard Worker        ('X', 'fruit::Annotated<Annotation2, XImpl>', 'fruit::Annotated<Annotation2, const XImpl>'),
102*a65addddSAndroid Build Coastguard Worker    ])
103*a65addddSAndroid Build Coastguard Worker    def test_add_interface_multibinding_const_target_error_binding_first(self, XAnnot, XImplAnnot, ConstXImplAnnot):
104*a65addddSAndroid Build Coastguard Worker        source = '''
105*a65addddSAndroid Build Coastguard Worker            struct X {
106*a65addddSAndroid Build Coastguard Worker              virtual int foo() = 0;
107*a65addddSAndroid Build Coastguard Worker            };
108*a65addddSAndroid Build Coastguard Worker
109*a65addddSAndroid Build Coastguard Worker            struct XImpl : public X {
110*a65addddSAndroid Build Coastguard Worker              int foo() override {
111*a65addddSAndroid Build Coastguard Worker                return 5;
112*a65addddSAndroid Build Coastguard Worker              }
113*a65addddSAndroid Build Coastguard Worker            };
114*a65addddSAndroid Build Coastguard Worker
115*a65addddSAndroid Build Coastguard Worker            fruit::Component<ConstXImplAnnot> getXImplComponent();
116*a65addddSAndroid Build Coastguard Worker
117*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
118*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
119*a65addddSAndroid Build Coastguard Worker                .addMultibinding<XAnnot, XImplAnnot>()
120*a65addddSAndroid Build Coastguard Worker                .install(getXImplComponent);
121*a65addddSAndroid Build Coastguard Worker            }
122*a65addddSAndroid Build Coastguard Worker            '''
123*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
124*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<XImplAnnot>',
125*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
126*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
127*a65addddSAndroid Build Coastguard Worker            source,
128*a65addddSAndroid Build Coastguard Worker            locals())
129*a65addddSAndroid Build Coastguard Worker
130*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
131*a65addddSAndroid Build Coastguard Worker        ('X', 'int'),
132*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, int>'),
133*a65addddSAndroid Build Coastguard Worker    ])
134*a65addddSAndroid Build Coastguard Worker    def test_error_not_base(self, XAnnot, intAnnot):
135*a65addddSAndroid Build Coastguard Worker        source = '''
136*a65addddSAndroid Build Coastguard Worker            struct X {};
137*a65addddSAndroid Build Coastguard Worker
138*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
139*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
140*a65addddSAndroid Build Coastguard Worker                .addMultibinding<XAnnot, intAnnot>();
141*a65addddSAndroid Build Coastguard Worker            }
142*a65addddSAndroid Build Coastguard Worker            '''
143*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
144*a65addddSAndroid Build Coastguard Worker            'NotABaseClassOfError<X,int>',
145*a65addddSAndroid Build Coastguard Worker            'I is not a base class of C.',
146*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
147*a65addddSAndroid Build Coastguard Worker            source,
148*a65addddSAndroid Build Coastguard Worker            locals())
149*a65addddSAndroid Build Coastguard Worker
150*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
151*a65addddSAndroid Build Coastguard Worker        ('Scaler', 'ScalerImpl'),
152*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, Scaler>', 'fruit::Annotated<Annotation2, ScalerImpl>'),
153*a65addddSAndroid Build Coastguard Worker    ])
154*a65addddSAndroid Build Coastguard Worker    def test_error_abstract_class(self, ScalerAnnot, ScalerImplAnnot):
155*a65addddSAndroid Build Coastguard Worker        source = '''
156*a65addddSAndroid Build Coastguard Worker            struct Scaler {
157*a65addddSAndroid Build Coastguard Worker              virtual double scale(double x) = 0;
158*a65addddSAndroid Build Coastguard Worker            };
159*a65addddSAndroid Build Coastguard Worker
160*a65addddSAndroid Build Coastguard Worker            struct ScalerImpl : public Scaler {
161*a65addddSAndroid Build Coastguard Worker              // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class.
162*a65addddSAndroid Build Coastguard Worker            };
163*a65addddSAndroid Build Coastguard Worker
164*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getComponent() {
165*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
166*a65addddSAndroid Build Coastguard Worker                .addMultibinding<ScalerAnnot, ScalerImplAnnot>();
167*a65addddSAndroid Build Coastguard Worker            }
168*a65addddSAndroid Build Coastguard Worker            '''
169*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
170*a65addddSAndroid Build Coastguard Worker            'NoBindingFoundForAbstractClassError<ScalerImplAnnot,ScalerImpl>',
171*a65addddSAndroid Build Coastguard Worker            'No explicit binding was found for T, and note that C is an abstract class',
172*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
173*a65addddSAndroid Build Coastguard Worker            source,
174*a65addddSAndroid Build Coastguard Worker            locals())
175*a65addddSAndroid Build Coastguard Worker
176*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
177*a65addddSAndroid Build Coastguard Worker        ('Scaler', 'ScalerImpl'),
178*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, Scaler>', 'fruit::Annotated<Annotation2, ScalerImpl>'),
179*a65addddSAndroid Build Coastguard Worker    ])
180*a65addddSAndroid Build Coastguard Worker    def test_error_abstract_class_clang(self, ScalerAnnot, ScalerImplAnnot):
181*a65addddSAndroid Build Coastguard Worker        if re.search('Clang', CXX_COMPILER_NAME) is None:
182*a65addddSAndroid Build Coastguard Worker            # This is Clang-only because GCC >=4.9 refuses to even mention the type C() when C is an abstract class,
183*a65addddSAndroid Build Coastguard Worker            # while Clang allows to mention the type (but of course there can be no functions with this type)
184*a65addddSAndroid Build Coastguard Worker            return
185*a65addddSAndroid Build Coastguard Worker        source = '''
186*a65addddSAndroid Build Coastguard Worker            struct Scaler {
187*a65addddSAndroid Build Coastguard Worker              virtual double scale(double x) = 0;
188*a65addddSAndroid Build Coastguard Worker            };
189*a65addddSAndroid Build Coastguard Worker
190*a65addddSAndroid Build Coastguard Worker            struct ScalerImpl : public Scaler {
191*a65addddSAndroid Build Coastguard Worker              INJECT(ScalerImpl()) = default;
192*a65addddSAndroid Build Coastguard Worker
193*a65addddSAndroid Build Coastguard Worker              // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class.
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                .addMultibinding<ScalerAnnot, ScalerImplAnnot>();
199*a65addddSAndroid Build Coastguard Worker            }
200*a65addddSAndroid Build Coastguard Worker            '''
201*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
202*a65addddSAndroid Build Coastguard Worker            'CannotConstructAbstractClassError<ScalerImpl>',
203*a65addddSAndroid Build Coastguard Worker            'The specified class can.t be constructed because it.s an abstract class.',
204*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
205*a65addddSAndroid Build Coastguard Worker            source,
206*a65addddSAndroid Build Coastguard Worker            locals())
207*a65addddSAndroid Build Coastguard Worker
208*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__':
209*a65addddSAndroid Build Coastguard Worker    absltest.main()
210