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 TestInstall(parameterized.TestCase): 29 @parameterized.parameters([ 30 ('X', 'X'), 31 ('X', 'const X'), 32 ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'), 33 ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'), 34 ]) 35 def test_success(self, XParamInChildComponent, XParamInRootComponent): 36 source = ''' 37 struct X { 38 int n; 39 X(int n) : n(n) {} 40 }; 41 42 fruit::Component<XParamInChildComponent> getChildComponent() { 43 return fruit::createComponent() 44 .registerProvider<XParamInChildComponent()>([]() { return X(5); }); 45 } 46 47 fruit::Component<XParamInRootComponent> getRootComponent() { 48 return fruit::createComponent() 49 .install(getChildComponent); 50 } 51 52 int main() { 53 fruit::Injector<XParamInRootComponent> injector(getRootComponent); 54 X x = injector.get<XParamInRootComponent>(); 55 Assert(x.n == 5); 56 } 57 ''' 58 expect_success( 59 COMMON_DEFINITIONS, 60 source, 61 locals()) 62 63 @parameterized.parameters([ 64 ('const X', 'X'), 65 ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'), 66 ]) 67 def test_install_error_child_component_provides_const(self, XParamInChildComponent, XParamInRootComponent): 68 source = ''' 69 struct X {}; 70 71 fruit::Component<XParamInChildComponent> getChildComponent(); 72 73 fruit::Component<XParamInRootComponent> getRootComponent() { 74 return fruit::createComponent() 75 .install(getChildComponent); 76 } 77 ''' 78 expect_compile_error( 79 'NonConstBindingRequiredButConstBindingProvidedError<XParamInRootComponent>', 80 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 81 COMMON_DEFINITIONS, 82 source, 83 locals()) 84 85 @parameterized.parameters([ 86 ('X', 'X'), 87 ('X', 'const X'), 88 ('const X', 'const X'), 89 ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'), 90 ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'), 91 ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X>'), 92 ]) 93 def test_with_requirements_success(self, ProvidedXParam, RequiredXParam): 94 ProvidedXParamWithoutConst = ProvidedXParam.replace('const ', '') 95 source = ''' 96 struct X { 97 int n; 98 X(int n) : n(n) {} 99 }; 100 101 struct Y { 102 X x; 103 Y(X x): x(x) {} 104 }; 105 106 fruit::Component<fruit::Required<RequiredXParam>, Y> getChildComponent1() { 107 return fruit::createComponent() 108 .registerProvider<Y(RequiredXParam)>([](X x) { return Y(x); }); 109 } 110 111 fruit::Component<ProvidedXParam> getChildComponent2() { 112 return fruit::createComponent() 113 .registerProvider<ProvidedXParamWithoutConst()>([]() { return X(5); }); 114 } 115 116 fruit::Component<Y> getRootComponent() { 117 return fruit::createComponent() 118 .install(getChildComponent1) 119 .install(getChildComponent2); 120 } 121 122 int main() { 123 fruit::Injector<Y> injector(getRootComponent); 124 Y y = injector.get<Y>(); 125 Assert(y.x.n == 5); 126 } 127 ''' 128 expect_success( 129 COMMON_DEFINITIONS, 130 source, 131 locals()) 132 133 @parameterized.parameters([ 134 ('const X', 'X'), 135 ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'), 136 ]) 137 def test_with_requirements_error_only_nonconst_provided(self, ProvidedXParam, RequiredXParam): 138 source = ''' 139 struct X {}; 140 struct Y {}; 141 142 fruit::Component<fruit::Required<RequiredXParam>, Y> getChildComponent1(); 143 144 fruit::Component<ProvidedXParam> getChildComponent2(); 145 146 fruit::Component<Y> getRootComponent() { 147 return fruit::createComponent() 148 .install(getChildComponent1) 149 .install(getChildComponent2); 150 } 151 ''' 152 expect_compile_error( 153 'NonConstBindingRequiredButConstBindingProvidedError<RequiredXParam>', 154 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 155 COMMON_DEFINITIONS, 156 source, 157 locals()) 158 159 @parameterized.parameters([ 160 ('const X', 'X'), 161 ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'), 162 ]) 163 def test_with_requirements_error_only_nonconst_provided_reversed_install_order(self, ProvidedXParam, RequiredXParam): 164 source = ''' 165 struct X {}; 166 struct Y {}; 167 168 fruit::Component<fruit::Required<RequiredXParam>, Y> getChildComponent1(); 169 170 fruit::Component<ProvidedXParam> getChildComponent2(); 171 172 fruit::Component<Y> getRootComponent() { 173 return fruit::createComponent() 174 .install(getChildComponent2) 175 .install(getChildComponent1); 176 } 177 ''' 178 expect_compile_error( 179 'NonConstBindingRequiredButConstBindingProvidedError<RequiredXParam>', 180 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 181 COMMON_DEFINITIONS, 182 source, 183 locals()) 184 185 def test_with_requirements_not_specified_in_child_component_error(self): 186 source = ''' 187 struct X { 188 int n; 189 X(int n) : n(n) {} 190 }; 191 192 struct Y { 193 X x; 194 Y(X x): x(x) {} 195 }; 196 197 fruit::Component<fruit::Required<X>, Y> getParentYComponent() { 198 return fruit::createComponent() 199 .registerProvider([](X x) { return Y(x); }); 200 } 201 202 // We intentionally don't have fruit::Required<X> here, we want to test that this results in an error. 203 fruit::Component<Y> getYComponent() { 204 return fruit::createComponent() 205 .install(getParentYComponent); 206 } 207 ''' 208 expect_compile_error( 209 'NoBindingFoundError<X>', 210 'No explicit binding nor C::Inject definition was found for T', 211 COMMON_DEFINITIONS, 212 source) 213 214 @parameterized.parameters([ 215 ('X', 'const X'), 216 ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'), 217 ]) 218 def test_install_requiring_nonconst_then_install_requiring_const_ok(self, XAnnot, ConstXAnnot): 219 source = ''' 220 struct X {}; 221 struct Y {}; 222 struct Z {}; 223 224 fruit::Component<fruit::Required<XAnnot>, Y> getChildComponent1() { 225 return fruit::createComponent() 226 .registerConstructor<Y()>(); 227 } 228 229 fruit::Component<fruit::Required<ConstXAnnot>, Z> getChildComponent2() { 230 return fruit::createComponent() 231 .registerConstructor<Z()>(); 232 } 233 234 fruit::Component<Y, Z> getRootComponent() { 235 return fruit::createComponent() 236 .install(getChildComponent1) 237 .install(getChildComponent2) 238 .registerConstructor<XAnnot()>(); 239 } 240 241 int main() { 242 fruit::Injector<Y, Z> injector(getRootComponent); 243 injector.get<Y>(); 244 injector.get<Z>(); 245 } 246 ''' 247 expect_success( 248 COMMON_DEFINITIONS, 249 source, 250 locals()) 251 252 def test_install_requiring_nonconst_then_install_requiring_const_declaring_const_requirement_error(self): 253 source = ''' 254 struct X {}; 255 struct Y {}; 256 struct Z {}; 257 258 fruit::Component<fruit::Required<X>, Y> getChildComponent1(); 259 fruit::Component<fruit::Required<const X>, Z> getChildComponent2(); 260 261 fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() { 262 return fruit::createComponent() 263 .install(getChildComponent1) 264 .install(getChildComponent2); 265 } 266 ''' 267 expect_compile_error( 268 'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>', 269 'The type T was declared as a const Required type in the returned Component, however', 270 COMMON_DEFINITIONS, 271 source, 272 locals()) 273 274 def test_install_requiring_const_then_install_requiring_nonconst_ok(self): 275 source = ''' 276 struct X {}; 277 struct Y {}; 278 struct Z {}; 279 280 fruit::Component<fruit::Required<const X>, Y> getChildComponent1() { 281 return fruit::createComponent() 282 .registerConstructor<Y()>(); 283 } 284 285 fruit::Component<fruit::Required<X>, Z> getChildComponent2() { 286 return fruit::createComponent() 287 .registerConstructor<Z()>(); 288 } 289 290 fruit::Component<Y, Z> getRootComponent() { 291 return fruit::createComponent() 292 .install(getChildComponent1) 293 .install(getChildComponent2) 294 .registerConstructor<X()>(); 295 } 296 297 int main() { 298 fruit::Injector<Y, Z> injector(getRootComponent); 299 injector.get<Y>(); 300 injector.get<Z>(); 301 } 302 ''' 303 expect_success( 304 COMMON_DEFINITIONS, 305 source, 306 locals()) 307 308 def test_install_requiring_const_then_install_requiring_nonconst_declaring_const_requirement_error(self): 309 source = ''' 310 struct X {}; 311 struct Y {}; 312 struct Z {}; 313 314 fruit::Component<fruit::Required<const X>, Y> getChildComponent1(); 315 fruit::Component<fruit::Required<X>, Z> getChildComponent2(); 316 317 fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() { 318 return fruit::createComponent() 319 .install(getChildComponent1) 320 .install(getChildComponent2); 321 } 322 ''' 323 expect_compile_error( 324 'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>', 325 'The type T was declared as a const Required type in the returned Component, however', 326 COMMON_DEFINITIONS, 327 source, 328 locals()) 329 330 def test_install_with_args_success(self): 331 source = ''' 332 struct X { 333 int n; 334 X(int n) : n(n) {} 335 }; 336 337 struct Arg { 338 Arg(int) {} 339 Arg() = default; 340 Arg(const Arg&) = default; 341 Arg(Arg&&) = default; 342 Arg& operator=(const Arg&) = default; 343 Arg& operator=(Arg&&) = default; 344 }; 345 346 bool operator==(const Arg&, const Arg&) { 347 return true; 348 } 349 350 namespace std { 351 template <> 352 struct hash<Arg> { 353 size_t operator()(const Arg&) { 354 return 0; 355 } 356 }; 357 } 358 359 fruit::Component<X> getParentComponent(int, std::string, Arg, Arg) { 360 return fruit::createComponent() 361 .registerProvider([]() { return X(5); }); 362 } 363 364 fruit::Component<X> getComponent() { 365 return fruit::createComponent() 366 .install(getParentComponent, 5, std::string("Hello"), Arg{}, 15); 367 } 368 369 int main() { 370 fruit::Injector<X> injector(getComponent); 371 X x = injector.get<X>(); 372 Assert(x.n == 5); 373 } 374 ''' 375 expect_success(COMMON_DEFINITIONS, source) 376 377 def test_install_with_args_error_not_move_constructible(self): 378 source = ''' 379 struct Arg { 380 Arg() = default; 381 Arg(const Arg&) = default; 382 Arg(Arg&&) = delete; 383 Arg& operator=(const Arg&) = default; 384 Arg& operator=(Arg&&) = default; 385 }; 386 387 bool operator==(const Arg&, const Arg&); 388 389 namespace std { 390 template <> 391 struct hash<Arg> { 392 size_t operator()(const Arg&); 393 }; 394 } 395 396 fruit::Component<X> getParentComponent(int, std::string, Arg); 397 398 fruit::Component<X> getComponent() { 399 return fruit::createComponent() 400 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 401 } 402 ''' 403 expect_generic_compile_error( 404 r'error: use of deleted function .Arg::Arg\(Arg&&\).' 405 r'|error: call to deleted constructor of .Arg.' 406 r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.', 407 COMMON_DEFINITIONS, 408 source) 409 410 def test_install_with_args_error_not_move_constructible_with_conversion(self): 411 source = ''' 412 struct Arg { 413 Arg(int) {} 414 Arg() = default; 415 Arg(const Arg&) = default; 416 Arg(Arg&&) = delete; 417 Arg& operator=(const Arg&) = default; 418 Arg& operator=(Arg&&) = default; 419 }; 420 421 bool operator==(const Arg&, const Arg&); 422 423 namespace std { 424 template <> 425 struct hash<Arg> { 426 size_t operator()(const Arg&); 427 }; 428 } 429 430 fruit::Component<X> getParentComponent(int, std::string, Arg); 431 432 fruit::Component<X> getComponent() { 433 return fruit::createComponent() 434 .install(getParentComponent, 5, std::string("Hello"), 15); 435 } 436 ''' 437 expect_generic_compile_error( 438 r'error: use of deleted function .Arg::Arg\(Arg&&\).' 439 r'|error: call to deleted constructor of .Arg.' 440 r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.', 441 COMMON_DEFINITIONS, 442 source) 443 444 def test_install_with_args_error_not_copy_constructible(self): 445 source = ''' 446 struct X { 447 int n; 448 X(int n) : n(n) {} 449 }; 450 451 struct Arg { 452 Arg() = default; 453 Arg(const Arg&) = delete; 454 Arg(Arg&&) = default; 455 Arg& operator=(const Arg&) = default; 456 Arg& operator=(Arg&&) = default; 457 }; 458 459 bool operator==(const Arg&, const Arg&); 460 461 namespace std { 462 template <> 463 struct hash<Arg> { 464 size_t operator()(const Arg&); 465 }; 466 } 467 468 fruit::Component<X> getParentComponent(int, std::string, Arg); 469 470 fruit::Component<X> getComponent() { 471 return fruit::createComponent() 472 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 473 } 474 ''' 475 expect_generic_compile_error( 476 r'error: use of deleted function .Arg::Arg\(const Arg&\).' 477 r'|error: call to deleted constructor of .Arg.' 478 r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function', 479 COMMON_DEFINITIONS, 480 source) 481 482 def test_install_with_args_error_not_copy_constructible_with_conversion(self): 483 source = ''' 484 struct X { 485 int n; 486 X(int n) : n(n) {} 487 }; 488 489 struct Arg { 490 Arg(int) {} 491 Arg() = default; 492 Arg(const Arg&) = delete; 493 Arg(Arg&&) = default; 494 Arg& operator=(const Arg&) = default; 495 Arg& operator=(Arg&&) = default; 496 }; 497 498 bool operator==(const Arg&, const Arg&); 499 500 namespace std { 501 template <> 502 struct hash<Arg> { 503 size_t operator()(const Arg&); 504 }; 505 } 506 507 fruit::Component<X> getParentComponent(int, std::string, Arg); 508 509 fruit::Component<X> getComponent() { 510 return fruit::createComponent() 511 .install(getParentComponent, 5, std::string("Hello"), 15); 512 } 513 ''' 514 expect_generic_compile_error( 515 r'error: use of deleted function .Arg::Arg\(const Arg&\).' 516 r'|error: call to deleted constructor of .Arg.' 517 r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function', 518 COMMON_DEFINITIONS, 519 source) 520 521 def test_install_with_args_error_not_move_assignable(self): 522 source = ''' 523 struct Arg { 524 Arg() = default; 525 Arg(const Arg&) = default; 526 Arg(Arg&&) = default; 527 Arg& operator=(const Arg&) = default; 528 Arg& operator=(Arg&&) = delete; 529 }; 530 531 bool operator==(const Arg&, const Arg&); 532 533 namespace std { 534 template <> 535 struct hash<Arg> { 536 size_t operator()(const Arg&); 537 }; 538 } 539 540 fruit::Component<X> getParentComponent(int, std::string, Arg); 541 542 fruit::Component<X> getComponent() { 543 return fruit::createComponent() 544 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 545 } 546 ''' 547 expect_generic_compile_error( 548 r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).' 549 r'|error: overload resolution selected deleted operator .=.' 550 r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function', 551 COMMON_DEFINITIONS, 552 source) 553 554 def test_install_with_args_error_not_move_assignable_with_conversion(self): 555 source = ''' 556 struct Arg { 557 Arg(int) {} 558 Arg() = default; 559 Arg(const Arg&) = default; 560 Arg(Arg&&) = default; 561 Arg& operator=(const Arg&) = default; 562 Arg& operator=(Arg&&) = delete; 563 }; 564 565 bool operator==(const Arg&, const Arg&); 566 567 namespace std { 568 template <> 569 struct hash<Arg> { 570 size_t operator()(const Arg&); 571 }; 572 } 573 574 fruit::Component<X> getParentComponent(int, std::string, Arg); 575 576 fruit::Component<X> getComponent() { 577 return fruit::createComponent() 578 .install(getParentComponent, 5, std::string("Hello"), 15); 579 } 580 ''' 581 expect_generic_compile_error( 582 r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).' 583 r'|error: overload resolution selected deleted operator .=.' 584 r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function', 585 COMMON_DEFINITIONS, 586 source) 587 588 def test_install_with_args_error_not_copy_assignable(self): 589 source = ''' 590 struct X { 591 int n; 592 X(int n) : n(n) {} 593 }; 594 595 struct Arg { 596 Arg() = default; 597 Arg(const Arg&) = default; 598 Arg(Arg&&) = default; 599 Arg& operator=(const Arg&) = delete; 600 Arg& operator=(Arg&&) = default; 601 }; 602 603 bool operator==(const Arg&, const Arg&); 604 605 namespace std { 606 template <> 607 struct hash<Arg> { 608 size_t operator()(const Arg&); 609 }; 610 } 611 612 fruit::Component<X> getParentComponent(int, std::string, Arg); 613 614 fruit::Component<X> getComponent() { 615 return fruit::createComponent() 616 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 617 } 618 ''' 619 expect_generic_compile_error( 620 r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).' 621 r'|error: overload resolution selected deleted operator .=.' 622 r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function', 623 COMMON_DEFINITIONS, 624 source) 625 626 def test_install_with_args_error_not_copy_assignable_with_conversion(self): 627 source = ''' 628 struct X { 629 int n; 630 X(int n) : n(n) {} 631 }; 632 633 struct Arg { 634 Arg(int) {} 635 Arg() = default; 636 Arg(const Arg&) = default; 637 Arg(Arg&&) = default; 638 Arg& operator=(const Arg&) = delete; 639 Arg& operator=(Arg&&) = default; 640 }; 641 642 bool operator==(const Arg&, const Arg&); 643 644 namespace std { 645 template <> 646 struct hash<Arg> { 647 size_t operator()(const Arg&); 648 }; 649 } 650 651 fruit::Component<X> getParentComponent(int, std::string, Arg); 652 653 fruit::Component<X> getComponent() { 654 return fruit::createComponent() 655 .install(getParentComponent, 5, std::string("Hello"), 15); 656 } 657 ''' 658 expect_generic_compile_error( 659 r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).' 660 r'|error: overload resolution selected deleted operator .=.' 661 r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function', 662 COMMON_DEFINITIONS, 663 source) 664 665 def test_install_with_args_error_not_equality_comparable(self): 666 source = ''' 667 struct X { 668 int n; 669 X(int n) : n(n) {} 670 }; 671 672 struct Arg { 673 Arg() = default; 674 Arg(const Arg&) = default; 675 Arg(Arg&&) = default; 676 Arg& operator=(const Arg&) = default; 677 Arg& operator=(Arg&&) = default; 678 }; 679 680 namespace std { 681 template <> 682 struct hash<Arg> { 683 size_t operator()(const Arg&); 684 }; 685 } 686 687 fruit::Component<X> getParentComponent(int, std::string, Arg); 688 689 fruit::Component<X> getComponent() { 690 return fruit::createComponent() 691 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 692 } 693 ''' 694 expect_generic_compile_error( 695 r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)' 696 r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)' 697 r'|error C2676: binary .==.: .const Arg. does not define this operator', 698 COMMON_DEFINITIONS, 699 source) 700 701 def test_install_with_args_error_not_equality_comparable_with_conversion(self): 702 source = ''' 703 struct X { 704 int n; 705 X(int n) : n(n) {} 706 }; 707 708 struct Arg { 709 Arg(int) {} 710 Arg() = default; 711 Arg(const Arg&) = default; 712 Arg(Arg&&) = default; 713 Arg& operator=(const Arg&) = default; 714 Arg& operator=(Arg&&) = default; 715 }; 716 717 namespace std { 718 template <> 719 struct hash<Arg> { 720 size_t operator()(const Arg&); 721 }; 722 } 723 724 fruit::Component<X> getParentComponent(int, std::string, Arg); 725 726 fruit::Component<X> getComponent() { 727 return fruit::createComponent() 728 .install(getParentComponent, 5, std::string("Hello"), 15); 729 } 730 ''' 731 expect_generic_compile_error( 732 r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)' 733 r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)' 734 r'|error C2676: binary .==.: .const Arg. does not define this operator', 735 COMMON_DEFINITIONS, 736 source) 737 738 def test_install_with_args_error_not_hashable(self): 739 source = ''' 740 struct Arg { 741 Arg() = default; 742 Arg(const Arg&) = default; 743 Arg(Arg&&) = default; 744 Arg& operator=(const Arg&) = default; 745 Arg& operator=(Arg&&) = default; 746 }; 747 748 bool operator==(const Arg&, const Arg&); 749 750 fruit::Component<X> getParentComponent(int, std::string, Arg); 751 752 fruit::Component<X> getComponent() { 753 return fruit::createComponent() 754 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 755 } 756 ''' 757 expect_generic_compile_error( 758 r'error: use of deleted function .std::hash<Arg>::hash\(\).' 759 r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.' 760 r'|error: invalid use of incomplete type .struct std::hash<Arg>.' 761 r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.' 762 r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.' 763 r'|error C2064: term does not evaluate to a function taking 1 arguments', 764 COMMON_DEFINITIONS, 765 source) 766 767 def test_install_with_args_error_not_hashable_with_conversion(self): 768 source = ''' 769 struct Arg { 770 Arg(int) {} 771 Arg() = default; 772 Arg(const Arg&) = default; 773 Arg(Arg&&) = default; 774 Arg& operator=(const Arg&) = default; 775 Arg& operator=(Arg&&) = default; 776 }; 777 778 bool operator==(const Arg&, const Arg&); 779 780 fruit::Component<X> getParentComponent(int, std::string, Arg); 781 782 fruit::Component<X> getComponent() { 783 return fruit::createComponent() 784 .install(getParentComponent, 5, std::string("Hello"), 15); 785 } 786 ''' 787 expect_generic_compile_error( 788 r'error: use of deleted function .std::hash<Arg>::hash\(\).' 789 r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.' 790 r'|error: invalid use of incomplete type .struct std::hash<Arg>.' 791 r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.' 792 r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.' 793 r'|error C2064: term does not evaluate to a function taking 1 arguments', 794 COMMON_DEFINITIONS, 795 source) 796 797 @parameterized.parameters([ 798 'X', 799 'fruit::Annotated<Annotation1, X>', 800 ]) 801 def test_install_component_functions_deduped(self, XAnnot): 802 source = ''' 803 struct X {}; 804 805 X x; 806 807 fruit::Component<> getComponent() { 808 return fruit::createComponent() 809 .addInstanceMultibinding<XAnnot, X>(x); 810 } 811 812 fruit::Component<> getComponent2() { 813 return fruit::createComponent() 814 .install(getComponent); 815 } 816 817 fruit::Component<> getComponent3() { 818 return fruit::createComponent() 819 .install(getComponent); 820 } 821 822 fruit::Component<> getComponent4() { 823 return fruit::createComponent() 824 .install(getComponent2) 825 .install(getComponent3); 826 } 827 828 int main() { 829 fruit::Injector<> injector(getComponent4); 830 831 // We test multibindings because the effect on other bindings is not user-visible (that only affects 832 // performance). 833 std::vector<X*> multibindings = injector.getMultibindings<XAnnot>(); 834 Assert(multibindings.size() == 1); 835 Assert(multibindings[0] == &x); 836 } 837 ''' 838 expect_success( 839 COMMON_DEFINITIONS, 840 source, 841 locals()) 842 843 @parameterized.parameters([ 844 'X', 845 'fruit::Annotated<Annotation1, X>', 846 ]) 847 def test_install_component_functions_deduped_across_normalized_component(self, XAnnot): 848 source = ''' 849 struct X {}; 850 851 X x; 852 853 fruit::Component<> getComponent() { 854 return fruit::createComponent() 855 .addInstanceMultibinding<XAnnot, X>(x); 856 } 857 858 fruit::Component<> getComponent2() { 859 return fruit::createComponent() 860 .install(getComponent); 861 } 862 863 fruit::Component<> getComponent3() { 864 return fruit::createComponent() 865 .install(getComponent); 866 } 867 868 int main() { 869 fruit::NormalizedComponent<> normalizedComponent(getComponent2); 870 fruit::Injector<> injector(normalizedComponent, getComponent3); 871 872 // We test multibindings because the effect on other bindings is not user-visible (that only affects 873 // performance). 874 std::vector<X*> multibindings = injector.getMultibindings<XAnnot>(); 875 Assert(multibindings.size() == 1); 876 Assert(multibindings[0] == &x); 877 } 878 ''' 879 expect_success( 880 COMMON_DEFINITIONS, 881 source, 882 locals()) 883 884 @parameterized.parameters([ 885 'X', 886 'fruit::Annotated<Annotation1, X>', 887 ]) 888 def test_install_component_functions_with_args_deduped(self, XAnnot): 889 source = ''' 890 struct X {}; 891 892 X x; 893 894 fruit::Component<> getComponent(int) { 895 return fruit::createComponent() 896 .addInstanceMultibinding<XAnnot, X>(x); 897 } 898 899 fruit::Component<> getComponent2() { 900 return fruit::createComponent() 901 .install(getComponent, 1); 902 } 903 904 fruit::Component<> getComponent3() { 905 return fruit::createComponent() 906 .install(getComponent, 1); 907 } 908 909 fruit::Component<> getComponent4() { 910 return fruit::createComponent() 911 .install(getComponent2) 912 .install(getComponent3); 913 } 914 915 int main() { 916 fruit::Injector<> injector(getComponent4); 917 918 // We test multibindings because the effect on other bindings is not user-visible (that only affects 919 // performance). 920 std::vector<X*> multibindings = injector.getMultibindings<XAnnot>(); 921 Assert(multibindings.size() == 1); 922 Assert(multibindings[0] == &x); 923 } 924 ''' 925 expect_success( 926 COMMON_DEFINITIONS, 927 source, 928 locals()) 929 930 @parameterized.parameters([ 931 'X', 932 'fruit::Annotated<Annotation1, X>', 933 ]) 934 def test_install_component_functions_different_args_not_deduped(self, XAnnot): 935 source = ''' 936 struct X {}; 937 938 X x; 939 940 fruit::Component<> getComponent(int) { 941 return fruit::createComponent() 942 .addInstanceMultibinding<XAnnot, X>(x); 943 } 944 945 fruit::Component<> getComponent2() { 946 return fruit::createComponent() 947 .install(getComponent, 1); 948 } 949 950 fruit::Component<> getComponent3() { 951 return fruit::createComponent() 952 .install(getComponent, 2); 953 } 954 955 fruit::Component<> getComponent4() { 956 return fruit::createComponent() 957 .install(getComponent2) 958 .install(getComponent3); 959 } 960 961 int main() { 962 fruit::Injector<> injector(getComponent4); 963 964 // We test multibindings because the effect on other bindings is not user-visible (it only affects 965 // performance). 966 std::vector<X*> multibindings = injector.getMultibindings<XAnnot>(); 967 Assert(multibindings.size() == 2); 968 Assert(multibindings[0] == &x); 969 Assert(multibindings[1] == &x); 970 } 971 ''' 972 expect_success( 973 COMMON_DEFINITIONS, 974 source, 975 locals()) 976 977 def test_install_component_functions_loop(self): 978 source = ''' 979 struct X {}; 980 struct Y {}; 981 struct Z {}; 982 983 // X -> Y -> Z -> Y 984 985 fruit::Component<X> getXComponent(); 986 fruit::Component<Y> getYComponent(); 987 fruit::Component<Z> getZComponent(); 988 989 fruit::Component<X> getXComponent() { 990 return fruit::createComponent() 991 .registerConstructor<X()>() 992 .install(getYComponent); 993 } 994 995 fruit::Component<Y> getYComponent() { 996 return fruit::createComponent() 997 .registerConstructor<Y()>() 998 .install(getZComponent); 999 } 1000 1001 fruit::Component<Z> getZComponent() { 1002 return fruit::createComponent() 1003 .registerConstructor<Z()>() 1004 .install(getYComponent); 1005 } 1006 1007 int main() { 1008 fruit::Injector<X> injector(getXComponent); 1009 (void)injector; 1010 } 1011 ''' 1012 expect_runtime_error( 1013 r'Component installation trace \(from top-level to the most deeply-nested\):\n' 1014 r'(class )?fruit::Component<(struct )?X> ?\((__cdecl)?\*\)\((void)?\)\n' 1015 r'<-- The loop starts here\n' 1016 r'(class )?fruit::Component<(struct )?Y> ?\((__cdecl)?\*\)\((void)?\)\n' 1017 r'(class )?fruit::Component<(struct )?Z> ?\((__cdecl)?\*\)\((void)?\)\n' 1018 r'(class )?fruit::Component<(struct )?Y> ?\((__cdecl)?\*\)\((void)?\)\n', 1019 COMMON_DEFINITIONS, 1020 source, 1021 locals()) 1022 1023 def test_install_component_functions_different_arguments_loop_not_reported(self): 1024 source = ''' 1025 struct X {}; 1026 struct Y {}; 1027 struct Z {}; 1028 1029 // X -> Y(1) -> Z -> Y(2) 1030 1031 fruit::Component<X> getXComponent(); 1032 fruit::Component<Y> getYComponent(int); 1033 fruit::Component<Z> getZComponent(); 1034 1035 fruit::Component<X> getXComponent() { 1036 return fruit::createComponent() 1037 .registerConstructor<X()>() 1038 .install(getYComponent, 1); 1039 } 1040 1041 fruit::Component<Y> getYComponent(int n) { 1042 if (n == 1) { 1043 return fruit::createComponent() 1044 .registerConstructor<Y()>() 1045 .install(getZComponent); 1046 } else { 1047 return fruit::createComponent() 1048 .registerConstructor<Y()>(); 1049 } 1050 } 1051 1052 fruit::Component<Z> getZComponent() { 1053 return fruit::createComponent() 1054 .registerConstructor<Z()>() 1055 .install(getYComponent, 2); 1056 } 1057 1058 int main() { 1059 fruit::Injector<X> injector(getXComponent); 1060 injector.get<X>(); 1061 } 1062 ''' 1063 expect_success( 1064 COMMON_DEFINITIONS, 1065 source, 1066 locals()) 1067 1068if __name__ == '__main__': 1069 absltest.main() 1070