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