blob: 8dc6a76ee4a5608f60cbf30833327986f17fcb8b [file] [log] [blame]
Marco Poletti3c9c5172018-08-18 21:49:27 +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 Poletti3c9c5172018-08-18 21:49:27 +010017from fruit_test_common import *
18
19COMMON_DEFINITIONS = '''
20 #include "test_common.h"
21 '''
22
Marco Poletti4ded6e22019-07-20 19:21:21 -070023class 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;
Marco Poletti3c9c5172018-08-18 21:49:27 +010042 }
Marco Poletti4ded6e22019-07-20 19:21:21 -070043
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)
Marco Poletti3c9c5172018-08-18 21:49:27 +010070
Marco Poletti4ded6e22019-07-20 19:21:21 -070071 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +010095
Marco Poletti4ded6e22019-07-20 19:21:21 -070096 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100120
Marco Poletti4ded6e22019-07-20 19:21:21 -0700121 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100156
Marco Poletti4ded6e22019-07-20 19:21:21 -0700157 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.'
Marco Polettie1afb1b2020-05-02 14:16:10 -0700190 r'|error: copying parameter of type .Arg. invokes deleted constructor'
191 r'|error C2280: .Arg::Arg\(Arg &&\).: attempting to reference a deleted function',
Marco Poletti4ded6e22019-07-20 19:21:21 -0700192 COMMON_DEFINITIONS,
193 source)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100194
Marco Poletti4ded6e22019-07-20 19:21:21 -0700195 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100235
Marco Poletti4ded6e22019-07-20 19:21:21 -0700236 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100277
Marco Poletti4ded6e22019-07-20 19:21:21 -0700278 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100312
Marco Poletti4ded6e22019-07-20 19:21:21 -0700313 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100348
Marco Poletti4ded6e22019-07-20 19:21:21 -0700349 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100386
Marco Poletti4ded6e22019-07-20 19:21:21 -0700387 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100425
Marco Poletti4ded6e22019-07-20 19:21:21 -0700426 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100461
Marco Poletti4ded6e22019-07-20 19:21:21 -0700462 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100498
Marco Poletti4ded6e22019-07-20 19:21:21 -0700499 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100529
Marco Poletti4ded6e22019-07-20 19:21:21 -0700530 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)
Marco Poletti3c9c5172018-08-18 21:49:27 +0100561
Marco Poletti5dba7172019-04-27 10:06:30 +0100562if __name__ == '__main__':
Marco Poletti4ded6e22019-07-20 19:21:21 -0700563 absltest.main()