PageRenderTime 142ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 1ms

/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java

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