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