xref: /aosp_15_r20/external/google-fruit/tests/test_dependency_loop.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    struct Annotation3 {};
31*a65addddSAndroid Build Coastguard Worker    using XAnnot3 = fruit::Annotated<Annotation3, X>;
32*a65addddSAndroid Build Coastguard Worker    '''
33*a65addddSAndroid Build Coastguard Worker
34*a65addddSAndroid Build Coastguard Workerclass TestDependencyLoop(parameterized.TestCase):
35*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
36*a65addddSAndroid Build Coastguard Worker        ('X', 'const X&', 'Y', 'const Y&'),
37*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, const X&)',
38*a65addddSAndroid Build Coastguard Worker         'fruit::Annotated<Annotation2, Y>', 'ANNOTATED(Annotation2, const Y&)')
39*a65addddSAndroid Build Coastguard Worker    ])
40*a65addddSAndroid Build Coastguard Worker    def test_loop_in_autoinject(self, XAnnot, XConstRefAnnot, YAnnot, YConstRefAnnot):
41*a65addddSAndroid Build Coastguard Worker        source = '''
42*a65addddSAndroid Build Coastguard Worker            struct Y;
43*a65addddSAndroid Build Coastguard Worker
44*a65addddSAndroid Build Coastguard Worker            struct X {
45*a65addddSAndroid Build Coastguard Worker              INJECT(X(YConstRefAnnot)) {};
46*a65addddSAndroid Build Coastguard Worker            };
47*a65addddSAndroid Build Coastguard Worker
48*a65addddSAndroid Build Coastguard Worker            struct Y {
49*a65addddSAndroid Build Coastguard Worker              INJECT(Y(XConstRefAnnot)) {};
50*a65addddSAndroid Build Coastguard Worker            };
51*a65addddSAndroid Build Coastguard Worker
52*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot> mutuallyConstructibleComponent() {
53*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent();
54*a65addddSAndroid Build Coastguard Worker            }
55*a65addddSAndroid Build Coastguard Worker            '''
56*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
57*a65addddSAndroid Build Coastguard Worker            'SelfLoopError<XAnnot,YAnnot>',
58*a65addddSAndroid Build Coastguard Worker            'Found a loop in the dependencies',
59*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
60*a65addddSAndroid Build Coastguard Worker            source,
61*a65addddSAndroid Build Coastguard Worker            locals())
62*a65addddSAndroid Build Coastguard Worker
63*a65addddSAndroid Build Coastguard Worker    @parameterized.parameters([
64*a65addddSAndroid Build Coastguard Worker        ('X', 'const X', 'const X&', 'Y', 'const Y&'),
65*a65addddSAndroid Build Coastguard Worker        ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, const X)', 'ANNOTATED(Annotation1, const X&)',
66*a65addddSAndroid Build Coastguard Worker         'fruit::Annotated<Annotation2, Y>', 'ANNOTATED(Annotation2, const Y&)')
67*a65addddSAndroid Build Coastguard Worker    ])
68*a65addddSAndroid Build Coastguard Worker    def test_loop_in_autoinject_const(self, XAnnot, ConstXAnnot, XConstRefAnnot, YAnnot, YConstRefAnnot):
69*a65addddSAndroid Build Coastguard Worker        source = '''
70*a65addddSAndroid Build Coastguard Worker            struct Y;
71*a65addddSAndroid Build Coastguard Worker
72*a65addddSAndroid Build Coastguard Worker            struct X {
73*a65addddSAndroid Build Coastguard Worker              INJECT(X(YConstRefAnnot)) {};
74*a65addddSAndroid Build Coastguard Worker            };
75*a65addddSAndroid Build Coastguard Worker
76*a65addddSAndroid Build Coastguard Worker            struct Y {
77*a65addddSAndroid Build Coastguard Worker              INJECT(Y(XConstRefAnnot)) {};
78*a65addddSAndroid Build Coastguard Worker            };
79*a65addddSAndroid Build Coastguard Worker
80*a65addddSAndroid Build Coastguard Worker            fruit::Component<ConstXAnnot> mutuallyConstructibleComponent() {
81*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent();
82*a65addddSAndroid Build Coastguard Worker            }
83*a65addddSAndroid Build Coastguard Worker            '''
84*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
85*a65addddSAndroid Build Coastguard Worker            'SelfLoopError<XAnnot,YAnnot>',
86*a65addddSAndroid Build Coastguard Worker            'Found a loop in the dependencies',
87*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
88*a65addddSAndroid Build Coastguard Worker            source,
89*a65addddSAndroid Build Coastguard Worker            locals())
90*a65addddSAndroid Build Coastguard Worker
91*a65addddSAndroid Build Coastguard Worker    def test_loop_in_register_provider(self):
92*a65addddSAndroid Build Coastguard Worker        source = '''
93*a65addddSAndroid Build Coastguard Worker            struct X {};
94*a65addddSAndroid Build Coastguard Worker            struct Y {};
95*a65addddSAndroid Build Coastguard Worker
96*a65addddSAndroid Build Coastguard Worker            fruit::Component<X> mutuallyConstructibleComponent() {
97*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
98*a65addddSAndroid Build Coastguard Worker                  .registerProvider<X(Y)>([](Y) {return X();})
99*a65addddSAndroid Build Coastguard Worker                  .registerProvider<Y(X)>([](X) {return Y();});
100*a65addddSAndroid Build Coastguard Worker            }
101*a65addddSAndroid Build Coastguard Worker            '''
102*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
103*a65addddSAndroid Build Coastguard Worker            'SelfLoopError<X,Y>',
104*a65addddSAndroid Build Coastguard Worker            'Found a loop in the dependencies',
105*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
106*a65addddSAndroid Build Coastguard Worker            source,
107*a65addddSAndroid Build Coastguard Worker            locals())
108*a65addddSAndroid Build Coastguard Worker
109*a65addddSAndroid Build Coastguard Worker    def test_loop_in_register_provider_with_annotations(self):
110*a65addddSAndroid Build Coastguard Worker        source = '''
111*a65addddSAndroid Build Coastguard Worker            struct X {};
112*a65addddSAndroid Build Coastguard Worker
113*a65addddSAndroid Build Coastguard Worker            fruit::Component<fruit::Annotated<Annotation1, X>> mutuallyConstructibleComponent() {
114*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
115*a65addddSAndroid Build Coastguard Worker                  .registerProvider<fruit::Annotated<Annotation1, X>(fruit::Annotated<Annotation2, X>)>([](X x) {return x;})
116*a65addddSAndroid Build Coastguard Worker                  .registerProvider<fruit::Annotated<Annotation2, X>(fruit::Annotated<Annotation1, X>)>([](X x) {return x;});
117*a65addddSAndroid Build Coastguard Worker            }
118*a65addddSAndroid Build Coastguard Worker            '''
119*a65addddSAndroid Build Coastguard Worker        expect_compile_error(
120*a65addddSAndroid Build Coastguard Worker            'SelfLoopError<fruit::Annotated<Annotation1, X>, fruit::Annotated<Annotation2, X>>',
121*a65addddSAndroid Build Coastguard Worker            'Found a loop in the dependencies',
122*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
123*a65addddSAndroid Build Coastguard Worker            source,
124*a65addddSAndroid Build Coastguard Worker            locals())
125*a65addddSAndroid Build Coastguard Worker
126*a65addddSAndroid Build Coastguard Worker    def test_with_different_annotations_ok(self):
127*a65addddSAndroid Build Coastguard Worker        source = '''
128*a65addddSAndroid Build Coastguard Worker            struct X {};
129*a65addddSAndroid Build Coastguard Worker
130*a65addddSAndroid Build Coastguard Worker            fruit::Component<XAnnot3> getComponent() {
131*a65addddSAndroid Build Coastguard Worker              return fruit::createComponent()
132*a65addddSAndroid Build Coastguard Worker                  .registerProvider<XAnnot1()>([](){return X();})
133*a65addddSAndroid Build Coastguard Worker                  .registerProvider<XAnnot2(XAnnot1)>([](X x){return x;})
134*a65addddSAndroid Build Coastguard Worker                  .registerProvider<XAnnot3(XAnnot2)>([](X x){return x;});
135*a65addddSAndroid Build Coastguard Worker            }
136*a65addddSAndroid Build Coastguard Worker
137*a65addddSAndroid Build Coastguard Worker            int main() {
138*a65addddSAndroid Build Coastguard Worker              fruit::Injector<XAnnot3> injector(getComponent);
139*a65addddSAndroid Build Coastguard Worker              injector.get<XAnnot3>();
140*a65addddSAndroid Build Coastguard Worker            }
141*a65addddSAndroid Build Coastguard Worker            '''
142*a65addddSAndroid Build Coastguard Worker        expect_success(
143*a65addddSAndroid Build Coastguard Worker            COMMON_DEFINITIONS,
144*a65addddSAndroid Build Coastguard Worker            source)
145*a65addddSAndroid Build Coastguard Worker
146*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__':
147*a65addddSAndroid Build Coastguard Worker    absltest.main()
148