1 /* 2 * Copyright (C) 2008 Google Inc. 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 */ 16 17 package com.google.inject.assistedinject; 18 19 import static com.google.inject.Asserts.assertContains; 20 import static com.google.inject.Asserts.assertEqualsBothWays; 21 22 import com.google.inject.AbstractModule; 23 import com.google.inject.ConfigurationException; 24 import com.google.inject.CreationException; 25 import com.google.inject.Guice; 26 import com.google.inject.Inject; 27 import com.google.inject.Injector; 28 import com.google.inject.Key; 29 import com.google.inject.Provider; 30 import com.google.inject.Stage; 31 import com.google.inject.TypeLiteral; 32 import com.google.inject.assistedinject.FactoryProvider2Test.Equals.ComparisonMethod; 33 import com.google.inject.assistedinject.FactoryProvider2Test.Equals.Impl; 34 import com.google.inject.internal.Annotations; 35 import com.google.inject.matcher.Matchers; 36 import com.google.inject.name.Named; 37 import com.google.inject.name.Names; 38 import java.util.Collection; 39 import java.util.Collections; 40 import java.util.Set; 41 import java.util.concurrent.atomic.AtomicInteger; 42 import junit.framework.TestCase; 43 44 @SuppressWarnings("deprecation") 45 public class FactoryProvider2Test extends TestCase { 46 47 private enum Color { 48 BLUE, 49 GREEN, 50 RED, 51 GRAY, 52 BLACK, 53 ORANGE, 54 PINK 55 } 56 testAssistedFactory()57 public void testAssistedFactory() { 58 Injector injector = 59 Guice.createInjector( 60 new AbstractModule() { 61 @Override 62 protected void configure() { 63 bind(Double.class).toInstance(5.0d); 64 bind(ColoredCarFactory.class) 65 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 66 } 67 }); 68 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 69 70 Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE); 71 assertEquals(Color.BLUE, blueMustang.color); 72 assertEquals(5.0d, blueMustang.engineSize, 0.0); 73 74 Mustang redMustang = (Mustang) carFactory.create(Color.RED); 75 assertEquals(Color.RED, redMustang.color); 76 assertEquals(5.0d, redMustang.engineSize, 0.0); 77 } 78 testAssistedFactoryWithAnnotations()79 public void testAssistedFactoryWithAnnotations() { 80 Injector injector = 81 Guice.createInjector( 82 new AbstractModule() { 83 @Override 84 protected void configure() { 85 bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); 86 bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); 87 bind(ColoredCarFactory.class) 88 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Camaro.class)); 89 } 90 }); 91 92 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 93 94 Camaro blueCamaro = (Camaro) carFactory.create(Color.BLUE); 95 assertEquals(Color.BLUE, blueCamaro.color); 96 assertEquals(1984, blueCamaro.modelYear); 97 assertEquals(250, blueCamaro.horsePower); 98 99 Camaro redCamaro = (Camaro) carFactory.create(Color.RED); 100 assertEquals(Color.RED, redCamaro.color); 101 assertEquals(1984, redCamaro.modelYear); 102 assertEquals(250, redCamaro.horsePower); 103 } 104 105 public interface Car {} 106 107 interface ColoredCarFactory { create(Color color)108 Car create(Color color); 109 } 110 111 public static class Mustang implements Car { 112 private final double engineSize; 113 private final Color color; 114 115 @Inject Mustang(double engineSize, @Assisted Color color)116 public Mustang(double engineSize, @Assisted Color color) { 117 this.engineSize = engineSize; 118 this.color = color; 119 } 120 drive()121 public void drive() {} 122 } 123 124 public static class Camaro implements Car { 125 private final int horsePower; 126 private final int modelYear; 127 private final Color color; 128 129 @Inject Camaro( @amed"horsePower") int horsePower, @Named("modelYear") int modelYear, @Assisted Color color)130 public Camaro( 131 @Named("horsePower") int horsePower, 132 @Named("modelYear") int modelYear, 133 @Assisted Color color) { 134 this.horsePower = horsePower; 135 this.modelYear = modelYear; 136 this.color = color; 137 } 138 } 139 140 interface SummerCarFactory { create(Color color, boolean convertable)141 Car create(Color color, boolean convertable); 142 } 143 testFactoryUsesInjectedConstructor()144 public void testFactoryUsesInjectedConstructor() { 145 Injector injector = 146 Guice.createInjector( 147 new AbstractModule() { 148 @Override 149 protected void configure() { 150 bind(float.class).toInstance(140f); 151 bind(SummerCarFactory.class) 152 .toProvider(FactoryProvider.newFactory(SummerCarFactory.class, Corvette.class)); 153 } 154 }); 155 156 SummerCarFactory carFactory = injector.getInstance(SummerCarFactory.class); 157 158 Corvette redCorvette = (Corvette) carFactory.create(Color.RED, false); 159 assertEquals(Color.RED, redCorvette.color); 160 assertEquals(140f, redCorvette.maxMph, 0.0f); 161 assertFalse(redCorvette.isConvertable); 162 } 163 164 public static class Corvette implements Car { 165 private boolean isConvertable; 166 private Color color; 167 private float maxMph; 168 169 @SuppressWarnings("unused") Corvette(Color color, boolean isConvertable)170 public Corvette(Color color, boolean isConvertable) { 171 throw new IllegalStateException("Not an @AssistedInject constructor"); 172 } 173 174 @Inject Corvette(@ssisted Color color, Float maxMph, @Assisted boolean isConvertable)175 public Corvette(@Assisted Color color, Float maxMph, @Assisted boolean isConvertable) { 176 this.isConvertable = isConvertable; 177 this.color = color; 178 this.maxMph = maxMph; 179 } 180 } 181 testConstructorDoesntNeedAllFactoryMethodArguments()182 public void testConstructorDoesntNeedAllFactoryMethodArguments() { 183 Injector injector = 184 Guice.createInjector( 185 new AbstractModule() { 186 @Override 187 protected void configure() { 188 bind(SummerCarFactory.class) 189 .toProvider(FactoryProvider.newFactory(SummerCarFactory.class, Beetle.class)); 190 } 191 }); 192 SummerCarFactory factory = injector.getInstance(SummerCarFactory.class); 193 194 Beetle beetle = (Beetle) factory.create(Color.RED, true); 195 assertSame(Color.RED, beetle.color); 196 } 197 198 public static class Beetle implements Car { 199 private final Color color; 200 201 @Inject Beetle(@ssisted Color color)202 public Beetle(@Assisted Color color) { 203 this.color = color; 204 } 205 } 206 testMethodsAndFieldsGetInjected()207 public void testMethodsAndFieldsGetInjected() { 208 Injector injector = 209 Guice.createInjector( 210 new AbstractModule() { 211 @Override 212 protected void configure() { 213 bind(String.class).toInstance("turbo"); 214 bind(int.class).toInstance(911); 215 bind(double.class).toInstance(50000d); 216 bind(ColoredCarFactory.class) 217 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Porsche.class)); 218 } 219 }); 220 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 221 222 Porsche grayPorsche = (Porsche) carFactory.create(Color.GRAY); 223 assertEquals(Color.GRAY, grayPorsche.color); 224 assertEquals(50000d, grayPorsche.price, 0.0); 225 assertEquals(911, grayPorsche.model); 226 assertEquals("turbo", grayPorsche.name); 227 } 228 229 public static class Porsche implements Car { 230 private final Color color; 231 private final double price; 232 private @Inject String name; 233 private int model; 234 235 @Inject Porsche(@ssisted Color color, double price)236 public Porsche(@Assisted Color color, double price) { 237 this.color = color; 238 this.price = price; 239 } 240 241 @Inject setModel(int model)242 void setModel(int model) { 243 this.model = model; 244 } 245 } 246 testProviderInjection()247 public void testProviderInjection() { 248 Injector injector = 249 Guice.createInjector( 250 new AbstractModule() { 251 @Override 252 protected void configure() { 253 bind(String.class).toInstance("trans am"); 254 bind(ColoredCarFactory.class) 255 .toProvider( 256 FactoryProvider.newFactory(ColoredCarFactory.class, Firebird.class)); 257 } 258 }); 259 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 260 261 Firebird blackFirebird = (Firebird) carFactory.create(Color.BLACK); 262 assertEquals(Color.BLACK, blackFirebird.color); 263 assertEquals("trans am", blackFirebird.modifiersProvider.get()); 264 } 265 266 public static class Firebird implements Car { 267 private final Provider<String> modifiersProvider; 268 private final Color color; 269 270 @Inject Firebird(Provider<String> modifiersProvider, @Assisted Color color)271 public Firebird(Provider<String> modifiersProvider, @Assisted Color color) { 272 this.modifiersProvider = modifiersProvider; 273 this.color = color; 274 } 275 } 276 testAssistedProviderInjection()277 public void testAssistedProviderInjection() { 278 Injector injector = 279 Guice.createInjector( 280 new AbstractModule() { 281 @Override 282 protected void configure() { 283 bind(String.class).toInstance("trans am"); 284 bind(ColoredCarFactory.class) 285 .toProvider( 286 FactoryProvider.newFactory(ColoredCarFactory.class, Flamingbird.class)); 287 } 288 }); 289 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 290 291 Flamingbird flamingbird = (Flamingbird) carFactory.create(Color.BLACK); 292 assertEquals(Color.BLACK, flamingbird.colorProvider.get()); 293 assertEquals("trans am", flamingbird.modifiersProvider.get()); 294 295 Flamingbird flamingbird2 = (Flamingbird) carFactory.create(Color.RED); 296 assertEquals(Color.RED, flamingbird2.colorProvider.get()); 297 assertEquals("trans am", flamingbird2.modifiersProvider.get()); 298 // Make sure the original flamingbird is black still. 299 assertEquals(Color.BLACK, flamingbird.colorProvider.get()); 300 } 301 302 public static class Flamingbird implements Car { 303 private final Provider<String> modifiersProvider; 304 private final Provider<Color> colorProvider; 305 306 @Inject Flamingbird( Provider<String> modifiersProvider, @Assisted Provider<Color> colorProvider)307 public Flamingbird( 308 Provider<String> modifiersProvider, @Assisted Provider<Color> colorProvider) { 309 this.modifiersProvider = modifiersProvider; 310 this.colorProvider = colorProvider; 311 } 312 } 313 testTypeTokenInjection()314 public void testTypeTokenInjection() { 315 Injector injector = 316 Guice.createInjector( 317 new AbstractModule() { 318 @Override 319 protected void configure() { 320 bind(new TypeLiteral<Set<String>>() {}) 321 .toInstance(Collections.singleton("Flux Capacitor")); 322 bind(new TypeLiteral<Set<Integer>>() {}).toInstance(Collections.singleton(88)); 323 bind(ColoredCarFactory.class) 324 .toProvider( 325 FactoryProvider.newFactory(ColoredCarFactory.class, DeLorean.class)); 326 } 327 }); 328 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 329 330 DeLorean deLorean = (DeLorean) carFactory.create(Color.GRAY); 331 assertEquals(Color.GRAY, deLorean.color); 332 assertEquals("Flux Capacitor", deLorean.features.iterator().next()); 333 assertEquals(Integer.valueOf(88), deLorean.featureActivationSpeeds.iterator().next()); 334 } 335 336 public static class DeLorean implements Car { 337 private final Set<String> features; 338 private final Set<Integer> featureActivationSpeeds; 339 private final Color color; 340 341 @Inject DeLorean( Set<String> extraFeatures, Set<Integer> featureActivationSpeeds, @Assisted Color color)342 public DeLorean( 343 Set<String> extraFeatures, Set<Integer> featureActivationSpeeds, @Assisted Color color) { 344 this.features = extraFeatures; 345 this.featureActivationSpeeds = featureActivationSpeeds; 346 this.color = color; 347 } 348 } 349 testTypeTokenProviderInjection()350 public void testTypeTokenProviderInjection() { 351 Injector injector = 352 Guice.createInjector( 353 new AbstractModule() { 354 @Override 355 protected void configure() { 356 bind(new TypeLiteral<Set<String>>() {}).toInstance(Collections.singleton("Datsun")); 357 bind(ColoredCarFactory.class) 358 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Z.class)); 359 } 360 }); 361 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 362 363 Z orangeZ = (Z) carFactory.create(Color.ORANGE); 364 assertEquals(Color.ORANGE, orangeZ.color); 365 assertEquals("Datsun", orangeZ.manufacturersProvider.get().iterator().next()); 366 } 367 368 public static class Z implements Car { 369 private final Provider<Set<String>> manufacturersProvider; 370 private final Color color; 371 372 @Inject Z(Provider<Set<String>> manufacturersProvider, @Assisted Color color)373 public Z(Provider<Set<String>> manufacturersProvider, @Assisted Color color) { 374 this.manufacturersProvider = manufacturersProvider; 375 this.color = color; 376 } 377 } 378 379 public static class Prius implements Car { 380 final Color color; 381 382 @Inject Prius(@ssisted Color color)383 private Prius(@Assisted Color color) { 384 this.color = color; 385 } 386 } 387 testAssistInjectionInNonPublicConstructor()388 public void testAssistInjectionInNonPublicConstructor() { 389 Injector injector = 390 Guice.createInjector( 391 new AbstractModule() { 392 @Override 393 protected void configure() { 394 bind(ColoredCarFactory.class) 395 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Prius.class)); 396 } 397 }); 398 Prius prius = (Prius) injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE); 399 assertEquals(prius.color, Color.ORANGE); 400 } 401 402 public static class ExplodingCar implements Car { 403 @Inject ExplodingCar(@uppressWarnings"unused") @ssisted Color color)404 public ExplodingCar(@SuppressWarnings("unused") @Assisted Color color) { 405 throw new IllegalStateException("kaboom!"); 406 } 407 } 408 testExceptionDuringConstruction()409 public void testExceptionDuringConstruction() { 410 Injector injector = 411 Guice.createInjector( 412 new AbstractModule() { 413 @Override 414 protected void configure() { 415 bind(ColoredCarFactory.class) 416 .toProvider( 417 FactoryProvider.newFactory(ColoredCarFactory.class, ExplodingCar.class)); 418 } 419 }); 420 try { 421 injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE); 422 fail(); 423 } catch (IllegalStateException e) { 424 assertEquals("kaboom!", e.getMessage()); 425 } 426 } 427 428 public static class DefectiveCar implements Car { 429 @Inject DefectiveCar()430 public DefectiveCar() throws ExplosionException { 431 throw new ExplosionException(); 432 } 433 } 434 435 public static class ExplosionException extends Exception {} 436 437 public static class FireException extends Exception {} 438 439 public interface DefectiveCarFactoryWithNoExceptions { createCar()440 Car createCar(); 441 } 442 443 public interface DefectiveCarFactory { createCar()444 Car createCar() throws FireException; 445 } 446 447 public interface CorrectDefectiveCarFactory { createCar()448 Car createCar() throws FireException, ExplosionException; 449 } 450 testConstructorExceptionsAreThrownByFactory()451 public void testConstructorExceptionsAreThrownByFactory() { 452 Injector injector = 453 Guice.createInjector( 454 new AbstractModule() { 455 @Override 456 protected void configure() { 457 bind(CorrectDefectiveCarFactory.class) 458 .toProvider( 459 FactoryProvider.newFactory( 460 CorrectDefectiveCarFactory.class, DefectiveCar.class)); 461 } 462 }); 463 try { 464 injector.getInstance(CorrectDefectiveCarFactory.class).createCar(); 465 fail(); 466 } catch (FireException e) { 467 fail(); 468 } catch (ExplosionException expected) { 469 } 470 } 471 472 public static class WildcardCollection { 473 474 public interface Factory { create(Collection<?> items)475 WildcardCollection create(Collection<?> items); 476 } 477 478 @Inject WildcardCollection(@uppressWarnings"unused") @ssisted Collection<?> items)479 public WildcardCollection(@SuppressWarnings("unused") @Assisted Collection<?> items) {} 480 } 481 testWildcardGenerics()482 public void testWildcardGenerics() { 483 Injector injector = 484 Guice.createInjector( 485 new AbstractModule() { 486 @Override 487 protected void configure() { 488 bind(WildcardCollection.Factory.class) 489 .toProvider( 490 FactoryProvider.newFactory( 491 WildcardCollection.Factory.class, WildcardCollection.class)); 492 } 493 }); 494 WildcardCollection.Factory factory = injector.getInstance(WildcardCollection.Factory.class); 495 factory.create(Collections.emptyList()); 496 } 497 498 public static class SteeringWheel {} 499 500 public static class Fiat implements Car { 501 private final SteeringWheel steeringWheel; 502 private final Color color; 503 504 @Inject Fiat(SteeringWheel steeringWheel, @Assisted Color color)505 public Fiat(SteeringWheel steeringWheel, @Assisted Color color) { 506 this.steeringWheel = steeringWheel; 507 this.color = color; 508 } 509 } 510 testFactoryWithImplicitBindings()511 public void testFactoryWithImplicitBindings() { 512 Injector injector = 513 Guice.createInjector( 514 new AbstractModule() { 515 @Override 516 protected void configure() { 517 bind(ColoredCarFactory.class) 518 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Fiat.class)); 519 } 520 }); 521 522 ColoredCarFactory coloredCarFactory = injector.getInstance(ColoredCarFactory.class); 523 Fiat fiat = (Fiat) coloredCarFactory.create(Color.GREEN); 524 assertEquals(Color.GREEN, fiat.color); 525 assertNotNull(fiat.steeringWheel); 526 } 527 testFactoryFailsWithMissingBinding()528 public void testFactoryFailsWithMissingBinding() { 529 try { 530 Guice.createInjector( 531 new AbstractModule() { 532 @Override 533 protected void configure() { 534 bind(ColoredCarFactory.class) 535 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 536 } 537 }); 538 fail(); 539 } catch (CreationException expected) { 540 assertContains( 541 expected.getMessage(), 542 "Could not find a suitable constructor in java.lang.Double.", 543 "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java"); 544 } 545 } 546 testFactoryFailsWithMissingBindingInToolStage()547 public void testFactoryFailsWithMissingBindingInToolStage() { 548 try { 549 Guice.createInjector( 550 Stage.TOOL, 551 new AbstractModule() { 552 @Override 553 protected void configure() { 554 bind(ColoredCarFactory.class) 555 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 556 } 557 }); 558 fail(); 559 } catch (CreationException expected) { 560 assertContains( 561 expected.getMessage(), 562 "Could not find a suitable constructor in java.lang.Double.", 563 "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java"); 564 } 565 } 566 testMethodsDeclaredInObject()567 public void testMethodsDeclaredInObject() { 568 Injector injector = 569 Guice.createInjector( 570 new AbstractModule() { 571 @Override 572 protected void configure() { 573 bind(Double.class).toInstance(5.0d); 574 bind(ColoredCarFactory.class) 575 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 576 } 577 }); 578 579 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 580 581 assertEqualsBothWays(carFactory, carFactory); 582 } 583 584 static class Subaru implements Car { 585 @Inject @Assisted Provider<Color> colorProvider; 586 } 587 testInjectingProviderOfParameter()588 public void testInjectingProviderOfParameter() { 589 Injector injector = 590 Guice.createInjector( 591 new AbstractModule() { 592 @Override 593 protected void configure() { 594 bind(ColoredCarFactory.class) 595 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)); 596 } 597 }); 598 599 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 600 Subaru subaru = (Subaru) carFactory.create(Color.RED); 601 602 assertSame(Color.RED, subaru.colorProvider.get()); 603 assertSame(Color.RED, subaru.colorProvider.get()); 604 605 Subaru sedan = (Subaru) carFactory.create(Color.BLUE); 606 assertSame(Color.BLUE, sedan.colorProvider.get()); 607 assertSame(Color.BLUE, sedan.colorProvider.get()); 608 609 // and make sure the subaru is still red 610 assertSame(Color.RED, subaru.colorProvider.get()); 611 } 612 testInjectingNullParameter()613 public void testInjectingNullParameter() { 614 Injector injector = 615 Guice.createInjector( 616 new AbstractModule() { 617 @Override 618 protected void configure() { 619 bind(ColoredCarFactory.class) 620 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)); 621 } 622 }); 623 624 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 625 Subaru subaru = (Subaru) carFactory.create(null); 626 627 assertNull(subaru.colorProvider.get()); 628 assertNull(subaru.colorProvider.get()); 629 } 630 631 interface ProviderBasedColoredCarFactory { createCar(Provider<Color> colorProvider, Provider<String> stringProvider)632 Car createCar(Provider<Color> colorProvider, Provider<String> stringProvider); 633 createMustang(@ssisted"color") Provider<Color> colorProvider)634 Mustang createMustang(@Assisted("color") Provider<Color> colorProvider); 635 } 636 testAssistedProviderIsDisallowed()637 public void testAssistedProviderIsDisallowed() { 638 try { 639 Guice.createInjector( 640 new AbstractModule() { 641 @Override 642 protected void configure() { 643 bind(ProviderBasedColoredCarFactory.class) 644 .toProvider( 645 FactoryProvider.newFactory( 646 ProviderBasedColoredCarFactory.class, Subaru.class)); 647 } 648 }); 649 fail(); 650 } catch (CreationException expected) { 651 assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size()); 652 // Assert each method individually, because JDK7 doesn't guarantee method ordering. 653 assertContains( 654 expected.getMessage(), 655 ") A Provider may not be a type in a factory method of an AssistedInject." 656 + "\n Offending instance is parameter [1] with key" 657 + " [com.google.inject.Provider<" 658 + Color.class.getName() 659 + ">] on method [" 660 + ProviderBasedColoredCarFactory.class.getName() 661 + ".createCar()]"); 662 assertContains( 663 expected.getMessage(), 664 ") A Provider may not be a type in a factory method of an AssistedInject." 665 + "\n Offending instance is parameter [2] with key" 666 + " [com.google.inject.Provider<java.lang.String>] on method [" 667 + ProviderBasedColoredCarFactory.class.getName() 668 + ".createCar()]"); 669 assertContains( 670 expected.getMessage(), 671 ") A Provider may not be a type in a factory method of an AssistedInject." 672 + "\n Offending instance is parameter [1] with key" 673 + " [com.google.inject.Provider<" 674 + Color.class.getName() 675 + ">" 676 + " annotated with @com.google.inject.assistedinject.Assisted(value=" 677 + Annotations.memberValueString("color") 678 + ")]" 679 + " on method [" 680 + ProviderBasedColoredCarFactory.class.getName() 681 + ".createMustang()]"); 682 assertContains( 683 expected.getMessage(), 684 ") No implementation for com.google.inject.assistedinject." 685 + "FactoryProvider2Test$ProviderBasedColoredCarFactory was bound."); 686 } 687 } 688 689 interface JavaxProviderBasedColoredCarFactory { createCar( javax.inject.Provider<Color> colorProvider, javax.inject.Provider<String> stringProvider)690 Car createCar( 691 javax.inject.Provider<Color> colorProvider, javax.inject.Provider<String> stringProvider); 692 createMustang(@ssisted"color") javax.inject.Provider<Color> colorProvider)693 Mustang createMustang(@Assisted("color") javax.inject.Provider<Color> colorProvider); 694 } 695 testAssistedJavaxProviderIsDisallowed()696 public void testAssistedJavaxProviderIsDisallowed() { 697 try { 698 Guice.createInjector( 699 new AbstractModule() { 700 @Override 701 protected void configure() { 702 bind(JavaxProviderBasedColoredCarFactory.class) 703 .toProvider( 704 FactoryProvider.newFactory( 705 JavaxProviderBasedColoredCarFactory.class, Subaru.class)); 706 } 707 }); 708 fail(); 709 } catch (CreationException expected) { 710 assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size()); 711 assertContains( 712 expected.getMessage(), 713 ") A Provider may not be a type in a factory method of an AssistedInject." 714 + "\n Offending instance is parameter [1] with key" 715 + " [com.google.inject.Provider<" 716 + Color.class.getName() 717 + ">] on method [" 718 + JavaxProviderBasedColoredCarFactory.class.getName() 719 + ".createCar()]"); 720 assertContains( 721 expected.getMessage(), 722 ") A Provider may not be a type in a factory method of an AssistedInject." 723 + "\n Offending instance is parameter [2] with key" 724 + " [com.google.inject.Provider<java.lang.String>] on method [" 725 + JavaxProviderBasedColoredCarFactory.class.getName() 726 + ".createCar()]"); 727 assertContains( 728 expected.getMessage(), 729 ") A Provider may not be a type in a factory method of an AssistedInject." 730 + "\n Offending instance is parameter [1] with key" 731 + " [com.google.inject.Provider<" 732 + Color.class.getName() 733 + ">" 734 + " annotated with @com.google.inject.assistedinject.Assisted(value=" 735 + Annotations.memberValueString("color") 736 + ")]" 737 + " on method [" 738 + JavaxProviderBasedColoredCarFactory.class.getName() 739 + ".createMustang()]"); 740 assertContains( 741 expected.getMessage(), 742 ") No implementation for com.google.inject.assistedinject." 743 + "FactoryProvider2Test$JavaxProviderBasedColoredCarFactory was bound."); 744 } 745 } 746 testFactoryUseBeforeInitialization()747 public void testFactoryUseBeforeInitialization() { 748 ColoredCarFactory carFactory = 749 FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class).get(); 750 try { 751 carFactory.create(Color.RED); 752 fail(); 753 } catch (IllegalStateException expected) { 754 assertContains( 755 expected.getMessage(), 756 "Factories.create() factories cannot be used until they're initialized by Guice."); 757 } 758 } 759 760 interface MustangFactory { create(Color color)761 Mustang create(Color color); 762 } 763 testFactoryBuildingConcreteTypes()764 public void testFactoryBuildingConcreteTypes() { 765 Injector injector = 766 Guice.createInjector( 767 new AbstractModule() { 768 @Override 769 protected void configure() { 770 bind(double.class).toInstance(5.0d); 771 // note there is no 'thatMakes()' call here: 772 bind(MustangFactory.class) 773 .toProvider(FactoryProvider.newFactory(MustangFactory.class, Mustang.class)); 774 } 775 }); 776 MustangFactory factory = injector.getInstance(MustangFactory.class); 777 778 Mustang mustang = factory.create(Color.RED); 779 assertSame(Color.RED, mustang.color); 780 assertEquals(5.0d, mustang.engineSize, 0.0); 781 } 782 783 static class Fleet { 784 @Inject Mustang mustang; 785 @Inject Camaro camaro; 786 } 787 788 interface FleetFactory { createFleet(Color color)789 Fleet createFleet(Color color); 790 } 791 testInjectDeepIntoConstructedObjects()792 public void testInjectDeepIntoConstructedObjects() { 793 Injector injector = 794 Guice.createInjector( 795 new AbstractModule() { 796 @Override 797 protected void configure() { 798 bind(double.class).toInstance(5.0d); 799 bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); 800 bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); 801 bind(FleetFactory.class) 802 .toProvider(FactoryProvider.newFactory(FleetFactory.class, Fleet.class)); 803 } 804 }); 805 806 FleetFactory fleetFactory = injector.getInstance(FleetFactory.class); 807 Fleet fleet = fleetFactory.createFleet(Color.RED); 808 809 assertSame(Color.RED, fleet.mustang.color); 810 assertEquals(5.0d, fleet.mustang.engineSize, 0.0); 811 assertSame(Color.RED, fleet.camaro.color); 812 assertEquals(250, fleet.camaro.horsePower); 813 assertEquals(1984, fleet.camaro.modelYear); 814 } 815 816 interface TwoToneCarFactory { create(@ssisted"paint") Color paint, @Assisted("fabric") Color fabric)817 Car create(@Assisted("paint") Color paint, @Assisted("fabric") Color fabric); 818 } 819 820 static class Maxima implements Car { 821 @Inject 822 @Assisted("paint") 823 Color paint; 824 825 @Inject 826 @Assisted("fabric") 827 Color fabric; 828 } 829 testDistinctKeys()830 public void testDistinctKeys() { 831 Injector injector = 832 Guice.createInjector( 833 new AbstractModule() { 834 @Override 835 protected void configure() { 836 bind(TwoToneCarFactory.class) 837 .toProvider(FactoryProvider.newFactory(TwoToneCarFactory.class, Maxima.class)); 838 } 839 }); 840 841 TwoToneCarFactory factory = injector.getInstance(TwoToneCarFactory.class); 842 Maxima maxima = (Maxima) factory.create(Color.BLACK, Color.GRAY); 843 assertSame(Color.BLACK, maxima.paint); 844 assertSame(Color.GRAY, maxima.fabric); 845 } 846 847 interface DoubleToneCarFactory { create(@ssisted"paint") Color paint, @Assisted("paint") Color morePaint)848 Car create(@Assisted("paint") Color paint, @Assisted("paint") Color morePaint); 849 } 850 testDuplicateKeys()851 public void testDuplicateKeys() { 852 try { 853 Guice.createInjector( 854 new AbstractModule() { 855 @Override 856 protected void configure() { 857 bind(DoubleToneCarFactory.class) 858 .toProvider(FactoryProvider.newFactory(DoubleToneCarFactory.class, Maxima.class)); 859 } 860 }); 861 fail(); 862 } catch (CreationException expected) { 863 assertContains( 864 expected.getMessage(), 865 "A binding to " 866 + Color.class.getName() 867 + " annotated with @" 868 + Assisted.class.getName() 869 + "(value=" 870 + Annotations.memberValueString("paint") 871 + ") was already configured at"); 872 } 873 } 874 875 /*if[AOP]*/ testMethodInterceptorsOnAssistedTypes()876 public void testMethodInterceptorsOnAssistedTypes() { 877 final AtomicInteger invocationCount = new AtomicInteger(); 878 final org.aopalliance.intercept.MethodInterceptor interceptor = 879 new org.aopalliance.intercept.MethodInterceptor() { 880 @Override 881 public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) 882 throws Throwable { 883 invocationCount.incrementAndGet(); 884 return methodInvocation.proceed(); 885 } 886 }; 887 888 Injector injector = 889 Guice.createInjector( 890 new AbstractModule() { 891 @Override 892 protected void configure() { 893 bindInterceptor(Matchers.any(), Matchers.any(), interceptor); 894 bind(Double.class).toInstance(5.0d); 895 bind(ColoredCarFactory.class) 896 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 897 } 898 }); 899 900 ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class); 901 Mustang mustang = (Mustang) factory.create(Color.GREEN); 902 assertEquals(0, invocationCount.get()); 903 mustang.drive(); 904 assertEquals(1, invocationCount.get()); 905 } 906 /*end[AOP]*/ 907 908 /** 909 * Our factories aren't reusable across injectors. Although this behaviour isn't something we 910 * like, I have a test case to make sure the error message is pretty. 911 */ testFactoryReuseErrorMessageIsPretty()912 public void testFactoryReuseErrorMessageIsPretty() { 913 final Provider<ColoredCarFactory> factoryProvider = 914 FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class); 915 916 Guice.createInjector( 917 new AbstractModule() { 918 @Override 919 protected void configure() { 920 bind(Double.class).toInstance(5.0d); 921 bind(ColoredCarFactory.class).toProvider(factoryProvider); 922 } 923 }); 924 925 try { 926 Guice.createInjector( 927 new AbstractModule() { 928 @Override 929 protected void configure() { 930 bind(Double.class).toInstance(5.0d); 931 bind(ColoredCarFactory.class).toProvider(factoryProvider); 932 } 933 }); 934 fail(); 935 } catch (CreationException expected) { 936 assertContains( 937 expected.getMessage(), "Factories.create() factories may only be used in one Injector!"); 938 } 939 } 940 testNonAssistedFactoryMethodParameter()941 public void testNonAssistedFactoryMethodParameter() { 942 try { 943 FactoryProvider.newFactory(NamedParameterFactory.class, Mustang.class); 944 fail(); 945 } catch (ConfigurationException expected) { 946 assertContains( 947 expected.getMessage(), 948 "Only @Assisted is allowed for factory parameters, but found @" + Named.class.getName()); 949 } 950 } 951 952 interface NamedParameterFactory { create(@amed"seats") int seats, double engineSize)953 Car create(@Named("seats") int seats, double engineSize); 954 } 955 testDefaultAssistedAnnotation()956 public void testDefaultAssistedAnnotation() throws NoSuchFieldException { 957 Assisted plainAssisted = 958 Subaru.class.getDeclaredField("colorProvider").getAnnotation(Assisted.class); 959 assertEqualsBothWays(FactoryProvider2.DEFAULT_ANNOTATION, plainAssisted); 960 assertEquals(FactoryProvider2.DEFAULT_ANNOTATION.toString(), plainAssisted.toString()); 961 } 962 963 interface GenericColoredCarFactory<T extends Car> { create(Color color)964 T create(Color color); 965 } 966 testGenericAssistedFactory()967 public void testGenericAssistedFactory() { 968 final TypeLiteral<GenericColoredCarFactory<Mustang>> mustangTypeLiteral = 969 new TypeLiteral<GenericColoredCarFactory<Mustang>>() {}; 970 final TypeLiteral<GenericColoredCarFactory<Camaro>> camaroTypeLiteral = 971 new TypeLiteral<GenericColoredCarFactory<Camaro>>() {}; 972 973 Injector injector = 974 Guice.createInjector( 975 new AbstractModule() { 976 @Override 977 protected void configure() { 978 bind(Double.class).toInstance(5.0d); 979 bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); 980 bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); 981 bind(mustangTypeLiteral) 982 .toProvider( 983 FactoryProvider.newFactory( 984 mustangTypeLiteral, TypeLiteral.get(Mustang.class))); 985 bind(camaroTypeLiteral) 986 .toProvider( 987 FactoryProvider.newFactory( 988 camaroTypeLiteral, TypeLiteral.get(Camaro.class))); 989 } 990 }); 991 992 GenericColoredCarFactory<Mustang> mustangFactory = 993 injector.getInstance(Key.get(mustangTypeLiteral)); 994 GenericColoredCarFactory<Camaro> camaroFactory = 995 injector.getInstance(Key.get(camaroTypeLiteral)); 996 997 Mustang blueMustang = mustangFactory.create(Color.BLUE); 998 assertEquals(Color.BLUE, blueMustang.color); 999 assertEquals(5.0d, blueMustang.engineSize, 0.0); 1000 1001 Camaro redCamaro = camaroFactory.create(Color.RED); 1002 assertEquals(Color.RED, redCamaro.color); 1003 assertEquals(1984, redCamaro.modelYear); 1004 assertEquals(250, redCamaro.horsePower); 1005 } 1006 1007 @SuppressWarnings("unused") 1008 public interface Insurance<T extends Car> {} 1009 1010 public static class MustangInsurance implements Insurance<Mustang> { 1011 private final double premium; 1012 private final double limit; 1013 1014 @SuppressWarnings("unused") 1015 private Mustang car; 1016 1017 @Inject MustangInsurance( @amed"lowLimit") double limit, @Assisted Mustang car, @Assisted double premium)1018 public MustangInsurance( 1019 @Named("lowLimit") double limit, @Assisted Mustang car, @Assisted double premium) { 1020 this.premium = premium; 1021 this.limit = limit; 1022 this.car = car; 1023 } 1024 sell()1025 public void sell() {} 1026 } 1027 1028 public static class CamaroInsurance implements Insurance<Camaro> { 1029 private final double premium; 1030 private final double limit; 1031 1032 @SuppressWarnings("unused") 1033 private Camaro car; 1034 1035 @Inject CamaroInsurance( @amed"highLimit") double limit, @Assisted Camaro car, @Assisted double premium)1036 public CamaroInsurance( 1037 @Named("highLimit") double limit, @Assisted Camaro car, @Assisted double premium) { 1038 this.premium = premium; 1039 this.limit = limit; 1040 this.car = car; 1041 } 1042 sell()1043 public void sell() {} 1044 } 1045 1046 public interface MustangInsuranceFactory { create(Mustang car, double premium)1047 public Insurance<Mustang> create(Mustang car, double premium); 1048 } 1049 1050 public interface CamaroInsuranceFactory { create(Camaro car, double premium)1051 public Insurance<Camaro> create(Camaro car, double premium); 1052 } 1053 testAssistedFactoryForConcreteType()1054 public void testAssistedFactoryForConcreteType() { 1055 1056 Injector injector = 1057 Guice.createInjector( 1058 new AbstractModule() { 1059 @Override 1060 protected void configure() { 1061 bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d); 1062 bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d); 1063 bind(MustangInsuranceFactory.class) 1064 .toProvider( 1065 FactoryProvider.newFactory( 1066 MustangInsuranceFactory.class, MustangInsurance.class)); 1067 bind(CamaroInsuranceFactory.class) 1068 .toProvider( 1069 FactoryProvider.newFactory( 1070 CamaroInsuranceFactory.class, CamaroInsurance.class)); 1071 } 1072 }); 1073 1074 MustangInsuranceFactory mustangInsuranceFactory = 1075 injector.getInstance(MustangInsuranceFactory.class); 1076 CamaroInsuranceFactory camaroInsuranceFactory = 1077 injector.getInstance(CamaroInsuranceFactory.class); 1078 1079 Mustang mustang = new Mustang(5000d, Color.BLACK); 1080 MustangInsurance mustangPolicy = 1081 (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d); 1082 assertEquals(800.0d, mustangPolicy.premium, 0.0); 1083 assertEquals(50000.0d, mustangPolicy.limit, 0.0); 1084 1085 Camaro camaro = new Camaro(3000, 1967, Color.BLUE); 1086 CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d); 1087 assertEquals(800.0d, camaroPolicy.premium, 0.0); 1088 assertEquals(100000.0d, camaroPolicy.limit, 0.0); 1089 } 1090 1091 public interface InsuranceFactory<T extends Car> { create(T car, double premium)1092 public Insurance<T> create(T car, double premium); 1093 } 1094 testAssistedFactoryForParameterizedType()1095 public void testAssistedFactoryForParameterizedType() { 1096 final TypeLiteral<InsuranceFactory<Mustang>> mustangInsuranceFactoryType = 1097 new TypeLiteral<InsuranceFactory<Mustang>>() {}; 1098 final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType = 1099 new TypeLiteral<InsuranceFactory<Camaro>>() {}; 1100 1101 Injector injector = 1102 Guice.createInjector( 1103 new AbstractModule() { 1104 @Override 1105 protected void configure() { 1106 bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d); 1107 bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d); 1108 bind(mustangInsuranceFactoryType) 1109 .toProvider( 1110 FactoryProvider.newFactory( 1111 mustangInsuranceFactoryType, TypeLiteral.get(MustangInsurance.class))); 1112 bind(camaroInsuranceFactoryType) 1113 .toProvider( 1114 FactoryProvider.newFactory( 1115 camaroInsuranceFactoryType, TypeLiteral.get(CamaroInsurance.class))); 1116 } 1117 }); 1118 1119 InsuranceFactory<Mustang> mustangInsuranceFactory = 1120 injector.getInstance(Key.get(mustangInsuranceFactoryType)); 1121 InsuranceFactory<Camaro> camaroInsuranceFactory = 1122 injector.getInstance(Key.get(camaroInsuranceFactoryType)); 1123 1124 Mustang mustang = new Mustang(5000d, Color.BLACK); 1125 MustangInsurance mustangPolicy = 1126 (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d); 1127 assertEquals(800.0d, mustangPolicy.premium, 0.0); 1128 assertEquals(50000.0d, mustangPolicy.limit, 0.0); 1129 1130 Camaro camaro = new Camaro(3000, 1967, Color.BLUE); 1131 CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d); 1132 assertEquals(800.0d, camaroPolicy.premium, 0.0); 1133 assertEquals(100000.0d, camaroPolicy.limit, 0.0); 1134 } 1135 1136 public static class AutoInsurance<T extends Car> implements Insurance<T> { 1137 private final double premium; 1138 private final double limit; 1139 private final T car; 1140 1141 @Inject AutoInsurance(double limit, @Assisted T car, @Assisted double premium)1142 public AutoInsurance(double limit, @Assisted T car, @Assisted double premium) { 1143 this.limit = limit; 1144 this.car = car; 1145 this.premium = premium; 1146 } 1147 sell()1148 public void sell() {} 1149 } 1150 testAssistedFactoryForTypeVariableParameters()1151 public void testAssistedFactoryForTypeVariableParameters() { 1152 final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType = 1153 new TypeLiteral<InsuranceFactory<Camaro>>() {}; 1154 1155 Injector injector = 1156 Guice.createInjector( 1157 new AbstractModule() { 1158 @Override 1159 protected void configure() { 1160 bind(Double.class).toInstance(50000.0d); 1161 bind(camaroInsuranceFactoryType) 1162 .toProvider( 1163 FactoryProvider.newFactory( 1164 camaroInsuranceFactoryType, 1165 new TypeLiteral<AutoInsurance<Camaro>>() {})); 1166 } 1167 }); 1168 1169 InsuranceFactory<Camaro> camaroInsuranceFactory = 1170 injector.getInstance(Key.get(camaroInsuranceFactoryType)); 1171 1172 Camaro camaro = new Camaro(3000, 1967, Color.BLUE); 1173 AutoInsurance<?> camaroPolicy = 1174 (AutoInsurance<?>) camaroInsuranceFactory.create(camaro, 800.0d); 1175 assertEquals(800.0d, camaroPolicy.premium, 0.0); 1176 assertEquals(50000.0d, camaroPolicy.limit, 0.0); 1177 assertEquals(camaro, camaroPolicy.car); 1178 } 1179 testInjectingAndUsingInjector()1180 public void testInjectingAndUsingInjector() { 1181 Injector injector = 1182 Guice.createInjector( 1183 new AbstractModule() { 1184 @Override 1185 protected void configure() { 1186 bind(ColoredCarFactory.class) 1187 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Segway.class)); 1188 } 1189 }); 1190 1191 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 1192 Segway green = (Segway) carFactory.create(Color.GREEN); 1193 assertSame(Color.GREEN, green.getColor()); 1194 assertSame(Color.GREEN, green.getColor()); 1195 1196 Segway pink = (Segway) carFactory.create(Color.PINK); 1197 assertSame(Color.PINK, pink.getColor()); 1198 assertSame(Color.PINK, pink.getColor()); 1199 assertSame(Color.GREEN, green.getColor()); 1200 } 1201 testDuplicateAssistedFactoryBinding()1202 public void testDuplicateAssistedFactoryBinding() { 1203 Injector injector = 1204 Guice.createInjector( 1205 new AbstractModule() { 1206 @Override 1207 protected void configure() { 1208 bind(Double.class).toInstance(5.0d); 1209 bind(ColoredCarFactory.class) 1210 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 1211 bind(ColoredCarFactory.class) 1212 .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 1213 } 1214 }); 1215 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 1216 1217 Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE); 1218 assertEquals(Color.BLUE, blueMustang.color); 1219 assertEquals(5.0d, blueMustang.engineSize, 0.0); 1220 1221 Mustang redMustang = (Mustang) carFactory.create(Color.RED); 1222 assertEquals(Color.RED, redMustang.color); 1223 assertEquals(5.0d, redMustang.engineSize, 0.0); 1224 } 1225 1226 public interface Equals { 1227 1228 enum ComparisonMethod { 1229 SHALLOW, 1230 DEEP; 1231 } 1232 1233 interface Factory { equals(Equals.ComparisonMethod comparisonMethod)1234 Equals equals(Equals.ComparisonMethod comparisonMethod); 1235 } 1236 1237 public static class Impl implements Equals { 1238 private final double sigma; 1239 private final ComparisonMethod comparisonMethod; 1240 1241 @AssistedInject Impl(double sigma, @Assisted ComparisonMethod comparisonMethod)1242 public Impl(double sigma, @Assisted ComparisonMethod comparisonMethod) { 1243 this.sigma = sigma; 1244 this.comparisonMethod = comparisonMethod; 1245 } 1246 } 1247 } 1248 testFactoryMethodCalledEquals()1249 public void testFactoryMethodCalledEquals() { 1250 Injector injector = 1251 Guice.createInjector( 1252 new AbstractModule() { 1253 @Override 1254 protected void configure() { 1255 bind(Double.class).toInstance(0.01d); 1256 bind(Equals.Factory.class) 1257 .toProvider( 1258 FactoryProvider.newFactory(Equals.Factory.class, Equals.Impl.class)); 1259 } 1260 }); 1261 Equals.Factory equalsFactory = injector.getInstance(Equals.Factory.class); 1262 Equals.Impl shallowEquals = (Impl) equalsFactory.equals(ComparisonMethod.SHALLOW); 1263 assertEquals(ComparisonMethod.SHALLOW, shallowEquals.comparisonMethod); 1264 assertEquals(0.01d, shallowEquals.sigma, 0.0); 1265 } 1266 1267 static class Segway implements Car { 1268 @Inject Injector injector; 1269 getColor()1270 Color getColor() { 1271 return injector.getInstance(Key.get(Color.class, FactoryProvider2.DEFAULT_ANNOTATION)); 1272 } 1273 } 1274 testReturnValueMatchesParamValue()1275 public void testReturnValueMatchesParamValue() { 1276 Injector injector = 1277 Guice.createInjector( 1278 new AbstractModule() { 1279 @Override 1280 public void configure() { 1281 install(new FactoryModuleBuilder().build(Delegater.Factory.class)); 1282 } 1283 }); 1284 Delegater delegate = new Delegater(); 1285 Delegater user = injector.getInstance(Delegater.Factory.class).create(delegate); 1286 assertSame(delegate, user.delegate); 1287 } 1288 1289 static class Delegater { 1290 interface Factory { create(Delegater delegate)1291 Delegater create(Delegater delegate); 1292 } 1293 1294 private final Delegater delegate; 1295 1296 @Inject Delegater(@ssisted Delegater delegater)1297 Delegater(@Assisted Delegater delegater) { 1298 this.delegate = delegater; 1299 } 1300 Delegater()1301 Delegater() { 1302 this.delegate = null; 1303 } 1304 } 1305 1306 public abstract static class AbstractAssisted { 1307 interface Factory<O extends AbstractAssisted, I extends CharSequence> { create(I string)1308 O create(I string); 1309 } 1310 } 1311 1312 static class ConcreteAssisted extends AbstractAssisted { 1313 @Inject ConcreteAssisted(@uppressWarnings"unused") @ssisted String string)1314 ConcreteAssisted(@SuppressWarnings("unused") @Assisted String string) {} 1315 } 1316 1317 static class ConcreteAssistedWithOverride extends AbstractAssisted { 1318 @AssistedInject ConcreteAssistedWithOverride(@uppressWarnings"unused") @ssisted String string)1319 ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted String string) {} 1320 1321 @AssistedInject ConcreteAssistedWithOverride(@uppressWarnings"unused") @ssisted StringBuilder sb)1322 ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted StringBuilder sb) {} 1323 1324 interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> { 1325 @Override create(String string)1326 ConcreteAssistedWithOverride create(String string); 1327 } 1328 1329 interface Factory2 extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> { 1330 @Override create(String string)1331 ConcreteAssistedWithOverride create(String string); 1332 create(StringBuilder sb)1333 ConcreteAssistedWithOverride create(StringBuilder sb); 1334 } 1335 } 1336 1337 static class ConcreteAssistedWithoutOverride extends AbstractAssisted { 1338 @Inject ConcreteAssistedWithoutOverride(@uppressWarnings"unused") @ssisted String string)1339 ConcreteAssistedWithoutOverride(@SuppressWarnings("unused") @Assisted String string) {} 1340 1341 interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> {} 1342 } 1343 1344 public static class Public extends AbstractAssisted { 1345 @AssistedInject Public(@uppressWarnings"unused") @ssisted String string)1346 Public(@SuppressWarnings("unused") @Assisted String string) {} 1347 1348 @AssistedInject Public(@uppressWarnings"unused") @ssisted StringBuilder sb)1349 Public(@SuppressWarnings("unused") @Assisted StringBuilder sb) {} 1350 1351 public interface Factory extends AbstractAssisted.Factory<Public, String> { 1352 @Override create(String string)1353 Public create(String string); 1354 create(StringBuilder sb)1355 Public create(StringBuilder sb); 1356 } 1357 } 1358 1359 // See https://github.com/google/guice/issues/904 testGeneratedDefaultMethodsForwardCorrectly()1360 public void testGeneratedDefaultMethodsForwardCorrectly() { 1361 final Key<AbstractAssisted.Factory<ConcreteAssisted, String>> concreteKey = 1362 new Key<AbstractAssisted.Factory<ConcreteAssisted, String>>() {}; 1363 Injector injector = 1364 Guice.createInjector( 1365 new AbstractModule() { 1366 @Override 1367 protected void configure() { 1368 install( 1369 new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory.class)); 1370 install( 1371 new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory2.class)); 1372 install( 1373 new FactoryModuleBuilder() 1374 .build(ConcreteAssistedWithoutOverride.Factory.class)); 1375 install(new FactoryModuleBuilder().build(Public.Factory.class)); 1376 install(new FactoryModuleBuilder().build(concreteKey)); 1377 } 1378 }); 1379 1380 ConcreteAssistedWithOverride.Factory factory1 = 1381 injector.getInstance(ConcreteAssistedWithOverride.Factory.class); 1382 factory1.create("foo"); 1383 AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory1Abstract = factory1; 1384 factory1Abstract.create("foo"); 1385 1386 ConcreteAssistedWithOverride.Factory2 factory2 = 1387 injector.getInstance(ConcreteAssistedWithOverride.Factory2.class); 1388 factory2.create("foo"); 1389 factory2.create(new StringBuilder("foo")); 1390 AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory2Abstract = factory2; 1391 factory2Abstract.create("foo"); 1392 1393 ConcreteAssistedWithoutOverride.Factory factory3 = 1394 injector.getInstance(ConcreteAssistedWithoutOverride.Factory.class); 1395 factory3.create("foo"); 1396 AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> factory3Abstract = factory3; 1397 factory3Abstract.create("foo"); 1398 1399 Public.Factory factory4 = injector.getInstance(Public.Factory.class); 1400 factory4.create("foo"); 1401 factory4.create(new StringBuilder("foo")); 1402 AbstractAssisted.Factory<Public, String> factory4Abstract = factory4; 1403 factory4Abstract.create("foo"); 1404 1405 AbstractAssisted.Factory<ConcreteAssisted, String> factory5 = injector.getInstance(concreteKey); 1406 factory5.create("foo"); 1407 } 1408 } 1409