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