xref: /aosp_15_r20/external/google-fruit/tests/test_normalized_component.py (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
1*a65addddSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*a65addddSAndroid Build Coastguard Worker#  Copyright 2016 Google Inc. All Rights Reserved.
3*a65addddSAndroid Build Coastguard Worker#
4*a65addddSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker#
8*a65addddSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker#
10*a65addddSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS-IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker# limitations under the License.
15*a65addddSAndroid Build Coastguard Worker
16*a65addddSAndroid Build Coastguard Workerfrom absl.testing import parameterized
17*a65addddSAndroid Build Coastguard Workerfrom fruit_test_common import *
18*a65addddSAndroid Build Coastguard Worker
19*a65addddSAndroid Build Coastguard WorkerCOMMON_DEFINITIONS = '''
20*a65addddSAndroid Build Coastguard Worker    #include "test_common.h"
21*a65addddSAndroid Build Coastguard Worker
22*a65addddSAndroid Build Coastguard Worker    struct X;
23*a65addddSAndroid Build Coastguard Worker
24*a65addddSAndroid Build Coastguard Worker    struct Annotation1 {};
25*a65addddSAndroid Build Coastguard Worker    using XAnnot1 = fruit::Annotated<Annotation1, X>;
26*a65addddSAndroid Build Coastguard Worker
27*a65addddSAndroid Build Coastguard Worker    struct Annotation2 {};
28*a65addddSAndroid Build Coastguard Worker    using XAnnot2 = fruit::Annotated<Annotation2, X>;
29*a65addddSAndroid Build Coastguard Worker    '''
30*a65addddSAndroid Build Coastguard Worker
31*a65addddSAndroid Build Coastguard Workerclass TestNormalizedComponent(parameterized.TestCase):
32*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
33*a65addddSAndroid Build Coastguard Worker        ('X', 'X', 'Y'),
34*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, X)', 'fruit::Annotated<Annotation2, Y>'),
35*a65addddSAndroid Build Coastguard Worker    ])
36*a65addddSAndroid Build Coastguard Worker    def test_success_normalized_component_provides_unused(self, XAnnot, X_ANNOT, YAnnot):
37*a65addddSAndroid Build Coastguard Worker        source = '''
38*a65addddSAndroid Build Coastguard Worker            struct X {};
39*a65addddSAndroid Build Coastguard Worker
40*a65addddSAndroid Build Coastguard Worker            struct Y {
41*a65addddSAndroid Build Coastguard Worker              INJECT(Y(X_ANNOT)) {};
42*a65addddSAndroid Build Coastguard Worker            };
43*a65addddSAndroid Build Coastguard Worker
44*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<XAnnot>, YAnnot> getComponent() {
45*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent();
46*a65addddSAndroid Build Coastguard Worker            }
47*a65addddSAndroid Build Coastguard Worker
48*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getXComponent(X* x) {
49*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
50*a65addddSAndroid Build Coastguard Worker                .bindInstance<XAnnot, X>(*x);
51*a65addddSAndroid Build Coastguard Worker            }
52*a65addddSAndroid Build Coastguard Worker
53*a65addddSAndroid Build Coastguard Worker            int main() {
54*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<fruit::Required<XAnnot>, YAnnot> normalizedComponent(getComponent);
55*a65addddSAndroid Build Coastguard Worker
56*a65addddSAndroid Build Coastguard Worker              X x{};
57*a65addddSAndroid Build Coastguard Worker
58*a65addddSAndroid Build Coastguard Worker              fruit::Injector<XAnnot> injector(normalizedComponent, getXComponent, &x);
59*a65addddSAndroid Build Coastguard Worker              injector.get<XAnnot>();
60*a65addddSAndroid Build Coastguard Worker            }
61*a65addddSAndroid Build Coastguard Worker            '''
62*a65addddSAndroid Build Coastguard Worker        expect_success(
63*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
64*a65addddSAndroid Build Coastguard Worker            source,
65*a65addddSAndroid Build Coastguard Worker            locals())
66*a65addddSAndroid Build Coastguard Worker
67*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
68*a65addddSAndroid Build Coastguard Worker        ('X', 'X', 'Y'),
69*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, X)', 'fruit::Annotated<Annotation2, Y>'),
70*a65addddSAndroid Build Coastguard Worker    ])
71*a65addddSAndroid Build Coastguard Worker    def test_success(self, XAnnot, X_ANNOT, YAnnot):
72*a65addddSAndroid Build Coastguard Worker        source = '''
73*a65addddSAndroid Build Coastguard Worker            struct X {};
74*a65addddSAndroid Build Coastguard Worker
75*a65addddSAndroid Build Coastguard Worker            struct Y {
76*a65addddSAndroid Build Coastguard Worker              INJECT(Y(X_ANNOT)) {};
77*a65addddSAndroid Build Coastguard Worker            };
78*a65addddSAndroid Build Coastguard Worker
79*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<XAnnot>, YAnnot> getComponent() {
80*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent();
81*a65addddSAndroid Build Coastguard Worker            }
82*a65addddSAndroid Build Coastguard Worker
83*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getXComponent(X* x) {
84*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
85*a65addddSAndroid Build Coastguard Worker                .bindInstance<XAnnot, X>(*x);
86*a65addddSAndroid Build Coastguard Worker            }
87*a65addddSAndroid Build Coastguard Worker
88*a65addddSAndroid Build Coastguard Worker            int main() {
89*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<fruit::Required<XAnnot>, YAnnot> normalizedComponent(getComponent);
90*a65addddSAndroid Build Coastguard Worker
91*a65addddSAndroid Build Coastguard Worker              X x{};
92*a65addddSAndroid Build Coastguard Worker
93*a65addddSAndroid Build Coastguard Worker              fruit::Injector<YAnnot> injector(normalizedComponent, getXComponent, &x);
94*a65addddSAndroid Build Coastguard Worker              injector.get<YAnnot>();
95*a65addddSAndroid Build Coastguard Worker            }
96*a65addddSAndroid Build Coastguard Worker            '''
97*a65addddSAndroid Build Coastguard Worker        expect_success(
98*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
99*a65addddSAndroid Build Coastguard Worker            source,
100*a65addddSAndroid Build Coastguard Worker            locals())
101*a65addddSAndroid Build Coastguard Worker
102*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
103*a65addddSAndroid Build Coastguard Worker        ('X', 'X', 'Y'),
104*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, X)', 'fruit::Annotated<Annotation2, Y>'),
105*a65addddSAndroid Build Coastguard Worker    ])
106*a65addddSAndroid Build Coastguard Worker    def test_success_inline_component(self, XAnnot, X_ANNOT, YAnnot):
107*a65addddSAndroid Build Coastguard Worker        source = '''
108*a65addddSAndroid Build Coastguard Worker            struct X {};
109*a65addddSAndroid Build Coastguard Worker
110*a65addddSAndroid Build Coastguard Worker            struct Y {
111*a65addddSAndroid Build Coastguard Worker              INJECT(Y(X_ANNOT)) {};
112*a65addddSAndroid Build Coastguard Worker            };
113*a65addddSAndroid Build Coastguard Worker
114*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<XAnnot>, YAnnot> getComponent() {
115*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent();
116*a65addddSAndroid Build Coastguard Worker            }
117*a65addddSAndroid Build Coastguard Worker
118*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getAdditionalComponent(X* x) {
119*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
120*a65addddSAndroid Build Coastguard Worker                .bindInstance<XAnnot, X>(*x);
121*a65addddSAndroid Build Coastguard Worker            }
122*a65addddSAndroid Build Coastguard Worker
123*a65addddSAndroid Build Coastguard Worker            int main() {
124*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<fruit::Required<XAnnot>, YAnnot> normalizedComponent(getComponent);
125*a65addddSAndroid Build Coastguard Worker
126*a65addddSAndroid Build Coastguard Worker              X x{};
127*a65addddSAndroid Build Coastguard Worker
128*a65addddSAndroid Build Coastguard Worker              fruit::Injector<YAnnot> injector(normalizedComponent, getAdditionalComponent, &x);
129*a65addddSAndroid Build Coastguard Worker              injector.get<YAnnot>();
130*a65addddSAndroid Build Coastguard Worker            }
131*a65addddSAndroid Build Coastguard Worker            '''
132*a65addddSAndroid Build Coastguard Worker        expect_success(
133*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
134*a65addddSAndroid Build Coastguard Worker            source,
135*a65addddSAndroid Build Coastguard Worker            locals())
136*a65addddSAndroid Build Coastguard Worker
137*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
138*a65addddSAndroid Build Coastguard Worker        'X',
139*a65addddSAndroid Build Coastguard Worker        'fruit::Annotated<Annotation1, X>',
140*a65addddSAndroid Build Coastguard Worker    ])
141*a65addddSAndroid Build Coastguard Worker    def test_injector_from_normalized_component_unsatisfied_requirements(self, XAnnot):
142*a65addddSAndroid Build Coastguard Worker        source = '''
143*a65addddSAndroid Build Coastguard Worker            struct X {};
144*a65addddSAndroid Build Coastguard Worker
145*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Required<XAnnot>> getComponent();
146*a65addddSAndroid Build Coastguard Worker            fruit::Component<> getEmptyComponent();
147*a65addddSAndroid Build Coastguard Worker
148*a65addddSAndroid Build Coastguard Worker            int main() {
149*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<fruit::Required<XAnnot>> normalizedComponent(getComponent);
150*a65addddSAndroid Build Coastguard Worker              fruit::Injector<> injector(normalizedComponent, getEmptyComponent);
151*a65addddSAndroid Build Coastguard Worker            }
152*a65addddSAndroid Build Coastguard Worker            '''
153*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
154*a65addddSAndroid Build Coastguard Worker            'UnsatisfiedRequirementsInNormalizedComponentError<XAnnot>',
155*a65addddSAndroid Build Coastguard Worker            'The requirements in UnsatisfiedRequirements are required by the NormalizedComponent but are not provided by the Component',
156*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
157*a65addddSAndroid Build Coastguard Worker            source,
158*a65addddSAndroid Build Coastguard Worker            locals())
159*a65addddSAndroid Build Coastguard Worker
160*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
161*a65addddSAndroid Build Coastguard Worker        ('X', 'const X'),
162*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'),
163*a65addddSAndroid Build Coastguard Worker    ])
164*a65addddSAndroid Build Coastguard Worker    def test_normalized_component_providing_nonconst_from_component_providing_const_error(self, XAnnot, ConstXAnnot):
165*a65addddSAndroid Build Coastguard Worker        source = '''
166*a65addddSAndroid Build Coastguard Worker            struct X {};
167*a65addddSAndroid Build Coastguard Worker
168*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> getComponent();
169*a65addddSAndroid Build Coastguard Worker
170*a65addddSAndroid Build Coastguard Worker            int main() {
171*a65addddSAndroid Build Coastguard Worker              fruit::NormalizedComponent<ConstXAnnot> normalizedComponent(getComponent);
172*a65addddSAndroid Build Coastguard Worker              (void) normalizedComponent;
173*a65addddSAndroid Build Coastguard Worker            }
174*a65addddSAndroid Build Coastguard Worker            '''
175*a65addddSAndroid Build Coastguard Worker        expect_generic_compile_error(
176*a65addddSAndroid Build Coastguard Worker            r'no matching function for call to .fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent\(fruit::Component<XAnnot> \(&\)\(\)\).'
177*a65addddSAndroid Build Coastguard Worker            r'|no matching constructor for initialization of .fruit::NormalizedComponent<ConstXAnnot>.'
178*a65addddSAndroid Build Coastguard Worker            r'|.fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent.: no overloaded function could convert all the argument types'
179*a65addddSAndroid Build Coastguard Worker            r'|.fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent.: none of the .* overloads could convert all the argument types',
180*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
181*a65addddSAndroid Build Coastguard Worker            source,
182*a65addddSAndroid Build Coastguard Worker            locals())
183*a65addddSAndroid Build Coastguard Worker
184*a65addddSAndroid Build Coastguard Worker    # TODO: we should probably return a more specific error here.
185*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
186*a65addddSAndroid Build Coastguard Worker        ('X', 'Y'),
187*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, Y>'),
188*a65addddSAndroid Build Coastguard Worker    ])
189*a65addddSAndroid Build Coastguard Worker    def test_injector_from_normalized_component_nonconst_requirements_provided_as_const_error(self, XAnnot, YAnnot):
190*a65addddSAndroid Build Coastguard Worker        source = '''
191*a65addddSAndroid Build Coastguard Worker            struct X {};
192*a65addddSAndroid Build Coastguard Worker            struct Y {};
193*a65addddSAndroid Build Coastguard Worker
194*a65addddSAndroid Build Coastguard Worker            fruit::Component<const XAnnot> getXComponent();
195*a65addddSAndroid Build Coastguard Worker
196*a65addddSAndroid Build Coastguard Worker            void f(fruit::NormalizedComponent<fruit::Required<XAnnot>, YAnnot> normalizedComponent) {
197*a65addddSAndroid Build Coastguard Worker              fruit::Injector<YAnnot> injector(normalizedComponent, getXComponent);
198*a65addddSAndroid Build Coastguard Worker            }
199*a65addddSAndroid Build Coastguard Worker            '''
200*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
201*a65addddSAndroid Build Coastguard Worker            'NonConstBindingRequiredButConstBindingProvidedError<XAnnot>',
202*a65addddSAndroid Build Coastguard Worker            'The type T was provided as constant, however one of the constructors/providers/factories in this component',
203*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
204*a65addddSAndroid Build Coastguard Worker            source,
205*a65addddSAndroid Build Coastguard Worker            locals())
206*a65addddSAndroid Build Coastguard Worker
207*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__':
208*a65addddSAndroid Build Coastguard Worker    absltest.main()
209