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