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\(const Arg &\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.' 407 r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.', 408 COMMON_DEFINITIONS, 409 source) 410 411 def test_install_with_args_error_not_move_constructible_with_conversion(self): 412 source = ''' 413 struct Arg { 414 Arg(int) {} 415 Arg() = default; 416 Arg(const Arg&) = default; 417 Arg(Arg&&) = delete; 418 Arg& operator=(const Arg&) = default; 419 Arg& operator=(Arg&&) = default; 420 }; 421 422 bool operator==(const Arg&, const Arg&); 423 424 namespace std { 425 template <> 426 struct hash<Arg> { 427 size_t operator()(const Arg&); 428 }; 429 } 430 431 fruit::Component<X> getParentComponent(int, std::string, Arg); 432 433 fruit::Component<X> getComponent() { 434 return fruit::createComponent() 435 .install(getParentComponent, 5, std::string("Hello"), 15); 436 } 437 ''' 438 expect_generic_compile_error( 439 r'error: use of deleted function .Arg::Arg\(Arg&&\).' 440 r'|error: call to deleted constructor of .Arg.' 441 r'|.Arg::Arg\((int|Arg &&)\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.', 442 COMMON_DEFINITIONS, 443 source) 444 445 def test_install_with_args_error_not_copy_constructible(self): 446 source = ''' 447 struct X { 448 int n; 449 X(int n) : n(n) {} 450 }; 451 452 struct Arg { 453 Arg() = default; 454 Arg(const Arg&) = delete; 455 Arg(Arg&&) = default; 456 Arg& operator=(const Arg&) = default; 457 Arg& operator=(Arg&&) = default; 458 }; 459 460 bool operator==(const Arg&, const Arg&); 461 462 namespace std { 463 template <> 464 struct hash<Arg> { 465 size_t operator()(const Arg&); 466 }; 467 } 468 469 fruit::Component<X> getParentComponent(int, std::string, Arg); 470 471 fruit::Component<X> getComponent() { 472 return fruit::createComponent() 473 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 474 } 475 ''' 476 expect_generic_compile_error( 477 r'error: use of deleted function .Arg::Arg\(const Arg&\).' 478 r'|error: call to deleted constructor of .Arg.' 479 r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function', 480 COMMON_DEFINITIONS, 481 source) 482 483 def test_install_with_args_error_not_copy_constructible_with_conversion(self): 484 source = ''' 485 struct X { 486 int n; 487 X(int n) : n(n) {} 488 }; 489 490 struct Arg { 491 Arg(int) {} 492 Arg() = default; 493 Arg(const Arg&) = delete; 494 Arg(Arg&&) = default; 495 Arg& operator=(const Arg&) = default; 496 Arg& operator=(Arg&&) = default; 497 }; 498 499 bool operator==(const Arg&, const Arg&); 500 501 namespace std { 502 template <> 503 struct hash<Arg> { 504 size_t operator()(const Arg&); 505 }; 506 } 507 508 fruit::Component<X> getParentComponent(int, std::string, Arg); 509 510 fruit::Component<X> getComponent() { 511 return fruit::createComponent() 512 .install(getParentComponent, 5, std::string("Hello"), 15); 513 } 514 ''' 515 expect_generic_compile_error( 516 r'error: use of deleted function .Arg::Arg\(const Arg&\).' 517 r'|error: call to deleted constructor of .Arg.' 518 r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function', 519 COMMON_DEFINITIONS, 520 source) 521 522 def test_install_with_args_error_not_move_assignable(self): 523 source = ''' 524 struct Arg { 525 Arg() = default; 526 Arg(const Arg&) = default; 527 Arg(Arg&&) = default; 528 Arg& operator=(const Arg&) = default; 529 Arg& operator=(Arg&&) = delete; 530 }; 531 532 bool operator==(const Arg&, const Arg&); 533 534 namespace std { 535 template <> 536 struct hash<Arg> { 537 size_t operator()(const Arg&); 538 }; 539 } 540 541 fruit::Component<X> getParentComponent(int, std::string, Arg); 542 543 fruit::Component<X> getComponent() { 544 return fruit::createComponent() 545 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 546 } 547 ''' 548 expect_generic_compile_error( 549 r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).' 550 r'|error: overload resolution selected deleted operator .=.' 551 r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function', 552 COMMON_DEFINITIONS, 553 source) 554 555 def test_install_with_args_error_not_move_assignable_with_conversion(self): 556 source = ''' 557 struct Arg { 558 Arg(int) {} 559 Arg() = default; 560 Arg(const Arg&) = default; 561 Arg(Arg&&) = default; 562 Arg& operator=(const Arg&) = default; 563 Arg& operator=(Arg&&) = delete; 564 }; 565 566 bool operator==(const Arg&, const Arg&); 567 568 namespace std { 569 template <> 570 struct hash<Arg> { 571 size_t operator()(const Arg&); 572 }; 573 } 574 575 fruit::Component<X> getParentComponent(int, std::string, Arg); 576 577 fruit::Component<X> getComponent() { 578 return fruit::createComponent() 579 .install(getParentComponent, 5, std::string("Hello"), 15); 580 } 581 ''' 582 expect_generic_compile_error( 583 r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).' 584 r'|error: overload resolution selected deleted operator .=.' 585 r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function', 586 COMMON_DEFINITIONS, 587 source) 588 589 def test_install_with_args_error_not_copy_assignable(self): 590 source = ''' 591 struct X { 592 int n; 593 X(int n) : n(n) {} 594 }; 595 596 struct Arg { 597 Arg() = default; 598 Arg(const Arg&) = default; 599 Arg(Arg&&) = default; 600 Arg& operator=(const Arg&) = delete; 601 Arg& operator=(Arg&&) = default; 602 }; 603 604 bool operator==(const Arg&, const Arg&); 605 606 namespace std { 607 template <> 608 struct hash<Arg> { 609 size_t operator()(const Arg&); 610 }; 611 } 612 613 fruit::Component<X> getParentComponent(int, std::string, Arg); 614 615 fruit::Component<X> getComponent() { 616 return fruit::createComponent() 617 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 618 } 619 ''' 620 expect_generic_compile_error( 621 r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).' 622 r'|error: overload resolution selected deleted operator .=.' 623 r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function', 624 COMMON_DEFINITIONS, 625 source) 626 627 def test_install_with_args_error_not_copy_assignable_with_conversion(self): 628 source = ''' 629 struct X { 630 int n; 631 X(int n) : n(n) {} 632 }; 633 634 struct Arg { 635 Arg(int) {} 636 Arg() = default; 637 Arg(const Arg&) = default; 638 Arg(Arg&&) = default; 639 Arg& operator=(const Arg&) = delete; 640 Arg& operator=(Arg&&) = default; 641 }; 642 643 bool operator==(const Arg&, const Arg&); 644 645 namespace std { 646 template <> 647 struct hash<Arg> { 648 size_t operator()(const Arg&); 649 }; 650 } 651 652 fruit::Component<X> getParentComponent(int, std::string, Arg); 653 654 fruit::Component<X> getComponent() { 655 return fruit::createComponent() 656 .install(getParentComponent, 5, std::string("Hello"), 15); 657 } 658 ''' 659 expect_generic_compile_error( 660 r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).' 661 r'|error: overload resolution selected deleted operator .=.' 662 r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function', 663 COMMON_DEFINITIONS, 664 source) 665 666 def test_install_with_args_error_not_equality_comparable(self): 667 source = ''' 668 struct X { 669 int n; 670 X(int n) : n(n) {} 671 }; 672 673 struct Arg { 674 Arg() = default; 675 Arg(const Arg&) = default; 676 Arg(Arg&&) = default; 677 Arg& operator=(const Arg&) = default; 678 Arg& operator=(Arg&&) = default; 679 }; 680 681 namespace std { 682 template <> 683 struct hash<Arg> { 684 size_t operator()(const Arg&); 685 }; 686 } 687 688 fruit::Component<X> getParentComponent(int, std::string, Arg); 689 690 fruit::Component<X> getComponent() { 691 return fruit::createComponent() 692 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 693 } 694 ''' 695 expect_generic_compile_error( 696 r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)' 697 r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)' 698 r'|error C2676: binary .==.: .const Arg. does not define this operator', 699 COMMON_DEFINITIONS, 700 source) 701 702 def test_install_with_args_error_not_equality_comparable_with_conversion(self): 703 source = ''' 704 struct X { 705 int n; 706 X(int n) : n(n) {} 707 }; 708 709 struct Arg { 710 Arg(int) {} 711 Arg() = default; 712 Arg(const Arg&) = default; 713 Arg(Arg&&) = default; 714 Arg& operator=(const Arg&) = default; 715 Arg& operator=(Arg&&) = default; 716 }; 717 718 namespace std { 719 template <> 720 struct hash<Arg> { 721 size_t operator()(const Arg&); 722 }; 723 } 724 725 fruit::Component<X> getParentComponent(int, std::string, Arg); 726 727 fruit::Component<X> getComponent() { 728 return fruit::createComponent() 729 .install(getParentComponent, 5, std::string("Hello"), 15); 730 } 731 ''' 732 expect_generic_compile_error( 733 r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)' 734 r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)' 735 r'|error C2676: binary .==.: .const Arg. does not define this operator', 736 COMMON_DEFINITIONS, 737 source) 738 739 def test_install_with_args_error_not_hashable(self): 740 source = ''' 741 struct Arg { 742 Arg() = default; 743 Arg(const Arg&) = default; 744 Arg(Arg&&) = default; 745 Arg& operator=(const Arg&) = default; 746 Arg& operator=(Arg&&) = default; 747 }; 748 749 bool operator==(const Arg&, const Arg&); 750 751 fruit::Component<X> getParentComponent(int, std::string, Arg); 752 753 fruit::Component<X> getComponent() { 754 return fruit::createComponent() 755 .install(getParentComponent, 5, std::string("Hello"), Arg{}); 756 } 757 ''' 758 expect_generic_compile_error( 759 r'error: use of deleted function .std::hash<Arg>::hash\(\).' 760 r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.' 761 r'|error: invalid use of incomplete type .struct std::hash<Arg>.' 762 r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.' 763 r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.' 764 r'|error C2064: term does not evaluate to a function taking 1 arguments', 765 COMMON_DEFINITIONS, 766 source) 767 768 def test_install_with_args_error_not_hashable_with_conversion(self): 769 source = ''' 770 struct Arg { 771 Arg(int) {} 772 Arg() = default; 773 Arg(const Arg&) = default; 774 Arg(Arg&&) = default; 775 Arg& operator=(const Arg&) = default; 776 Arg& operator=(Arg&&) = default; 777 }; 778 779 bool operator==(const Arg&, const Arg&); 780 781 fruit::Component<X> getParentComponent(int, std::string, Arg); 782 783 fruit::Component<X> getComponent() { 784 return fruit::createComponent() 785 .install(getParentComponent, 5, std::string("Hello"), 15); 786 } 787 ''' 788 expect_generic_compile_error( 789 r'error: use of deleted function .std::hash<Arg>::hash\(\).' 790 r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.' 791 r'|error: invalid use of incomplete type .struct std::hash<Arg>.' 792 r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.' 793 r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.' 794 r'|error C2064: term does not evaluate to a function taking 1 arguments', 795 COMMON_DEFINITIONS, 796 source) 797 798 @parameterized.parameters([ 799 'X', 800 'fruit::Annotated<Annotation1, X>', 801 ]) 802 def test_install_component_functions_deduped(self, XAnnot): 803 source = ''' 804 struct X {}; 805 806 X x; 807 808 fruit::Component<> getComponent() { 809 return fruit::createComponent() 810 .addInstanceMultibinding<XAnnot, X>(x); 811 } 812 813 fruit::Component<> getComponent2() { 814 return fruit::createComponent() 815 .install(getComponent); 816 } 817 818 fruit::Component<> getComponent3() { 819 return fruit::createComponent() 820 .install(getComponent); 821 } 822 823 fruit::Component<> getComponent4() { 824 return fruit::createComponent() 825 .install(getComponent2) 826 .install(getComponent3); 827 } 828 829 int main() { 830 fruit::Injector<> injector(getComponent4); 831 832 // We test multibindings because the effect on other bindings is not user-visible (that only affects 833 // performance). 834 std::vector<X*> multibindings = injector.getMultibindings<XAnnot>(); 835 Assert(multibindings.size() == 1); 836 Assert(multibindings[0] == &x); 837 } 838 ''' 839 expect_success( 840 COMMON_DEFINITIONS, 841 source, 842 locals()) 843 844 @parameterized.parameters([ 845 'X', 846 'fruit::Annotated<Annotation1, X>', 847 ]) 848 def test_install_component_functions_deduped_across_normalized_component(self, XAnnot): 849 source = ''' 850 struct X {}; 851 852 X x; 853 854 fruit::Component<> getComponent() { 855 return fruit::createComponent() 856 .addInstanceMultibinding<XAnnot, X>(x); 857 } 858 859 fruit::Component<> getComponent2() { 860 return fruit::createComponent() 861 .install(getComponent); 862 } 863 864 fruit::Component<> getComponent3() { 865 return fruit::createComponent() 866 .install(getComponent); 867 } 868 869 int main() { 870 fruit::NormalizedComponent<> normalizedComponent(getComponent2); 871 fruit::Injector<> injector(normalizedComponent, getComponent3); 872 873 // We test multibindings because the effect on other bindings is not user-visible (that only affects 874 // performance). 875 std::vector<X*> multibindings = injector.getMultibindings<XAnnot>(); 876 Assert(multibindings.size() == 1); 877 Assert(multibindings[0] == &x); 878 } 879 ''' 880 expect_success( 881 COMMON_DEFINITIONS, 882 source, 883 locals()) 884 885 @parameterized.parameters([ 886 'X', 887 'fruit::Annotated<Annotation1, X>', 888 ]) 889 def test_install_component_functions_with_args_deduped(self, XAnnot): 890 source = ''' 891 struct X {}; 892 893 X x; 894 895 fruit::Component<> getComponent(int) { 896 return fruit::createComponent() 897 .addInstanceMultibinding<XAnnot, X>(x); 898 } 899 900 fruit::Component<> getComponent2() { 901 return fruit::createComponent() 902 .install(getComponent, 1); 903 } 904 905 fruit::Component<> getComponent3() { 906 return fruit::createComponent() 907 .install(getComponent, 1); 908 } 909 910 fruit::Component<> getComponent4() { 911 return fruit::createComponent() 912 .install(getComponent2) 913 .install(getComponent3); 914 } 915 916 int main() { 917 fruit::Injector<> injector(getComponent4); 918 919 // We test multibindings because the effect on other bindings is not user-visible (that only affects 920 // performance). 921 std::vector<X*> multibindings = injector.getMultibindings<XAnnot>(); 922 Assert(multibindings.size() == 1); 923 Assert(multibindings[0] == &x); 924 } 925 ''' 926 expect_success( 927 COMMON_DEFINITIONS, 928 source, 929 locals()) 930 931 @parameterized.parameters([ 932 'X', 933 'fruit::Annotated<Annotation1, X>', 934 ]) 935 def test_install_component_functions_different_args_not_deduped(self, XAnnot): 936 source = ''' 937 struct X {}; 938 939 X x; 940 941 fruit::Component<> getComponent(int) { 942 return fruit::createComponent() 943 .addInstanceMultibinding<XAnnot, X>(x); 944 } 945 946 fruit::Component<> getComponent2() { 947 return fruit::createComponent() 948 .install(getComponent, 1); 949 } 950 951 fruit::Component<> getComponent3() { 952 return fruit::createComponent() 953 .install(getComponent, 2); 954 } 955 956 fruit::Component<> getComponent4() { 957 return fruit::createComponent() 958 .install(getComponent2) 959 .install(getComponent3); 960 } 961 962 int main() { 963 fruit::Injector<> injector(getComponent4); 964 965 // We test multibindings because the effect on other bindings is not user-visible (it only affects 966 // performance). 967 std::vector<X*> multibindings = injector.getMultibindings<XAnnot>(); 968 Assert(multibindings.size() == 2); 969 Assert(multibindings[0] == &x); 970 Assert(multibindings[1] == &x); 971 } 972 ''' 973 expect_success( 974 COMMON_DEFINITIONS, 975 source, 976 locals()) 977 978 def test_install_component_functions_loop(self): 979 source = ''' 980 struct X {}; 981 struct Y {}; 982 struct Z {}; 983 984 // X -> Y -> Z -> Y 985 986 fruit::Component<X> getXComponent(); 987 fruit::Component<Y> getYComponent(); 988 fruit::Component<Z> getZComponent(); 989 990 fruit::Component<X> getXComponent() { 991 return fruit::createComponent() 992 .registerConstructor<X()>() 993 .install(getYComponent); 994 } 995 996 fruit::Component<Y> getYComponent() { 997 return fruit::createComponent() 998 .registerConstructor<Y()>() 999 .install(getZComponent); 1000 } 1001 1002 fruit::Component<Z> getZComponent() { 1003 return fruit::createComponent() 1004 .registerConstructor<Z()>() 1005 .install(getYComponent); 1006 } 1007 1008 int main() { 1009 fruit::Injector<X> injector(getXComponent); 1010 (void)injector; 1011 } 1012 ''' 1013 expect_runtime_error( 1014 r'Component installation trace \(from top-level to the most deeply-nested\):\n' 1015 r'(class )?fruit::Component<(struct )?X> ?\((__cdecl)?\*\)\((void)?\)\n' 1016 r'<-- The loop starts here\n' 1017 r'(class )?fruit::Component<(struct )?Y> ?\((__cdecl)?\*\)\((void)?\)\n' 1018 r'(class )?fruit::Component<(struct )?Z> ?\((__cdecl)?\*\)\((void)?\)\n' 1019 r'(class )?fruit::Component<(struct )?Y> ?\((__cdecl)?\*\)\((void)?\)\n', 1020 COMMON_DEFINITIONS, 1021 source, 1022 locals()) 1023 1024 def test_install_component_functions_different_arguments_loop_not_reported(self): 1025 source = ''' 1026 struct X {}; 1027 struct Y {}; 1028 struct Z {}; 1029 1030 // X -> Y(1) -> Z -> Y(2) 1031 1032 fruit::Component<X> getXComponent(); 1033 fruit::Component<Y> getYComponent(int); 1034 fruit::Component<Z> getZComponent(); 1035 1036 fruit::Component<X> getXComponent() { 1037 return fruit::createComponent() 1038 .registerConstructor<X()>() 1039 .install(getYComponent, 1); 1040 } 1041 1042 fruit::Component<Y> getYComponent(int n) { 1043 if (n == 1) { 1044 return fruit::createComponent() 1045 .registerConstructor<Y()>() 1046 .install(getZComponent); 1047 } else { 1048 return fruit::createComponent() 1049 .registerConstructor<Y()>(); 1050 } 1051 } 1052 1053 fruit::Component<Z> getZComponent() { 1054 return fruit::createComponent() 1055 .registerConstructor<Z()>() 1056 .install(getYComponent, 2); 1057 } 1058 1059 int main() { 1060 fruit::Injector<X> injector(getXComponent); 1061 injector.get<X>(); 1062 } 1063 ''' 1064 expect_success( 1065 COMMON_DEFINITIONS, 1066 source, 1067 locals()) 1068 1069if __name__ == '__main__': 1070 absltest.main() 1071