• 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
23class TestComponentFunctions(parameterized.TestCase):
24    def test_component_function_success(self):
25        source = '''
26            struct X {
27              int n;
28              X(int n) : n(n) {}
29            };
30
31            struct Arg {
32              Arg(int) {}
33              Arg() = default;
34              Arg(const Arg&) = default;
35              Arg(Arg&&) = default;
36              Arg& operator=(const Arg&) = default;
37              Arg& operator=(Arg&&) = default;
38            };
39
40            bool operator==(const Arg&, const Arg&) {
41              return true;
42            }
43
44            namespace std {
45              template <>
46              struct hash<Arg> {
47                size_t operator()(const Arg&) {
48                  return 0;
49                }
50              };
51            }
52
53            fruit::Component<X> getParentComponent(int, std::string, Arg, Arg) {
54              return fruit::createComponent()
55                .registerProvider([]() { return X(5); });
56            }
57
58            fruit::Component<X> getComponent() {
59              return fruit::createComponent()
60                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}, 15));
61            }
62
63            int main() {
64              fruit::Injector<X> injector(getComponent);
65              X x = injector.get<X>();
66              Assert(x.n == 5);
67            }
68            '''
69        expect_success(COMMON_DEFINITIONS, source)
70
71    def test_component_function_no_args_success(self):
72        source = '''
73            struct X {
74              int n;
75              X(int n) : n(n) {}
76            };
77
78            fruit::Component<X> getParentComponent() {
79              return fruit::createComponent()
80                .registerProvider([]() { return X(5); });
81            }
82
83            fruit::Component<X> getComponent() {
84              return fruit::createComponent()
85                .installComponentFunctions(fruit::componentFunction(getParentComponent));
86            }
87
88            int main() {
89              fruit::Injector<X> injector(getComponent);
90              X x = injector.get<X>();
91              Assert(x.n == 5);
92            }
93            '''
94        expect_success(COMMON_DEFINITIONS, source)
95
96    def test_component_function_one_arg_success(self):
97        source = '''
98            struct X {
99              int n;
100              X(int n) : n(n) {}
101            };
102
103            fruit::Component<X> getParentComponent(std::string) {
104              return fruit::createComponent()
105                .registerProvider([]() { return X(5); });
106            }
107
108            fruit::Component<X> getComponent() {
109              return fruit::createComponent()
110                .installComponentFunctions(fruit::componentFunction(getParentComponent, std::string("Hello")));
111            }
112
113            int main() {
114              fruit::Injector<X> injector(getComponent);
115              X x = injector.get<X>();
116              Assert(x.n == 5);
117            }
118            '''
119        expect_success(COMMON_DEFINITIONS, source)
120
121    def test_component_function_error_not_move_constructible(self):
122        source = '''
123            struct X {};
124
125            struct Arg {
126              Arg() = default;
127              Arg(const Arg&) = default;
128              Arg(Arg&&) = delete;
129              Arg& operator=(const Arg&) = default;
130              Arg& operator=(Arg&&) = default;
131            };
132
133            bool operator==(const Arg&, const Arg&);
134
135            namespace std {
136              template <>
137              struct hash<Arg> {
138                size_t operator()(const Arg&);
139              };
140            }
141
142            fruit::Component<X> getParentComponent(int, std::string, Arg);
143
144            fruit::Component<X> getComponent() {
145              return fruit::createComponent()
146                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
147            }
148            '''
149        expect_generic_compile_error(
150            r'error: use of deleted function .Arg::Arg\(Arg&&\).'
151            r'|error: call to deleted constructor of .Arg.'
152            r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.'
153            r'|.Arg::Arg\(Arg &&\).: attempting to reference a deleted function',
154            COMMON_DEFINITIONS,
155            source)
156
157    def test_component_function_error_not_move_constructible_with_conversion(self):
158        source = '''
159            struct X {};
160
161            struct Arg {
162              Arg(int) {}
163              Arg() = default;
164              Arg(const Arg&) = default;
165              Arg(Arg&&) = delete;
166              Arg& operator=(const Arg&) = default;
167              Arg& operator=(Arg&&) = default;
168            };
169
170            bool operator==(const Arg&, const Arg&);
171
172            namespace std {
173              template <>
174              struct hash<Arg> {
175                size_t operator()(const Arg&);
176              };
177            }
178
179            fruit::Component<X> getParentComponent(int, std::string, Arg);
180
181            fruit::Component<X> getComponent() {
182              return fruit::createComponent()
183                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
184            }
185            '''
186        expect_generic_compile_error(
187            r'error: use of deleted function .Arg::Arg\(Arg&&\).'
188            r'|error: call to deleted constructor of .Arg.'
189            r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.'
190            r'|error: copying parameter of type .Arg. invokes deleted constructor'
191            r'|error C2280: .Arg::Arg\(Arg &&\).: attempting to reference a deleted function',
192            COMMON_DEFINITIONS,
193            source)
194
195    def test_component_function_error_not_copy_constructible(self):
196        source = '''
197            struct X {
198              int n;
199              X(int n) : n(n) {}
200            };
201
202            struct Arg {
203              Arg() = default;
204              Arg(const Arg&) = delete;
205              Arg(Arg&&) = default;
206              Arg& operator=(const Arg&) = default;
207              Arg& operator=(Arg&&) = default;
208            };
209
210            bool operator==(const Arg&, const Arg&);
211
212            namespace std {
213              template <>
214              struct hash<Arg> {
215                size_t operator()(const Arg&);
216              };
217            }
218
219            fruit::Component<X> getParentComponent(int, std::string, Arg);
220
221            fruit::Component<X> getComponent() {
222              return fruit::createComponent()
223                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
224            }
225            '''
226        expect_generic_compile_error(
227            r'error: use of deleted function .Arg::Arg\(const Arg&\).'
228            r'|error: call to deleted constructor of .Arg.'
229            r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function'
230            # This is the error printed by MSVC. It's not great but I couldn't find a way to have it print
231            # a more useful error.
232            r'|cannot convert argument 1 from .int. to .std::allocator_arg_t.',
233            COMMON_DEFINITIONS,
234            source)
235
236    def test_component_function_error_not_copy_constructible_with_conversion(self):
237        source = '''
238            struct X {
239              int n;
240              X(int n) : n(n) {}
241            };
242
243            struct Arg {
244              Arg(int) {}
245              Arg() = default;
246              Arg(const Arg&) = delete;
247              Arg(Arg&&) = default;
248              Arg& operator=(const Arg&) = default;
249              Arg& operator=(Arg&&) = default;
250            };
251
252            bool operator==(const Arg&, const Arg&);
253
254            namespace std {
255              template <>
256              struct hash<Arg> {
257                size_t operator()(const Arg&);
258              };
259            }
260
261            fruit::Component<X> getParentComponent(int, std::string, Arg);
262
263            fruit::Component<X> getComponent() {
264              return fruit::createComponent()
265                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
266            }
267            '''
268        expect_generic_compile_error(
269            r'error: use of deleted function .Arg::Arg\(const Arg&\).'
270            r'|error: call to deleted constructor of .Arg.'
271            r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function'
272            # This is the error printed by MSVC. It's not great but I couldn't find a way to have it print
273            # a more useful error.
274            r'|cannot convert argument 1 from .int. to .std::allocator_arg_t.',
275            COMMON_DEFINITIONS,
276            source)
277
278    def test_component_function_error_not_move_assignable(self):
279        source = '''
280            struct X {};
281
282            struct Arg {
283              Arg() = default;
284              Arg(const Arg&) = default;
285              Arg(Arg&&) = default;
286              Arg& operator=(const Arg&) = default;
287              Arg& operator=(Arg&&) = delete;
288            };
289
290            bool operator==(const Arg&, const Arg&);
291
292            namespace std {
293              template <>
294              struct hash<Arg> {
295                size_t operator()(const Arg&);
296              };
297            }
298
299            fruit::Component<X> getParentComponent(int, std::string, Arg);
300
301            fruit::Component<X> getComponent() {
302              return fruit::createComponent()
303                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
304            }
305            '''
306        expect_generic_compile_error(
307            r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).'
308            r'|error: overload resolution selected deleted operator .=.'
309            r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function',
310            COMMON_DEFINITIONS,
311            source)
312
313    def test_component_function_error_not_move_assignable_with_conversion(self):
314        source = '''
315            struct X {};
316
317            struct Arg {
318              Arg(int) {}
319              Arg() = default;
320              Arg(const Arg&) = default;
321              Arg(Arg&&) = default;
322              Arg& operator=(const Arg&) = default;
323              Arg& operator=(Arg&&) = delete;
324            };
325
326            bool operator==(const Arg&, const Arg&);
327
328            namespace std {
329              template <>
330              struct hash<Arg> {
331                size_t operator()(const Arg&);
332              };
333            }
334
335            fruit::Component<X> getParentComponent(int, std::string, Arg);
336
337            fruit::Component<X> getComponent() {
338              return fruit::createComponent()
339                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
340            }
341            '''
342        expect_generic_compile_error(
343            r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).'
344            r'|error: overload resolution selected deleted operator .=.'
345            r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function',
346            COMMON_DEFINITIONS,
347            source)
348
349    def test_component_function_error_not_copy_assignable(self):
350        source = '''
351            struct X {
352              int n;
353              X(int n) : n(n) {}
354            };
355
356            struct Arg {
357              Arg() = default;
358              Arg(const Arg&) = default;
359              Arg(Arg&&) = default;
360              Arg& operator=(const Arg&) = delete;
361              Arg& operator=(Arg&&) = default;
362            };
363
364            bool operator==(const Arg&, const Arg&);
365
366            namespace std {
367              template <>
368              struct hash<Arg> {
369                size_t operator()(const Arg&);
370              };
371            }
372
373            fruit::Component<X> getParentComponent(int, std::string, Arg);
374
375            fruit::Component<X> getComponent() {
376              return fruit::createComponent()
377                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
378            }
379            '''
380        expect_generic_compile_error(
381            r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).'
382            r'|error: overload resolution selected deleted operator .=.'
383            r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function',
384            COMMON_DEFINITIONS,
385            source)
386
387    def test_component_function_error_not_copy_assignable_with_conversion(self):
388        source = '''
389            struct X {
390              int n;
391              X(int n) : n(n) {}
392            };
393
394            struct Arg {
395              Arg(int) {}
396              Arg() = default;
397              Arg(const Arg&) = default;
398              Arg(Arg&&) = default;
399              Arg& operator=(const Arg&) = delete;
400              Arg& operator=(Arg&&) = default;
401            };
402
403            bool operator==(const Arg&, const Arg&);
404
405            namespace std {
406              template <>
407              struct hash<Arg> {
408                size_t operator()(const Arg&);
409              };
410            }
411
412            fruit::Component<X> getParentComponent(int, std::string, Arg);
413
414            fruit::Component<X> getComponent() {
415              return fruit::createComponent()
416                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
417            }
418            '''
419        expect_generic_compile_error(
420            r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).'
421            r'|error: overload resolution selected deleted operator .=.'
422            r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function',
423            COMMON_DEFINITIONS,
424            source)
425
426    def test_component_function_error_not_equality_comparable(self):
427        source = '''
428            struct X {
429              int n;
430              X(int n) : n(n) {}
431            };
432
433            struct Arg {
434              Arg() = default;
435              Arg(const Arg&) = default;
436              Arg(Arg&&) = default;
437              Arg& operator=(const Arg&) = default;
438              Arg& operator=(Arg&&) = default;
439            };
440
441            namespace std {
442              template <>
443              struct hash<Arg> {
444                size_t operator()(const Arg&);
445              };
446            }
447
448            fruit::Component<X> getParentComponent(int, std::string, Arg);
449
450            fruit::Component<X> getComponent() {
451              return fruit::createComponent()
452                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
453            }
454            '''
455        expect_generic_compile_error(
456            r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)'
457            r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)'
458            r'|error C2676: binary .==.: .const Arg. does not define this operator',
459            COMMON_DEFINITIONS,
460            source)
461
462    def test_component_function_error_not_equality_comparable_with_conversion(self):
463        source = '''
464            struct X {
465              int n;
466              X(int n) : n(n) {}
467            };
468
469            struct Arg {
470              Arg(int) {}
471              Arg() = default;
472              Arg(const Arg&) = default;
473              Arg(Arg&&) = default;
474              Arg& operator=(const Arg&) = default;
475              Arg& operator=(Arg&&) = default;
476            };
477
478            namespace std {
479              template <>
480              struct hash<Arg> {
481                size_t operator()(const Arg&);
482              };
483            }
484
485            fruit::Component<X> getParentComponent(int, std::string, Arg);
486
487            fruit::Component<X> getComponent() {
488              return fruit::createComponent()
489                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
490            }
491            '''
492        expect_generic_compile_error(
493            r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)'
494            r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)'
495            r'|error C2676: binary .==.: .const Arg. does not define this operator',
496            COMMON_DEFINITIONS,
497            source)
498
499    def test_component_function_error_not_hashable(self):
500        source = '''
501            struct X {};
502
503            struct Arg {
504              Arg() = default;
505              Arg(const Arg&) = default;
506              Arg(Arg&&) = default;
507              Arg& operator=(const Arg&) = default;
508              Arg& operator=(Arg&&) = default;
509            };
510
511            bool operator==(const Arg&, const Arg&);
512
513            fruit::Component<X> getParentComponent(int, std::string, Arg);
514
515            fruit::Component<X> getComponent() {
516              return fruit::createComponent()
517                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
518            }
519            '''
520        expect_generic_compile_error(
521            r'error: use of deleted function .std::hash<Arg>::hash\(\).'
522            r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.'
523            r'|error: invalid use of incomplete type .struct std::hash<Arg>.'
524            r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.'
525            r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.'
526            r'|error C2064: term does not evaluate to a function taking 1 arguments',
527            COMMON_DEFINITIONS,
528            source)
529
530    def test_component_function_error_not_hashable_with_conversion(self):
531        source = '''
532            struct X {};
533
534            struct Arg {
535              Arg(int) {}
536              Arg() = default;
537              Arg(const Arg&) = default;
538              Arg(Arg&&) = default;
539              Arg& operator=(const Arg&) = default;
540              Arg& operator=(Arg&&) = default;
541            };
542
543            bool operator==(const Arg&, const Arg&);
544
545            fruit::Component<X> getParentComponent(int, std::string, Arg);
546
547            fruit::Component<X> getComponent() {
548              return fruit::createComponent()
549                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
550            }
551            '''
552        expect_generic_compile_error(
553            r'error: use of deleted function .std::hash<Arg>::hash\(\).'
554            r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.'
555            r'|error: invalid use of incomplete type .struct std::hash<Arg>.'
556            r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.'
557            r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.'
558            r'|error C2064: term does not evaluate to a function taking 1 arguments',
559            COMMON_DEFINITIONS,
560            source)
561
562if __name__ == '__main__':
563    absltest.main()
564