PageRenderTime 40ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/metamorphiccode/guice
Java | 1221 lines | 980 code | 135 blank | 106 comment | 26 complexity | af5b9b300fb72ef4e11679c424e982af MD5 | raw file
  1. /**
  2. * Copyright (C) 2008 Google Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.google.inject.multibindings;
  17. import static com.google.inject.Asserts.assertContains;
  18. import static com.google.inject.multibindings.Multibinder.collectionOfJavaxProvidersOf;
  19. import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH;
  20. import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE;
  21. import static com.google.inject.multibindings.SpiUtils.assertSetVisitor;
  22. import static com.google.inject.multibindings.SpiUtils.instance;
  23. import static com.google.inject.multibindings.SpiUtils.providerInstance;
  24. import static com.google.inject.name.Names.named;
  25. import static java.lang.annotation.RetentionPolicy.RUNTIME;
  26. import com.google.common.base.Optional;
  27. import com.google.common.base.Predicates;
  28. import com.google.common.collect.FluentIterable;
  29. import com.google.common.collect.ImmutableList;
  30. import com.google.common.collect.ImmutableMap;
  31. import com.google.common.collect.ImmutableSet;
  32. import com.google.common.collect.Iterables;
  33. import com.google.common.collect.Lists;
  34. import com.google.common.collect.Sets;
  35. import com.google.inject.AbstractModule;
  36. import com.google.inject.Binding;
  37. import com.google.inject.BindingAnnotation;
  38. import com.google.inject.CreationException;
  39. import com.google.inject.Guice;
  40. import com.google.inject.Injector;
  41. import com.google.inject.Key;
  42. import com.google.inject.Module;
  43. import com.google.inject.Provider;
  44. import com.google.inject.Provides;
  45. import com.google.inject.ProvisionException;
  46. import com.google.inject.Scopes;
  47. import com.google.inject.Stage;
  48. import com.google.inject.TypeLiteral;
  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.Element;
  53. import com.google.inject.spi.Elements;
  54. import com.google.inject.spi.HasDependencies;
  55. import com.google.inject.spi.InstanceBinding;
  56. import com.google.inject.spi.LinkedKeyBinding;
  57. import com.google.inject.util.Modules;
  58. import com.google.inject.util.Providers;
  59. import com.google.inject.util.Types;
  60. import junit.framework.TestCase;
  61. import java.io.ByteArrayInputStream;
  62. import java.io.ByteArrayOutputStream;
  63. import java.io.IOException;
  64. import java.io.ObjectInputStream;
  65. import java.io.ObjectOutputStream;
  66. import java.lang.annotation.Annotation;
  67. import java.lang.annotation.ElementType;
  68. import java.lang.annotation.Retention;
  69. import java.lang.annotation.RetentionPolicy;
  70. import java.lang.annotation.Target;
  71. import java.lang.reflect.Method;
  72. import java.util.Collection;
  73. import java.util.Collections;
  74. import java.util.HashSet;
  75. import java.util.List;
  76. import java.util.Map;
  77. import java.util.Map.Entry;
  78. import java.util.Set;
  79. /**
  80. * @author jessewilson@google.com (Jesse Wilson)
  81. */
  82. public class MultibinderTest extends TestCase {
  83. final TypeLiteral<Optional<String>> optionalOfString =
  84. new TypeLiteral<Optional<String>>() {};
  85. final TypeLiteral<Map<String, String>> mapOfStringString =
  86. new TypeLiteral<Map<String, String>>() {};
  87. final TypeLiteral<Set<String>> setOfString = new TypeLiteral<Set<String>>() {};
  88. final TypeLiteral<Set<Integer>> setOfInteger = new TypeLiteral<Set<Integer>>() {};
  89. final TypeLiteral<String> stringType = TypeLiteral.get(String.class);
  90. final TypeLiteral<Integer> intType = TypeLiteral.get(Integer.class);
  91. final TypeLiteral<List<String>> listOfStrings = new TypeLiteral<List<String>>() {};
  92. final TypeLiteral<Set<List<String>>> setOfListOfStrings = new TypeLiteral<Set<List<String>>>() {};
  93. final TypeLiteral<Collection<Provider<String>>> collectionOfProvidersOfStrings =
  94. new TypeLiteral<Collection<Provider<String>>>() {};
  95. public void testMultibinderAggregatesMultipleModules() {
  96. Module abc = new AbstractModule() {
  97. @Override protected void configure() {
  98. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  99. multibinder.addBinding().toInstance("A");
  100. multibinder.addBinding().toInstance("B");
  101. multibinder.addBinding().toInstance("C");
  102. }
  103. };
  104. Module de = new AbstractModule() {
  105. @Override protected void configure() {
  106. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  107. multibinder.addBinding().toInstance("D");
  108. multibinder.addBinding().toInstance("E");
  109. }
  110. };
  111. Injector injector = Guice.createInjector(abc, de);
  112. Key<Set<String>> setKey = Key.get(setOfString);
  113. Set<String> abcde = injector.getInstance(setKey);
  114. Set<String> results = setOf("A", "B", "C", "D", "E");
  115. assertEquals(results, abcde);
  116. assertSetVisitor(setKey, stringType, setOf(abc, de), BOTH, false, 0,
  117. instance("A"), instance("B"), instance("C"), instance("D"), instance("E"));
  118. }
  119. public void testMultibinderAggregationForAnnotationInstance() {
  120. Module module = new AbstractModule() {
  121. @Override protected void configure() {
  122. Multibinder<String> multibinder
  123. = Multibinder.newSetBinder(binder(), String.class, Names.named("abc"));
  124. multibinder.addBinding().toInstance("A");
  125. multibinder.addBinding().toInstance("B");
  126. multibinder = Multibinder.newSetBinder(binder(), String.class, Names.named("abc"));
  127. multibinder.addBinding().toInstance("C");
  128. }
  129. };
  130. Injector injector = Guice.createInjector(module);
  131. Key<Set<String>> setKey = Key.get(setOfString, Names.named("abc"));
  132. Set<String> abc = injector.getInstance(setKey);
  133. Set<String> results = setOf("A", "B", "C");
  134. assertEquals(results, abc);
  135. assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0,
  136. instance("A"), instance("B"), instance("C"));
  137. }
  138. public void testMultibinderAggregationForAnnotationType() {
  139. Module module = new AbstractModule() {
  140. @Override protected void configure() {
  141. Multibinder<String> multibinder
  142. = Multibinder.newSetBinder(binder(), String.class, Abc.class);
  143. multibinder.addBinding().toInstance("A");
  144. multibinder.addBinding().toInstance("B");
  145. multibinder = Multibinder.newSetBinder(binder(), String.class, Abc.class);
  146. multibinder.addBinding().toInstance("C");
  147. }
  148. };
  149. Injector injector = Guice.createInjector(module);
  150. Key<Set<String>> setKey = Key.get(setOfString, Abc.class);
  151. Set<String> abcde = injector.getInstance(setKey);
  152. Set<String> results = setOf("A", "B", "C");
  153. assertEquals(results, abcde);
  154. assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0,
  155. instance("A"), instance("B"), instance("C"));
  156. }
  157. public void testMultibinderWithMultipleAnnotationValueSets() {
  158. Module module = new AbstractModule() {
  159. @Override protected void configure() {
  160. Multibinder<String> abcMultibinder
  161. = Multibinder.newSetBinder(binder(), String.class, named("abc"));
  162. abcMultibinder.addBinding().toInstance("A");
  163. abcMultibinder.addBinding().toInstance("B");
  164. abcMultibinder.addBinding().toInstance("C");
  165. Multibinder<String> deMultibinder
  166. = Multibinder.newSetBinder(binder(), String.class, named("de"));
  167. deMultibinder.addBinding().toInstance("D");
  168. deMultibinder.addBinding().toInstance("E");
  169. }
  170. };
  171. Injector injector = Guice.createInjector(module);
  172. Key<Set<String>> abcSetKey = Key.get(setOfString, named("abc"));
  173. Set<String> abc = injector.getInstance(abcSetKey);
  174. Key<Set<String>> deSetKey = Key.get(setOfString, named("de"));
  175. Set<String> de = injector.getInstance(deSetKey);
  176. Set<String> abcResults = setOf("A", "B", "C");
  177. assertEquals(abcResults, abc);
  178. Set<String> deResults = setOf("D", "E");
  179. assertEquals(deResults, de);
  180. assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1,
  181. instance("A"), instance("B"), instance("C"));
  182. assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1,
  183. instance("D"), instance("E"));
  184. }
  185. public void testMultibinderWithMultipleAnnotationTypeSets() {
  186. Module module = new AbstractModule() {
  187. @Override protected void configure() {
  188. Multibinder<String> abcMultibinder
  189. = Multibinder.newSetBinder(binder(), String.class, Abc.class);
  190. abcMultibinder.addBinding().toInstance("A");
  191. abcMultibinder.addBinding().toInstance("B");
  192. abcMultibinder.addBinding().toInstance("C");
  193. Multibinder<String> deMultibinder
  194. = Multibinder.newSetBinder(binder(), String.class, De.class);
  195. deMultibinder.addBinding().toInstance("D");
  196. deMultibinder.addBinding().toInstance("E");
  197. }
  198. };
  199. Injector injector = Guice.createInjector(module);
  200. Key<Set<String>> abcSetKey = Key.get(setOfString, Abc.class);
  201. Set<String> abc = injector.getInstance(abcSetKey);
  202. Key<Set<String>> deSetKey = Key.get(setOfString, De.class);
  203. Set<String> de = injector.getInstance(deSetKey);
  204. Set<String> abcResults = setOf("A", "B", "C");
  205. assertEquals(abcResults, abc);
  206. Set<String> deResults = setOf("D", "E");
  207. assertEquals(deResults, de);
  208. assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1,
  209. instance("A"), instance("B"), instance("C"));
  210. assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1,
  211. instance("D"), instance("E"));
  212. }
  213. public void testMultibinderWithMultipleSetTypes() {
  214. Module module = new AbstractModule() {
  215. @Override protected void configure() {
  216. Multibinder.newSetBinder(binder(), String.class)
  217. .addBinding().toInstance("A");
  218. Multibinder.newSetBinder(binder(), Integer.class)
  219. .addBinding().toInstance(1);
  220. }
  221. };
  222. Injector injector = Guice.createInjector(module);
  223. assertEquals(setOf("A"), injector.getInstance(Key.get(setOfString)));
  224. assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger)));
  225. assertSetVisitor(Key.get(setOfString), stringType, setOf(module), BOTH, false, 1,
  226. instance("A"));
  227. assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 1,
  228. instance(1));
  229. }
  230. public void testMultibinderWithEmptySet() {
  231. Module module = new AbstractModule() {
  232. @Override protected void configure() {
  233. Multibinder.newSetBinder(binder(), String.class);
  234. }
  235. };
  236. Injector injector = Guice.createInjector(module);
  237. Set<String> set = injector.getInstance(Key.get(setOfString));
  238. assertEquals(Collections.emptySet(), set);
  239. assertSetVisitor(Key.get(setOfString), stringType,
  240. setOf(module), BOTH, false, 0);
  241. }
  242. public void testMultibinderSetIsUnmodifiable() {
  243. Injector injector = Guice.createInjector(new AbstractModule() {
  244. @Override protected void configure() {
  245. Multibinder.newSetBinder(binder(), String.class)
  246. .addBinding().toInstance("A");
  247. }
  248. });
  249. Set<String> set = injector.getInstance(Key.get(setOfString));
  250. try {
  251. set.clear();
  252. fail();
  253. } catch(UnsupportedOperationException expected) {
  254. }
  255. }
  256. public void testMultibinderSetIsSerializable() throws IOException, ClassNotFoundException {
  257. Injector injector = Guice.createInjector(new AbstractModule() {
  258. @Override protected void configure() {
  259. Multibinder.newSetBinder(binder(), String.class)
  260. .addBinding().toInstance("A");
  261. }
  262. });
  263. Set<String> set = injector.getInstance(Key.get(setOfString));
  264. ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
  265. ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream);
  266. try {
  267. objectOutputStream.writeObject(set);
  268. } finally {
  269. objectOutputStream.close();
  270. }
  271. ObjectInputStream objectInputStream = new ObjectInputStream(
  272. new ByteArrayInputStream(byteStream.toByteArray()));
  273. try {
  274. Object setCopy = objectInputStream.readObject();
  275. assertEquals(set, setCopy);
  276. } finally {
  277. objectInputStream.close();
  278. }
  279. }
  280. public void testMultibinderSetIsLazy() {
  281. Module module = new AbstractModule() {
  282. @Override protected void configure() {
  283. Multibinder.newSetBinder(binder(), Integer.class)
  284. .addBinding().toProvider(new Provider<Integer>() {
  285. int nextValue = 1;
  286. public Integer get() {
  287. return nextValue++;
  288. }
  289. });
  290. }
  291. };
  292. Injector injector = Guice.createInjector(module);
  293. assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger)));
  294. assertEquals(setOf(2), injector.getInstance(Key.get(setOfInteger)));
  295. assertEquals(setOf(3), injector.getInstance(Key.get(setOfInteger)));
  296. assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 0,
  297. providerInstance(1));
  298. }
  299. public void testMultibinderSetForbidsDuplicateElements() {
  300. Module module1 = new AbstractModule() {
  301. @Override protected void configure() {
  302. final Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  303. multibinder.addBinding().toProvider(Providers.of("A"));
  304. }
  305. };
  306. Module module2 = new AbstractModule() {
  307. @Override protected void configure() {
  308. final Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  309. multibinder.addBinding().toInstance("A");
  310. }
  311. };
  312. Injector injector = Guice.createInjector(module1, module2);
  313. try {
  314. injector.getInstance(Key.get(setOfString));
  315. fail();
  316. } catch (ProvisionException expected) {
  317. assertContains(expected.getMessage(),
  318. "1) Set injection failed due to duplicated element \"A\"",
  319. "Bound at " + module1.getClass().getName(),
  320. "Bound at " + module2.getClass().getName());
  321. }
  322. // But we can still visit the module!
  323. assertSetVisitor(Key.get(setOfString), stringType, setOf(module1, module2), MODULE, false, 0,
  324. instance("A"), instance("A"));
  325. }
  326. public void testMultibinderSetShowsBothElementsIfToStringDifferent() {
  327. // A simple example of a type whose toString returns more information than its equals method
  328. // considers.
  329. class ValueType {
  330. int a;
  331. int b;
  332. ValueType(int a, int b) {
  333. this.a = a;
  334. this.b = b;
  335. }
  336. @Override
  337. public boolean equals(Object obj) {
  338. return (obj instanceof ValueType) && (((ValueType) obj).a == a);
  339. }
  340. @Override
  341. public int hashCode() {
  342. return a;
  343. }
  344. @Override
  345. public String toString() {
  346. return String.format("ValueType(%d,%d)", a, b);
  347. }
  348. }
  349. Module module1 = new AbstractModule() {
  350. @Override protected void configure() {
  351. final Multibinder<ValueType> multibinder =
  352. Multibinder.newSetBinder(binder(), ValueType.class);
  353. multibinder.addBinding().toProvider(Providers.of(new ValueType(1, 2)));
  354. }
  355. };
  356. Module module2 = new AbstractModule() {
  357. @Override protected void configure() {
  358. final Multibinder<ValueType> multibinder =
  359. Multibinder.newSetBinder(binder(), ValueType.class);
  360. multibinder.addBinding().toInstance(new ValueType(1, 3));
  361. }
  362. };
  363. Injector injector = Guice.createInjector(module1, module2);
  364. TypeLiteral<ValueType> valueType = TypeLiteral.get(ValueType.class);
  365. TypeLiteral<Set<ValueType>> setOfValueType = new TypeLiteral<Set<ValueType>>() {};
  366. try {
  367. injector.getInstance(Key.get(setOfValueType));
  368. fail();
  369. } catch (ProvisionException expected) {
  370. assertContains(expected.getMessage(),
  371. "1) Set injection failed due to multiple elements comparing equal:",
  372. "\"ValueType(1,2)\"",
  373. "bound at " + module1.getClass().getName(),
  374. "\"ValueType(1,3)\"",
  375. "bound at " + module2.getClass().getName());
  376. }
  377. // But we can still visit the module!
  378. assertSetVisitor(Key.get(setOfValueType), valueType, setOf(module1, module2), MODULE, false, 0,
  379. instance(new ValueType(1, 2)), instance(new ValueType(1, 3)));
  380. }
  381. public void testMultibinderSetPermitDuplicateElements() {
  382. Module ab = new AbstractModule() {
  383. @Override protected void configure() {
  384. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  385. multibinder.addBinding().toInstance("A");
  386. multibinder.addBinding().toInstance("B");
  387. }
  388. };
  389. Module bc = new AbstractModule() {
  390. @Override protected void configure() {
  391. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  392. multibinder.permitDuplicates();
  393. multibinder.addBinding().toInstance("B");
  394. multibinder.addBinding().toInstance("C");
  395. }
  396. };
  397. Injector injector = Guice.createInjector(ab, bc);
  398. assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString)));
  399. assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0,
  400. instance("A"), instance("B"), instance("C"));
  401. }
  402. public void testMultibinderSetPermitDuplicateCallsToPermitDuplicates() {
  403. Module ab = new AbstractModule() {
  404. @Override protected void configure() {
  405. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  406. multibinder.permitDuplicates();
  407. multibinder.addBinding().toInstance("A");
  408. multibinder.addBinding().toInstance("B");
  409. }
  410. };
  411. Module bc = new AbstractModule() {
  412. @Override protected void configure() {
  413. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  414. multibinder.permitDuplicates();
  415. multibinder.addBinding().toInstance("B");
  416. multibinder.addBinding().toInstance("C");
  417. }
  418. };
  419. Injector injector = Guice.createInjector(ab, bc);
  420. assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString)));
  421. assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0,
  422. instance("A"), instance("B"), instance("C"));
  423. }
  424. public void testMultibinderSetForbidsNullElements() {
  425. Module m = new AbstractModule() {
  426. @Override protected void configure() {
  427. Multibinder.newSetBinder(binder(), String.class)
  428. .addBinding().toProvider(Providers.<String>of(null));
  429. }
  430. };
  431. Injector injector = Guice.createInjector(m);
  432. try {
  433. injector.getInstance(Key.get(setOfString));
  434. fail();
  435. } catch(ProvisionException expected) {
  436. assertContains(expected.getMessage(),
  437. "1) Set injection failed due to null element bound at: "
  438. + m.getClass().getName() + ".configure(");
  439. }
  440. }
  441. public void testSourceLinesInMultibindings() {
  442. try {
  443. Guice.createInjector(new AbstractModule() {
  444. @Override protected void configure() {
  445. Multibinder.newSetBinder(binder(), Integer.class).addBinding();
  446. }
  447. });
  448. fail();
  449. } catch (CreationException expected) {
  450. assertContains(expected.getMessage(), "No implementation for java.lang.Integer",
  451. "at " + getClass().getName());
  452. }
  453. }
  454. /**
  455. * We just want to make sure that multibinder's binding depends on each of its values. We don't
  456. * really care about the underlying structure of those bindings, which are implementation details.
  457. */
  458. public void testMultibinderDependencies() {
  459. Injector injector = Guice.createInjector(new AbstractModule() {
  460. @Override protected void configure() {
  461. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  462. multibinder.addBinding().toInstance("A");
  463. multibinder.addBinding().to(Key.get(String.class, Names.named("b")));
  464. bindConstant().annotatedWith(Names.named("b")).to("B");
  465. }
  466. });
  467. Binding<Set<String>> binding = injector.getBinding(new Key<Set<String>>() {});
  468. HasDependencies withDependencies = (HasDependencies) binding;
  469. Set<String> elements = Sets.newHashSet();
  470. for (Dependency<?> dependency : withDependencies.getDependencies()) {
  471. elements.add((String) injector.getInstance(dependency.getKey()));
  472. }
  473. assertEquals(ImmutableSet.of("A", "B"), elements);
  474. }
  475. /**
  476. * We just want to make sure that multibinder's binding depends on each of its values. We don't
  477. * really care about the underlying structure of those bindings, which are implementation details.
  478. */
  479. public void testMultibinderDependenciesInToolStage() {
  480. Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() {
  481. @Override protected void configure() {
  482. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  483. multibinder.addBinding().toInstance("A");
  484. multibinder.addBinding().to(Key.get(String.class, Names.named("b")));
  485. bindConstant().annotatedWith(Names.named("b")).to("B");
  486. }
  487. });
  488. Binding<Set<String>> binding = injector.getBinding(new Key<Set<String>>() {});
  489. HasDependencies withDependencies = (HasDependencies) binding;
  490. InstanceBinding<?> instanceBinding = null;
  491. LinkedKeyBinding<?> linkedBinding = null;
  492. // The non-tool stage test can test this by calling injector.getInstance to ensure
  493. // the right values are returned -- in tool stage we can't do that. It's also a
  494. // little difficult to validate the dependencies & bindings, because they're
  495. // bindings created internally within Multibinder.
  496. // To workaround this, we just validate that the dependencies lookup to a single
  497. // InstanceBinding whose value is "A" and another LinkedBinding whose target is
  498. // the Key of @Named("b") String=B
  499. for (Dependency<?> dependency : withDependencies.getDependencies()) {
  500. Binding<?> b = injector.getBinding(dependency.getKey());
  501. if(b instanceof InstanceBinding) {
  502. if(instanceBinding != null) {
  503. fail("Already have an instance binding of: " + instanceBinding + ", and now want to add: " + b);
  504. } else {
  505. instanceBinding = (InstanceBinding)b;
  506. }
  507. } else if(b instanceof LinkedKeyBinding) {
  508. if(linkedBinding != null) {
  509. fail("Already have a linked binding of: " + linkedBinding + ", and now want to add: " + b);
  510. } else {
  511. linkedBinding = (LinkedKeyBinding)b;
  512. }
  513. } else {
  514. fail("Unexpected dependency of: " + dependency);
  515. }
  516. }
  517. assertNotNull(instanceBinding);
  518. assertNotNull(linkedBinding);
  519. assertEquals("A", instanceBinding.getInstance());
  520. assertEquals(Key.get(String.class, Names.named("b")), linkedBinding.getLinkedKey());
  521. }
  522. /**
  523. * Our implementation maintains order, but doesn't guarantee it in the API spec.
  524. * TODO: specify the iteration order?
  525. */
  526. public void testBindOrderEqualsIterationOrder() {
  527. Injector injector = Guice.createInjector(
  528. new AbstractModule() {
  529. @Override protected void configure() {
  530. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  531. multibinder.addBinding().toInstance("leonardo");
  532. multibinder.addBinding().toInstance("donatello");
  533. install(new AbstractModule() {
  534. @Override protected void configure() {
  535. Multibinder.newSetBinder(binder(), String.class)
  536. .addBinding().toInstance("michaelangelo");
  537. }
  538. });
  539. }
  540. },
  541. new AbstractModule() {
  542. @Override protected void configure() {
  543. Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("raphael");
  544. }
  545. });
  546. List<String> inOrder = ImmutableList.copyOf(injector.getInstance(Key.get(setOfString)));
  547. assertEquals(ImmutableList.of("leonardo", "donatello", "michaelangelo", "raphael"), inOrder);
  548. }
  549. @Retention(RUNTIME) @BindingAnnotation
  550. @interface Abc {}
  551. @Retention(RUNTIME) @BindingAnnotation
  552. @interface De {}
  553. private <T> Set<T> setOf(T... elements) {
  554. Set<T> result = Sets.newHashSet();
  555. Collections.addAll(result, elements);
  556. return result;
  557. }
  558. /**
  559. * With overrides, we should get the union of all multibindings.
  560. */
  561. public void testModuleOverrideAndMultibindings() {
  562. Module ab = new AbstractModule() {
  563. @Override protected void configure() {
  564. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  565. multibinder.addBinding().toInstance("A");
  566. multibinder.addBinding().toInstance("B");
  567. }
  568. };
  569. Module cd = new AbstractModule() {
  570. @Override protected void configure() {
  571. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  572. multibinder.addBinding().toInstance("C");
  573. multibinder.addBinding().toInstance("D");
  574. }
  575. };
  576. Module ef = new AbstractModule() {
  577. @Override protected void configure() {
  578. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  579. multibinder.addBinding().toInstance("E");
  580. multibinder.addBinding().toInstance("F");
  581. }
  582. };
  583. Module abcd = Modules.override(ab).with(cd);
  584. Injector injector = Guice.createInjector(abcd, ef);
  585. assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"),
  586. injector.getInstance(Key.get(setOfString)));
  587. assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, false, 0,
  588. instance("A"), instance("B"), instance("C"), instance("D"), instance("E"), instance("F"));
  589. }
  590. /**
  591. * With overrides, we should get the union of all multibindings.
  592. */
  593. public void testModuleOverrideAndMultibindingsWithPermitDuplicates() {
  594. Module abc = new AbstractModule() {
  595. @Override protected void configure() {
  596. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  597. multibinder.addBinding().toInstance("A");
  598. multibinder.addBinding().toInstance("B");
  599. multibinder.addBinding().toInstance("C");
  600. multibinder.permitDuplicates();
  601. }
  602. };
  603. Module cd = new AbstractModule() {
  604. @Override protected void configure() {
  605. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  606. multibinder.addBinding().toInstance("C");
  607. multibinder.addBinding().toInstance("D");
  608. multibinder.permitDuplicates();
  609. }
  610. };
  611. Module ef = new AbstractModule() {
  612. @Override protected void configure() {
  613. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  614. multibinder.addBinding().toInstance("E");
  615. multibinder.addBinding().toInstance("F");
  616. multibinder.permitDuplicates();
  617. }
  618. };
  619. Module abcd = Modules.override(abc).with(cd);
  620. Injector injector = Guice.createInjector(abcd, ef);
  621. assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"),
  622. injector.getInstance(Key.get(setOfString)));
  623. assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, true, 0,
  624. instance("A"), instance("B"), instance("C"), instance("D"), instance("E"), instance("F"));
  625. }
  626. /**
  627. * Doubly-installed modules should not conflict, even when one is overridden.
  628. */
  629. public void testModuleOverrideRepeatedInstallsAndMultibindings_toInstance() {
  630. Module ab = new AbstractModule() {
  631. @Override protected void configure() {
  632. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  633. multibinder.addBinding().toInstance("A");
  634. multibinder.addBinding().toInstance("B");
  635. }
  636. };
  637. // Guice guarantees this assertion, as the same module cannot be installed twice.
  638. assertEquals(ImmutableSet.of("A", "B"),
  639. Guice.createInjector(ab, ab).getInstance(Key.get(setOfString)));
  640. // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
  641. Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
  642. assertEquals(ImmutableSet.of("A", "B"),
  643. injector.getInstance(Key.get(setOfString)));
  644. }
  645. public void testModuleOverrideRepeatedInstallsAndMultibindings_toKey() {
  646. Module ab = new AbstractModule() {
  647. @Override protected void configure() {
  648. Key<String> aKey = Key.get(String.class, Names.named("A_string"));
  649. Key<String> bKey = Key.get(String.class, Names.named("B_string"));
  650. bind(aKey).toInstance("A");
  651. bind(bKey).toInstance("B");
  652. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  653. multibinder.addBinding().to(aKey);
  654. multibinder.addBinding().to(bKey);
  655. }
  656. };
  657. // Guice guarantees this assertion, as the same module cannot be installed twice.
  658. assertEquals(ImmutableSet.of("A", "B"),
  659. Guice.createInjector(ab, ab).getInstance(Key.get(setOfString)));
  660. // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
  661. Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
  662. assertEquals(ImmutableSet.of("A", "B"),
  663. injector.getInstance(Key.get(setOfString)));
  664. }
  665. public void testModuleOverrideRepeatedInstallsAndMultibindings_toProviderInstance() {
  666. Module ab = new AbstractModule() {
  667. @Override protected void configure() {
  668. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  669. multibinder.addBinding().toProvider(Providers.of("A"));
  670. multibinder.addBinding().toProvider(Providers.of("B"));
  671. }
  672. };
  673. // Guice guarantees this assertion, as the same module cannot be installed twice.
  674. assertEquals(ImmutableSet.of("A", "B"),
  675. Guice.createInjector(ab, ab).getInstance(Key.get(setOfString)));
  676. // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
  677. Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
  678. assertEquals(ImmutableSet.of("A", "B"),
  679. injector.getInstance(Key.get(setOfString)));
  680. }
  681. private static class AStringProvider implements Provider<String> {
  682. public String get() {
  683. return "A";
  684. }
  685. }
  686. private static class BStringProvider implements Provider<String> {
  687. public String get() {
  688. return "B";
  689. }
  690. }
  691. public void testModuleOverrideRepeatedInstallsAndMultibindings_toProviderKey() {
  692. Module ab = new AbstractModule() {
  693. @Override protected void configure() {
  694. Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  695. multibinder.addBinding().toProvider(Key.get(AStringProvider.class));
  696. multibinder.addBinding().toProvider(Key.get(BStringProvider.class));
  697. }
  698. };
  699. // Guice guarantees this assertion, as the same module cannot be installed twice.
  700. assertEquals(ImmutableSet.of("A", "B"),
  701. Guice.createInjector(ab, ab).getInstance(Key.get(setOfString)));
  702. // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
  703. Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
  704. assertEquals(ImmutableSet.of("A", "B"),
  705. injector.getInstance(Key.get(setOfString)));
  706. }
  707. private static class StringGrabber {
  708. private final String string;
  709. @SuppressWarnings("unused") // Found by reflection
  710. public StringGrabber(@Named("A_string") String string) {
  711. this.string = string;
  712. }
  713. @SuppressWarnings("unused") // Found by reflection
  714. public StringGrabber(@Named("B_string") String string, int unused) {
  715. this.string = string;
  716. }
  717. @Override
  718. public int hashCode() {
  719. return string.hashCode();
  720. }
  721. @Override
  722. public boolean equals(Object obj) {
  723. return (obj instanceof StringGrabber) && ((StringGrabber) obj).string.equals(string);
  724. }
  725. @Override
  726. public String toString() {
  727. return "StringGrabber(" + string + ")";
  728. }
  729. static Set<String> values(Iterable<StringGrabber> grabbers) {
  730. Set<String> result = new HashSet<String>();
  731. for (StringGrabber grabber : grabbers) {
  732. result.add(grabber.string);
  733. }
  734. return result;
  735. }
  736. }
  737. public void testModuleOverrideRepeatedInstallsAndMultibindings_toConstructor() {
  738. TypeLiteral<Set<StringGrabber>> setOfStringGrabber = new TypeLiteral<Set<StringGrabber>>() {};
  739. Module ab = new AbstractModule() {
  740. @Override protected void configure() {
  741. Key<String> aKey = Key.get(String.class, Names.named("A_string"));
  742. Key<String> bKey = Key.get(String.class, Names.named("B_string"));
  743. bind(aKey).toInstance("A");
  744. bind(bKey).toInstance("B");
  745. bind(Integer.class).toInstance(0); // used to disambiguate constructors
  746. Multibinder<StringGrabber> multibinder =
  747. Multibinder.newSetBinder(binder(), StringGrabber.class);
  748. try {
  749. multibinder.addBinding().toConstructor(
  750. StringGrabber.class.getConstructor(String.class));
  751. multibinder.addBinding().toConstructor(
  752. StringGrabber.class.getConstructor(String.class, int.class));
  753. } catch (NoSuchMethodException e) {
  754. fail("No such method: " + e.getMessage());
  755. }
  756. }
  757. };
  758. // Guice guarantees this assertion, as the same module cannot be installed twice.
  759. assertEquals(ImmutableSet.of("A", "B"),
  760. StringGrabber.values(
  761. Guice.createInjector(ab, ab).getInstance(Key.get(setOfStringGrabber))));
  762. // Guice will only guarantee this assertion if Multibinder ensures the bindings match.
  763. Injector injector = Guice.createInjector(ab, Modules.override(ab).with(ab));
  764. assertEquals(ImmutableSet.of("A", "B"),
  765. StringGrabber.values(injector.getInstance(Key.get(setOfStringGrabber))));
  766. }
  767. /**
  768. * Unscoped bindings should not conflict, whether they were bound with no explicit scope, or
  769. * explicitly bound in {@link Scopes#NO_SCOPE}.
  770. */
  771. public void testDuplicateUnscopedBindings() {
  772. Module singleBinding = new AbstractModule() {
  773. @Override protected void configure() {
  774. bind(Integer.class).to(Key.get(Integer.class, named("A")));
  775. bind(Integer.class).to(Key.get(Integer.class, named("A"))).in(Scopes.NO_SCOPE);
  776. }
  777. @Provides @Named("A")
  778. int provideInteger() {
  779. return 5;
  780. }
  781. };
  782. Module multibinding = new AbstractModule() {
  783. @Override protected void configure() {
  784. Multibinder<Integer> multibinder = Multibinder.newSetBinder(binder(), Integer.class);
  785. multibinder.addBinding().to(Key.get(Integer.class, named("A")));
  786. multibinder.addBinding().to(Key.get(Integer.class, named("A"))).in(Scopes.NO_SCOPE);
  787. }
  788. };
  789. assertEquals(5,
  790. (int) Guice.createInjector(singleBinding).getInstance(Integer.class));
  791. assertEquals(ImmutableSet.of(5),
  792. Guice.createInjector(singleBinding, multibinding).getInstance(Key.get(setOfInteger)));
  793. }
  794. /**
  795. * Ensure key hash codes are fixed at injection time, not binding time.
  796. */
  797. public void testKeyHashCodesFixedAtInjectionTime() {
  798. Module ab = new AbstractModule() {
  799. @Override protected void configure() {
  800. Multibinder<List<String>> multibinder = Multibinder.newSetBinder(binder(), listOfStrings);
  801. List<String> list = Lists.newArrayList();
  802. multibinder.addBinding().toInstance(list);
  803. list.add("A");
  804. list.add("B");
  805. }
  806. };
  807. Injector injector = Guice.createInjector(ab);
  808. for (Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) {
  809. Key<?> bindingKey = entry.getKey();
  810. Key<?> clonedKey;
  811. if (bindingKey.getAnnotation() != null) {
  812. clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotation());
  813. } else if (bindingKey.getAnnotationType() != null) {
  814. clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotationType());
  815. } else {
  816. clonedKey = Key.get(bindingKey.getTypeLiteral());
  817. }
  818. assertEquals(bindingKey, clonedKey);
  819. assertEquals("Incorrect hashcode for " + bindingKey + " -> " + entry.getValue(),
  820. bindingKey.hashCode(), clonedKey.hashCode());
  821. }
  822. }
  823. /**
  824. * Ensure bindings do not rehash their keys once returned from {@link Elements#getElements}.
  825. */
  826. public void testBindingKeysFixedOnReturnFromGetElements() {
  827. final List<String> list = Lists.newArrayList();
  828. Module ab = new AbstractModule() {
  829. @Override protected void configure() {
  830. Multibinder<List<String>> multibinder = Multibinder.newSetBinder(binder(), listOfStrings);
  831. multibinder.addBinding().toInstance(list);
  832. list.add("A");
  833. list.add("B");
  834. }
  835. };
  836. InstanceBinding<?> binding = Iterables.getOnlyElement(
  837. Iterables.filter(Elements.getElements(ab), InstanceBinding.class));
  838. Key<?> keyBefore = binding.getKey();
  839. assertEquals(listOfStrings, keyBefore.getTypeLiteral());
  840. list.add("C");
  841. Key<?> keyAfter = binding.getKey();
  842. assertSame(keyBefore, keyAfter);
  843. }
  844. /*
  845. * Verify through gratuitous mutation that key hashCode snapshots and whatnot happens at the right
  846. * times, by binding two lists that are different at injector creation, but compare equal when the
  847. * module is configured *and* when the set is instantiated.
  848. */
  849. public void testConcurrentMutation_bindingsDiffentAtInjectorCreation() {
  850. // We initially bind two equal lists
  851. final List<String> list1 = Lists.newArrayList();
  852. final List<String> list2 = Lists.newArrayList();
  853. Module module = new AbstractModule() {
  854. @Override protected void configure() {
  855. Multibinder<List<String>> multibinder = Multibinder.newSetBinder(binder(), listOfStrings);
  856. multibinder.addBinding().toInstance(list1);
  857. multibinder.addBinding().toInstance(list2);
  858. }
  859. };
  860. List<Element> elements = Elements.getElements(module);
  861. // Now we change the lists so they no longer match, and create the injector.
  862. list1.add("A");
  863. list2.add("B");
  864. Injector injector = Guice.createInjector(Elements.getModule(elements));
  865. // Now we change the lists so they compare equal again, and create the set.
  866. list1.add(1, "B");
  867. list2.add(0, "A");
  868. try {
  869. injector.getInstance(Key.get(setOfListOfStrings));
  870. fail();
  871. } catch (ProvisionException e) {
  872. assertEquals(1, e.getErrorMessages().size());
  873. assertContains(
  874. Iterables.getOnlyElement(e.getErrorMessages()).getMessage().toString(),
  875. "Set injection failed due to duplicated element \"[A, B]\"");
  876. }
  877. // Finally, we change the lists again so they are once more different, and ensure the set
  878. // contains both.
  879. list1.remove("A");
  880. list2.remove("B");
  881. Set<List<String>> set = injector.getInstance(Key.get(setOfListOfStrings));
  882. assertEquals(ImmutableSet.of(ImmutableList.of("A"), ImmutableList.of("B")), set);
  883. }
  884. /*
  885. * Verify through gratuitous mutation that key hashCode snapshots and whatnot happen at the right
  886. * times, by binding two lists that compare equal at injector creation, but are different when the
  887. * module is configured *and* when the set is instantiated.
  888. */
  889. public void testConcurrentMutation_bindingsSameAtInjectorCreation() {
  890. // We initially bind two distinct lists
  891. final List<String> list1 = Lists.newArrayList("A");
  892. final List<String> list2 = Lists.newArrayList("B");
  893. Module module = new AbstractModule() {
  894. @Override protected void configure() {
  895. Multibinder<List<String>> multibinder = Multibinder.newSetBinder(binder(), listOfStrings);
  896. multibinder.addBinding().toInstance(list1);
  897. multibinder.addBinding().toInstance(list2);
  898. }
  899. };
  900. List<Element> elements = Elements.getElements(module);
  901. // Now we change the lists so they compare equal, and create the injector.
  902. list1.add(1, "B");
  903. list2.add(0, "A");
  904. Injector injector = Guice.createInjector(Elements.getModule(elements));
  905. // Now we change the lists again so they are once more different, and create the set.
  906. list1.remove("A");
  907. list2.remove("B");
  908. Set<List<String>> set = injector.getInstance(Key.get(setOfListOfStrings));
  909. // The set will contain just one of the two lists.
  910. // (In fact, it will be the first one we bound, but we don't promise that, so we won't test it.)
  911. assertTrue(ImmutableSet.of(ImmutableList.of("A")).equals(set)
  912. || ImmutableSet.of(ImmutableList.of("B")).equals(set));
  913. }
  914. @BindingAnnotation
  915. @Retention(RetentionPolicy.RUNTIME)
  916. @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
  917. private static @interface Marker {}
  918. @Marker
  919. public void testMultibinderMatching() throws Exception {
  920. Method m = MultibinderTest.class.getDeclaredMethod("testMultibinderMatching");
  921. assertNotNull(m);
  922. final Annotation marker = m.getAnnotation(Marker.class);
  923. Injector injector = Guice.createInjector(new AbstractModule() {
  924. @Override public void configure() {
  925. Multibinder<Integer> mb1 = Multibinder.newSetBinder(binder(), Integer.class, Marker.class);
  926. Multibinder<Integer> mb2 = Multibinder.newSetBinder(binder(), Integer.class, marker);
  927. mb1.addBinding().toInstance(1);
  928. mb2.addBinding().toInstance(2);
  929. // This assures us that the two binders are equivalent, so we expect the instance added to
  930. // each to have been added to one set.
  931. assertEquals(mb1, mb2);
  932. }
  933. });
  934. TypeLiteral<Set<Integer>> t = new TypeLiteral<Set<Integer>>() {};
  935. Set<Integer> s1 = injector.getInstance(Key.get(t, Marker.class));
  936. Set<Integer> s2 = injector.getInstance(Key.get(t, marker));
  937. // This assures us that the two sets are in fact equal. They may not be same set (as in Java
  938. // object identical), but we shouldn't expect that, since probably Guice creates the set each
  939. // time in case the elements are dependent on scope.
  940. assertEquals(s1, s2);
  941. // This ensures that MultiBinder is internally using the correct set name --
  942. // making sure that instances of marker annotations have the same set name as
  943. // MarkerAnnotation.class.
  944. Set<Integer> expected = new HashSet<Integer>();
  945. expected.add(1);
  946. expected.add(2);
  947. assertEquals(expected, s1);
  948. }
  949. // See issue 670
  950. public void testSetAndMapValueAreDistinct() {
  951. Injector injector = Guice.createInjector(new AbstractModule() {
  952. @Override protected void configure() {
  953. Multibinder.newSetBinder(binder(), String.class)
  954. .addBinding().toInstance("A");
  955. MapBinder.newMapBinder(binder(), String.class, String.class)
  956. .addBinding("B").toInstance("b");
  957. OptionalBinder.newOptionalBinder(binder(), String.class)
  958. .setDefault().toInstance("C");
  959. OptionalBinder.newOptionalBinder(binder(), String.class)
  960. .setBinding().toInstance("D");
  961. }
  962. });
  963. assertEquals(ImmutableSet.of("A"), injector.getInstance(Key.get(setOfString)));
  964. assertEquals(ImmutableMap.of("B", "b"), injector.getInstance(Key.get(mapOfStringString)));
  965. assertEquals(Optional.of("D"), injector.getInstance(Key.get(optionalOfString)));
  966. }
  967. // See issue 670
  968. public void testSetAndMapValueAreDistinctInSpi() {
  969. Injector injector = Guice.createInjector(new AbstractModule() {
  970. @Override protected void configure() {
  971. Multibinder.newSetBinder(binder(), String.class)
  972. .addBinding().toInstance("A");
  973. MapBinder.newMapBinder(binder(), String.class, String.class)
  974. .addBinding("B").toInstance("b");
  975. OptionalBinder.newOptionalBinder(binder(), String.class)
  976. .setDefault().toInstance("C");
  977. }
  978. });
  979. Collector collector = new Collector();
  980. Binding<Map<String, String>> mapbinding = injector.getBinding(Key.get(mapOfStringString));
  981. mapbinding.acceptTargetVisitor(collector);
  982. assertNotNull(collector.mapbinding);
  983. Binding<Set<String>> setbinding = injector.getBinding(Key.get(setOfString));
  984. setbinding.acceptTargetVisitor(collector);
  985. assertNotNull(collector.setbinding);
  986. Binding<Optional<String>> optionalbinding = injector.getBinding(Key.get(optionalOfString));
  987. optionalbinding.acceptTargetVisitor(collector);
  988. assertNotNull(collector.optionalbinding);
  989. // There should only be three instance bindings for string types
  990. // (but because of the OptionalBinder, there's 2 ProviderInstanceBindings also).
  991. // We also know the InstanceBindings will be in the order: A, b, C because that's
  992. // how we bound them, and binding order is preserved.
  993. List<Binding<String>> bindings = FluentIterable.from(injector.findBindingsByType(stringType))
  994. .filter(Predicates.instanceOf(InstanceBinding.class))
  995. .toList();
  996. assertEquals(bindings.toString(), 3, bindings.size());
  997. Binding<String> a = bindings.get(0);
  998. Binding<String> b = bindings.get(1);
  999. Binding<String> c = bindings.get(2);
  1000. assertEquals("A", ((InstanceBinding<String>) a).getInstance());
  1001. assertEquals("b", ((InstanceBinding<String>) b).getInstance());
  1002. assertEquals("C", ((InstanceBinding<String>) c).getInstance());
  1003. // Make sure the correct elements belong to their own sets.
  1004. assertFalse(collector.mapbinding.containsElement(a));
  1005. assertTrue(collector.mapbinding.containsElement(b));
  1006. assertFalse(collector.mapbinding.containsElement(c));
  1007. assertTrue(collector.setbinding.containsElement(a));
  1008. assertFalse(collector.setbinding.containsElement(b));
  1009. assertFalse(collector.setbinding.containsElement(c));
  1010. assertFalse(collector.optionalbinding.containsElement(a));
  1011. assertFalse(collector.optionalbinding.containsElement(b));
  1012. assertTrue(collector.optionalbinding.containsElement(c));
  1013. }
  1014. public void testMultibinderCanInjectCollectionOfProviders() {
  1015. Module module = new AbstractModule() {
  1016. @Override protected void configure() {
  1017. final Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
  1018. multibinder.addBinding().toProvider(Providers.of("A"));
  1019. multibinder.addBinding().toProvider(Providers.of("B"));
  1020. multibinder.addBinding().toInstance("C");
  1021. }
  1022. };
  1023. Collection<String> expectedValues = ImmutableList.of("A", "B", "C");
  1024. Injector injector = Guice.createInjector(module);
  1025. Collection<Provider<String>> providers =
  1026. injector.getInstance(Key.get(collectionOfProvidersOfStrings));
  1027. assertEquals(expectedValues, collectValues(providers));
  1028. Collection<javax.inject.Provider<String>> javaxProviders =
  1029. injector.getInstance(Key.get(collectionOfJavaxProvidersOf(stringType)));
  1030. assertEquals(expectedValues, collectValues(javaxProviders));
  1031. }
  1032. public void testMultibinderCanInjectCollectionOfProvidersWithAnnotation() {
  1033. final Annotation ann = Names.named("foo");
  1034. Module module = new AbstractModule() {
  1035. @Override protected void configure() {
  1036. final Multibinder<String> multibinder =
  1037. Multibinder.newSetBinder(binder(), String.class, ann);
  1038. multibinder.addBinding().toProvider(Providers.of("A"));
  1039. multibinder.addBinding().toProvider(Providers.of("B"));
  1040. multibinder.addBinding().toInstance("C");
  1041. }
  1042. };
  1043. Collection<String> expectedValues = ImmutableList.of("A", "B", "C");
  1044. Injector injector = Guice.createInjector(module);
  1045. Collection<Provider<String>> providers =
  1046. injector.getInstance(Key.get(collectionOfProvidersOfStrings, ann));
  1047. Collection<String> values = collectValues(providers);
  1048. assertEquals(expectedValues, values);
  1049. Collection<javax.inject.Provider<String>> javaxProviders =
  1050. injector.getInstance(Key.get(collectionOfJavaxProvidersOf(stringType), ann));
  1051. assertEquals(expectedValues, collectValues(javaxProviders));
  1052. }
  1053. public void testMultibindingProviderDependencies() {
  1054. final Annotation setAnn = Names.named("foo");
  1055. Injector injector = Guice.createInjector(new AbstractModule() {
  1056. @Override protected void configure() {
  1057. Multibinder<String> multibinder =
  1058. Multibinder.newSetBinder(binder(), String.class, setAnn);
  1059. multibinder.addBinding().toInstance("a");
  1060. multibinder.addBinding().toInstance("b");
  1061. }
  1062. });
  1063. HasDependencies providerBinding =
  1064. (HasDependencies) injector.getBinding(new Key<Collection<Provider<String>>>(setAnn) {});
  1065. HasDependencies setBinding =
  1066. (HasDependencies) injector.getBinding(new Key<Set<String>>(setAnn) {});
  1067. // sanity check the size
  1068. assertEquals(setBinding.getDependencies().toString(), 2, setBinding.getDependencies().size());
  1069. Set<Dependency<?>> expected = Sets.newHashSet();
  1070. for (Dependency<?> dep : setBinding.getDependencies()) {
  1071. Key key = dep.getKey();
  1072. Dependency<?> providerDependency =
  1073. Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType())));
  1074. expected.add(providerDependency);
  1075. }
  1076. assertEquals(expected, providerBinding.getDependencies());
  1077. }
  1078. private <T> Collection<T> collectValues(
  1079. Collection<? extends javax.inject.Provider<T>> providers) {
  1080. Collection<T> values = Lists.newArrayList();
  1081. for (javax.inject.Provider<T> provider : providers) {
  1082. values.add(provider.get());
  1083. }
  1084. return values;
  1085. }
  1086. }