• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/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
16from absl.testing import parameterized
17from fruit_test_common import *
18
19COMMON_DEFINITIONS = '''
20    #include "test_common.h"
21
22    struct X;
23
24    struct Annotation1 {};
25    using XAnnot1 = fruit::Annotated<Annotation1, X>;
26    '''
27
28class TestInstallComponentFunctions(parameterized.TestCase):
29    def test_install_component_functions_deduped_against_previous_install_no_args(self):
30        source = '''
31            int num_executions = 0;
32
33            fruit::Component<int> getChildComponent() {
34              static int n = 5;
35              ++num_executions;
36              return fruit::createComponent()
37                  .bindInstance(n);
38            }
39
40            fruit::Component<> getMiddleComponent() {
41              return fruit::createComponent()
42                  .install(getChildComponent);
43            }
44
45            fruit::Component<int> getMainComponent() {
46              return fruit::createComponent()
47                  .install(getMiddleComponent)
48                  .installComponentFunctions(fruit::componentFunction(getChildComponent));
49            }
50
51            int main() {
52              fruit::Injector<int> injector(getMainComponent);
53              int n = injector.get<int>();
54              Assert(n == 5);
55              Assert(num_executions == 1);
56            }
57            '''
58        expect_success(
59            COMMON_DEFINITIONS,
60            source,
61            locals())
62
63    def test_install_component_functions_deduped_against_following_install_no_args(self):
64        source = '''
65            int num_executions = 0;
66
67            fruit::Component<int> getChildComponent() {
68              static int n = 5;
69              ++num_executions;
70              return fruit::createComponent()
71                  .bindInstance(n);
72            }
73
74            fruit::Component<> getMiddleComponent() {
75              return fruit::createComponent()
76                  .installComponentFunctions(fruit::componentFunction(getChildComponent));
77            }
78
79            fruit::Component<int> getMainComponent() {
80              return fruit::createComponent()
81                  .install(getMiddleComponent)
82                  .install(getChildComponent);
83            }
84
85            int main() {
86              fruit::Injector<int> injector(getMainComponent);
87              int n = injector.get<int>();
88              Assert(n == 5);
89              Assert(num_executions == 1);
90            }
91            '''
92        expect_success(
93            COMMON_DEFINITIONS,
94            source,
95            locals())
96
97    def test_install_component_functions_deduped_against_previous_install_with_args(self):
98        source = '''
99            int num_executions = 0;
100
101            fruit::Component<int> getChildComponent(int) {
102              static int n = 5;
103              ++num_executions;
104              return fruit::createComponent()
105                  .bindInstance(n);
106            }
107
108            fruit::Component<> getMiddleComponent() {
109              return fruit::createComponent()
110                  .install(getChildComponent, 42);
111            }
112
113            fruit::Component<int> getMainComponent() {
114              return fruit::createComponent()
115                  .install(getMiddleComponent)
116                  .installComponentFunctions(fruit::componentFunction(getChildComponent, 42));
117            }
118
119            int main() {
120              fruit::Injector<int> injector(getMainComponent);
121              int n = injector.get<int>();
122              Assert(n == 5);
123              Assert(num_executions == 1);
124            }
125            '''
126        expect_success(
127            COMMON_DEFINITIONS,
128            source,
129            locals())
130
131    def test_install_component_functions_deduped_against_following_install_with_args(self):
132        source = '''
133            int num_executions = 0;
134
135            fruit::Component<int> getChildComponent(int) {
136              static int n = 5;
137              ++num_executions;
138              return fruit::createComponent()
139                  .bindInstance(n);
140            }
141
142            fruit::Component<> getMiddleComponent() {
143              return fruit::createComponent()
144                  .installComponentFunctions(fruit::componentFunction(getChildComponent, 42));
145            }
146
147            fruit::Component<int> getMainComponent() {
148              return fruit::createComponent()
149                  .install(getMiddleComponent)
150                  .install(getChildComponent, 42);
151            }
152
153            int main() {
154              fruit::Injector<int> injector(getMainComponent);
155              int n = injector.get<int>();
156              Assert(n == 5);
157              Assert(num_executions == 1);
158            }
159            '''
160        expect_success(
161            COMMON_DEFINITIONS,
162            source,
163            locals())
164
165    def test_install_component_functions_same_as_with_previous_install_with_different_args(self):
166        source = '''
167            int num_executions = 0;
168
169            fruit::Component<int> getChildComponent(int) {
170              static int n = 5;
171              ++num_executions;
172              return fruit::createComponent()
173                  .bindInstance(n);
174            }
175
176            fruit::Component<> getMiddleComponent() {
177              return fruit::createComponent()
178                  .install(getChildComponent, 42);
179            }
180
181            fruit::Component<int> getMainComponent() {
182              return fruit::createComponent()
183                  .install(getMiddleComponent)
184                  .installComponentFunctions(fruit::componentFunction(getChildComponent, 2));
185            }
186
187            int main() {
188              fruit::Injector<int> injector(getMainComponent);
189              int n = injector.get<int>();
190              Assert(n == 5);
191              Assert(num_executions == 2);
192            }
193            '''
194        expect_success(
195            COMMON_DEFINITIONS,
196            source,
197            locals())
198
199    def test_install_component_functions_same_as_following_install_with_different_args(self):
200        source = '''
201            int num_executions = 0;
202
203            fruit::Component<int> getChildComponent(int) {
204              static int n = 5;
205              ++num_executions;
206              return fruit::createComponent()
207                  .bindInstance(n);
208            }
209
210            fruit::Component<> getMiddleComponent() {
211              return fruit::createComponent()
212                  .installComponentFunctions(fruit::componentFunction(getChildComponent, 42));
213            }
214
215            fruit::Component<int> getMainComponent() {
216              return fruit::createComponent()
217                  .install(getMiddleComponent)
218                  .install(getChildComponent, 2);
219            }
220
221            int main() {
222              fruit::Injector<int> injector(getMainComponent);
223              (void)injector;
224              Assert(num_executions == 2);
225            }
226            '''
227        expect_success(
228            COMMON_DEFINITIONS,
229            source,
230            locals())
231
232    def test_install_component_functions_no_component_functions(self):
233        source = '''
234            fruit::Component<> getComponent() {
235              return fruit::createComponent()
236                .installComponentFunctions();
237            }
238
239            int main() {
240              fruit::Injector<> injector(getComponent);
241              (void)injector;
242            }
243            '''
244        expect_success(COMMON_DEFINITIONS, source)
245
246    def test_install_component_functions_one_component_function(self):
247        source = '''
248            struct X {
249              int n;
250              X(int n) : n(n) {}
251            };
252
253            fruit::Component<X> getParentComponent(std::string) {
254              return fruit::createComponent()
255                .registerProvider([]() { return X(5); });
256            }
257
258            fruit::Component<X> getComponent() {
259              return fruit::createComponent()
260                .installComponentFunctions(fruit::componentFunction(getParentComponent, std::string("Hello")));
261            }
262
263            int main() {
264              fruit::Injector<X> injector(getComponent);
265              X x = injector.get<X>();
266              Assert(x.n == 5);
267            }
268            '''
269        expect_success(COMMON_DEFINITIONS, source)
270
271    def test_install_component_functions_two_component_functions(self):
272        source = '''
273            struct X {
274              int n;
275              X(int n) : n(n) {}
276            };
277
278            struct Y {
279              int n;
280              Y(int n) : n(n) {}
281            };
282
283            fruit::Component<X> getParentComponent1(std::string) {
284              return fruit::createComponent()
285                .registerProvider([]() { return X(5); });
286            }
287
288            fruit::Component<Y> getParentComponent2(std::string) {
289              return fruit::createComponent()
290                  .registerProvider([]() { return Y(42); });
291            }
292
293            fruit::Component<X, Y> getComponent() {
294              return fruit::createComponent()
295                  .installComponentFunctions(
296                      fruit::componentFunction(getParentComponent1, std::string("Hello")),
297                      fruit::componentFunction(getParentComponent2, std::string("World")));
298            }
299
300            int main() {
301              fruit::Injector<X, Y> injector(getComponent);
302              X x = injector.get<X>();
303              Y y = injector.get<Y>();
304              Assert(x.n == 5);
305              Assert(y.n == 42);
306            }
307            '''
308        expect_success(COMMON_DEFINITIONS, source)
309
310    def test_install_component_functions_with_template_parameter_pack_unpacking(self):
311        source = '''
312            template <typename T>
313            struct GetComponentHolder;
314
315            struct X {
316              int n;
317              X(int n) : n(n) {}
318            };
319
320            struct Y {
321              int n;
322              Y(int n) : n(n) {}
323            };
324
325            template <>
326            struct GetComponentHolder<X> {
327                static fruit::Component<X> getComponent(std::string) {
328                  return fruit::createComponent()
329                    .registerProvider([]() { return X(5); });
330                }
331            };
332
333            template <>
334            struct GetComponentHolder<Y> {
335                static fruit::Component<Y> getComponent(std::string) {
336                  return fruit::createComponent()
337                      .registerProvider([]() { return Y(42); });
338                }
339            };
340
341            template <typename... Ts>
342            fruit::Component<Ts...> getComponent() {
343              return fruit::createComponent()
344                  .installComponentFunctions(
345                      fruit::componentFunction(GetComponentHolder<Ts>::getComponent, std::string("Hello"))...);
346            }
347
348            int main() {
349              fruit::Injector<X, Y> injector(getComponent<X, Y>);
350              X x = injector.get<X>();
351              Y y = injector.get<Y>();
352              Assert(x.n == 5);
353              Assert(y.n == 42);
354            }
355            '''
356        expect_success(COMMON_DEFINITIONS, source)
357
358    def test_install_component_functions_wrong_argument_type(self):
359        source = '''
360            fruit::Component<> getMainComponent() {
361              return fruit::createComponent()
362                  .installComponentFunctions(42);
363            }
364            '''
365        expect_compile_error(
366            'IncorrectArgTypePassedToInstallComponentFuntionsError<int>',
367            'All arguments passed to installComponentFunctions.. must be fruit::ComponentFunction<...> objects but an '
368            'argument with type Arg was passed instead.',
369            COMMON_DEFINITIONS,
370            source,
371            locals())
372
373if __name__ == '__main__':
374    absltest.main()
375