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. 15import pytest 16 17from fruit_test_common import * 18from fruit_test_config import CXX_COMPILER_NAME 19 20COMMON_DEFINITIONS = ''' 21 #include "test_common.h" 22 23 struct Scaler; 24 struct ScalerImpl; 25 26 struct Annotation1 {}; 27 using ScalerAnnot1 = fruit::Annotated<Annotation1, Scaler>; 28 using ScalerImplAnnot1 = fruit::Annotated<Annotation1, ScalerImpl>; 29 30 struct Annotation2 {}; 31 using ScalerAnnot2 = fruit::Annotated<Annotation2, Scaler>; 32 using ScalerImplAnnot2 = fruit::Annotated<Annotation2, ScalerImpl>; 33 34 template <typename T> 35 using WithNoAnnotation = T; 36 37 template <typename T> 38 using WithAnnotation1 = fruit::Annotated<Annotation1, T>; 39 ''' 40 41@pytest.mark.parametrize('XFactoryAnnot', [ 42 'std::function<X()>', 43 'fruit::Annotated<Annotation1, std::function<X()>>', 44]) 45def test_register_factory_success_no_params_autoinject(XFactoryAnnot): 46 source = ''' 47 struct X { 48 INJECT(X()) = default; 49 }; 50 51 fruit::Component<XFactoryAnnot> getComponent() { 52 return fruit::createComponent(); 53 } 54 55 int main() { 56 fruit::Injector<XFactoryAnnot> injector(getComponent); 57 injector.get<XFactoryAnnot>()(); 58 } 59 ''' 60 expect_success( 61 COMMON_DEFINITIONS, 62 source, 63 locals()) 64 65@pytest.mark.parametrize('ConstructX,XPtrAnnot,XPtrFactoryAnnot', [ 66 ('X()', 'X', 'std::function<X()>'), 67 ('X()', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, std::function<X()>>'), 68 ('std::unique_ptr<X>()', 'std::unique_ptr<X>', 'std::function<std::unique_ptr<X>()>'), 69 ('std::unique_ptr<X>()', 'fruit::Annotated<Annotation1, std::unique_ptr<X>>', 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>'), 70]) 71def test_register_factory_success_no_params(ConstructX, XPtrAnnot, XPtrFactoryAnnot): 72 source = ''' 73 struct X {}; 74 75 fruit::Component<XPtrFactoryAnnot> getComponent() { 76 return fruit::createComponent() 77 .registerFactory<XPtrAnnot()>([](){return ConstructX;}); 78 } 79 80 int main() { 81 fruit::Injector<XPtrFactoryAnnot> injector(getComponent); 82 injector.get<XPtrFactoryAnnot>()(); 83 } 84 ''' 85 expect_success( 86 COMMON_DEFINITIONS, 87 source, 88 locals()) 89 90@pytest.mark.parametrize('MaybeConst', [ 91 '', 92 'const', 93]) 94def test_register_factory_autoinject_success(MaybeConst): 95 source = ''' 96 struct Scaler { 97 virtual double scale(double x) = 0; 98 virtual ~Scaler() = default; 99 }; 100 101 struct ScalerImpl : public Scaler { 102 private: 103 double factor; 104 105 public: 106 INJECT(ScalerImpl(ASSISTED(double) factor)) 107 : factor(factor) { 108 } 109 110 double scale(double x) override { 111 return x * factor; 112 } 113 }; 114 115 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 116 117 fruit::Component<MaybeConst ScalerFactory> getScalerComponent() { 118 return fruit::createComponent() 119 .bind<Scaler, ScalerImpl>(); 120 } 121 122 int main() { 123 fruit::Injector<MaybeConst ScalerFactory> injector(getScalerComponent); 124 ScalerFactory scalerFactory(injector); 125 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 126 std::cout << scaler->scale(3) << std::endl; 127 } 128 ''' 129 expect_success( 130 COMMON_DEFINITIONS, 131 source, 132 locals()) 133 134def test_register_factory_autoinject_abstract_class_with_no_virtual_destructor_error(): 135 source = ''' 136 struct Scaler { 137 virtual double scale(double x) = 0; 138 }; 139 140 struct ScalerImpl : public Scaler { 141 public: 142 INJECT(ScalerImpl(ASSISTED(double))) { 143 } 144 145 double scale(double x) override { 146 return x; 147 } 148 }; 149 150 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 151 152 fruit::Component<ScalerFactory> getScalerComponent() { 153 return fruit::createComponent() 154 .bind<Scaler, ScalerImpl>(); 155 } 156 ''' 157 expect_compile_error( 158 'FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError<std::function<std::unique_ptr<Scaler(,std::default_delete<Scaler>)?>\(double\)>,std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>>', 159 'Fruit was trying to bind BaseFactory to DerivedFactory but the return type of BaseFactory is a std::unique_ptr of a class with no virtual destructor', 160 COMMON_DEFINITIONS, 161 source, 162 locals()) 163 164def test_register_factory_autoinject_non_abstract_class_with_no_virtual_destructor_error(): 165 source = ''' 166 struct Scaler { 167 }; 168 169 struct ScalerImpl : public Scaler { 170 public: 171 INJECT(ScalerImpl(ASSISTED(double))) { 172 } 173 }; 174 175 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 176 177 fruit::Component<ScalerFactory> getScalerComponent() { 178 return fruit::createComponent() 179 .bind<Scaler, ScalerImpl>(); 180 } 181 ''' 182 expect_compile_error( 183 'FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError<std::function<std::unique_ptr<Scaler(,std::default_delete<Scaler>)?>\(double\)>,std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>>', 184 'Fruit was trying to bind BaseFactory to DerivedFactory but the return type of BaseFactory is a std::unique_ptr of a class with no virtual destructor', 185 COMMON_DEFINITIONS, 186 source, 187 locals()) 188 189@pytest.mark.parametrize('ScalerAnnot,ScalerFactoryAnnot,MaybeConstScalerFactoryAnnot', [ 190 ('Scaler', 191 'std::function<std::unique_ptr<Scaler>(double)>', 192 'std::function<std::unique_ptr<Scaler>(double)>'), 193 ('Scaler', 194 'std::function<std::unique_ptr<Scaler>(double)>', 195 'const std::function<std::unique_ptr<Scaler>(double)>'), 196 ('fruit::Annotated<Annotation1, Scaler>', 197 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>', 198 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'), 199 ('fruit::Annotated<Annotation1, Scaler>', 200 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>', 201 'fruit::Annotated<Annotation1, const std::function<std::unique_ptr<Scaler>(double)>>'), 202]) 203def test_autoinject(ScalerAnnot, ScalerFactoryAnnot, MaybeConstScalerFactoryAnnot): 204 source = ''' 205 struct Scaler { 206 virtual double scale(double x) = 0; 207 virtual ~Scaler() = default; 208 }; 209 210 struct ScalerImpl : public Scaler { 211 private: 212 double factor; 213 214 public: 215 INJECT(ScalerImpl(ASSISTED(double) factor)) 216 : factor(factor) { 217 } 218 219 double scale(double x) override { 220 return x * factor; 221 } 222 }; 223 224 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 225 226 fruit::Component<MaybeConstScalerFactoryAnnot> getScalerComponent() { 227 return fruit::createComponent() 228 .bind<ScalerAnnot, ScalerImpl>(); 229 } 230 231 int main() { 232 fruit::Injector<MaybeConstScalerFactoryAnnot> injector(getScalerComponent); 233 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 234 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 235 std::cout << scaler->scale(3) << std::endl; 236 } 237 ''' 238 expect_success( 239 COMMON_DEFINITIONS, 240 source, 241 locals()) 242 243@pytest.mark.parametrize('MaybeConst', [ 244 '', 245 'const', 246]) 247def test_autoinject_returning_value(MaybeConst): 248 source = ''' 249 struct X { 250 INJECT(X()) = default; 251 }; 252 253 struct Scaler { 254 private: 255 double factor; 256 257 public: 258 INJECT(Scaler(ASSISTED(double) factor, X)) 259 : factor(factor) { 260 } 261 262 double scale(double x) { 263 return x * factor; 264 } 265 }; 266 267 using ScalerFactory = std::function<Scaler(double)>; 268 269 fruit::Component<MaybeConst ScalerFactory> getScalerComponent() { 270 return fruit::createComponent(); 271 } 272 273 int main() { 274 fruit::Injector<MaybeConst ScalerFactory> injector(getScalerComponent); 275 ScalerFactory scalerFactory(injector); 276 Scaler scaler = scalerFactory(12.1); 277 std::cout << scaler.scale(3) << std::endl; 278 } 279 ''' 280 expect_success( 281 COMMON_DEFINITIONS, 282 source, 283 locals()) 284 285@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerFactoryAnnot,ScalerImplFactoryAnnotRegex', [ 286 ('Scaler', 287 'ScalerImpl', 288 'std::function<std::unique_ptr<Scaler>(double)>', 289 'std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>', 290 ), 291 ('fruit::Annotated<Annotation1, Scaler>', 292 'fruit::Annotated<Annotation2, ScalerImpl>', 293 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>', 294 'fruit::Annotated<Annotation2,std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>>', 295 ), 296]) 297def test_autoinject_error_abstract_class(ScalerAnnot, ScalerImplAnnot, ScalerFactoryAnnot, ScalerImplFactoryAnnotRegex): 298 source = ''' 299 struct Scaler { 300 virtual double scale(double x) = 0; 301 }; 302 303 struct ScalerImpl : public Scaler { 304 private: 305 double factor; 306 307 public: 308 ScalerImpl(double factor) 309 : factor(factor) { 310 } 311 312 // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class. 313 }; 314 315 fruit::Component<ScalerFactoryAnnot> getScalerComponent() { 316 return fruit::createComponent() 317 .bind<ScalerAnnot, ScalerImplAnnot>(); 318 } 319 ''' 320 expect_compile_error( 321 'NoBindingFoundForAbstractClassError<ScalerImplFactoryAnnotRegex,ScalerImpl>', 322 'No explicit binding was found for T, and note that C is an abstract class', 323 COMMON_DEFINITIONS, 324 source, 325 locals()) 326 327def test_autoinject_nonmovable_ok(): 328 source = ''' 329 struct I { 330 virtual ~I() = default; 331 }; 332 333 struct C : public I { 334 INJECT(C()) = default; 335 336 C(const C&) = delete; 337 C(C&&) = delete; 338 C& operator=(const C&) = delete; 339 C& operator=(C&&) = delete; 340 }; 341 342 using IFactory = std::function<std::unique_ptr<I>()>; 343 344 fruit::Component<IFactory> getIFactory() { 345 return fruit::createComponent() 346 .bind<I, C>(); 347 } 348 349 int main() { 350 fruit::Injector<IFactory> injector(getIFactory); 351 IFactory iFactory(injector); 352 std::unique_ptr<I> i = iFactory(); 353 (void)i; 354 } 355 ''' 356 expect_success( 357 COMMON_DEFINITIONS, 358 source) 359 360def test_autoinject_2_assisted_params(): 361 source = ''' 362 struct Foo { 363 Foo(int x, float y) { 364 (void)x; 365 (void)y; 366 } 367 }; 368 369 using FooFactory = std::function<Foo(int, float)>; 370 371 fruit::Component<FooFactory> getComponent() { 372 return fruit::createComponent() 373 .registerFactory<Foo(fruit::Assisted<int>, fruit::Assisted<float>)>( 374 [](int x, float y) { 375 return Foo(x, y); 376 }); 377 } 378 379 int main() { 380 fruit::Injector<FooFactory> injector(getComponent); 381 FooFactory fooFactory(injector); 382 Foo foo = fooFactory(1, 2.3f); 383 (void)foo; 384 } 385 ''' 386 expect_success( 387 COMMON_DEFINITIONS, 388 source) 389 390def test_autoinject_2_assisted_params_returning_value(): 391 source = ''' 392 struct Foo { 393 Foo(int x, float y) { 394 (void)x; 395 (void)y; 396 } 397 }; 398 399 using FooFactory = std::function<Foo(int, float)>; 400 401 fruit::Component<FooFactory> getComponent() { 402 return fruit::createComponent() 403 .registerFactory<Foo(fruit::Assisted<int>, fruit::Assisted<float>)>( 404 [](int x, float y) { 405 return Foo(x, y); 406 }); 407 } 408 409 int main() { 410 fruit::Injector<FooFactory> injector(getComponent); 411 FooFactory fooFactory(injector); 412 Foo foo = fooFactory(1, 2.3f); 413 (void)foo; 414 } 415 ''' 416 expect_success( 417 COMMON_DEFINITIONS, 418 source) 419 420def test_autoinject_instances_bound_to_assisted_params(): 421 source = ''' 422 struct X {}; 423 struct Y {}; 424 425 struct Foo { 426 Foo(X x, Y y) { 427 (void)x; 428 (void)y; 429 } 430 }; 431 432 using FooFactory = std::function<Foo()>; 433 434 fruit::Component<FooFactory> getComponent() { 435 static X x = X(); 436 static Y y = Y(); 437 return fruit::createComponent() 438 .bindInstance(x) 439 .bindInstance(y) 440 .registerFactory<Foo(X, Y)>( 441 [](X x, Y y) { 442 return Foo(x, y); 443 }); 444 } 445 446 447 int main() { 448 fruit::Injector<FooFactory> injector(getComponent); 449 FooFactory fooFactory(injector); 450 Foo foo = fooFactory(); 451 (void)foo; 452 } 453 ''' 454 expect_success( 455 COMMON_DEFINITIONS, 456 source) 457 458def test_autoinject_2_assisted_params_plus_nonassisted_params(): 459 source = ''' 460 struct X {}; 461 struct Y {}; 462 struct Z {}; 463 464 struct Foo { 465 Foo(X, Y, int, float, Z) { 466 } 467 }; 468 469 using FooPtrFactory = std::function<std::unique_ptr<Foo>(int, float)>; 470 471 fruit::Component<FooPtrFactory> getComponent() { 472 static X x = X(); 473 static Y y = Y(); 474 static Z z = Z(); 475 return fruit::createComponent() 476 .bindInstance(x) 477 .bindInstance(y) 478 .bindInstance(z) 479 .registerFactory<std::unique_ptr<Foo>(X, Y, fruit::Assisted<int>, fruit::Assisted<float>, Z)>( 480 [](X x, Y y, int n, float a, Z z) { 481 return std::unique_ptr<Foo>(new Foo(x, y, n, a, z)); 482 }); 483 } 484 485 int main() { 486 fruit::Injector<FooPtrFactory> injector(getComponent); 487 FooPtrFactory fooPtrFactory(injector); 488 std::unique_ptr<Foo> foo = fooPtrFactory(1, 3.4f); 489 (void)foo; 490 } 491 ''' 492 expect_success( 493 COMMON_DEFINITIONS, 494 source) 495 496def test_autoinject_2_assisted_params_plus_nonassisted_params_returning_value(): 497 source = ''' 498 struct X {}; 499 struct Y {}; 500 struct Z {}; 501 502 struct Foo { 503 Foo(X, Y, int, float, Z) { 504 } 505 }; 506 507 using FooFactory = std::function<Foo(int, float)>; 508 509 fruit::Component<FooFactory> getComponent() { 510 static X x = X(); 511 static Y y = Y(); 512 static Z z = Z(); 513 return fruit::createComponent() 514 .bindInstance(x) 515 .bindInstance(y) 516 .bindInstance(z) 517 .registerFactory<Foo(X, Y, fruit::Assisted<int>, fruit::Assisted<float>, Z)>( 518 [](X x, Y y, int n, float a, Z z) { 519 return Foo(x, y, n, a, z); 520 }); 521 } 522 523 int main() { 524 fruit::Injector<FooFactory> injector(getComponent); 525 FooFactory fooFactory(injector); 526 Foo foo = fooFactory(1, 3.4f); 527 (void)foo; 528 } 529 ''' 530 expect_success( 531 COMMON_DEFINITIONS, 532 source) 533 534def test_autoinject_mixed_assisted_and_injected_params(): 535 source = ''' 536 struct X {}; 537 struct Y {}; 538 539 struct Foo { 540 Foo(int, float, X, Y, double) { 541 } 542 }; 543 544 using FooFactory = std::function<Foo(int, float, double)>; 545 546 fruit::Component<FooFactory> getComponent() { 547 static X x = X(); 548 static Y y = Y(); 549 return fruit::createComponent() 550 .bindInstance(x) 551 .bindInstance(y) 552 .registerFactory<Foo(fruit::Assisted<int>, fruit::Assisted<float>, X, Y, fruit::Assisted<double>)>( 553 [](int n, float a, X x, Y y, double d) { 554 return Foo(n, a, x, y, d); 555 }); 556 } 557 558 int main() { 559 fruit::Injector<FooFactory> injector(getComponent); 560 FooFactory fooFactory(injector); 561 Foo foo = fooFactory(1, 3.4f, 3.456); 562 (void)foo; 563 } 564 ''' 565 expect_success( 566 COMMON_DEFINITIONS, 567 source) 568 569def test_autoinject_annotation_in_signature_return_type(): 570 source = ''' 571 struct X { 572 using Inject = fruit::Annotated<Annotation1, X>(); 573 }; 574 575 fruit::Component<fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>> getComponent() { 576 return fruit::createComponent(); 577 } 578 ''' 579 expect_compile_error( 580 'InjectTypedefWithAnnotationError<X>', 581 'C::Inject is a signature that returns an annotated type', 582 COMMON_DEFINITIONS, 583 source) 584 585def test_autoinject_annotation_in_signature_return_type_returning_value(): 586 source = ''' 587 struct X { 588 using Inject = fruit::Annotated<Annotation1, X>(); 589 }; 590 591 fruit::Component<fruit::Annotated<Annotation1, std::function<X()>>> getComponent() { 592 return fruit::createComponent(); 593 } 594 ''' 595 expect_compile_error( 596 'InjectTypedefWithAnnotationError<X>', 597 'C::Inject is a signature that returns an annotated type', 598 COMMON_DEFINITIONS, 599 source) 600 601def test_autoinject_from_provider_simple(): 602 source = ''' 603 struct X { 604 INJECT(X()) = default; 605 }; 606 607 struct Scaler { 608 virtual double scale(double x) = 0; 609 virtual ~Scaler() = default; 610 }; 611 612 struct ScalerImpl : public Scaler { 613 private: 614 double factor; 615 616 public: 617 ScalerImpl(double factor, X) 618 : factor(factor) { 619 } 620 621 double scale(double x) override { 622 return x * factor; 623 } 624 }; 625 626 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 627 628 fruit::Component<ScalerFactory> getScalerComponent() { 629 return fruit::createComponent() 630 .registerProvider([](X x) { 631 return std::function<std::unique_ptr<ScalerImpl>(double)>([x](double n){ 632 return std::unique_ptr<ScalerImpl>(new ScalerImpl(n, x)); 633 }); 634 }) 635 .bind<Scaler, ScalerImpl>(); 636 } 637 638 int main() { 639 fruit::Injector<ScalerFactory> injector(getScalerComponent); 640 ScalerFactory scalerFactory(injector); 641 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 642 std::cout << scaler->scale(3) << std::endl; 643 } 644 ''' 645 expect_success( 646 COMMON_DEFINITIONS, 647 source) 648 649@pytest.mark.parametrize('ScalerAnnot,ScalerFactoryAnnot,MaybeConstScalerFactoryAnnot,ScalerImplAnnot,ScalerImplFactoryAnnot', [ 650 ('Scaler', 651 'std::function<std::unique_ptr<Scaler>(double)>', 652 'std::function<std::unique_ptr<Scaler>(double)>', 653 'ScalerImpl', 654 'std::function<std::unique_ptr<ScalerImpl>(double)>'), 655 ('Scaler', 656 'std::function<std::unique_ptr<Scaler>(double)>', 657 'const std::function<std::unique_ptr<Scaler>(double)>', 658 'ScalerImpl', 659 'std::function<std::unique_ptr<ScalerImpl>(double)>'), 660 ('fruit::Annotated<Annotation1, Scaler>', 661 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>', 662 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>', 663 'fruit::Annotated<Annotation2, ScalerImpl>', 664 'fruit::Annotated<Annotation2, std::function<std::unique_ptr<ScalerImpl>(double)>>'), 665 ('fruit::Annotated<Annotation1, Scaler>', 666 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>', 667 'fruit::Annotated<Annotation1, const std::function<std::unique_ptr<Scaler>(double)>>', 668 'fruit::Annotated<Annotation2, ScalerImpl>', 669 'fruit::Annotated<Annotation2, std::function<std::unique_ptr<ScalerImpl>(double)>>'), 670]) 671def test_autoinject_from_provider(ScalerAnnot, ScalerFactoryAnnot, MaybeConstScalerFactoryAnnot, ScalerImplAnnot, ScalerImplFactoryAnnot): 672 source = ''' 673 struct X { 674 INJECT(X()) = default; 675 }; 676 677 struct Scaler { 678 virtual double scale(double x) = 0; 679 virtual ~Scaler() = default; 680 }; 681 682 struct ScalerImpl : public Scaler { 683 private: 684 double factor; 685 686 public: 687 ScalerImpl(double factor, X) 688 : factor(factor) { 689 } 690 691 double scale(double x) override { 692 return x * factor; 693 } 694 }; 695 696 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 697 using ScalerImplFactory = std::function<std::unique_ptr<ScalerImpl>(double)>; 698 699 fruit::Component<MaybeConstScalerFactoryAnnot> getScalerComponent() { 700 return fruit::createComponent() 701 .registerProvider<ScalerImplFactoryAnnot(X)>([](X x) { 702 return std::function<std::unique_ptr<ScalerImpl>(double)>([x](double n){ 703 return std::unique_ptr<ScalerImpl>(new ScalerImpl(n, x)); 704 }); 705 }) 706 .bind<ScalerAnnot, ScalerImplAnnot>(); 707 } 708 709 int main() { 710 fruit::Injector<MaybeConstScalerFactoryAnnot> injector(getScalerComponent); 711 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 712 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 713 std::cout << scaler->scale(3) << std::endl; 714 } 715 ''' 716 expect_success( 717 COMMON_DEFINITIONS, 718 source, 719 locals()) 720 721@pytest.mark.parametrize('ScalerFactoryAnnot', [ 722 'ScalerFactory', 723 'fruit::Annotated<Annotation1, ScalerFactory>', 724]) 725def test_autoinject_from_provider_returning_value(ScalerFactoryAnnot): 726 source = ''' 727 struct X { 728 INJECT(X()) = default; 729 }; 730 731 struct Scaler { 732 private: 733 double factor; 734 735 public: 736 Scaler(double factor, X) 737 : factor(factor) { 738 } 739 740 double scale(double x) { 741 return x * factor; 742 } 743 }; 744 745 using ScalerFactory = std::function<Scaler(double)>; 746 747 fruit::Component<ScalerFactoryAnnot> getScalerComponent() { 748 return fruit::createComponent() 749 .registerProvider<ScalerFactoryAnnot(X)>([](X x) { 750 return std::function<Scaler(double)>([x](double n){ 751 return Scaler(n, x); 752 }); 753 }); 754 } 755 756 int main() { 757 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent); 758 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 759 Scaler scaler = scalerFactory(12.1); 760 std::cout << scaler.scale(3) << std::endl; 761 } 762 ''' 763 expect_success( 764 COMMON_DEFINITIONS, 765 source, 766 locals()) 767 768@pytest.mark.parametrize('MaybeConst', [ 769 '', 770 'const', 771]) 772@pytest.mark.parametrize('X_ANNOT', [ 773 'X', 774 'ANNOTATED(Annotation1, X)', 775]) 776def test_autoinject_with_binding(MaybeConst, X_ANNOT): 777 source = ''' 778 struct X { 779 using Inject = X(); 780 }; 781 782 struct Scaler { 783 virtual double scale(double x) = 0; 784 virtual ~Scaler() = default; 785 }; 786 787 struct ScalerImpl : public Scaler { 788 private: 789 double factor; 790 791 public: 792 INJECT(ScalerImpl(ASSISTED(double) factor, X_ANNOT x)) 793 : factor(factor) { 794 (void)x; 795 } 796 797 double scale(double x) override { 798 return x * factor; 799 } 800 }; 801 802 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 803 804 fruit::Component<MaybeConst ScalerFactory> getScalerComponent() { 805 return fruit::createComponent() 806 .bind<Scaler, ScalerImpl>(); 807 } 808 809 int main() { 810 fruit::Injector<MaybeConst ScalerFactory> injector(getScalerComponent); 811 ScalerFactory scalerFactory(injector); 812 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 813 std::cout << scaler->scale(3) << std::endl; 814 } 815 ''' 816 expect_success( 817 COMMON_DEFINITIONS, 818 source, 819 locals()) 820 821@pytest.mark.parametrize('MaybeConst', [ 822 '', 823 'const', 824]) 825@pytest.mark.parametrize('X_ANNOT', [ 826 'X', 827 'ANNOTATED(Annotation1, X)', 828]) 829def test_autoinject_with_binding_returning_value(MaybeConst, X_ANNOT): 830 source = ''' 831 struct X { 832 using Inject = X(); 833 }; 834 835 struct Scaler { 836 private: 837 double factor; 838 839 public: 840 INJECT(Scaler(ASSISTED(double) factor, X_ANNOT x)) 841 : factor(factor) { 842 (void)x; 843 } 844 845 double scale(double x) { 846 return x * factor; 847 } 848 }; 849 850 using ScalerFactory = std::function<Scaler(double)>; 851 852 fruit::Component<MaybeConst ScalerFactory> getScalerComponent() { 853 return fruit::createComponent(); 854 } 855 856 int main() { 857 fruit::Injector<MaybeConst ScalerFactory> injector(getScalerComponent); 858 ScalerFactory scalerFactory(injector); 859 Scaler scaler = scalerFactory(12.1); 860 std::cout << scaler.scale(3) << std::endl; 861 } 862 ''' 863 expect_success( 864 COMMON_DEFINITIONS, 865 source, 866 locals()) 867 868def test_autoinject_with_binding2(): 869 source = ''' 870 struct X { 871 INJECT(X()) = default; 872 }; 873 874 struct Scaler { 875 virtual double scale(double x) = 0; 876 virtual ~Scaler() = default; 877 }; 878 879 struct ScalerImpl : public Scaler { 880 private: 881 double factor; 882 883 public: 884 INJECT(ScalerImpl(X, ASSISTED(double) factor)) 885 : factor(factor) { 886 } 887 888 double scale(double x) override { 889 return x * factor; 890 } 891 }; 892 893 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 894 895 fruit::Component<ScalerFactory> getScalerComponent() { 896 return fruit::createComponent() 897 .bind<Scaler, ScalerImpl>(); 898 } 899 900 int main() { 901 fruit::Injector<ScalerFactory> injector(getScalerComponent); 902 ScalerFactory scalerFactory(injector); 903 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 904 std::cout << scaler->scale(3) << std::endl; 905 } 906 ''' 907 expect_success( 908 COMMON_DEFINITIONS, 909 source) 910 911def test_autoinject_with_binding2_returning_value(): 912 source = ''' 913 struct X { 914 INJECT(X()) = default; 915 }; 916 917 struct Scaler { 918 private: 919 double factor; 920 921 public: 922 INJECT(Scaler(X, ASSISTED(double) factor)) 923 : factor(factor) { 924 } 925 926 double scale(double x) { 927 return x * factor; 928 } 929 }; 930 931 using ScalerFactory = std::function<Scaler(double)>; 932 933 fruit::Component<ScalerFactory> getScalerComponent() { 934 return fruit::createComponent(); 935 } 936 937 int main() { 938 fruit::Injector<ScalerFactory> injector(getScalerComponent); 939 ScalerFactory scalerFactory(injector); 940 Scaler scaler = scalerFactory(12.1); 941 std::cout << scaler.scale(3) << std::endl; 942 } 943 ''' 944 expect_success( 945 COMMON_DEFINITIONS, 946 source) 947 948@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerFactoryAnnot', [ 949 ('Scaler', 950 'ScalerImpl', 951 'std::function<std::unique_ptr<Scaler>(double)>'), 952 ('fruit::Annotated<Annotation1, Scaler>', 953 'fruit::Annotated<Annotation2, ScalerImpl>', 954 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'), 955]) 956def test_register_factory_success(ScalerAnnot, ScalerImplAnnot, ScalerFactoryAnnot): 957 source = ''' 958 struct Scaler { 959 virtual double scale(double x) = 0; 960 virtual ~Scaler() = default; 961 }; 962 963 struct ScalerImpl : public Scaler { 964 private: 965 double factor; 966 967 public: 968 ScalerImpl(double factor) 969 : factor(factor) { 970 } 971 972 double scale(double x) override { 973 return x * factor; 974 } 975 }; 976 977 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 978 979 fruit::Component<ScalerFactoryAnnot> getScalerComponent() { 980 return fruit::createComponent() 981 .bind<ScalerAnnot, ScalerImplAnnot>() 982 .registerFactory<ScalerImplAnnot(fruit::Assisted<double>)>([](double factor) { return ScalerImpl(factor); }); 983 } 984 985 int main() { 986 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent); 987 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 988 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 989 std::cout << scaler->scale(3) << std::endl; 990 } 991 ''' 992 expect_success( 993 COMMON_DEFINITIONS, 994 source, 995 locals()) 996 997def test_register_factory_with_annotation_returning_value(): 998 source = ''' 999 struct Scaler { 1000 private: 1001 double factor; 1002 1003 public: 1004 Scaler(double factor) 1005 : factor(factor) { 1006 } 1007 1008 double scale(double x) { 1009 return x * factor; 1010 } 1011 }; 1012 1013 using ScalerFactory = std::function<Scaler(double)>; 1014 using ScalerFactoryAnnot1 = fruit::Annotated<Annotation1, ScalerFactory>; 1015 1016 fruit::Component<ScalerFactoryAnnot1> getScalerComponent() { 1017 return fruit::createComponent() 1018 .registerFactory<ScalerAnnot1(fruit::Assisted<double>)>( 1019 [](double factor) { 1020 return Scaler(factor); 1021 }); 1022 } 1023 1024 int main() { 1025 fruit::Injector<ScalerFactoryAnnot1> injector(getScalerComponent); 1026 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot1>(); 1027 Scaler scaler = scalerFactory(12.1); 1028 std::cout << scaler.scale(3) << std::endl; 1029 } 1030 ''' 1031 expect_success( 1032 COMMON_DEFINITIONS, 1033 source) 1034 1035def test_register_factory_with_different_annotation(): 1036 source = ''' 1037 struct Scaler { 1038 virtual double scale(double x) = 0; 1039 virtual ~Scaler() = default; 1040 }; 1041 1042 struct ScalerImpl : public Scaler { 1043 private: 1044 double factor; 1045 1046 public: 1047 ScalerImpl(double factor) 1048 : factor(factor) { 1049 } 1050 1051 double scale(double x) override { 1052 return x * factor; 1053 } 1054 }; 1055 1056 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 1057 using ScalerFactoryAnnot1 = fruit::Annotated<Annotation1, ScalerFactory>; 1058 1059 fruit::Component<ScalerFactoryAnnot1> getScalerComponent() { 1060 return fruit::createComponent() 1061 .bind<ScalerAnnot1, ScalerImplAnnot2>() 1062 .registerFactory<ScalerImplAnnot2(fruit::Assisted<double>)>( 1063 [](double factor) { 1064 return ScalerImpl(factor); 1065 }); 1066 } 1067 1068 int main() { 1069 fruit::Injector<ScalerFactoryAnnot1> injector(getScalerComponent); 1070 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot1>(); 1071 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 1072 std::cout << scaler->scale(3) << std::endl; 1073 } 1074 ''' 1075 expect_success( 1076 COMMON_DEFINITIONS, 1077 source) 1078 1079 1080@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerFactoryAnnot', [ 1081 ('Scaler', 1082 'ScalerImpl', 1083 'std::function<std::unique_ptr<Scaler>(double, double)>'), 1084 ('fruit::Annotated<Annotation1, Scaler>', 1085 'fruit::Annotated<Annotation2, ScalerImpl>', 1086 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double, double)>>'), 1087]) 1088def test_register_factory_2arg_success(ScalerAnnot, ScalerImplAnnot, ScalerFactoryAnnot): 1089 source = ''' 1090 struct Scaler { 1091 virtual double scale(double x) = 0; 1092 virtual ~Scaler() = default; 1093 }; 1094 1095 struct ScalerImpl : public Scaler { 1096 private: 1097 double factor; 1098 1099 public: 1100 ScalerImpl(double factor) 1101 : factor(factor) { 1102 } 1103 1104 double scale(double x) override { 1105 return x * factor; 1106 } 1107 }; 1108 1109 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double, double)>; 1110 1111 fruit::Component<ScalerFactoryAnnot> getScalerComponent() { 1112 return fruit::createComponent() 1113 .bind<ScalerAnnot, ScalerImplAnnot>() 1114 .registerFactory<ScalerImplAnnot(fruit::Assisted<double>, fruit::Assisted<double>)>( 1115 [](double factor, double) { 1116 return ScalerImpl(factor); 1117 }); 1118 } 1119 1120 int main() { 1121 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent); 1122 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 1123 std::unique_ptr<Scaler> scaler = scalerFactory(12.1, 34.2); 1124 std::cout << scaler->scale(3) << std::endl; 1125 } 1126 ''' 1127 expect_success( 1128 COMMON_DEFINITIONS, 1129 source, 1130 locals()) 1131 1132def test_register_factory_with_different_annotation_error(): 1133 source = ''' 1134 struct Scaler { 1135 virtual double scale(double x) = 0; 1136 }; 1137 1138 struct ScalerImpl : public Scaler { 1139 private: 1140 double factor; 1141 1142 public: 1143 ScalerImpl(double factor) 1144 : factor(factor) { 1145 } 1146 1147 double scale(double x) override { 1148 return x * factor; 1149 } 1150 }; 1151 1152 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 1153 using ScalerFactoryAnnot1 = fruit::Annotated<Annotation1, ScalerFactory>; 1154 1155 fruit::Component<ScalerFactoryAnnot1> getScalerComponent() { 1156 return fruit::createComponent() 1157 .bind<ScalerAnnot1, ScalerImplAnnot1>() 1158 .registerFactory<ScalerImplAnnot2(fruit::Assisted<double>)>([](double factor) { return ScalerImpl(factor); }); 1159 } 1160 1161 int main() { 1162 fruit::Injector<ScalerFactoryAnnot1> injector(getScalerComponent); 1163 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot1>(); 1164 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 1165 std::cout << scaler->scale(3) << std::endl; 1166 } 1167 ''' 1168 expect_compile_error( 1169 'NoBindingFoundError<fruit::Annotated<Annotation1,std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>>>', 1170 '', 1171 COMMON_DEFINITIONS, 1172 source) 1173 1174 1175def test_register_factory_dep_on_provider(): 1176 source = ''' 1177 struct Scaler { 1178 virtual double scale(double x) = 0; 1179 virtual ~Scaler() = default; 1180 }; 1181 1182 struct ScalerImpl : public Scaler { 1183 private: 1184 double factor; 1185 1186 public: 1187 ScalerImpl(double factor) 1188 : factor(factor) { 1189 } 1190 1191 double scale(double x) override { 1192 return x * factor; 1193 } 1194 }; 1195 1196 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 1197 1198 fruit::Component<ScalerFactory> getScalerComponent() { 1199 return fruit::createComponent() 1200 .bind<Scaler, ScalerImpl>() 1201 .registerProvider([](){return 23;}) 1202 .registerFactory<ScalerImpl(fruit::Assisted<double>, fruit::Provider<int>)>( 1203 [](double factor, fruit::Provider<int> provider) { 1204 return ScalerImpl(factor * provider.get<int>()); 1205 }); 1206 } 1207 1208 int main() { 1209 fruit::Injector<ScalerFactory> injector(getScalerComponent); 1210 ScalerFactory scalerFactory(injector); 1211 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 1212 std::cout << scaler->scale(3) << std::endl; 1213 } 1214 ''' 1215 expect_success( 1216 COMMON_DEFINITIONS, 1217 source) 1218 1219def test_register_factory_dep_on_provider_returning_value(): 1220 source = ''' 1221 struct Scaler { 1222 private: 1223 double factor; 1224 1225 public: 1226 Scaler(double factor) 1227 : factor(factor) { 1228 } 1229 1230 double scale(double x) { 1231 return x * factor; 1232 } 1233 }; 1234 1235 using ScalerFactory = std::function<Scaler(double)>; 1236 1237 fruit::Component<ScalerFactory> getScalerComponent() { 1238 return fruit::createComponent() 1239 .registerProvider([](){return 23;}) 1240 .registerFactory<Scaler(fruit::Assisted<double>, fruit::Provider<int>)>( 1241 [](double factor, fruit::Provider<int> provider) { 1242 return Scaler(factor * provider.get<int>()); 1243 }); 1244 } 1245 1246 int main() { 1247 fruit::Injector<ScalerFactory> injector(getScalerComponent); 1248 ScalerFactory scalerFactory(injector); 1249 Scaler scaler = scalerFactory(12.1); 1250 std::cout << scaler.scale(3) << std::endl; 1251 } 1252 ''' 1253 expect_success( 1254 COMMON_DEFINITIONS, 1255 source) 1256 1257def test_register_factory_error_abstract_class(): 1258 source = ''' 1259 struct Scaler { 1260 virtual double scale(double x) = 0; 1261 }; 1262 1263 struct ScalerImpl : public Scaler { 1264 private: 1265 double factor; 1266 1267 public: 1268 ScalerImpl(double factor) 1269 : factor(factor) { 1270 } 1271 1272 // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class. 1273 }; 1274 1275 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 1276 1277 fruit::Component<ScalerFactory> getScalerComponent() { 1278 return fruit::createComponent() 1279 .bind<Scaler, ScalerImpl>() 1280 .registerFactory<fruit::Annotated<Annotation1, ScalerImpl>(fruit::Assisted<double>)>([](double) { return (ScalerImpl*)nullptr; }); 1281 } 1282 ''' 1283 expect_compile_error( 1284 'CannotConstructAbstractClassError<ScalerImpl>', 1285 'The specified class can.t be constructed because it.s an abstract class.', 1286 COMMON_DEFINITIONS, 1287 source) 1288 1289def test_register_factory_error_not_function(): 1290 source = ''' 1291 struct X { 1292 X(int) {} 1293 }; 1294 1295 fruit::Component<std::function<X()>> getComponent() { 1296 int n = 3; 1297 return fruit::createComponent() 1298 .registerFactory<X()>([=]{return X(n);}); 1299 } 1300 ''' 1301 expect_compile_error( 1302 'LambdaWithCapturesError<.*>', 1303 'Only lambdas with no captures are supported', 1304 COMMON_DEFINITIONS, 1305 source) 1306 1307@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerImplPtrAnnot,ScalerFactoryAnnot,ScalerImplFactorySignatureAnnotRegex', [ 1308 ('Scaler', 1309 'ScalerImpl', 1310 'ScalerImpl*', 1311 'std::function<std::unique_ptr<Scaler>(double)>', 1312 'ScalerImpl\*\(fruit::Assisted<double>\)'), 1313 ('fruit::Annotated<Annotation1, Scaler>', 1314 'fruit::Annotated<Annotation2, ScalerImpl>', 1315 'fruit::Annotated<Annotation2, ScalerImpl*>', 1316 'fruit::Annotated<Annotation2, std::function<std::unique_ptr<Scaler>(double)>>', 1317 'fruit::Annotated<Annotation2,ScalerImpl\*>\(fruit::Assisted<double>\)') 1318]) 1319def test_register_factory_for_pointer(ScalerAnnot, ScalerImplAnnot, ScalerImplPtrAnnot, ScalerFactoryAnnot, ScalerImplFactorySignatureAnnotRegex): 1320 source = ''' 1321 struct Scaler { 1322 virtual double scale(double x) = 0; 1323 }; 1324 1325 struct ScalerImpl : public Scaler { 1326 private: 1327 double factor; 1328 1329 public: 1330 ScalerImpl(double factor) 1331 : factor(factor) { 1332 } 1333 1334 double scale(double x) override { 1335 return x * factor; 1336 } 1337 }; 1338 1339 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 1340 1341 fruit::Component<ScalerFactoryAnnot> getScalerComponent() { 1342 return fruit::createComponent() 1343 .bind<ScalerAnnot, ScalerImplAnnot>() 1344 .registerFactory<ScalerImplPtrAnnot(fruit::Assisted<double>)>([](double factor) { return new ScalerImpl(factor); }); 1345 } 1346 1347 int main() { 1348 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent); 1349 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 1350 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 1351 std::cout << scaler->scale(3) << std::endl; 1352 } 1353 ''' 1354 expect_compile_error( 1355 'FactoryReturningPointerError<ScalerImplFactorySignatureAnnotRegex>', 1356 'The specified factory returns a pointer. This is not supported', 1357 COMMON_DEFINITIONS, 1358 source, 1359 locals()) 1360 1361@pytest.mark.parametrize('ScalerPtrAnnot,ScalerFactoryAnnot,ScalerFactorySignatureAnnotRegex', [ 1362 ('Scaler*', 1363 'std::function<Scaler(double)>', 1364 'Scaler\*\(fruit::Assisted<double>\)'), 1365 ('fruit::Annotated<Annotation1, Scaler*>', 1366 'fruit::Annotated<Annotation1, std::function<Scaler(double)>>', 1367 'fruit::Annotated<Annotation1,Scaler\*>\(fruit::Assisted<double>\)'), 1368]) 1369def test_register_factory_for_pointer_returning_value(ScalerPtrAnnot, ScalerFactoryAnnot, ScalerFactorySignatureAnnotRegex): 1370 source = ''' 1371 struct Scaler { 1372 private: 1373 double factor; 1374 1375 public: 1376 Scaler(double factor) 1377 : factor(factor) { 1378 } 1379 1380 double scale(double x) { 1381 return x * factor; 1382 } 1383 }; 1384 1385 using ScalerFactory = std::function<Scaler(double)>; 1386 1387 fruit::Component<ScalerFactoryAnnot> getScalerComponent() { 1388 return fruit::createComponent() 1389 .registerFactory<ScalerPtrAnnot(fruit::Assisted<double>)>([](double factor) { return new Scaler(factor); }); 1390 } 1391 1392 int main() { 1393 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent); 1394 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 1395 Scaler scaler = scalerFactory(12.1); 1396 std::cout << scaler.scale(3) << std::endl; 1397 } 1398 ''' 1399 expect_compile_error( 1400 'FactoryReturningPointerError<ScalerFactorySignatureAnnotRegex>', 1401 'The specified factory returns a pointer. This is not supported', 1402 COMMON_DEFINITIONS, 1403 source, 1404 locals()) 1405 1406@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerImplPtrAnnot,ScalerFactoryAnnot', [ 1407 ('Scaler', 1408 'ScalerImpl', 1409 'std::unique_ptr<ScalerImpl>', 1410 'std::function<std::unique_ptr<Scaler>(double)>'), 1411 ('fruit::Annotated<Annotation1, Scaler>', 1412 'fruit::Annotated<Annotation2, ScalerImpl>', 1413 'fruit::Annotated<Annotation2, std::unique_ptr<ScalerImpl>>', 1414 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'), 1415]) 1416def test_register_factory_for_unique_pointer(ScalerAnnot, ScalerImplAnnot, ScalerImplPtrAnnot, ScalerFactoryAnnot): 1417 source = ''' 1418 struct Scaler { 1419 virtual double scale(double x) = 0; 1420 virtual ~Scaler() = default; 1421 }; 1422 1423 struct ScalerImpl : public Scaler { 1424 private: 1425 double factor; 1426 1427 public: 1428 ScalerImpl(double factor) 1429 : factor(factor) { 1430 } 1431 1432 double scale(double x) override { 1433 return x * factor; 1434 } 1435 }; 1436 1437 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 1438 1439 fruit::Component<ScalerFactoryAnnot> getScalerComponent() { 1440 return fruit::createComponent() 1441 .bind<ScalerAnnot, ScalerImplAnnot>() 1442 .registerFactory<ScalerImplPtrAnnot(fruit::Assisted<double>)>( 1443 [](double factor) { 1444 return std::unique_ptr<ScalerImpl>(new ScalerImpl(factor)); 1445 }); 1446 } 1447 1448 int main() { 1449 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent); 1450 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 1451 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 1452 std::cout << scaler->scale(3) << std::endl; 1453 } 1454 ''' 1455 expect_success( 1456 COMMON_DEFINITIONS, 1457 source, 1458 locals()) 1459 1460@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerImplPtrAnnot,ScalerFactoryAnnot', [ 1461 ('Scaler', 1462 'ScalerImpl', 1463 'std::unique_ptr<ScalerImpl>', 1464 'std::function<std::unique_ptr<Scaler>(double)>'), 1465 ('fruit::Annotated<Annotation1, Scaler>', 1466 'fruit::Annotated<Annotation2, ScalerImpl>', 1467 'fruit::Annotated<Annotation2, std::unique_ptr<ScalerImpl>>', 1468 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'), 1469]) 1470def test_register_factory_for_unique_pointer_returning_invalid_unique_ptr_ok(ScalerAnnot, ScalerImplAnnot, ScalerImplPtrAnnot, ScalerFactoryAnnot): 1471 source = ''' 1472 struct Scaler { 1473 virtual double scale(double x) = 0; 1474 virtual ~Scaler() = default; 1475 }; 1476 1477 struct ScalerImpl : public Scaler { 1478 private: 1479 double factor; 1480 1481 public: 1482 ScalerImpl(double factor) 1483 : factor(factor) { 1484 } 1485 1486 double scale(double x) override { 1487 return x * factor; 1488 } 1489 }; 1490 1491 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 1492 1493 fruit::Component<ScalerFactoryAnnot> getScalerComponent() { 1494 return fruit::createComponent() 1495 .bind<ScalerAnnot, ScalerImplAnnot>() 1496 .registerFactory<ScalerImplPtrAnnot(fruit::Assisted<double>)>( 1497 [](double) { 1498 return std::unique_ptr<ScalerImpl>(nullptr); 1499 }); 1500 } 1501 1502 int main() { 1503 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent); 1504 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 1505 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 1506 Assert(scaler.get() == nullptr); 1507 } 1508 ''' 1509 expect_success( 1510 COMMON_DEFINITIONS, 1511 source, 1512 locals()) 1513 1514@pytest.mark.parametrize('ScalerAnnot,ScalerFactoryAnnot', [ 1515 ('Scaler', 1516 'std::function<Scaler(double)>'), 1517 ('fruit::Annotated<Annotation1, Scaler>', 1518 'fruit::Annotated<Annotation1, std::function<Scaler(double)>>'), 1519]) 1520def test_register_factory_for_unique_pointer_returning_value(ScalerAnnot, ScalerFactoryAnnot): 1521 source = ''' 1522 struct Scaler { 1523 private: 1524 double factor; 1525 1526 public: 1527 Scaler(double factor) 1528 : factor(factor) { 1529 } 1530 1531 double scale(double x) { 1532 return x * factor; 1533 } 1534 }; 1535 1536 using ScalerFactory = std::function<Scaler(double)>; 1537 1538 fruit::Component<ScalerFactoryAnnot> getScalerComponent() { 1539 return fruit::createComponent() 1540 .registerFactory<ScalerAnnot(fruit::Assisted<double>)>( 1541 [](double factor) { 1542 return Scaler(factor); 1543 }); 1544 } 1545 1546 int main() { 1547 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent); 1548 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>(); 1549 Scaler scaler = scalerFactory(12.1); 1550 std::cout << scaler.scale(3) << std::endl; 1551 } 1552 ''' 1553 expect_success( 1554 COMMON_DEFINITIONS, 1555 source, 1556 locals()) 1557 1558@pytest.mark.parametrize('ScalerImplAnnot', [ 1559 'ScalerImpl', 1560 'fruit::Annotated<Annotation1, ScalerImpl>', 1561]) 1562def test_register_factory_inconsistent_signature(ScalerImplAnnot): 1563 source = ''' 1564 struct Scaler { 1565 virtual double scale(double x) = 0; 1566 }; 1567 1568 struct ScalerImpl : public Scaler { 1569 private: 1570 double factor; 1571 1572 public: 1573 ScalerImpl(double factor) 1574 : factor(factor) { 1575 } 1576 1577 double scale(double x) override { 1578 return x * factor; 1579 } 1580 }; 1581 1582 using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>; 1583 1584 fruit::Component<ScalerFactory> getScalerComponent() { 1585 return fruit::createComponent() 1586 .bind<Scaler, ScalerImplAnnot>() 1587 .registerFactory<ScalerImplAnnot(fruit::Assisted<double>)>([](float factor) { return ScalerImpl(factor); }); 1588 } 1589 1590 int main() { 1591 fruit::Injector<ScalerFactory> injector(getScalerComponent); 1592 ScalerFactory scalerFactory(injector); 1593 std::unique_ptr<Scaler> scaler = scalerFactory(12.1); 1594 std::cout << scaler->scale(3) << std::endl; 1595 } 1596 ''' 1597 expect_compile_error( 1598 'FunctorSignatureDoesNotMatchError<ScalerImpl\(double\),ScalerImpl\(float\)>', 1599 'Unexpected functor signature', 1600 COMMON_DEFINITIONS, 1601 source, 1602 locals()) 1603 1604def test_register_factory_inconsistent_signature_returning_value(): 1605 source = ''' 1606 struct Scaler { 1607 private: 1608 double factor; 1609 1610 public: 1611 Scaler(double factor) 1612 : factor(factor) { 1613 } 1614 1615 double scale(double x) { 1616 return x * factor; 1617 } 1618 }; 1619 1620 using ScalerFactory = std::function<Scaler(double)>; 1621 1622 fruit::Component<ScalerFactory> getScalerComponent() { 1623 return fruit::createComponent() 1624 .registerFactory<Scaler(fruit::Assisted<double>)>([](float factor) { return Scaler(factor); }); 1625 } 1626 1627 int main() { 1628 fruit::Injector<ScalerFactory> injector(getScalerComponent); 1629 ScalerFactory scalerFactory(injector); 1630 Scaler scaler = scalerFactory(12.1); 1631 std::cout << scaler.scale(3) << std::endl; 1632 } 1633 ''' 1634 expect_compile_error( 1635 'FunctorSignatureDoesNotMatchError<Scaler\(double\),Scaler\(float\)>', 1636 'Unexpected functor signature', 1637 COMMON_DEFINITIONS, 1638 source) 1639 1640def test_register_factory_nonmovable_ok(): 1641 source = ''' 1642 struct C { 1643 INJECT(C()) = default; 1644 1645 C(const C&) = delete; 1646 C(C&&) = delete; 1647 C& operator=(const C&) = delete; 1648 C& operator=(C&&) = delete; 1649 }; 1650 1651 using CFactory = std::function<std::unique_ptr<C>()>; 1652 1653 fruit::Component<CFactory> getCFactory() { 1654 return fruit::createComponent(); 1655 } 1656 1657 int main() { 1658 fruit::Injector<CFactory> injector(getCFactory); 1659 CFactory cFactory(injector); 1660 std::unique_ptr<C> c = cFactory(); 1661 (void)c; 1662 } 1663 ''' 1664 expect_success( 1665 COMMON_DEFINITIONS, 1666 source) 1667 1668# TODO: this might not be the best error message, maybe we should ignore the constructor entirely in the message, 1669# or mention that there are other ways to satisfy that dependency. 1670@pytest.mark.parametrize('XAnnot,XFactoryAnnot', [ 1671 ('X', 1672 'std::function<X(int)>'), 1673 ('fruit::Annotated<Annotation1, X>', 1674 'fruit::Annotated<Annotation1, std::function<X(int)>>'), 1675]) 1676def test_register_factory_not_existing_constructor1(XAnnot, XFactoryAnnot): 1677 source = ''' 1678 struct X { 1679 INJECT(X()) = default; 1680 }; 1681 1682 fruit::Component<XFactoryAnnot> getComponent() { 1683 return fruit::createComponent(); 1684 } 1685 ''' 1686 expect_compile_error( 1687 'FunctorSignatureDoesNotMatchError<XAnnot\(int\),XAnnot\((void)?\)>', 1688 'Unexpected functor signature', 1689 COMMON_DEFINITIONS, 1690 source, 1691 locals()) 1692 1693# TODO: this might not be the best error message, maybe we should ignore the constructor entirely in the message, 1694# or mention that there are other ways to satisfy that dependency. 1695@pytest.mark.parametrize('XIntFactoryAnnot,XIntFactoryAnnotRegex,XVoidFactoryAnnotRegex', [ 1696 ('std::function<std::unique_ptr<X>(int)>', 1697 'std::unique_ptr<X(,std::default_delete<X>)?>\(int\)', 1698 'std::unique_ptr<X(,std::default_delete<X>)?>\((void)?\)'), 1699 ('fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>(int)>>', 1700 'fruit::Annotated<Annotation1,std::unique_ptr<X(,std::default_delete<X>)?>>\(int\)', 1701 'fruit::Annotated<Annotation1,std::unique_ptr<X(,std::default_delete<X>)?>>\((void)?\)') 1702]) 1703def test_register_factory_not_existing_constructor2(XIntFactoryAnnot, XIntFactoryAnnotRegex, XVoidFactoryAnnotRegex): 1704 source = ''' 1705 struct X { 1706 using Inject = X(); 1707 }; 1708 1709 fruit::Component<XIntFactoryAnnot> getComponent() { 1710 return fruit::createComponent(); 1711 } 1712 ''' 1713 expect_compile_error( 1714 'FunctorSignatureDoesNotMatchError<XIntFactoryAnnotRegex,XVoidFactoryAnnotRegex>', 1715 'Unexpected functor signature', 1716 COMMON_DEFINITIONS, 1717 source, 1718 locals()) 1719 1720# TODO: this might not be the best error message, maybe we should ignore the constructor entirely in the message, 1721# or mention that there are other ways to satisfy that dependency. 1722@pytest.mark.parametrize('XAnnot,XFactoryAnnot', [ 1723 ('X', 1724 'std::function<X(int)>'), 1725 ('fruit::Annotated<Annotation1, X>', 1726 'fruit::Annotated<Annotation1, std::function<X(int)>>'), 1727]) 1728def test_register_factory_not_existing_constructor2_returning_value(XAnnot, XFactoryAnnot): 1729 source = ''' 1730 struct X { 1731 using Inject = X(); 1732 }; 1733 1734 fruit::Component<XFactoryAnnot> getComponent() { 1735 return fruit::createComponent(); 1736 } 1737 ''' 1738 expect_compile_error( 1739 'FunctorSignatureDoesNotMatchError<XAnnot\(int\), XAnnot\((void)?\)>', 1740 'Unexpected functor signature', 1741 COMMON_DEFINITIONS, 1742 source, 1743 locals()) 1744 1745 1746@pytest.mark.parametrize('XFactoryAnnot', [ 1747 'std::function<X()>', 1748 'fruit::Annotated<Annotation1, std::function<X()>>', 1749]) 1750def test_register_factory_success_factory_movable_only_implicit(XFactoryAnnot): 1751 source = ''' 1752 struct X { 1753 INJECT(X()) = default; 1754 X(X&&) = default; 1755 X(const X&) = delete; 1756 }; 1757 1758 fruit::Component<XFactoryAnnot> getComponent() { 1759 return fruit::createComponent(); 1760 } 1761 1762 int main() { 1763 fruit::Injector<XFactoryAnnot> injector(getComponent); 1764 injector.get<XFactoryAnnot>()(); 1765 } 1766 ''' 1767 expect_success( 1768 COMMON_DEFINITIONS, 1769 source, 1770 locals()) 1771 1772@pytest.mark.parametrize('XPtrAnnot,ConstructX,XPtrFactoryAnnot', [ 1773 ('X', 'X()', 'std::function<X()>'), 1774 ('fruit::Annotated<Annotation1, X>', 'X()', 'fruit::Annotated<Annotation1, std::function<X()>>'), 1775 ('std::unique_ptr<X>', 'std::unique_ptr<X>(new X())', 'std::function<std::unique_ptr<X>()>'), 1776 ('fruit::Annotated<Annotation1, std::unique_ptr<X>>', 'std::unique_ptr<X>(new X())', 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>'), 1777]) 1778def test_register_factory_success_factory_movable_only_explicit(XPtrAnnot, ConstructX, XPtrFactoryAnnot): 1779 source = ''' 1780 struct X { 1781 X() = default; 1782 X(X&&) = default; 1783 X(const X&) = delete; 1784 }; 1785 1786 fruit::Component<XPtrFactoryAnnot> getComponent() { 1787 return fruit::createComponent() 1788 .registerFactory<XPtrAnnot()>([](){return ConstructX;}); 1789 } 1790 1791 int main() { 1792 fruit::Injector<XPtrFactoryAnnot> injector(getComponent); 1793 injector.get<XPtrFactoryAnnot>()(); 1794 } 1795 ''' 1796 expect_success( 1797 COMMON_DEFINITIONS, 1798 source, 1799 locals()) 1800 1801@pytest.mark.parametrize('XPtrFactoryAnnot', [ 1802 'std::function<std::unique_ptr<X>()>', 1803 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>', 1804]) 1805def test_register_factory_success_factory_not_movable_implicit(XPtrFactoryAnnot): 1806 source = ''' 1807 struct X { 1808 INJECT(X()) = default; 1809 X(X&&) = delete; 1810 X(const X&) = delete; 1811 }; 1812 1813 fruit::Component<XPtrFactoryAnnot> getComponent() { 1814 return fruit::createComponent(); 1815 } 1816 1817 int main() { 1818 fruit::Injector<XPtrFactoryAnnot> injector(getComponent); 1819 injector.get<XPtrFactoryAnnot>()(); 1820 } 1821 ''' 1822 expect_success( 1823 COMMON_DEFINITIONS, 1824 source, 1825 locals()) 1826 1827@pytest.mark.parametrize('XPtrAnnot,XPtrFactoryAnnot', [ 1828 ('std::unique_ptr<X>', 'std::function<std::unique_ptr<X>()>'), 1829 ('fruit::Annotated<Annotation1, std::unique_ptr<X>>', 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>'), 1830]) 1831def test_register_factory_success_factory_not_movable_explicit_returning_pointer(XPtrAnnot, XPtrFactoryAnnot): 1832 source = ''' 1833 struct X { 1834 X() = default; 1835 X(X&&) = delete; 1836 X(const X&) = delete; 1837 }; 1838 1839 fruit::Component<XPtrFactoryAnnot> getComponent() { 1840 return fruit::createComponent() 1841 .registerFactory<XPtrAnnot()>([](){return std::unique_ptr<X>(new X());}); 1842 } 1843 1844 int main() { 1845 fruit::Injector<XPtrFactoryAnnot> injector(getComponent); 1846 injector.get<XPtrFactoryAnnot>()(); 1847 } 1848 ''' 1849 expect_success( 1850 COMMON_DEFINITIONS, 1851 source, 1852 locals()) 1853 1854@pytest.mark.parametrize('ConstructX,XPtr', [ 1855 ('X()', 'X'), 1856 ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'), 1857]) 1858@pytest.mark.parametrize('WithAnnot', [ 1859 'WithNoAnnotation', 1860 'WithAnnotation1', 1861]) 1862@pytest.mark.parametrize('YVariant', [ 1863 'Y', 1864 'Y*', 1865 'const Y*', 1866 'Y&', 1867 'const Y&', 1868 'std::shared_ptr<Y>', 1869 'fruit::Provider<Y>', 1870 'fruit::Provider<const Y>', 1871]) 1872def test_register_factory_with_param_success(ConstructX, XPtr, WithAnnot, YVariant): 1873 source = ''' 1874 struct Y {}; 1875 struct X {}; 1876 1877 fruit::Component<WithAnnot<Y>> getYComponent() { 1878 return fruit::createComponent() 1879 .registerConstructor<WithAnnot<Y>()>(); 1880 } 1881 1882 fruit::Component<std::function<XPtr()>> getComponent() { 1883 return fruit::createComponent() 1884 .install(getYComponent) 1885 .registerFactory<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; }); 1886 } 1887 1888 int main() { 1889 fruit::Injector<std::function<XPtr()>> injector(getComponent); 1890 XPtr x = injector.get<std::function<XPtr()>>()(); 1891 (void) x; 1892 } 1893 ''' 1894 expect_success( 1895 COMMON_DEFINITIONS, 1896 source, 1897 locals()) 1898 1899@pytest.mark.parametrize('ConstructX,XPtr', [ 1900 ('X()', 'X'), 1901 ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'), 1902]) 1903@pytest.mark.parametrize('WithAnnot', [ 1904 'WithNoAnnotation', 1905 'WithAnnotation1', 1906]) 1907@pytest.mark.parametrize('YVariant', [ 1908 'Y', 1909 'const Y*', 1910 'const Y&', 1911 'fruit::Provider<const Y>', 1912]) 1913def test_register_factory_with_param_const_binding_success(ConstructX, XPtr, WithAnnot, YVariant): 1914 source = ''' 1915 struct Y {}; 1916 struct X {}; 1917 1918 const Y y{}; 1919 1920 fruit::Component<WithAnnot<const Y>> getYComponent() { 1921 return fruit::createComponent() 1922 .bindInstance<WithAnnot<Y>, Y>(y); 1923 } 1924 1925 fruit::Component<std::function<XPtr()>> getComponent() { 1926 return fruit::createComponent() 1927 .install(getYComponent) 1928 .registerFactory<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; }); 1929 } 1930 1931 int main() { 1932 fruit::Injector<std::function<XPtr()>> injector(getComponent); 1933 XPtr x = injector.get<std::function<XPtr()>>()(); 1934 (void) x; 1935 } 1936 ''' 1937 expect_success( 1938 COMMON_DEFINITIONS, 1939 source, 1940 locals()) 1941 1942@pytest.mark.parametrize('ConstructX,XPtr', [ 1943 ('X()', 'X'), 1944 ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'), 1945]) 1946@pytest.mark.parametrize('WithAnnot,YAnnotRegex', [ 1947 ('WithNoAnnotation', 'Y'), 1948 ('WithAnnotation1', 'fruit::Annotated<Annotation1, Y>'), 1949]) 1950@pytest.mark.parametrize('XFactoryResult', [ 1951 'X', 1952 'std::unique_ptr<X>', 1953]) 1954@pytest.mark.parametrize('YVariant', [ 1955 'Y*', 1956 'Y&', 1957 'std::shared_ptr<Y>', 1958 'fruit::Provider<Y>', 1959]) 1960def test_register_factory_with_param_error_nonconst_param_required(ConstructX, XPtr, WithAnnot, YAnnotRegex, XFactoryResult, YVariant): 1961 source = ''' 1962 struct Y {}; 1963 struct X {}; 1964 1965 fruit::Component<WithAnnot<const Y>> getYComponent(); 1966 1967 fruit::Component<std::function<XFactoryResult()>> getComponent() { 1968 return fruit::createComponent() 1969 .install(getYComponent) 1970 .registerFactory<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; }); 1971 } 1972 ''' 1973 expect_compile_error( 1974 'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>', 1975 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 1976 COMMON_DEFINITIONS, 1977 source, 1978 locals()) 1979 1980@pytest.mark.parametrize('ConstructX,XPtr', [ 1981 ('X()', 'X'), 1982 ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'), 1983]) 1984@pytest.mark.parametrize('XFactoryResult', [ 1985 'X', 1986 'std::unique_ptr<X>', 1987]) 1988@pytest.mark.parametrize('WithAnnot,YAnnotRegex', [ 1989 ('WithNoAnnotation', 'Y'), 1990 ('WithAnnotation1', 'fruit::Annotated<Annotation1, Y>'), 1991]) 1992@pytest.mark.parametrize('YVariant', [ 1993 'Y*', 1994 'Y&', 1995 'std::shared_ptr<Y>', 1996 'fruit::Provider<Y>', 1997]) 1998def test_register_factory_with_param_error_nonconst_param_required_install_after(ConstructX, XPtr, XFactoryResult, WithAnnot, YAnnotRegex, YVariant): 1999 source = ''' 2000 struct Y {}; 2001 struct X {}; 2002 2003 fruit::Component<WithAnnot<const Y>> getYComponent(); 2004 2005 fruit::Component<std::function<XFactoryResult()>> getComponent() { 2006 return fruit::createComponent() 2007 .registerFactory<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; }) 2008 .install(getYComponent); 2009 } 2010 ''' 2011 expect_compile_error( 2012 'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>', 2013 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 2014 COMMON_DEFINITIONS, 2015 source, 2016 locals()) 2017 2018def test_register_factory_requiring_nonconst_then_requiring_const_ok(): 2019 source = ''' 2020 struct X {}; 2021 struct Y {}; 2022 struct Z {}; 2023 2024 fruit::Component<std::function<Y()>, std::function<Z()>> getRootComponent() { 2025 return fruit::createComponent() 2026 .registerFactory<Y(X&)>([](X&) { return Y();}) 2027 .registerFactory<Z(const X&)>([](const X&) { return Z();}) 2028 .registerConstructor<X()>(); 2029 } 2030 2031 int main() { 2032 fruit::Injector<std::function<Y()>, std::function<Z()>> injector(getRootComponent); 2033 std::function<Y()> yFactory = injector.get<std::function<Y()>>(); 2034 yFactory(); 2035 std::function<Z()> zFactory = injector.get<std::function<Z()>>(); 2036 zFactory(); 2037 } 2038 ''' 2039 expect_success( 2040 COMMON_DEFINITIONS, 2041 source, 2042 locals()) 2043 2044def test_register_factory_requiring_nonconst_then_requiring_const_declaring_const_requirement_error(): 2045 source = ''' 2046 struct X {}; 2047 struct Y {}; 2048 struct Z {}; 2049 2050 fruit::Component<fruit::Required<const X>, std::function<Y()>, std::function<Z()>> getRootComponent() { 2051 return fruit::createComponent() 2052 .registerFactory<Y(X&)>([](X&) { return Y();}) 2053 .registerFactory<Z(const X&)>([](const X&) { return Z();}); 2054 } 2055 ''' 2056 expect_compile_error( 2057 'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>', 2058 'The type T was declared as a const Required type in the returned Component, however', 2059 COMMON_DEFINITIONS, 2060 source, 2061 locals()) 2062 2063def test_register_factory_requiring_const_then_requiring_nonconst_ok(): 2064 source = ''' 2065 struct X {}; 2066 struct Y {}; 2067 struct Z {}; 2068 2069 fruit::Component<std::function<Y()>, std::function<Z()>> getRootComponent() { 2070 return fruit::createComponent() 2071 .registerFactory<Y(const X&)>([](const X&) { return Y();}) 2072 .registerFactory<Z(X&)>([](X&) { return Z();}) 2073 .registerConstructor<X()>(); 2074 } 2075 2076 int main() { 2077 fruit::Injector<std::function<Y()>, std::function<Z()>> injector(getRootComponent); 2078 std::function<Y()> yFactory = injector.get<std::function<Y()>>(); 2079 yFactory(); 2080 std::function<Z()> zFactory = injector.get<std::function<Z()>>(); 2081 zFactory(); 2082 } 2083 ''' 2084 expect_success( 2085 COMMON_DEFINITIONS, 2086 source, 2087 locals()) 2088 2089def test_register_factory_requiring_const_then_requiring_nonconst_declaring_const_requirement_error(): 2090 source = ''' 2091 struct X {}; 2092 struct Y {}; 2093 struct Z {}; 2094 2095 fruit::Component<fruit::Required<const X>, std::function<Y()>, std::function<Z()>> getRootComponent() { 2096 return fruit::createComponent() 2097 .registerFactory<Y(const X&)>([](const X&) { return Y();}) 2098 .registerFactory<Z(X&)>([](X&) { return Z();}); 2099 } 2100 ''' 2101 expect_compile_error( 2102 'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>', 2103 'The type T was declared as a const Required type in the returned Component, however', 2104 COMMON_DEFINITIONS, 2105 source, 2106 locals()) 2107 2108def test_provider_get_error_type_unique_pointer_pointer_not_provided(): 2109 source = ''' 2110 struct X {}; 2111 2112 void f(fruit::Provider<X> provider) { 2113 provider.get<std::unique_ptr<X>*>(); 2114 } 2115 ''' 2116 expect_compile_error( 2117 'TypeNotProvidedError<std::unique_ptr<X(,std::default_delete<X>)?>\*>', 2118 'Trying to get an instance of T, but it is not provided by this Provider/Injector.', 2119 COMMON_DEFINITIONS, 2120 source) 2121 2122@pytest.mark.parametrize('ConstructX,XPtr', [ 2123 ('X()', 'X'), 2124 ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'), 2125]) 2126@pytest.mark.parametrize('XFactoryResult', [ 2127 'X', 2128 'std::unique_ptr<X>', 2129]) 2130@pytest.mark.parametrize('YVariant,YVariantRegex', [ 2131 ('Y**', r'Y\*\*'), 2132 ('std::shared_ptr<Y>*', r'std::shared_ptr<Y>\*'), 2133 ('std::nullptr_t', r'(std::)?nullptr(_t)?'), 2134 ('Y*&', r'Y\*&'), 2135 ('Y(*)()', r'Y(\((__cdecl)?\*\))?\((void)?\)'), 2136 ('fruit::Annotated<Annotation1, Y**>', r'Y\*\*'), 2137]) 2138def test_register_factory_with_param_error_type_not_injectable( 2139 ConstructX, XPtr, XFactoryResult, YVariant, YVariantRegex): 2140 source = ''' 2141 struct Y {}; 2142 struct X {}; 2143 2144 fruit::Component<> getComponent() { 2145 return fruit::createComponent() 2146 .registerFactory<XPtr(YVariant)>([](YVariant){ return ConstructX; }); 2147 } 2148 ''' 2149 expect_compile_error( 2150 'NonInjectableTypeError<YVariantRegex>', 2151 'The type T is not injectable.', 2152 COMMON_DEFINITIONS, 2153 source, 2154 locals()) 2155 2156def test_register_factory_bind_nonconst_unique_ptr_factory_to_const_value_factory(): 2157 source = ''' 2158 struct X { 2159 INJECT(X()) = default; 2160 }; 2161 2162 fruit::Component<const std::function<X()>> getChildComponent() { 2163 return fruit::createComponent(); 2164 } 2165 2166 fruit::Component<std::function<std::unique_ptr<X>()>> getRootComponent() { 2167 return fruit::createComponent() 2168 .install(getChildComponent); 2169 } 2170 2171 int main() { 2172 fruit::Injector<std::function<std::unique_ptr<X>()>> injector(getRootComponent); 2173 std::function<std::unique_ptr<X>()> xFactory(injector); 2174 xFactory(); 2175 } 2176 ''' 2177 expect_success( 2178 COMMON_DEFINITIONS, 2179 source, 2180 locals()) 2181 2182def test_register_factory_bind_const_interface_factory_to_nonconst_implementation_factory(): 2183 source = ''' 2184 struct X { 2185 virtual void foo() = 0; 2186 virtual ~X() = default; 2187 }; 2188 2189 struct Y : public X { 2190 INJECT(Y()) = default; 2191 2192 void foo() override { 2193 } 2194 }; 2195 2196 fruit::Component<std::function<std::unique_ptr<Y>()>> getChildComponent() { 2197 return fruit::createComponent(); 2198 } 2199 2200 fruit::Component<const std::function<std::unique_ptr<X>()>> getRootComponent() { 2201 return fruit::createComponent() 2202 .install(getChildComponent) 2203 .bind<X, Y>(); 2204 } 2205 2206 int main() { 2207 fruit::Injector<const std::function<std::unique_ptr<X>()>> injector(getRootComponent); 2208 std::function<std::unique_ptr<X>()> xFactory(injector); 2209 xFactory(); 2210 } 2211 ''' 2212 expect_success( 2213 COMMON_DEFINITIONS, 2214 source, 2215 locals()) 2216 2217def test_register_factory_bind_nonconst_interface_factory_to_const_implementation_factory(): 2218 source = ''' 2219 struct X { 2220 virtual void foo() = 0; 2221 virtual ~X() = default; 2222 }; 2223 2224 struct Y : public X { 2225 INJECT(Y()) = default; 2226 2227 void foo() override { 2228 } 2229 }; 2230 2231 fruit::Component<const std::function<std::unique_ptr<Y>()>> getChildComponent() { 2232 return fruit::createComponent(); 2233 } 2234 2235 fruit::Component<std::function<std::unique_ptr<X>()>> getRootComponent() { 2236 return fruit::createComponent() 2237 .install(getChildComponent) 2238 .bind<X, Y>(); 2239 } 2240 2241 int main() { 2242 fruit::Injector<std::function<std::unique_ptr<X>()>> injector(getRootComponent); 2243 std::function<std::unique_ptr<X>()> xFactory(injector); 2244 xFactory(); 2245 } 2246 ''' 2247 expect_success( 2248 COMMON_DEFINITIONS, 2249 source, 2250 locals()) 2251 2252@pytest.mark.parametrize('WithAnnot', [ 2253 'WithNoAnnotation', 2254 'WithAnnotation1', 2255]) 2256def test_register_factory_abstract_class_ok(WithAnnot): 2257 source = ''' 2258 struct I { 2259 virtual int foo() = 0; 2260 virtual ~I() = default; 2261 }; 2262 2263 struct X : public I { 2264 int foo() override { 2265 return 5; 2266 } 2267 }; 2268 2269 fruit::Component<WithAnnot<std::function<std::unique_ptr<I>()>>> getComponent() { 2270 return fruit::createComponent() 2271 .registerFactory<WithAnnot<std::unique_ptr<I>>()>([](){return std::unique_ptr<I>(static_cast<I*>(new X()));}); 2272 } 2273 2274 int main() { 2275 fruit::Injector<WithAnnot<std::function<std::unique_ptr<I>()>>> injector(getComponent); 2276 2277 Assert(injector.get<WithAnnot<std::function<std::unique_ptr<I>()>>>()()->foo() == 5); 2278 } 2279 ''' 2280 expect_success( 2281 COMMON_DEFINITIONS, 2282 source, 2283 locals()) 2284 2285# TODO: investigate why this doesn't fail to compile with MSVC and then re-enable it for MSVC too. 2286@pytest.mark.skipif( 2287 re.search('MSVC', CXX_COMPILER_NAME), 2288 reason = 'This is disabled in MSVC because it compiles cleanly with the latest MSVC.') 2289@pytest.mark.parametrize('WithAnnot', [ 2290 'WithNoAnnotation', 2291 'WithAnnotation1', 2292]) 2293def test_register_factory_abstract_class_with_no_virtual_destructor_error(WithAnnot): 2294 source = ''' 2295 struct I { 2296 virtual int foo() = 0; 2297 }; 2298 2299 struct X : public I { 2300 int foo() override { 2301 return 5; 2302 } 2303 }; 2304 2305 fruit::Component<WithAnnot<std::function<std::unique_ptr<I>()>>> getComponent() { 2306 return fruit::createComponent() 2307 .registerFactory<WithAnnot<std::unique_ptr<I>>()>([](){return std::unique_ptr<I>(static_cast<I*>(new X()));}); 2308 } 2309 ''' 2310 expect_compile_error( 2311 'RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError<I>', 2312 'registerFactory\(\) was called with a lambda that returns a std::unique_ptr<T>, but T is an abstract class', 2313 COMMON_DEFINITIONS, 2314 source, 2315 locals(), 2316 ignore_warnings=True, 2317 disable_error_line_number_check=True) 2318 2319if __name__== '__main__': 2320 main(__file__) 2321