1#!/usr/bin/env python3 2# Copyright 2016 Google Inc. All Rights Reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS-IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16from absl.testing import parameterized 17from fruit_test_common import * 18 19COMMON_DEFINITIONS = ''' 20 #include "test_common.h" 21 22 ''' 23 24class TestComponentReplacement(parameterized.TestCase): 25 @multiple_parameters([ 26 ('', 'getReplacedComponent'), 27 ('double', 'getReplacedComponent, 1.0'), 28 ], [ 29 ('', 'getReplacementComponent'), 30 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 31 ]) 32 def test_replace_component_success(self, 33 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 34 source = ''' 35 fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) { 36 static int n = 10; 37 return fruit::createComponent() 38 .bindInstance(n); 39 } 40 41 fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) { 42 static int n = 20; 43 return fruit::createComponent() 44 .bindInstance(n); 45 } 46 47 fruit::Component<int> getRootComponent() { 48 return fruit::createComponent() 49 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 50 .install(ReplacedComponentInstallation); 51 } 52 53 int main() { 54 fruit::Injector<int> injector(getRootComponent); 55 int n = injector.get<int>(); 56 Assert(n == 20); 57 } 58 ''' 59 expect_success( 60 COMMON_DEFINITIONS, 61 source, 62 locals()) 63 64 @multiple_parameters([ 65 ('', 'getReplacedComponent'), 66 ('double', 'getReplacedComponent, 1.0'), 67 ], [ 68 ('', 'getReplacementComponent'), 69 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 70 ]) 71 def test_replace_component_success_across_normalized_component(self, 72 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 73 source = ''' 74 fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) { 75 static int n = 10; 76 return fruit::createComponent() 77 .bindInstance(n); 78 } 79 80 fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) { 81 static int n = 20; 82 return fruit::createComponent() 83 .bindInstance(n); 84 } 85 86 fruit::Component<> getRootComponent1() { 87 return fruit::createComponent() 88 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation); 89 } 90 91 fruit::Component<int> getRootComponent2() { 92 return fruit::createComponent() 93 .install(ReplacedComponentInstallation); 94 } 95 96 int main() { 97 fruit::NormalizedComponent<> normalizedComponent(getRootComponent1); 98 fruit::Injector<int> injector(normalizedComponent, getRootComponent2); 99 int n = injector.get<int>(); 100 Assert(n == 20); 101 } 102 ''' 103 expect_success( 104 COMMON_DEFINITIONS, 105 source, 106 locals()) 107 108 @multiple_parameters([ 109 ('', 'getReplacedComponent'), 110 ('double', 'getReplacedComponent, 1.0'), 111 ], [ 112 ('', 'getReplacementComponent'), 113 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 114 ]) 115 def test_replace_component_installed_using_component_function_success(self, 116 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 117 source = ''' 118 fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) { 119 static int n = 10; 120 return fruit::createComponent() 121 .bindInstance(n); 122 } 123 124 fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) { 125 static int n = 20; 126 return fruit::createComponent() 127 .bindInstance(n); 128 } 129 130 fruit::Component<int> getRootComponent() { 131 return fruit::createComponent() 132 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 133 .installComponentFunctions(fruit::componentFunction(ReplacedComponentInstallation)); 134 } 135 136 int main() { 137 fruit::Injector<int> injector(getRootComponent); 138 int n = injector.get<int>(); 139 Assert(n == 20); 140 } 141 ''' 142 expect_success( 143 COMMON_DEFINITIONS, 144 source, 145 locals()) 146 147 def test_replace_component_success_with_conversion(self): 148 source = ''' 149 fruit::Component<int> getReplacedComponent(std::string) { 150 static int n = 10; 151 return fruit::createComponent() 152 .bindInstance(n); 153 } 154 155 fruit::Component<int> getReplacementComponent(double, std::string, int) { 156 static int n = 20; 157 return fruit::createComponent() 158 .bindInstance(n); 159 } 160 161 fruit::Component<int> getRootComponent() { 162 return fruit::createComponent() 163 .replace(getReplacedComponent, "Hi").with(getReplacementComponent, 2.0, "Hello", 12) 164 .install(getReplacedComponent, "Hi"); 165 } 166 167 int main() { 168 fruit::Injector<int> injector(getRootComponent); 169 int n = injector.get<int>(); 170 Assert(n == 20); 171 } 172 ''' 173 expect_success( 174 COMMON_DEFINITIONS, 175 source, 176 locals()) 177 178 def test_replace_component_installed_using_component_function_success_with_conversion(self): 179 source = ''' 180 fruit::Component<int> getReplacedComponent(std::string) { 181 static int n = 10; 182 return fruit::createComponent() 183 .bindInstance(n); 184 } 185 186 fruit::Component<int> getReplacementComponent(double, std::string, int) { 187 static int n = 20; 188 return fruit::createComponent() 189 .bindInstance(n); 190 } 191 192 fruit::Component<int> getRootComponent() { 193 return fruit::createComponent() 194 .replace(getReplacedComponent, "Hi").with(getReplacementComponent, 2.0, "Hello", 12) 195 .installComponentFunctions(fruit::componentFunction(getReplacedComponent, "Hi")); 196 } 197 198 int main() { 199 fruit::Injector<int> injector(getRootComponent); 200 int n = injector.get<int>(); 201 Assert(n == 20); 202 } 203 ''' 204 expect_success( 205 COMMON_DEFINITIONS, 206 source, 207 locals()) 208 209 @multiple_parameters([ 210 ('', 'getReplacedComponent', 'getReplacementComponent', 'getReplacementReplacementComponent'), 211 ('double', 'getReplacedComponent, 1.0', 'getReplacementComponent, 1.0', 'getReplacementReplacementComponent, 1.0'), 212 ]) 213 def test_replace_component_chain_success(self, 214 ComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentInstallation, ReplacementReplacementComponentInstallation): 215 source = ''' 216 fruit::Component<int> getReplacedComponent(ComponentParamTypes) { 217 static int n = 10; 218 return fruit::createComponent() 219 .bindInstance(n); 220 } 221 222 fruit::Component<int> getReplacementComponent(ComponentParamTypes) { 223 static int n = 20; 224 return fruit::createComponent() 225 .bindInstance(n); 226 } 227 228 fruit::Component<int> getReplacementReplacementComponent(ComponentParamTypes) { 229 static int n = 30; 230 return fruit::createComponent() 231 .bindInstance(n); 232 } 233 234 fruit::Component<int> getRootComponent() { 235 return fruit::createComponent() 236 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 237 .replace(ReplacementComponentInstallation).with(ReplacementReplacementComponentInstallation) 238 .install(ReplacedComponentInstallation); 239 } 240 241 int main() { 242 fruit::Injector<int> injector(getRootComponent); 243 int n = injector.get<int>(); 244 Assert(n == 30); 245 } 246 ''' 247 expect_success( 248 COMMON_DEFINITIONS, 249 source, 250 locals()) 251 252 @multiple_parameters([ 253 ('', 'getReplacedComponent', 'getReplacementComponent', 'getReplacementReplacementComponent'), 254 ('double', 'getReplacedComponent, 1.0', 'getReplacementComponent, 1.0', 'getReplacementReplacementComponent, 1.0'), 255 ]) 256 def test_replace_component_chain_other_order_success(self, 257 ComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentInstallation, ReplacementReplacementComponentInstallation): 258 source = ''' 259 fruit::Component<int> getReplacedComponent(ComponentParamTypes) { 260 static int n = 10; 261 return fruit::createComponent() 262 .bindInstance(n); 263 } 264 265 fruit::Component<int> getReplacementComponent(ComponentParamTypes) { 266 static int n = 20; 267 return fruit::createComponent() 268 .bindInstance(n); 269 } 270 271 fruit::Component<int> getReplacementReplacementComponent(ComponentParamTypes) { 272 static int n = 30; 273 return fruit::createComponent() 274 .bindInstance(n); 275 } 276 277 fruit::Component<int> getRootComponent() { 278 return fruit::createComponent() 279 .replace(ReplacementComponentInstallation).with(ReplacementReplacementComponentInstallation) 280 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 281 .install(ReplacedComponentInstallation); 282 } 283 284 int main() { 285 fruit::Injector<int> injector(getRootComponent); 286 int n = injector.get<int>(); 287 Assert(n == 30); 288 } 289 ''' 290 expect_success( 291 COMMON_DEFINITIONS, 292 source, 293 locals()) 294 295 def test_replace_component_different_type_error(self): 296 source = ''' 297 fruit::Component<int> getReplacedComponent(); 298 fruit::Component<double> getReplacementComponent(); 299 300 fruit::Component<> getRootComponent() { 301 return fruit::createComponent() 302 .replace(getReplacedComponent).with(getReplacementComponent); 303 } 304 ''' 305 expect_generic_compile_error( 306 # Clang 307 r'candidate template ignored: could not match .Component<int>. against .Component<double>.' 308 # GCC 309 r'|mismatched types .int. and .double.' 310 # MSVC 311 r'|could not deduce template argument for .fruit::Component<int> \(__cdecl \*\)\(FormalArgs...\). from .fruit::Component<double> \(void\).', 312 COMMON_DEFINITIONS, 313 source) 314 315 @multiple_parameters([ 316 ('', 'getReplacedComponent'), 317 ('double', 'getReplacedComponent, 1.0'), 318 ], [ 319 ('', 'getReplacementComponent'), 320 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 321 ]) 322 def test_replace_component_already_replaced_consistent_ok(self, 323 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 324 source = ''' 325 fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) { 326 static int n = 10; 327 return fruit::createComponent() 328 .bindInstance(n); 329 } 330 331 fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) { 332 static int n = 20; 333 return fruit::createComponent() 334 .bindInstance(n); 335 } 336 337 fruit::Component<int> getRootComponent() { 338 return fruit::createComponent() 339 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 340 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 341 .install(ReplacedComponentInstallation); 342 } 343 344 int main() { 345 fruit::Injector<int> injector(getRootComponent); 346 int n = injector.get<int>(); 347 Assert(n == 20); 348 } 349 ''' 350 expect_success( 351 COMMON_DEFINITIONS, 352 source, 353 locals()) 354 355 @multiple_parameters([ 356 ('', 'getReplacedComponent'), 357 ('double', 'getReplacedComponent, 1.0'), 358 ], [ 359 ('', 'getReplacementComponent'), 360 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 361 ]) 362 def test_replace_component_already_replaced_across_normalized_component_consistent_ok(self, 363 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 364 source = ''' 365 fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) { 366 static int n = 10; 367 return fruit::createComponent() 368 .bindInstance(n); 369 } 370 371 fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) { 372 static int n = 20; 373 return fruit::createComponent() 374 .bindInstance(n); 375 } 376 377 fruit::Component<> getRootComponent1() { 378 return fruit::createComponent() 379 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation); 380 } 381 382 fruit::Component<int> getRootComponent2() { 383 return fruit::createComponent() 384 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 385 .install(ReplacedComponentInstallation); 386 } 387 388 int main() { 389 fruit::NormalizedComponent<> normalizedComponent(getRootComponent1); 390 fruit::Injector<int> injector(normalizedComponent, getRootComponent2); 391 int n = injector.get<int>(); 392 Assert(n == 20); 393 } 394 ''' 395 expect_success( 396 COMMON_DEFINITIONS, 397 source, 398 locals()) 399 400 @multiple_parameters([ 401 ('', 'getReplacedComponent'), 402 ('double', 'getReplacedComponent, 1.0'), 403 ], [ 404 ('', 'getReplacementComponent', 'getOtherReplacementComponent'), 405 ('std::string', 'getReplacementComponent, std::string("Hello, world")', 'getOtherReplacementComponent, std::string("Hello, world")'), 406 ]) 407 def test_replace_component_already_replaced_inconsistent_error(self, 408 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation, OtherReplacementComponentInstallation): 409 source = ''' 410 fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) { 411 static int n = 10; 412 return fruit::createComponent() 413 .bindInstance(n); 414 } 415 416 fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) { 417 static int n = 20; 418 return fruit::createComponent() 419 .bindInstance(n); 420 } 421 422 fruit::Component<int> getOtherReplacementComponent(ReplacementComponentParamTypes) { 423 static int n = 30; 424 return fruit::createComponent() 425 .bindInstance(n); 426 } 427 428 fruit::Component<> getRootComponent() { 429 return fruit::createComponent() 430 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 431 .replace(ReplacedComponentInstallation).with(OtherReplacementComponentInstallation); 432 } 433 434 int main() { 435 fruit::Injector<> injector(getRootComponent); 436 (void) injector; 437 } 438 ''' 439 expect_runtime_error( 440 r'Fatal injection error: the component function at (0x)?[0-9a-fA-F]* with signature ' 441 r'(class )?fruit::Component<int> \((__cdecl)?\*\)\((void)?ReplacedComponentParamTypes\) was replaced ' 442 r'\(using .replace\(...\).with\(...\)\) with both the component function at (0x)?[0-9a-fA-F]* with signature ' 443 r'(class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) and the component function at ' 444 r'(0x)?[0-9a-fA-F]* with signature (class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) .', 445 COMMON_DEFINITIONS, 446 source, 447 locals()) 448 449 @multiple_parameters([ 450 ('', 'getReplacedComponent'), 451 ('double', 'getReplacedComponent, 1.0'), 452 ], [ 453 ('', 'getReplacementComponent', 'getOtherReplacementComponent'), 454 ('std::string', 'getReplacementComponent, std::string("Hello, world")', 'getOtherReplacementComponent, std::string("Hello, world")'), 455 ]) 456 def test_replace_component_already_replaced_across_normalized_component_inconsistent_error(self, 457 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation, OtherReplacementComponentInstallation): 458 source = ''' 459 fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) { 460 static int n = 10; 461 return fruit::createComponent() 462 .bindInstance(n); 463 } 464 465 fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) { 466 static int n = 20; 467 return fruit::createComponent() 468 .bindInstance(n); 469 } 470 471 fruit::Component<int> getOtherReplacementComponent(ReplacementComponentParamTypes) { 472 static int n = 30; 473 return fruit::createComponent() 474 .bindInstance(n); 475 } 476 477 fruit::Component<> getRootComponent1() { 478 return fruit::createComponent() 479 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation); 480 } 481 482 fruit::Component<> getRootComponent2() { 483 return fruit::createComponent() 484 .replace(ReplacedComponentInstallation).with(OtherReplacementComponentInstallation); 485 } 486 487 int main() { 488 fruit::NormalizedComponent<> normalizedComponent(getRootComponent1); 489 fruit::Injector<> injector(normalizedComponent, getRootComponent2); 490 (void) injector; 491 } 492 ''' 493 expect_runtime_error( 494 r'Fatal injection error: the component function at (0x)?[0-9a-fA-F]* with signature ' 495 r'(class )?fruit::Component<int> \((__cdecl)?\*\)\((void)?ReplacedComponentParamTypes\) was replaced ' 496 r'\(using .replace\(...\).with\(...\)\) with both the component function at (0x)?[0-9a-fA-F]* with signature ' 497 r'(class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) and the component function at ' 498 r'(0x)?[0-9a-fA-F]* with signature (class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) .', 499 COMMON_DEFINITIONS, 500 source, 501 locals()) 502 503 @multiple_parameters([ 504 ('', 'getReplacedComponent'), 505 ('double', 'getReplacedComponent, 1.0'), 506 ], [ 507 ('', 'getReplacementComponent'), 508 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 509 ]) 510 def test_replace_component_after_install_error(self, 511 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 512 source = ''' 513 fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) { 514 static int n = 10; 515 return fruit::createComponent() 516 .bindInstance(n); 517 } 518 519 fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) { 520 static int n = 20; 521 return fruit::createComponent() 522 .bindInstance(n); 523 } 524 525 fruit::Component<int> getRootComponent() { 526 return fruit::createComponent() 527 .install(ReplacedComponentInstallation) 528 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation); 529 } 530 531 int main() { 532 fruit::Injector<int> injector(getRootComponent); 533 (void) injector; 534 } 535 ''' 536 expect_runtime_error( 537 r'Fatal injection error: unable to replace \(using .replace\(...\).with\(...\)\) the component function at ' 538 r'(0x)?[0-9a-fA-F]* with signature (class )?fruit::Component<int> \((__cdecl)?\*\)\((void)?ReplacedComponentParamTypes\) with the ' 539 r'component function at (0x)?[0-9a-fA-F]* with signature ' 540 r'(class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) because the former component function ' 541 r'was installed before the .replace\(...\).with\(...\).', 542 COMMON_DEFINITIONS, 543 source, 544 locals()) 545 546 @multiple_parameters([ 547 ('', 'getReplacedComponent'), 548 ('double', 'getReplacedComponent, 1.0'), 549 ], [ 550 ('', 'getReplacementComponent'), 551 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 552 ]) 553 def test_replace_component_after_install_across_normalized_component_error(self, 554 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 555 source = ''' 556 fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) { 557 static int n = 10; 558 return fruit::createComponent() 559 .bindInstance(n); 560 } 561 562 fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) { 563 static int n = 20; 564 return fruit::createComponent() 565 .bindInstance(n); 566 } 567 568 fruit::Component<int> getRootComponent1() { 569 return fruit::createComponent() 570 .install(ReplacedComponentInstallation); 571 } 572 573 fruit::Component<> getRootComponent2() { 574 return fruit::createComponent() 575 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation); 576 } 577 578 int main() { 579 fruit::NormalizedComponent<int> normalizedComponent(getRootComponent1); 580 fruit::Injector<int> injector(normalizedComponent, getRootComponent2); 581 (void) injector; 582 } 583 ''' 584 expect_runtime_error( 585 r'Fatal injection error: unable to replace \(using .replace\(...\).with\(...\)\) the component function at ' 586 r'(0x)?[0-9a-fA-F]* with signature (class )?fruit::Component<int> \((__cdecl)?\*\)\((void)?ReplacedComponentParamTypes\) with the ' 587 r'component function at (0x)?[0-9a-fA-F]* with signature ' 588 r'(class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) because the former component function ' 589 r'was installed before the .replace\(...\).with\(...\).', 590 COMMON_DEFINITIONS, 591 source, 592 locals()) 593 594 @parameterized.parameters([ 595 ('', 'getReplacedComponent', '', 'getReplacementComponent'), 596 ('double', 'getReplacedComponent, 1.0', 'std::string', 'getReplacementComponent, std::string("Hello, world")'), 597 ]) 598 def test_replace_component_unused_ok(self, 599 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 600 source = ''' 601 fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) { 602 static int n = 10; 603 return fruit::createComponent() 604 .addInstanceMultibinding(n); 605 } 606 607 fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) { 608 static int n = 20; 609 return fruit::createComponent() 610 .addInstanceMultibinding(n); 611 } 612 613 fruit::Component<> getRootComponent() { 614 return fruit::createComponent() 615 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation); 616 } 617 618 int main() { 619 fruit::Injector<> injector(getRootComponent); 620 621 std::vector<int*> multibindings = injector.getMultibindings<int>(); 622 Assert(multibindings.size() == 0); 623 } 624 ''' 625 expect_success( 626 COMMON_DEFINITIONS, 627 source, 628 locals()) 629 630 @multiple_parameters([ 631 ('', 'getReplacedComponent'), 632 ('double', 'getReplacedComponent, 1.0'), 633 ], [ 634 ('', 'getReplacementComponent'), 635 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 636 ]) 637 def test_replace_component_used_multiple_times_ok(self, 638 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 639 source = ''' 640 fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) { 641 static int n = 10; 642 return fruit::createComponent() 643 .addInstanceMultibinding(n); 644 } 645 646 fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) { 647 static int n = 20; 648 return fruit::createComponent() 649 .addInstanceMultibinding(n); 650 } 651 652 fruit::Component<> getRootComponent() { 653 return fruit::createComponent() 654 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 655 .install(ReplacedComponentInstallation) 656 .install(ReplacedComponentInstallation); 657 } 658 659 int main() { 660 fruit::Injector<> injector(getRootComponent); 661 662 std::vector<int*> multibindings = injector.getMultibindings<int>(); 663 Assert(multibindings.size() == 1); 664 Assert(*(multibindings[0]) == 20); 665 } 666 ''' 667 expect_success( 668 COMMON_DEFINITIONS, 669 source, 670 locals()) 671 672 @multiple_parameters([ 673 ('', 'getReplacedComponent'), 674 ('double', 'getReplacedComponent, 1.0'), 675 ], [ 676 ('', 'getReplacementComponent'), 677 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 678 ]) 679 def test_replace_component_also_installed_directly_before_ok(self, 680 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 681 source = ''' 682 fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) { 683 static int n = 10; 684 return fruit::createComponent() 685 .addInstanceMultibinding(n); 686 } 687 688 fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) { 689 static int n = 20; 690 return fruit::createComponent() 691 .addInstanceMultibinding(n); 692 } 693 694 fruit::Component<> getRootComponent() { 695 return fruit::createComponent() 696 .install(ReplacementComponentInstallation) 697 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 698 .install(ReplacedComponentInstallation); 699 } 700 701 int main() { 702 fruit::Injector<> injector(getRootComponent); 703 704 std::vector<int*> multibindings = injector.getMultibindings<int>(); 705 Assert(multibindings.size() == 1); 706 Assert(*(multibindings[0]) == 20); 707 } 708 ''' 709 expect_success( 710 COMMON_DEFINITIONS, 711 source, 712 locals()) 713 714 @multiple_parameters([ 715 ('', 'getReplacedComponent'), 716 ('double', 'getReplacedComponent, 1.0'), 717 ], [ 718 ('', 'getReplacementComponent'), 719 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 720 ]) 721 def test_replace_component_also_installed_directly_after_ok(self, 722 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 723 source = ''' 724 fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) { 725 static int n = 10; 726 return fruit::createComponent() 727 .addInstanceMultibinding(n); 728 } 729 730 fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) { 731 static int n = 20; 732 return fruit::createComponent() 733 .addInstanceMultibinding(n); 734 } 735 736 fruit::Component<> getRootComponent() { 737 return fruit::createComponent() 738 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 739 .install(ReplacedComponentInstallation) 740 .install(ReplacementComponentInstallation); 741 } 742 743 int main() { 744 fruit::Injector<> injector(getRootComponent); 745 746 std::vector<int*> multibindings = injector.getMultibindings<int>(); 747 Assert(multibindings.size() == 1); 748 Assert(*(multibindings[0]) == 20); 749 } 750 ''' 751 expect_success( 752 COMMON_DEFINITIONS, 753 source, 754 locals()) 755 756 @multiple_parameters([ 757 ('', 'getReplacedComponent'), 758 ('double', 'getReplacedComponent, 1.0'), 759 ], [ 760 ('', 'getReplacementComponent'), 761 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 762 ]) 763 def test_replace_component_also_installed_directly_before_across_normalized_component_ok(self, 764 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 765 source = ''' 766 fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) { 767 static int n = 10; 768 return fruit::createComponent() 769 .addInstanceMultibinding(n); 770 } 771 772 fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) { 773 static int n = 20; 774 return fruit::createComponent() 775 .addInstanceMultibinding(n); 776 } 777 778 fruit::Component<> getRootComponent1() { 779 return fruit::createComponent() 780 .install(ReplacementComponentInstallation); 781 } 782 783 fruit::Component<> getRootComponent2() { 784 return fruit::createComponent() 785 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 786 .install(ReplacedComponentInstallation); 787 } 788 789 int main() { 790 fruit::NormalizedComponent<> normalizedComponent(getRootComponent1); 791 fruit::Injector<> injector(normalizedComponent, getRootComponent2); 792 793 std::vector<int*> multibindings = injector.getMultibindings<int>(); 794 Assert(multibindings.size() == 1); 795 Assert(*(multibindings[0]) == 20); 796 } 797 ''' 798 expect_success( 799 COMMON_DEFINITIONS, 800 source, 801 locals()) 802 803 @multiple_parameters([ 804 ('', 'getReplacedComponent'), 805 ('double', 'getReplacedComponent, 1.0'), 806 ], [ 807 ('', 'getReplacementComponent'), 808 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 809 ]) 810 def test_replace_component_also_installed_directly_after_across_normalized_component_ok(self, 811 ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 812 source = ''' 813 fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) { 814 static int n = 10; 815 return fruit::createComponent() 816 .addInstanceMultibinding(n); 817 } 818 819 fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) { 820 static int n = 20; 821 return fruit::createComponent() 822 .addInstanceMultibinding(n); 823 } 824 825 fruit::Component<> getRootComponent1() { 826 return fruit::createComponent() 827 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 828 .install(ReplacedComponentInstallation); 829 } 830 831 fruit::Component<> getRootComponent2() { 832 return fruit::createComponent() 833 .install(ReplacementComponentInstallation); 834 } 835 836 int main() { 837 fruit::NormalizedComponent<> normalizedComponent(getRootComponent1); 838 fruit::Injector<> injector(normalizedComponent, getRootComponent2); 839 840 std::vector<int*> multibindings = injector.getMultibindings<int>(); 841 Assert(multibindings.size() == 1); 842 Assert(*(multibindings[0]) == 20); 843 } 844 ''' 845 expect_success( 846 COMMON_DEFINITIONS, 847 source, 848 locals()) 849 850 @multiple_parameters([ 851 ('', 'getReplacedComponent', 'getOtherReplacementComponent'), 852 ('double', 'getReplacedComponent, 1.0', 'getOtherReplacementComponent, 1.0'), 853 ], [ 854 ('', 'getReplacementComponent'), 855 ('std::string', 'getReplacementComponent, std::string("Hello, world")'), 856 ]) 857 def test_replace_multiple_components_with_same(self, 858 ReplacedComponentParamTypes, ReplacedComponentInstallation, OtherReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation): 859 source = ''' 860 fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) { 861 static int n = 10; 862 return fruit::createComponent() 863 .addInstanceMultibinding(n); 864 } 865 866 fruit::Component<> getOtherReplacementComponent(ReplacedComponentParamTypes) { 867 static int n = 20; 868 return fruit::createComponent() 869 .addInstanceMultibinding(n); 870 } 871 872 fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) { 873 static int n = 30; 874 return fruit::createComponent() 875 .addInstanceMultibinding(n); 876 } 877 878 fruit::Component<> getRootComponent() { 879 return fruit::createComponent() 880 .replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation) 881 .replace(OtherReplacedComponentInstallation).with(ReplacementComponentInstallation) 882 .install(ReplacedComponentInstallation) 883 .install(OtherReplacedComponentInstallation); 884 } 885 886 int main() { 887 fruit::Injector<> injector(getRootComponent); 888 889 std::vector<int*> multibindings = injector.getMultibindings<int>(); 890 Assert(multibindings.size() == 1); 891 Assert(*(multibindings[0]) == 30); 892 } 893 ''' 894 expect_success( 895 COMMON_DEFINITIONS, 896 source, 897 locals()) 898 899 def test_replace_component_one_set_of_args_only(self): 900 source = ''' 901 fruit::Component<> getReplacedComponent(double) { 902 static int n = 10; 903 return fruit::createComponent() 904 .addInstanceMultibinding(n); 905 } 906 907 fruit::Component<> getReplacementComponent() { 908 static int n = 20; 909 return fruit::createComponent() 910 .addInstanceMultibinding(n); 911 } 912 913 fruit::Component<> getRootComponent() { 914 return fruit::createComponent() 915 .replace(getReplacedComponent, 1.0).with(getReplacementComponent) 916 .install(getReplacedComponent, 1.0) 917 .install(getReplacedComponent, 5.0); 918 } 919 920 int main() { 921 fruit::Injector<> injector(getRootComponent); 922 923 std::vector<int*> multibindings = injector.getMultibindings<int>(); 924 Assert(multibindings.size() == 2); 925 Assert(*(multibindings[0]) == 20); 926 Assert(*(multibindings[1]) == 10); 927 } 928 ''' 929 expect_success( 930 COMMON_DEFINITIONS, 931 source, 932 locals()) 933 934 def test_replace_component_already_replaced_with_different_args(self): 935 source = ''' 936 fruit::Component<> getReplacedComponent(double) { 937 static int n = 10; 938 return fruit::createComponent() 939 .addInstanceMultibinding(n); 940 } 941 942 fruit::Component<> getReplacementComponent() { 943 static int n = 20; 944 return fruit::createComponent() 945 .addInstanceMultibinding(n); 946 } 947 948 fruit::Component<> getOtherReplacementComponent() { 949 static int n = 30; 950 return fruit::createComponent() 951 .addInstanceMultibinding(n); 952 } 953 954 fruit::Component<> getRootComponent() { 955 return fruit::createComponent() 956 .replace(getReplacedComponent, 1.0).with(getReplacementComponent) 957 .replace(getReplacedComponent, 5.0).with(getOtherReplacementComponent) 958 .install(getReplacedComponent, 1.0) 959 .install(getReplacedComponent, 5.0); 960 } 961 962 int main() { 963 fruit::Injector<> injector(getRootComponent); 964 965 std::vector<int*> multibindings = injector.getMultibindings<int>(); 966 Assert(multibindings.size() == 2); 967 Assert(*(multibindings[0]) == 20); 968 Assert(*(multibindings[1]) == 30); 969 } 970 ''' 971 expect_success( 972 COMMON_DEFINITIONS, 973 source, 974 locals()) 975 976if __name__ == '__main__': 977 absltest.main() 978