blob: 1c3ec7572013460e6d2b8a5b43c1333c84548a2f [file] [log] [blame]
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001#!/usr/bin/env python3
2# Copyright 2016 Google Inc. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS-IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
Marco Poletti4ded6e22019-07-20 19:21:21 -070016from absl.testing import parameterized
Marco Polettif9b2c6f2016-10-08 18:49:04 +010017from fruit_test_common import *
18
Marco Poletti21111b02016-11-12 10:49:02 +000019COMMON_DEFINITIONS = '''
Marco Polettif05259d2016-12-22 16:33:41 +010020 #include "test_common.h"
Marco Poletti83b1ad82016-11-12 11:24:51 +000021
Marco Poletti5e64bc62016-11-19 19:46:09 +000022 struct X;
23
Marco Polettif2962772016-11-19 18:49:46 +000024 struct Annotation1 {};
Marco Poletti5e64bc62016-11-19 19:46:09 +000025 using XAnnot1 = fruit::Annotated<Annotation1, X>;
26
Marco Polettif2962772016-11-19 18:49:46 +000027 struct Annotation2 {};
Marco Poletti5e64bc62016-11-19 19:46:09 +000028 using XAnnot2 = fruit::Annotated<Annotation2, X>;
29
Marco Polettif2962772016-11-19 18:49:46 +000030 struct Annotation3 {};
Marco Poletti5e64bc62016-11-19 19:46:09 +000031 using XAnnot3 = fruit::Annotated<Annotation3, X>;
Marco Polettif2962772016-11-19 18:49:46 +000032 '''
Marco Poletti21111b02016-11-12 10:49:02 +000033
Marco Poletti4ded6e22019-07-20 19:21:21 -070034class TestDependencyLoop(parameterized.TestCase):
35 @parameterized.parameters([
36 ('X', 'const X&', 'Y', 'const Y&'),
37 ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, const X&)',
38 'fruit::Annotated<Annotation2, Y>', 'ANNOTATED(Annotation2, const Y&)')
39 ])
40 def test_loop_in_autoinject(self, XAnnot, XConstRefAnnot, YAnnot, YConstRefAnnot):
41 source = '''
42 struct Y;
43
44 struct X {
45 INJECT(X(YConstRefAnnot)) {};
46 };
47
48 struct Y {
49 INJECT(Y(XConstRefAnnot)) {};
50 };
51
52 fruit::Component<XAnnot> mutuallyConstructibleComponent() {
53 return fruit::createComponent();
54 }
55 '''
56 expect_compile_error(
57 'SelfLoopError<XAnnot,YAnnot>',
58 'Found a loop in the dependencies',
59 COMMON_DEFINITIONS,
60 source,
61 locals())
Marco Polettif2962772016-11-19 18:49:46 +000062
Marco Poletti4ded6e22019-07-20 19:21:21 -070063 @parameterized.parameters([
64 ('X', 'const X', 'const X&', 'Y', 'const Y&'),
65 ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, const X)', 'ANNOTATED(Annotation1, const X&)',
66 'fruit::Annotated<Annotation2, Y>', 'ANNOTATED(Annotation2, const Y&)')
67 ])
68 def test_loop_in_autoinject_const(self, XAnnot, ConstXAnnot, XConstRefAnnot, YAnnot, YConstRefAnnot):
69 source = '''
70 struct Y;
71
72 struct X {
73 INJECT(X(YConstRefAnnot)) {};
74 };
75
76 struct Y {
77 INJECT(Y(XConstRefAnnot)) {};
78 };
79
80 fruit::Component<ConstXAnnot> mutuallyConstructibleComponent() {
81 return fruit::createComponent();
82 }
83 '''
84 expect_compile_error(
85 'SelfLoopError<XAnnot,YAnnot>',
86 'Found a loop in the dependencies',
87 COMMON_DEFINITIONS,
88 source,
89 locals())
Marco Polettif2962772016-11-19 18:49:46 +000090
Marco Poletti4ded6e22019-07-20 19:21:21 -070091 def test_loop_in_register_provider(self):
92 source = '''
93 struct X {};
94 struct Y {};
95
96 fruit::Component<X> mutuallyConstructibleComponent() {
97 return fruit::createComponent()
98 .registerProvider<X(Y)>([](Y) {return X();})
99 .registerProvider<Y(X)>([](X) {return Y();});
100 }
101 '''
102 expect_compile_error(
103 'SelfLoopError<X,Y>',
104 'Found a loop in the dependencies',
105 COMMON_DEFINITIONS,
106 source,
107 locals())
Marco Polettif2962772016-11-19 18:49:46 +0000108
Marco Poletti4ded6e22019-07-20 19:21:21 -0700109 def test_loop_in_register_provider_with_annotations(self):
110 source = '''
111 struct X {};
112
113 fruit::Component<fruit::Annotated<Annotation1, X>> mutuallyConstructibleComponent() {
114 return fruit::createComponent()
115 .registerProvider<fruit::Annotated<Annotation1, X>(fruit::Annotated<Annotation2, X>)>([](X x) {return x;})
116 .registerProvider<fruit::Annotated<Annotation2, X>(fruit::Annotated<Annotation1, X>)>([](X x) {return x;});
117 }
118 '''
119 expect_compile_error(
120 'SelfLoopError<fruit::Annotated<Annotation1, X>, fruit::Annotated<Annotation2, X>>',
121 'Found a loop in the dependencies',
122 COMMON_DEFINITIONS,
123 source,
124 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100125
Marco Poletti4ded6e22019-07-20 19:21:21 -0700126 def test_with_different_annotations_ok(self):
127 source = '''
128 struct X {};
129
130 fruit::Component<XAnnot3> getComponent() {
131 return fruit::createComponent()
132 .registerProvider<XAnnot1()>([](){return X();})
133 .registerProvider<XAnnot2(XAnnot1)>([](X x){return x;})
134 .registerProvider<XAnnot3(XAnnot2)>([](X x){return x;});
135 }
136
137 int main() {
138 fruit::Injector<XAnnot3> injector(getComponent);
139 injector.get<XAnnot3>();
140 }
141 '''
142 expect_success(
143 COMMON_DEFINITIONS,
144 source)
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100145
Marco Poletti5dba7172019-04-27 10:06:30 +0100146if __name__ == '__main__':
Marco Poletti4ded6e22019-07-20 19:21:21 -0700147 absltest.main()