xref: /aosp_15_r20/external/google-fruit/tests/test_component_functions.py (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
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\(const Arg &\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.'
153            r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.'
154            r'|.Arg::Arg\(Arg &&\).: attempting to reference a deleted function',
155            COMMON_DEFINITIONS,
156            source)
157
158    def test_component_function_error_not_move_constructible_with_conversion(self):
159        source = '''
160            struct X {};
161
162            struct Arg {
163              Arg(int) {}
164              Arg() = default;
165              Arg(const Arg&) = default;
166              Arg(Arg&&) = delete;
167              Arg& operator=(const Arg&) = default;
168              Arg& operator=(Arg&&) = default;
169            };
170
171            bool operator==(const Arg&, const Arg&);
172
173            namespace std {
174              template <>
175              struct hash<Arg> {
176                size_t operator()(const Arg&);
177              };
178            }
179
180            fruit::Component<X> getParentComponent(int, std::string, Arg);
181
182            fruit::Component<X> getComponent() {
183              return fruit::createComponent()
184                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
185            }
186            '''
187        expect_generic_compile_error(
188            r'error: use of deleted function .Arg::Arg\(Arg&&\).'
189            r'|error: call to deleted constructor of .Arg.'
190            r'|.Arg::Arg\((int|Arg &&)\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.'
191            r'|error: copying parameter of type .Arg. invokes deleted constructor'
192            r'|error C2280: .Arg::Arg\(Arg &&\).: attempting to reference a deleted function',
193            COMMON_DEFINITIONS,
194            source)
195
196    def test_component_function_error_not_copy_constructible(self):
197        source = '''
198            struct X {
199              int n;
200              X(int n) : n(n) {}
201            };
202
203            struct Arg {
204              Arg() = default;
205              Arg(const Arg&) = delete;
206              Arg(Arg&&) = default;
207              Arg& operator=(const Arg&) = default;
208              Arg& operator=(Arg&&) = default;
209            };
210
211            bool operator==(const Arg&, const Arg&);
212
213            namespace std {
214              template <>
215              struct hash<Arg> {
216                size_t operator()(const Arg&);
217              };
218            }
219
220            fruit::Component<X> getParentComponent(int, std::string, Arg);
221
222            fruit::Component<X> getComponent() {
223              return fruit::createComponent()
224                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
225            }
226            '''
227        expect_generic_compile_error(
228            r'error: use of deleted function .Arg::Arg\(const Arg&\).'
229            r'|error: call to deleted constructor of .Arg.'
230            r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function'
231            r'|.std::tuple<int,std::string,Arg>::tuple.: no overloaded function takes 3 arguments'
232            # This is the error printed by MSVC. It's not great but I couldn't find a way to have it print
233            # a more useful error.
234            r'|cannot convert argument 1 from .int. to .std::allocator_arg_t.',
235            COMMON_DEFINITIONS,
236            source)
237
238    def test_component_function_error_not_copy_constructible_with_conversion(self):
239        source = '''
240            struct X {
241              int n;
242              X(int n) : n(n) {}
243            };
244
245            struct Arg {
246              Arg(int) {}
247              Arg() = default;
248              Arg(const Arg&) = delete;
249              Arg(Arg&&) = default;
250              Arg& operator=(const Arg&) = default;
251              Arg& operator=(Arg&&) = default;
252            };
253
254            bool operator==(const Arg&, const Arg&);
255
256            namespace std {
257              template <>
258              struct hash<Arg> {
259                size_t operator()(const Arg&);
260              };
261            }
262
263            fruit::Component<X> getParentComponent(int, std::string, Arg);
264
265            fruit::Component<X> getComponent() {
266              return fruit::createComponent()
267                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
268            }
269            '''
270        expect_generic_compile_error(
271            r'error: use of deleted function .Arg::Arg\(const Arg&\).'
272            r'|error: call to deleted constructor of .Arg.'
273            r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function'
274            r'|.std::tuple<int,std::string,Arg>::tuple.: no overloaded function takes 3 arguments'
275            # This is the error printed by MSVC. It's not great but I couldn't find a way to have it print
276            # a more useful error.
277            r'|cannot convert argument 1 from .int. to .std::allocator_arg_t.',
278            COMMON_DEFINITIONS,
279            source)
280
281    def test_component_function_error_not_move_assignable(self):
282        source = '''
283            struct X {};
284
285            struct Arg {
286              Arg() = default;
287              Arg(const Arg&) = default;
288              Arg(Arg&&) = default;
289              Arg& operator=(const Arg&) = default;
290              Arg& operator=(Arg&&) = delete;
291            };
292
293            bool operator==(const Arg&, const Arg&);
294
295            namespace std {
296              template <>
297              struct hash<Arg> {
298                size_t operator()(const Arg&);
299              };
300            }
301
302            fruit::Component<X> getParentComponent(int, std::string, Arg);
303
304            fruit::Component<X> getComponent() {
305              return fruit::createComponent()
306                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
307            }
308            '''
309        expect_generic_compile_error(
310            r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).'
311            r'|error: overload resolution selected deleted operator .=.'
312            r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function',
313            COMMON_DEFINITIONS,
314            source)
315
316    def test_component_function_error_not_move_assignable_with_conversion(self):
317        source = '''
318            struct X {};
319
320            struct Arg {
321              Arg(int) {}
322              Arg() = default;
323              Arg(const Arg&) = default;
324              Arg(Arg&&) = default;
325              Arg& operator=(const Arg&) = default;
326              Arg& operator=(Arg&&) = delete;
327            };
328
329            bool operator==(const Arg&, const Arg&);
330
331            namespace std {
332              template <>
333              struct hash<Arg> {
334                size_t operator()(const Arg&);
335              };
336            }
337
338            fruit::Component<X> getParentComponent(int, std::string, Arg);
339
340            fruit::Component<X> getComponent() {
341              return fruit::createComponent()
342                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
343            }
344            '''
345        expect_generic_compile_error(
346            r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).'
347            r'|error: overload resolution selected deleted operator .=.'
348            r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function',
349            COMMON_DEFINITIONS,
350            source)
351
352    def test_component_function_error_not_copy_assignable(self):
353        source = '''
354            struct X {
355              int n;
356              X(int n) : n(n) {}
357            };
358
359            struct Arg {
360              Arg() = default;
361              Arg(const Arg&) = default;
362              Arg(Arg&&) = default;
363              Arg& operator=(const Arg&) = delete;
364              Arg& operator=(Arg&&) = default;
365            };
366
367            bool operator==(const Arg&, const Arg&);
368
369            namespace std {
370              template <>
371              struct hash<Arg> {
372                size_t operator()(const Arg&);
373              };
374            }
375
376            fruit::Component<X> getParentComponent(int, std::string, Arg);
377
378            fruit::Component<X> getComponent() {
379              return fruit::createComponent()
380                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
381            }
382            '''
383        expect_generic_compile_error(
384            r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).'
385            r'|error: overload resolution selected deleted operator .=.'
386            r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function',
387            COMMON_DEFINITIONS,
388            source)
389
390    def test_component_function_error_not_copy_assignable_with_conversion(self):
391        source = '''
392            struct X {
393              int n;
394              X(int n) : n(n) {}
395            };
396
397            struct Arg {
398              Arg(int) {}
399              Arg() = default;
400              Arg(const Arg&) = default;
401              Arg(Arg&&) = default;
402              Arg& operator=(const Arg&) = delete;
403              Arg& operator=(Arg&&) = default;
404            };
405
406            bool operator==(const Arg&, const Arg&);
407
408            namespace std {
409              template <>
410              struct hash<Arg> {
411                size_t operator()(const Arg&);
412              };
413            }
414
415            fruit::Component<X> getParentComponent(int, std::string, Arg);
416
417            fruit::Component<X> getComponent() {
418              return fruit::createComponent()
419                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
420            }
421            '''
422        expect_generic_compile_error(
423            r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).'
424            r'|error: overload resolution selected deleted operator .=.'
425            r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function',
426            COMMON_DEFINITIONS,
427            source)
428
429    def test_component_function_error_not_equality_comparable(self):
430        source = '''
431            struct X {
432              int n;
433              X(int n) : n(n) {}
434            };
435
436            struct Arg {
437              Arg() = default;
438              Arg(const Arg&) = default;
439              Arg(Arg&&) = default;
440              Arg& operator=(const Arg&) = default;
441              Arg& operator=(Arg&&) = default;
442            };
443
444            namespace std {
445              template <>
446              struct hash<Arg> {
447                size_t operator()(const Arg&);
448              };
449            }
450
451            fruit::Component<X> getParentComponent(int, std::string, Arg);
452
453            fruit::Component<X> getComponent() {
454              return fruit::createComponent()
455                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
456            }
457            '''
458        expect_generic_compile_error(
459            r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)'
460            r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)'
461            r'|error C2676: binary .==.: .const Arg. does not define this operator',
462            COMMON_DEFINITIONS,
463            source)
464
465    def test_component_function_error_not_equality_comparable_with_conversion(self):
466        source = '''
467            struct X {
468              int n;
469              X(int n) : n(n) {}
470            };
471
472            struct Arg {
473              Arg(int) {}
474              Arg() = default;
475              Arg(const Arg&) = default;
476              Arg(Arg&&) = default;
477              Arg& operator=(const Arg&) = default;
478              Arg& operator=(Arg&&) = default;
479            };
480
481            namespace std {
482              template <>
483              struct hash<Arg> {
484                size_t operator()(const Arg&);
485              };
486            }
487
488            fruit::Component<X> getParentComponent(int, std::string, Arg);
489
490            fruit::Component<X> getComponent() {
491              return fruit::createComponent()
492                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
493            }
494            '''
495        expect_generic_compile_error(
496            r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)'
497            r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)'
498            r'|error C2676: binary .==.: .const Arg. does not define this operator',
499            COMMON_DEFINITIONS,
500            source)
501
502    def test_component_function_error_not_hashable(self):
503        source = '''
504            struct X {};
505
506            struct Arg {
507              Arg() = default;
508              Arg(const Arg&) = default;
509              Arg(Arg&&) = default;
510              Arg& operator=(const Arg&) = default;
511              Arg& operator=(Arg&&) = default;
512            };
513
514            bool operator==(const Arg&, const Arg&);
515
516            fruit::Component<X> getParentComponent(int, std::string, Arg);
517
518            fruit::Component<X> getComponent() {
519              return fruit::createComponent()
520                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}));
521            }
522            '''
523        expect_generic_compile_error(
524            r'error: use of deleted function .std::hash<Arg>::hash\(\).'
525            r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.'
526            r'|error: invalid use of incomplete type .struct std::hash<Arg>.'
527            r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.'
528            r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.'
529            r'|error C2064: term does not evaluate to a function taking 1 arguments',
530            COMMON_DEFINITIONS,
531            source)
532
533    def test_component_function_error_not_hashable_with_conversion(self):
534        source = '''
535            struct X {};
536
537            struct Arg {
538              Arg(int) {}
539              Arg() = default;
540              Arg(const Arg&) = default;
541              Arg(Arg&&) = default;
542              Arg& operator=(const Arg&) = default;
543              Arg& operator=(Arg&&) = default;
544            };
545
546            bool operator==(const Arg&, const Arg&);
547
548            fruit::Component<X> getParentComponent(int, std::string, Arg);
549
550            fruit::Component<X> getComponent() {
551              return fruit::createComponent()
552                .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15));
553            }
554            '''
555        expect_generic_compile_error(
556            r'error: use of deleted function .std::hash<Arg>::hash\(\).'
557            r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.'
558            r'|error: invalid use of incomplete type .struct std::hash<Arg>.'
559            r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.'
560            r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.'
561            r'|error C2064: term does not evaluate to a function taking 1 arguments',
562            COMMON_DEFINITIONS,
563            source)
564
565if __name__ == '__main__':
566    absltest.main()
567