1 /** 2 * Copyright (C) 2014 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.multibindings; 18 19 import static com.google.inject.Asserts.assertContains; 20 import static com.google.inject.multibindings.SpiUtils.assertOptionalVisitor; 21 import static com.google.inject.multibindings.SpiUtils.instance; 22 import static com.google.inject.multibindings.SpiUtils.linked; 23 import static com.google.inject.multibindings.SpiUtils.providerInstance; 24 import static com.google.inject.multibindings.SpiUtils.providerKey; 25 import static com.google.inject.name.Names.named; 26 27 import com.google.common.base.Optional; 28 import com.google.common.collect.ImmutableSet; 29 import com.google.common.collect.Iterables; 30 import com.google.common.collect.Lists; 31 import com.google.common.collect.Sets; 32 import com.google.inject.AbstractModule; 33 import com.google.inject.Asserts; 34 import com.google.inject.Binding; 35 import com.google.inject.BindingAnnotation; 36 import com.google.inject.CreationException; 37 import com.google.inject.Guice; 38 import com.google.inject.Injector; 39 import com.google.inject.Key; 40 import com.google.inject.Module; 41 import com.google.inject.Provider; 42 import com.google.inject.Provides; 43 import com.google.inject.Scopes; 44 import com.google.inject.TypeLiteral; 45 import com.google.inject.internal.WeakKeySetUtils; 46 import com.google.inject.multibindings.OptionalBinder.Actual; 47 import com.google.inject.multibindings.OptionalBinder.Default; 48 import com.google.inject.multibindings.SpiUtils.VisitType; 49 import com.google.inject.name.Named; 50 import com.google.inject.name.Names; 51 import com.google.inject.spi.Dependency; 52 import com.google.inject.spi.Elements; 53 import com.google.inject.spi.HasDependencies; 54 import com.google.inject.spi.InstanceBinding; 55 import com.google.inject.util.Modules; 56 import com.google.inject.util.Providers; 57 58 import junit.framework.TestCase; 59 60 import java.lang.annotation.Annotation; 61 import java.lang.annotation.ElementType; 62 import java.lang.annotation.Retention; 63 import java.lang.annotation.RetentionPolicy; 64 import java.lang.annotation.Target; 65 import java.lang.ref.WeakReference; 66 import java.lang.reflect.Method; 67 import java.util.List; 68 import java.util.Map.Entry; 69 import java.util.Set; 70 71 /** 72 * @author sameb@google.com (Sam Berlin) 73 */ 74 public class OptionalBinderTest extends TestCase { 75 76 private static final boolean HAS_JAVA_OPTIONAL; 77 private static final Class<?> JAVA_OPTIONAL_CLASS; 78 private static final Method JAVA_OPTIONAL_OR_ELSE; 79 static { 80 Class<?> optional = null; 81 Method orElse = null; 82 try { 83 optional = Class.forName("java.util.Optional"); 84 orElse = optional.getDeclaredMethod("orElse", Object.class); 85 } catch (ClassNotFoundException ignored) { 86 } catch (NoSuchMethodException ignored) { 87 } catch (SecurityException ignored) { 88 } 89 HAS_JAVA_OPTIONAL = optional != null; 90 JAVA_OPTIONAL_CLASS = optional; 91 JAVA_OPTIONAL_OR_ELSE = orElse; 92 } 93 94 final Key<String> stringKey = Key.get(String.class); 95 final TypeLiteral<Optional<String>> optionalOfString = new TypeLiteral<Optional<String>>() {}; 96 final TypeLiteral<?> javaOptionalOfString = HAS_JAVA_OPTIONAL ? 97 OptionalBinder.javaOptionalOf(stringKey.getTypeLiteral()) : null; 98 final TypeLiteral<Optional<Provider<String>>> optionalOfProviderString = 99 new TypeLiteral<Optional<Provider<String>>>() {}; 100 final TypeLiteral<?> javaOptionalOfProviderString = HAS_JAVA_OPTIONAL ? 101 OptionalBinder.javaOptionalOfProvider(stringKey.getTypeLiteral()) : null; 102 final TypeLiteral<Optional<javax.inject.Provider<String>>> optionalOfJavaxProviderString = 103 new TypeLiteral<Optional<javax.inject.Provider<String>>>() {}; 104 final TypeLiteral<?> javaOptionalOfJavaxProviderString = HAS_JAVA_OPTIONAL ? 105 OptionalBinder.javaOptionalOfJavaxProvider(stringKey.getTypeLiteral()) : null; 106 107 final Key<Integer> intKey = Key.get(Integer.class); 108 final TypeLiteral<Optional<Integer>> optionalOfInteger = new TypeLiteral<Optional<Integer>>() {}; 109 final TypeLiteral<?> javaOptionalOfInteger = HAS_JAVA_OPTIONAL ? 110 OptionalBinder.javaOptionalOf(intKey.getTypeLiteral()) : null; 111 final TypeLiteral<Optional<Provider<Integer>>> optionalOfProviderInteger = 112 new TypeLiteral<Optional<Provider<Integer>>>() {}; 113 final TypeLiteral<?> javaOptionalOfProviderInteger = HAS_JAVA_OPTIONAL ? 114 OptionalBinder.javaOptionalOfProvider(intKey.getTypeLiteral()) : null; 115 final TypeLiteral<Optional<javax.inject.Provider<Integer>>> optionalOfJavaxProviderInteger = 116 new TypeLiteral<Optional<javax.inject.Provider<Integer>>>() {}; 117 final TypeLiteral<?> javaOptionalOfJavaxProviderInteger = HAS_JAVA_OPTIONAL ? 118 OptionalBinder.javaOptionalOfJavaxProvider(intKey.getTypeLiteral()) : null; 119 120 final TypeLiteral<List<String>> listOfStrings = new TypeLiteral<List<String>>() {}; 121 testTypeNotBoundByDefault()122 public void testTypeNotBoundByDefault() { 123 Module module = new AbstractModule() { 124 @Override protected void configure() { 125 OptionalBinder.newOptionalBinder(binder(), String.class); 126 requireBinding(new Key<Optional<String>>() {}); // the above specifies this. 127 requireBinding(String.class); // but it doesn't specify this. 128 binder().requireExplicitBindings(); // need to do this, otherwise String will JIT 129 130 if (HAS_JAVA_OPTIONAL) { 131 requireBinding(Key.get(javaOptionalOfString)); 132 } 133 } 134 }; 135 136 try { 137 Guice.createInjector(module); 138 fail(); 139 } catch (CreationException ce) { 140 assertContains(ce.getMessage(), 141 "1) Explicit bindings are required and java.lang.String is not explicitly bound."); 142 assertEquals(1, ce.getErrorMessages().size()); 143 } 144 } 145 testOptionalIsAbsentByDefault()146 public void testOptionalIsAbsentByDefault() throws Exception { 147 Module module = new AbstractModule() { 148 @Override protected void configure() { 149 OptionalBinder.newOptionalBinder(binder(), String.class); 150 } 151 }; 152 153 Injector injector = Guice.createInjector(module); 154 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 155 assertFalse(optional.isPresent()); 156 157 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 158 assertFalse(optionalP.isPresent()); 159 160 Optional<javax.inject.Provider<String>> optionalJxP = 161 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 162 assertFalse(optionalJxP.isPresent()); 163 164 assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, null, null); 165 166 if (HAS_JAVA_OPTIONAL) { 167 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 168 assertFalse(optional.isPresent()); 169 170 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 171 assertFalse(optionalP.isPresent()); 172 173 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 174 assertFalse(optionalJxP.isPresent()); 175 } 176 } 177 testUsesUserBoundValue()178 public void testUsesUserBoundValue() throws Exception { 179 Module module = new AbstractModule() { 180 @Override protected void configure() { 181 OptionalBinder.newOptionalBinder(binder(), String.class); 182 } 183 @Provides String provideString() { return "foo"; } 184 }; 185 186 Injector injector = Guice.createInjector(module); 187 assertEquals("foo", injector.getInstance(String.class)); 188 189 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 190 assertEquals("foo", optional.get()); 191 192 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 193 assertEquals("foo", optionalP.get().get()); 194 195 Optional<javax.inject.Provider<String>> optionalJxP = 196 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 197 assertEquals("foo", optionalJxP.get().get()); 198 199 assertOptionalVisitor(stringKey, 200 setOf(module), 201 VisitType.BOTH, 202 0, 203 null, 204 null, 205 providerInstance("foo")); 206 207 if (HAS_JAVA_OPTIONAL) { 208 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 209 assertEquals("foo", optional.get()); 210 211 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 212 assertEquals("foo", optionalP.get().get()); 213 214 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 215 assertEquals("foo", optionalJxP.get().get()); 216 } 217 } 218 testSetDefault()219 public void testSetDefault() throws Exception { 220 Module module = new AbstractModule() { 221 @Override protected void configure() { 222 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); 223 } 224 }; 225 Injector injector = Guice.createInjector(module); 226 assertEquals("a", injector.getInstance(String.class)); 227 228 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 229 assertTrue(optional.isPresent()); 230 assertEquals("a", optional.get()); 231 232 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 233 assertTrue(optionalP.isPresent()); 234 assertEquals("a", optionalP.get().get()); 235 236 Optional<javax.inject.Provider<String>> optionalJxP = 237 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 238 assertTrue(optionalJxP.isPresent()); 239 assertEquals("a", optionalJxP.get().get()); 240 241 assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null); 242 243 if (HAS_JAVA_OPTIONAL) { 244 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 245 assertTrue(optional.isPresent()); 246 assertEquals("a", optional.get()); 247 248 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 249 assertTrue(optionalP.isPresent()); 250 assertEquals("a", optionalP.get().get()); 251 252 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 253 assertTrue(optionalJxP.isPresent()); 254 assertEquals("a", optionalJxP.get().get()); 255 } 256 } 257 testSetBinding()258 public void testSetBinding() throws Exception { 259 Module module = new AbstractModule() { 260 @Override protected void configure() { 261 OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a"); 262 } 263 }; 264 Injector injector = Guice.createInjector(module); 265 assertEquals("a", injector.getInstance(String.class)); 266 267 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 268 assertTrue(optional.isPresent()); 269 assertEquals("a", optional.get()); 270 271 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 272 assertTrue(optionalP.isPresent()); 273 assertEquals("a", optionalP.get().get()); 274 275 Optional<javax.inject.Provider<String>> optionalJxP = 276 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 277 assertTrue(optionalJxP.isPresent()); 278 assertEquals("a", optionalJxP.get().get()); 279 280 assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null); 281 282 if (HAS_JAVA_OPTIONAL) { 283 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 284 assertTrue(optional.isPresent()); 285 assertEquals("a", optional.get()); 286 287 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 288 assertTrue(optionalP.isPresent()); 289 assertEquals("a", optionalP.get().get()); 290 291 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 292 assertTrue(optionalJxP.isPresent()); 293 assertEquals("a", optionalJxP.get().get()); 294 } 295 } 296 testSetBindingOverridesDefault()297 public void testSetBindingOverridesDefault() throws Exception { 298 Module module = new AbstractModule() { 299 @Override protected void configure() { 300 OptionalBinder<String> optionalBinder = 301 OptionalBinder.newOptionalBinder(binder(), String.class); 302 optionalBinder.setDefault().toInstance("a"); 303 optionalBinder.setBinding().toInstance("b"); 304 } 305 }; 306 Injector injector = Guice.createInjector(module); 307 assertEquals("b", injector.getInstance(String.class)); 308 309 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 310 assertTrue(optional.isPresent()); 311 assertEquals("b", optional.get()); 312 313 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 314 assertTrue(optionalP.isPresent()); 315 assertEquals("b", optionalP.get().get()); 316 317 Optional<javax.inject.Provider<String>> optionalJxP = 318 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 319 assertTrue(optionalJxP.isPresent()); 320 assertEquals("b", optionalJxP.get().get()); 321 322 assertOptionalVisitor(stringKey, 323 setOf(module), 324 VisitType.BOTH, 325 0, 326 instance("a"), 327 instance("b"), 328 null); 329 330 if (HAS_JAVA_OPTIONAL) { 331 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 332 assertTrue(optional.isPresent()); 333 assertEquals("b", optional.get()); 334 335 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 336 assertTrue(optionalP.isPresent()); 337 assertEquals("b", optionalP.get().get()); 338 339 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 340 assertTrue(optionalJxP.isPresent()); 341 assertEquals("b", optionalJxP.get().get()); 342 } 343 } 344 testSpreadAcrossModules()345 public void testSpreadAcrossModules() throws Exception { 346 Module module1 = new AbstractModule() { 347 @Override protected void configure() { 348 OptionalBinder.newOptionalBinder(binder(), String.class); 349 } 350 }; 351 Module module2 = new AbstractModule() { 352 @Override protected void configure() { 353 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); 354 } 355 }; 356 Module module3 = new AbstractModule() { 357 @Override protected void configure() { 358 OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b"); 359 } 360 }; 361 362 Injector injector = Guice.createInjector(module1, module2, module3); 363 assertEquals("b", injector.getInstance(String.class)); 364 365 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 366 assertTrue(optional.isPresent()); 367 assertEquals("b", optional.get()); 368 369 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 370 assertTrue(optionalP.isPresent()); 371 assertEquals("b", optionalP.get().get()); 372 373 Optional<javax.inject.Provider<String>> optionalJxP = 374 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 375 assertTrue(optionalJxP.isPresent()); 376 assertEquals("b", optionalJxP.get().get()); 377 378 assertOptionalVisitor(stringKey, 379 setOf(module1, module2, module3), 380 VisitType.BOTH, 381 0, 382 instance("a"), 383 instance("b"), 384 null); 385 386 if (HAS_JAVA_OPTIONAL) { 387 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 388 assertTrue(optional.isPresent()); 389 assertEquals("b", optional.get()); 390 391 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 392 assertTrue(optionalP.isPresent()); 393 assertEquals("b", optionalP.get().get()); 394 395 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 396 assertTrue(optionalJxP.isPresent()); 397 assertEquals("b", optionalJxP.get().get()); 398 } 399 } 400 testExactSameBindingCollapses_defaults()401 public void testExactSameBindingCollapses_defaults() throws Exception { 402 Module module = new AbstractModule() { 403 @Override protected void configure() { 404 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault() 405 .toInstance(new String("a")); // using new String to ensure .equals is checked. 406 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault() 407 .toInstance(new String("a")); 408 } 409 }; 410 Injector injector = Guice.createInjector(module); 411 assertEquals("a", injector.getInstance(String.class)); 412 413 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 414 assertTrue(optional.isPresent()); 415 assertEquals("a", optional.get()); 416 417 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 418 assertTrue(optionalP.isPresent()); 419 assertEquals("a", optionalP.get().get()); 420 421 Optional<javax.inject.Provider<String>> optionalJxP = 422 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 423 assertTrue(optionalJxP.isPresent()); 424 assertEquals("a", optionalJxP.get().get()); 425 426 assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null); 427 428 if (HAS_JAVA_OPTIONAL) { 429 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 430 assertTrue(optional.isPresent()); 431 assertEquals("a", optional.get()); 432 433 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 434 assertTrue(optionalP.isPresent()); 435 assertEquals("a", optionalP.get().get()); 436 437 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 438 assertTrue(optionalJxP.isPresent()); 439 assertEquals("a", optionalJxP.get().get()); 440 } 441 } 442 testExactSameBindingCollapses_actual()443 public void testExactSameBindingCollapses_actual() throws Exception { 444 Module module = new AbstractModule() { 445 @Override protected void configure() { 446 OptionalBinder.newOptionalBinder(binder(), String.class).setBinding() 447 .toInstance(new String("a")); // using new String to ensure .equals is checked. 448 OptionalBinder.newOptionalBinder(binder(), String.class).setBinding() 449 .toInstance(new String("a")); 450 } 451 }; 452 Injector injector = Guice.createInjector(module); 453 assertEquals("a", injector.getInstance(String.class)); 454 455 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 456 assertTrue(optional.isPresent()); 457 assertEquals("a", optional.get()); 458 459 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 460 assertTrue(optionalP.isPresent()); 461 assertEquals("a", optionalP.get().get()); 462 463 Optional<javax.inject.Provider<String>> optionalJxP = 464 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 465 assertTrue(optionalJxP.isPresent()); 466 assertEquals("a", optionalJxP.get().get()); 467 468 assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null); 469 470 if (HAS_JAVA_OPTIONAL) { 471 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 472 assertTrue(optional.isPresent()); 473 assertEquals("a", optional.get()); 474 475 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 476 assertTrue(optionalP.isPresent()); 477 assertEquals("a", optionalP.get().get()); 478 479 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 480 assertTrue(optionalJxP.isPresent()); 481 assertEquals("a", optionalJxP.get().get()); 482 } 483 } 484 testDifferentBindingsFail_defaults()485 public void testDifferentBindingsFail_defaults() { 486 Module module = new AbstractModule() { 487 @Override protected void configure() { 488 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); 489 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b"); 490 } 491 }; 492 try { 493 Guice.createInjector(module); 494 fail(); 495 } catch (CreationException ce) { 496 assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size()); 497 assertContains(ce.getMessage(), 498 "1) A binding to java.lang.String annotated with @" 499 + Default.class.getName() + " was already configured at " 500 + module.getClass().getName() + ".configure(", 501 "at " + module.getClass().getName() + ".configure("); 502 } 503 } 504 testDifferentBindingsFail_actual()505 public void testDifferentBindingsFail_actual() { 506 Module module = new AbstractModule() { 507 @Override protected void configure() { 508 OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a"); 509 OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b"); 510 } 511 }; 512 try { 513 Guice.createInjector(module); 514 fail(); 515 } catch (CreationException ce) { 516 assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size()); 517 assertContains(ce.getMessage(), 518 "1) A binding to java.lang.String annotated with @" 519 + Actual.class.getName() + " was already configured at " 520 + module.getClass().getName() + ".configure(", 521 "at " + module.getClass().getName() + ".configure("); 522 } 523 } 524 testDifferentBindingsFail_both()525 public void testDifferentBindingsFail_both() { 526 Module module = new AbstractModule() { 527 @Override protected void configure() { 528 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); 529 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b"); 530 OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b"); 531 OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("c"); 532 } 533 }; 534 try { 535 Guice.createInjector(module); 536 fail(); 537 } catch (CreationException ce) { 538 assertEquals(ce.getMessage(), 2, ce.getErrorMessages().size()); 539 assertContains(ce.getMessage(), 540 "1) A binding to java.lang.String annotated with @" 541 + Default.class.getName() + " was already configured at " 542 + module.getClass().getName() + ".configure(", 543 "at " + module.getClass().getName() + ".configure(", 544 "2) A binding to java.lang.String annotated with @" 545 + Actual.class.getName() + " was already configured at " 546 + module.getClass().getName() + ".configure(", 547 "at " + module.getClass().getName() + ".configure("); 548 } 549 } 550 testQualifiedAggregatesTogether()551 public void testQualifiedAggregatesTogether() throws Exception { 552 Module module1 = new AbstractModule() { 553 @Override 554 protected void configure() { 555 OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo"))); 556 } 557 }; 558 Module module2 = new AbstractModule() { 559 @Override 560 protected void configure() { 561 OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo"))) 562 .setDefault().toInstance("a"); 563 } 564 }; 565 Module module3 = new AbstractModule() { 566 @Override 567 protected void configure() { 568 OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo"))) 569 .setBinding().toInstance("b"); 570 } 571 }; 572 573 Injector injector = Guice.createInjector(module1, module2, module3); 574 assertEquals("b", injector.getInstance(Key.get(String.class, Names.named("foo")))); 575 576 Optional<String> optional = injector.getInstance(Key.get(optionalOfString, Names.named("foo"))); 577 assertTrue(optional.isPresent()); 578 assertEquals("b", optional.get()); 579 580 Optional<Provider<String>> optionalP = 581 injector.getInstance(Key.get(optionalOfProviderString, Names.named("foo"))); 582 assertTrue(optionalP.isPresent()); 583 assertEquals("b", optionalP.get().get()); 584 585 Optional<javax.inject.Provider<String>> optionalJxP = 586 injector.getInstance(Key.get(optionalOfJavaxProviderString, Names.named("foo"))); 587 assertTrue(optionalJxP.isPresent()); 588 assertEquals("b", optionalJxP.get().get()); 589 590 assertOptionalVisitor(Key.get(String.class, Names.named("foo")), 591 setOf(module1, module2, module3), 592 VisitType.BOTH, 593 0, 594 instance("a"), 595 instance("b"), 596 null); 597 598 if (HAS_JAVA_OPTIONAL) { 599 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString, Names.named("foo")))); 600 assertTrue(optional.isPresent()); 601 assertEquals("b", optional.get()); 602 603 optionalP = toOptional(injector.getInstance 604 (Key.get(javaOptionalOfProviderString, Names.named("foo")))); 605 assertTrue(optionalP.isPresent()); 606 assertEquals("b", optionalP.get().get()); 607 608 optionalJxP = toOptional(injector.getInstance( 609 Key.get(javaOptionalOfJavaxProviderString, Names.named("foo")))); 610 assertTrue(optionalJxP.isPresent()); 611 assertEquals("b", optionalJxP.get().get()); 612 } 613 } 614 testMultipleDifferentOptionals()615 public void testMultipleDifferentOptionals() { 616 final Key<String> bKey = Key.get(String.class, named("b")); 617 final Key<String> cKey = Key.get(String.class, named("c")); 618 Module module = new AbstractModule() { 619 @Override protected void configure() { 620 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); 621 OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault().toInstance(1); 622 623 OptionalBinder.newOptionalBinder(binder(), bKey).setDefault().toInstance("b"); 624 OptionalBinder.newOptionalBinder(binder(), cKey).setDefault().toInstance("c"); 625 } 626 }; 627 Injector injector = Guice.createInjector(module); 628 assertEquals("a", injector.getInstance(String.class)); 629 assertEquals(1, injector.getInstance(Integer.class).intValue()); 630 assertEquals("b", injector.getInstance(bKey)); 631 assertEquals("c", injector.getInstance(cKey)); 632 633 assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 3, instance("a"), null, null); 634 assertOptionalVisitor(intKey, setOf(module), VisitType.BOTH, 3, instance(1), null, null); 635 assertOptionalVisitor(bKey, setOf(module), VisitType.BOTH, 3, instance("b"), null, null); 636 assertOptionalVisitor(cKey, setOf(module), VisitType.BOTH, 3, instance("c"), null, null); 637 } 638 testOptionalIsAppropriatelyLazy()639 public void testOptionalIsAppropriatelyLazy() throws Exception { 640 Module module = new AbstractModule() { 641 int nextValue = 1; 642 @Override protected void configure() { 643 OptionalBinder.newOptionalBinder(binder(), Integer.class) 644 .setDefault().to(Key.get(Integer.class, Names.named("foo"))); 645 } 646 @Provides @Named("foo") int provideInt() { 647 return nextValue++; 648 } 649 }; 650 Injector injector = Guice.createInjector(module); 651 652 Optional<Provider<Integer>> optionalP = 653 injector.getInstance(Key.get(optionalOfProviderInteger)); 654 Optional<javax.inject.Provider<Integer>> optionalJxP = 655 injector.getInstance(Key.get(optionalOfJavaxProviderInteger)); 656 657 assertEquals(1, injector.getInstance(Integer.class).intValue()); 658 assertEquals(2, injector.getInstance(Integer.class).intValue()); 659 660 // Calling .get() on an Optional<Integer> multiple times will keep giving the same thing 661 Optional<Integer> optional = injector.getInstance(Key.get(optionalOfInteger)); 662 assertEquals(3, optional.get().intValue()); 663 assertEquals(3, optional.get().intValue()); 664 // But getting another Optional<Integer> will give a new one. 665 assertEquals(4, injector.getInstance(Key.get(optionalOfInteger)).get().intValue()); 666 667 // And the Optional<Provider> will return a provider that gives a new value each time. 668 assertEquals(5, optionalP.get().get().intValue()); 669 assertEquals(6, optionalP.get().get().intValue()); 670 671 assertEquals(7, optionalJxP.get().get().intValue()); 672 assertEquals(8, optionalJxP.get().get().intValue()); 673 674 // and same rules with java.util.Optional 675 if (HAS_JAVA_OPTIONAL) { 676 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger))); 677 assertEquals(9, optional.get().intValue()); 678 assertEquals(9, optional.get().intValue()); 679 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger))); 680 assertEquals(10, optional.get().intValue()); 681 682 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderInteger))); 683 assertEquals(11, optionalP.get().get().intValue()); 684 assertEquals(12, optionalP.get().get().intValue()); 685 686 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderInteger))); 687 assertEquals(13, optionalJxP.get().get().intValue()); 688 assertEquals(14, optionalJxP.get().get().intValue()); 689 } 690 } 691 testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_default()692 public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_default() 693 throws Exception { 694 Module module = new AbstractModule() { 695 @Override protected void configure() { 696 OptionalBinder.newOptionalBinder(binder(), String.class) 697 .setDefault().toProvider(Providers.<String>of(null)); 698 } 699 }; 700 Injector injector = Guice.createInjector(module); 701 assertNull(injector.getInstance(String.class)); 702 703 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 704 assertFalse(optional.isPresent()); 705 706 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 707 assertTrue(optionalP.isPresent()); 708 assertNull(optionalP.get().get()); 709 710 Optional<javax.inject.Provider<String>> optionalJxP = 711 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 712 assertTrue(optionalJxP.isPresent()); 713 assertNull(optionalJxP.get().get()); 714 715 assertOptionalVisitor(stringKey, 716 setOf(module), 717 VisitType.BOTH, 718 0, 719 SpiUtils.<String>providerInstance(null), 720 null, 721 null); 722 723 if (HAS_JAVA_OPTIONAL) { 724 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 725 assertFalse(optional.isPresent()); 726 727 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 728 assertTrue(optionalP.isPresent()); 729 assertNull(optionalP.get().get()); 730 731 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 732 assertTrue(optionalJxP.isPresent()); 733 assertNull(optionalJxP.get().get()); 734 } 735 } 736 testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_actual()737 public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_actual() 738 throws Exception { 739 Module module = new AbstractModule() { 740 @Override protected void configure() { 741 OptionalBinder.newOptionalBinder(binder(), String.class) 742 .setBinding().toProvider(Providers.<String>of(null)); 743 } 744 }; 745 Injector injector = Guice.createInjector(module); 746 assertNull(injector.getInstance(String.class)); 747 748 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 749 assertFalse(optional.isPresent()); 750 751 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 752 assertTrue(optionalP.isPresent()); 753 assertNull(optionalP.get().get()); 754 755 Optional<javax.inject.Provider<String>> optionalJxP = 756 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 757 assertTrue(optionalJxP.isPresent()); 758 assertNull(optionalJxP.get().get()); 759 760 assertOptionalVisitor(stringKey, 761 setOf(module), 762 VisitType.BOTH, 763 0, 764 null, 765 SpiUtils.<String>providerInstance(null), 766 null); 767 768 if (HAS_JAVA_OPTIONAL) { 769 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 770 assertFalse(optional.isPresent()); 771 772 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 773 assertTrue(optionalP.isPresent()); 774 assertNull(optionalP.get().get()); 775 776 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 777 assertTrue(optionalJxP.isPresent()); 778 assertNull(optionalJxP.get().get()); 779 } 780 } 781 782 // TODO(sameb): Maybe change this? testLinkedToNullActualDoesntFallbackToDefault()783 public void testLinkedToNullActualDoesntFallbackToDefault() throws Exception { 784 Module module = new AbstractModule() { 785 @Override protected void configure() { 786 OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a"); 787 OptionalBinder.newOptionalBinder(binder(), String.class) 788 .setBinding().toProvider(Providers.<String>of(null)); 789 } 790 }; 791 Injector injector = Guice.createInjector(module); 792 assertNull(injector.getInstance(String.class)); 793 794 Optional<String> optional = injector.getInstance(Key.get(optionalOfString)); 795 assertFalse(optional.isPresent()); 796 797 Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString)); 798 assertTrue(optionalP.isPresent()); 799 assertNull(optionalP.get().get()); 800 801 Optional<javax.inject.Provider<String>> optionalJxP = 802 injector.getInstance(Key.get(optionalOfJavaxProviderString)); 803 assertTrue(optionalJxP.isPresent()); 804 assertNull(optionalP.get().get()); 805 806 assertOptionalVisitor(stringKey, 807 setOf(module), 808 VisitType.BOTH, 809 0, 810 instance("a"), 811 SpiUtils.<String>providerInstance(null), 812 null); 813 814 if (HAS_JAVA_OPTIONAL) { 815 optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString))); 816 assertFalse(optional.isPresent()); 817 818 optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString))); 819 assertTrue(optionalP.isPresent()); 820 assertNull(optionalP.get().get()); 821 822 optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString))); 823 assertTrue(optionalJxP.isPresent()); 824 assertNull(optionalJxP.get().get()); 825 } 826 } 827 testSourceLinesInException()828 public void testSourceLinesInException() { 829 try { 830 Guice.createInjector(new AbstractModule() { 831 @Override protected void configure() { 832 OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault(); 833 } 834 }); 835 fail(); 836 } catch (CreationException expected) { 837 assertContains(expected.getMessage(), "No implementation for java.lang.Integer", 838 "at " + getClass().getName()); 839 } 840 } 841 testDependencies_both()842 public void testDependencies_both() { 843 Injector injector = Guice.createInjector(new AbstractModule() { 844 @Override protected void configure() { 845 OptionalBinder<String> optionalbinder = 846 OptionalBinder.newOptionalBinder(binder(), String.class); 847 optionalbinder.setDefault().toInstance("A"); 848 optionalbinder.setBinding().to(Key.get(String.class, Names.named("b"))); 849 bindConstant().annotatedWith(Names.named("b")).to("B"); 850 } 851 }); 852 853 Binding<String> binding = injector.getBinding(Key.get(String.class)); 854 HasDependencies withDependencies = (HasDependencies) binding; 855 Set<String> elements = Sets.newHashSet(); 856 elements.addAll(recurseForDependencies(injector, withDependencies)); 857 assertEquals(ImmutableSet.of("B"), elements); 858 } 859 testDependencies_actual()860 public void testDependencies_actual() { 861 Injector injector = Guice.createInjector(new AbstractModule() { 862 @Override protected void configure() { 863 OptionalBinder<String> optionalbinder = 864 OptionalBinder.newOptionalBinder(binder(), String.class); 865 optionalbinder.setBinding().to(Key.get(String.class, Names.named("b"))); 866 bindConstant().annotatedWith(Names.named("b")).to("B"); 867 } 868 }); 869 870 Binding<String> binding = injector.getBinding(Key.get(String.class)); 871 HasDependencies withDependencies = (HasDependencies) binding; 872 Set<String> elements = Sets.newHashSet(); 873 elements.addAll(recurseForDependencies(injector, withDependencies)); 874 assertEquals(ImmutableSet.of("B"), elements); 875 } 876 testDependencies_default()877 public void testDependencies_default() { 878 Injector injector = Guice.createInjector(new AbstractModule() { 879 @Override protected void configure() { 880 OptionalBinder<String> optionalbinder = 881 OptionalBinder.newOptionalBinder(binder(), String.class); 882 optionalbinder.setDefault().toInstance("A"); 883 } 884 }); 885 886 Binding<String> binding = injector.getBinding(Key.get(String.class)); 887 HasDependencies withDependencies = (HasDependencies) binding; 888 Set<String> elements = Sets.newHashSet(); 889 elements.addAll(recurseForDependencies(injector, withDependencies)); 890 assertEquals(ImmutableSet.of("A"), elements); 891 } 892 893 @SuppressWarnings("rawtypes") recurseForDependencies(Injector injector, HasDependencies hasDependencies)894 private Set<String> recurseForDependencies(Injector injector, HasDependencies hasDependencies) { 895 Set<String> elements = Sets.newHashSet(); 896 for (Dependency<?> dependency : hasDependencies.getDependencies()) { 897 Binding<?> binding = injector.getBinding(dependency.getKey()); 898 HasDependencies deps = (HasDependencies) binding; 899 if (binding instanceof InstanceBinding) { 900 elements.add((String) ((InstanceBinding) binding).getInstance()); 901 } else { 902 elements.addAll(recurseForDependencies(injector, deps)); 903 } 904 } 905 return elements; 906 } 907 908 /** 909 * Doubly-installed modules should not conflict, even when one is overridden. 910 */ testModuleOverrideRepeatedInstalls_toInstance()911 public void testModuleOverrideRepeatedInstalls_toInstance() { 912 Module m = new AbstractModule() { 913 @Override protected void configure() { 914 OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class); 915 b.setDefault().toInstance("A"); 916 b.setBinding().toInstance("B"); 917 } 918 }; 919 920 assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); 921 922 Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); 923 assertEquals("B", injector.getInstance(Key.get(String.class))); 924 925 assertOptionalVisitor(stringKey, 926 setOf(m, Modules.override(m).with(m)), 927 VisitType.BOTH, 928 0, 929 instance("A"), 930 instance("B"), 931 null); 932 } 933 testModuleOverrideRepeatedInstalls_toKey()934 public void testModuleOverrideRepeatedInstalls_toKey() { 935 final Key<String> aKey = Key.get(String.class, Names.named("A_string")); 936 final Key<String> bKey = Key.get(String.class, Names.named("B_string")); 937 Module m = new AbstractModule() { 938 @Override protected void configure() { 939 bind(aKey).toInstance("A"); 940 bind(bKey).toInstance("B"); 941 942 OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class); 943 b.setDefault().to(aKey); 944 b.setBinding().to(bKey); 945 } 946 }; 947 948 assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); 949 950 Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); 951 assertEquals("B", injector.getInstance(Key.get(String.class))); 952 953 assertOptionalVisitor(stringKey, 954 setOf(m, Modules.override(m).with(m)), 955 VisitType.BOTH, 956 0, 957 linked(aKey), 958 linked(bKey), 959 null); 960 } 961 testModuleOverrideRepeatedInstalls_toProviderInstance()962 public void testModuleOverrideRepeatedInstalls_toProviderInstance() { 963 // Providers#of() does not redefine equals/hashCode, so use the same one both times. 964 final Provider<String> aProvider = Providers.of("A"); 965 final Provider<String> bProvider = Providers.of("B"); 966 Module m = new AbstractModule() { 967 @Override protected void configure() { 968 OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class); 969 b.setDefault().toProvider(aProvider); 970 b.setBinding().toProvider(bProvider); 971 } 972 }; 973 974 assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); 975 976 Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); 977 assertEquals("B", injector.getInstance(Key.get(String.class))); 978 979 assertOptionalVisitor(stringKey, 980 setOf(m, Modules.override(m).with(m)), 981 VisitType.BOTH, 982 0, 983 providerInstance("A"), 984 providerInstance("B"), 985 null); 986 } 987 988 private static class AStringProvider implements Provider<String> { get()989 public String get() { 990 return "A"; 991 } 992 } 993 994 private static class BStringProvider implements Provider<String> { get()995 public String get() { 996 return "B"; 997 } 998 } 999 testModuleOverrideRepeatedInstalls_toProviderKey()1000 public void testModuleOverrideRepeatedInstalls_toProviderKey() { 1001 Module m = new AbstractModule() { 1002 @Override protected void configure() { 1003 OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class); 1004 b.setDefault().toProvider(Key.get(AStringProvider.class)); 1005 b.setBinding().toProvider(Key.get(BStringProvider.class)); 1006 } 1007 }; 1008 1009 assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class))); 1010 1011 Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); 1012 assertEquals("B", injector.getInstance(Key.get(String.class))); 1013 1014 assertOptionalVisitor(stringKey, 1015 setOf(m, Modules.override(m).with(m)), 1016 VisitType.BOTH, 1017 0, 1018 providerKey(Key.get(AStringProvider.class)), 1019 providerKey(Key.get(BStringProvider.class)), 1020 null); 1021 } 1022 1023 private static class StringGrabber { 1024 private final String string; 1025 1026 @SuppressWarnings("unused") // Found by reflection StringGrabber(@amed"A_string") String string)1027 public StringGrabber(@Named("A_string") String string) { 1028 this.string = string; 1029 } 1030 1031 @SuppressWarnings("unused") // Found by reflection StringGrabber(@amed"B_string") String string, int unused)1032 public StringGrabber(@Named("B_string") String string, int unused) { 1033 this.string = string; 1034 } 1035 1036 @Override hashCode()1037 public int hashCode() { 1038 return string.hashCode(); 1039 } 1040 1041 @Override equals(Object obj)1042 public boolean equals(Object obj) { 1043 return (obj instanceof StringGrabber) && ((StringGrabber) obj).string.equals(string); 1044 } 1045 1046 @Override toString()1047 public String toString() { 1048 return "StringGrabber(" + string + ")"; 1049 } 1050 } 1051 testModuleOverrideRepeatedInstalls_toConstructor()1052 public void testModuleOverrideRepeatedInstalls_toConstructor() { 1053 Module m = new AbstractModule() { 1054 @Override protected void configure() { 1055 Key<String> aKey = Key.get(String.class, Names.named("A_string")); 1056 Key<String> bKey = Key.get(String.class, Names.named("B_string")); 1057 bind(aKey).toInstance("A"); 1058 bind(bKey).toInstance("B"); 1059 bind(Integer.class).toInstance(0); // used to disambiguate constructors 1060 1061 1062 OptionalBinder<StringGrabber> b = 1063 OptionalBinder.newOptionalBinder(binder(), StringGrabber.class); 1064 try { 1065 b.setDefault().toConstructor( 1066 StringGrabber.class.getConstructor(String.class)); 1067 b.setBinding().toConstructor( 1068 StringGrabber.class.getConstructor(String.class, int.class)); 1069 } catch (NoSuchMethodException e) { 1070 fail("No such method: " + e.getMessage()); 1071 } 1072 } 1073 }; 1074 1075 assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(StringGrabber.class)).string); 1076 1077 Injector injector = Guice.createInjector(m, Modules.override(m).with(m)); 1078 assertEquals("B", injector.getInstance(Key.get(StringGrabber.class)).string); 1079 } 1080 1081 /** 1082 * Unscoped bindings should not conflict, whether they were bound with no explicit scope, or 1083 * explicitly bound in {@link Scopes#NO_SCOPE}. 1084 */ testDuplicateUnscopedBindings()1085 public void testDuplicateUnscopedBindings() { 1086 Module m = new AbstractModule() { 1087 @Override protected void configure() { 1088 OptionalBinder<Integer> b = OptionalBinder.newOptionalBinder(binder(), Integer.class); 1089 b.setDefault().to(Key.get(Integer.class, named("foo"))); 1090 b.setDefault().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE); 1091 b.setBinding().to(Key.get(Integer.class, named("foo"))); 1092 b.setBinding().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE); 1093 } 1094 @Provides @Named("foo") int provideInt() { return 5; } 1095 }; 1096 assertEquals(5, Guice.createInjector(m).getInstance(Integer.class).intValue()); 1097 } 1098 1099 /** 1100 * Ensure key hash codes are fixed at injection time, not binding time. 1101 */ testKeyHashCodesFixedAtInjectionTime()1102 public void testKeyHashCodesFixedAtInjectionTime() { 1103 Module m = new AbstractModule() { 1104 @Override protected void configure() { 1105 OptionalBinder<List<String>> b = OptionalBinder.newOptionalBinder(binder(), listOfStrings); 1106 List<String> list = Lists.newArrayList(); 1107 b.setDefault().toInstance(list); 1108 b.setBinding().toInstance(list); 1109 list.add("A"); 1110 list.add("B"); 1111 } 1112 }; 1113 1114 Injector injector = Guice.createInjector(m); 1115 for (Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) { 1116 Key<?> bindingKey = entry.getKey(); 1117 Key<?> clonedKey; 1118 if (bindingKey.getAnnotation() != null) { 1119 clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotation()); 1120 } else if (bindingKey.getAnnotationType() != null) { 1121 clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotationType()); 1122 } else { 1123 clonedKey = Key.get(bindingKey.getTypeLiteral()); 1124 } 1125 assertEquals(bindingKey, clonedKey); 1126 assertEquals("Incorrect hashcode for " + bindingKey + " -> " + entry.getValue(), 1127 bindingKey.hashCode(), clonedKey.hashCode()); 1128 } 1129 } 1130 1131 /** 1132 * Ensure bindings do not rehash their keys once returned from {@link Elements#getElements}. 1133 */ testBindingKeysFixedOnReturnFromGetElements()1134 public void testBindingKeysFixedOnReturnFromGetElements() { 1135 final List<String> list = Lists.newArrayList(); 1136 Module m = new AbstractModule() { 1137 @Override protected void configure() { 1138 OptionalBinder<List<String>> b = OptionalBinder.newOptionalBinder(binder(), listOfStrings); 1139 b.setDefault().toInstance(list); 1140 list.add("A"); 1141 list.add("B"); 1142 } 1143 }; 1144 1145 InstanceBinding<?> binding = Iterables.getOnlyElement( 1146 Iterables.filter(Elements.getElements(m), InstanceBinding.class)); 1147 Key<?> keyBefore = binding.getKey(); 1148 assertEquals(listOfStrings, keyBefore.getTypeLiteral()); 1149 1150 list.add("C"); 1151 Key<?> keyAfter = binding.getKey(); 1152 assertSame(keyBefore, keyAfter); 1153 } 1154 1155 @BindingAnnotation 1156 @Retention(RetentionPolicy.RUNTIME) 1157 @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) 1158 private static @interface Marker {} 1159 1160 @Marker testMatchingMarkerAnnotations()1161 public void testMatchingMarkerAnnotations() throws Exception { 1162 Method m = OptionalBinderTest.class.getDeclaredMethod("testMatchingMarkerAnnotations"); 1163 assertNotNull(m); 1164 final Annotation marker = m.getAnnotation(Marker.class); 1165 Injector injector = Guice.createInjector(new AbstractModule() { 1166 @Override public void configure() { 1167 OptionalBinder<Integer> mb1 = 1168 OptionalBinder.newOptionalBinder(binder(), Key.get(Integer.class, Marker.class)); 1169 OptionalBinder<Integer> mb2 = 1170 OptionalBinder.newOptionalBinder(binder(), Key.get(Integer.class, marker)); 1171 mb1.setDefault().toInstance(1); 1172 mb2.setBinding().toInstance(2); 1173 1174 // This assures us that the two binders are equivalent, so we expect the instance added to 1175 // each to have been added to one set. 1176 assertEquals(mb1, mb2); 1177 } 1178 }); 1179 Integer i1 = injector.getInstance(Key.get(Integer.class, Marker.class)); 1180 Integer i2 = injector.getInstance(Key.get(Integer.class, marker)); 1181 1182 // These must be identical, because the marker annotations collapsed to the same thing. 1183 assertSame(i1, i2); 1184 assertEquals(2, i2.intValue()); 1185 } 1186 1187 // Tests for com.google.inject.internal.WeakKeySet not leaking memory. testWeakKeySet_integration()1188 public void testWeakKeySet_integration() { 1189 Injector parentInjector = Guice.createInjector(new AbstractModule() { 1190 @Override protected void configure() { 1191 bind(String.class).toInstance("hi"); 1192 } 1193 }); 1194 WeakKeySetUtils.assertNotBlacklisted(parentInjector, Key.get(Integer.class)); 1195 1196 Injector childInjector = parentInjector.createChildInjector(new AbstractModule() { 1197 @Override protected void configure() { 1198 OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault().toInstance(4); 1199 } 1200 }); 1201 WeakReference<Injector> weakRef = new WeakReference<Injector>(childInjector); 1202 WeakKeySetUtils.assertBlacklisted(parentInjector, Key.get(Integer.class)); 1203 1204 // Clear the ref, GC, and ensure that we are no longer blacklisting. 1205 childInjector = null; 1206 1207 Asserts.awaitClear(weakRef); 1208 WeakKeySetUtils.assertNotBlacklisted(parentInjector, Key.get(Integer.class)); 1209 } 1210 testCompareEqualsAgainstOtherAnnotation()1211 public void testCompareEqualsAgainstOtherAnnotation() { 1212 OptionalBinder.Actual impl1 = new OptionalBinder.ActualImpl("foo"); 1213 OptionalBinder.Actual other1 = Dummy.class.getAnnotation(OptionalBinder.Actual.class); 1214 assertEquals(impl1, other1); 1215 1216 OptionalBinder.Default impl2 = new OptionalBinder.DefaultImpl("foo"); 1217 OptionalBinder.Default other2 = Dummy.class.getAnnotation(OptionalBinder.Default.class); 1218 assertEquals(impl2, other2); 1219 1220 assertFalse(impl1.equals(impl2)); 1221 assertFalse(impl1.equals(other2)); 1222 assertFalse(impl2.equals(other1)); 1223 assertFalse(other1.equals(other2)); 1224 } 1225 1226 @OptionalBinder.Actual("foo") 1227 @OptionalBinder.Default("foo") 1228 static class Dummy {} 1229 1230 @SuppressWarnings("unchecked") setOf(V... elements)1231 private <V> Set<V> setOf(V... elements) { 1232 return ImmutableSet.copyOf(elements); 1233 } 1234 1235 @SuppressWarnings("unchecked") toOptional(Object object)1236 private <T> Optional<T> toOptional(Object object) throws Exception { 1237 assertTrue("not a java.util.Optional: " + object.getClass(), 1238 JAVA_OPTIONAL_CLASS.isInstance(object)); 1239 return Optional.fromNullable((T) JAVA_OPTIONAL_OR_ELSE.invoke(object, (Void) null)); 1240 } 1241 } 1242