View Javadoc
1   /*
2    * Copyright (C) 2009 The Guava Authors
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.common.collect;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  
21  import com.google.common.annotations.GwtCompatible;
22  import com.google.common.collect.ImmutableSetMultimap.Builder;
23  import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
24  import com.google.common.testing.EqualsTester;
25  
26  import junit.framework.TestCase;
27  
28  import java.util.Arrays;
29  import java.util.Collections;
30  import java.util.Map.Entry;
31  
32  /**
33   * Tests for {@link ImmutableSetMultimap}.
34   *
35   * @author Mike Ward
36   */
37  @GwtCompatible(emulated = true)
38  public class ImmutableSetMultimapTest extends TestCase {
39  
40    public void testBuilder_withImmutableEntry() {
41      ImmutableSetMultimap<String, Integer> multimap = new Builder<String, Integer>()
42          .put(Maps.immutableEntry("one", 1))
43          .build();
44      assertEquals(ImmutableSet.of(1), multimap.get("one"));
45    }
46  
47    public void testBuilder_withImmutableEntryAndNullContents() {
48      Builder<String, Integer> builder = new Builder<String, Integer>();
49      try {
50        builder.put(Maps.immutableEntry("one", (Integer) null));
51        fail();
52      } catch (NullPointerException expected) {
53      }
54      try {
55        builder.put(Maps.immutableEntry((String) null, 1));
56        fail();
57      } catch (NullPointerException expected) {
58      }
59    }
60  
61    private static class StringHolder {
62      String string;
63    }
64  
65    public void testBuilder_withMutableEntry() {
66      ImmutableSetMultimap.Builder<String, Integer> builder =
67          new Builder<String, Integer>();
68      final StringHolder holder = new StringHolder();
69      holder.string = "one";
70      Entry<String, Integer> entry = new AbstractMapEntry<String, Integer>() {
71        @Override public String getKey() {
72          return holder.string;
73        }
74        @Override public Integer getValue() {
75          return 1;
76        }
77      };
78  
79      builder.put(entry);
80      holder.string = "two";
81      assertEquals(ImmutableSet.of(1), builder.build().get("one"));
82    }
83  
84    public void testBuilderPutAllIterable() {
85      ImmutableSetMultimap.Builder<String, Integer> builder
86          = ImmutableSetMultimap.builder();
87      builder.putAll("foo", Arrays.asList(1, 2, 3));
88      builder.putAll("bar", Arrays.asList(4, 5));
89      builder.putAll("foo", Arrays.asList(6, 7));
90      Multimap<String, Integer> multimap = builder.build();
91      assertEquals(ImmutableSet.of(1, 2, 3, 6, 7), multimap.get("foo"));
92      assertEquals(ImmutableSet.of(4, 5), multimap.get("bar"));
93      assertEquals(7, multimap.size());
94    }
95  
96    public void testBuilderPutAllVarargs() {
97      ImmutableSetMultimap.Builder<String, Integer> builder
98          = ImmutableSetMultimap.builder();
99      builder.putAll("foo", 1, 2, 3);
100     builder.putAll("bar", 4, 5);
101     builder.putAll("foo", 6, 7);
102     Multimap<String, Integer> multimap = builder.build();
103     assertEquals(ImmutableSet.of(1, 2, 3, 6, 7), multimap.get("foo"));
104     assertEquals(ImmutableSet.of(4, 5), multimap.get("bar"));
105     assertEquals(7, multimap.size());
106   }
107 
108   public void testBuilderPutAllMultimap() {
109     Multimap<String, Integer> toPut = LinkedListMultimap.create();
110     toPut.put("foo", 1);
111     toPut.put("bar", 4);
112     toPut.put("foo", 2);
113     toPut.put("foo", 3);
114     Multimap<String, Integer> moreToPut = LinkedListMultimap.create();
115     moreToPut.put("foo", 6);
116     moreToPut.put("bar", 5);
117     moreToPut.put("foo", 7);
118     ImmutableSetMultimap.Builder<String, Integer> builder
119         = ImmutableSetMultimap.builder();
120     builder.putAll(toPut);
121     builder.putAll(moreToPut);
122     Multimap<String, Integer> multimap = builder.build();
123     assertEquals(ImmutableSet.of(1, 2, 3, 6, 7), multimap.get("foo"));
124     assertEquals(ImmutableSet.of(4, 5), multimap.get("bar"));
125     assertEquals(7, multimap.size());
126   }
127 
128   public void testBuilderPutAllWithDuplicates() {
129     ImmutableSetMultimap.Builder<String, Integer> builder
130         = ImmutableSetMultimap.builder();
131     builder.putAll("foo", 1, 2, 3);
132     builder.putAll("bar", 4, 5);
133     builder.putAll("foo", 1, 6, 7);
134     ImmutableSetMultimap<String, Integer> multimap = builder.build();
135     assertEquals(7, multimap.size());
136   }
137 
138   public void testBuilderPutWithDuplicates() {
139     ImmutableSetMultimap.Builder<String, Integer> builder
140         = ImmutableSetMultimap.builder();
141     builder.putAll("foo", 1, 2, 3);
142     builder.putAll("bar", 4, 5);
143     builder.put("foo", 1);
144     ImmutableSetMultimap<String, Integer> multimap = builder.build();
145     assertEquals(5, multimap.size());
146   }
147 
148   public void testBuilderPutAllMultimapWithDuplicates() {
149     Multimap<String, Integer> toPut = LinkedListMultimap.create();
150     toPut.put("foo", 1);
151     toPut.put("bar", 4);
152     toPut.put("foo", 2);
153     toPut.put("foo", 1);
154     toPut.put("bar", 5);
155     ImmutableSetMultimap.Builder<String, Integer> builder
156         = ImmutableSetMultimap.builder();
157     builder.putAll(toPut);
158     ImmutableSetMultimap<String, Integer> multimap = builder.build();
159     assertEquals(4, multimap.size());
160   }
161 
162   public void testBuilderPutNullKey() {
163     Multimap<String, Integer> toPut = LinkedListMultimap.create();
164     toPut.put("foo", null);
165     ImmutableSetMultimap.Builder<String, Integer> builder
166         = ImmutableSetMultimap.builder();
167     try {
168       builder.put(null, 1);
169       fail();
170     } catch (NullPointerException expected) {}
171     try {
172       builder.putAll(null, Arrays.asList(1, 2, 3));
173       fail();
174     } catch (NullPointerException expected) {}
175     try {
176       builder.putAll(null, 1, 2, 3);
177       fail();
178     } catch (NullPointerException expected) {}
179     try {
180       builder.putAll(toPut);
181       fail();
182     } catch (NullPointerException expected) {}
183   }
184 
185   public void testBuilderPutNullValue() {
186     Multimap<String, Integer> toPut = LinkedListMultimap.create();
187     toPut.put(null, 1);
188     ImmutableSetMultimap.Builder<String, Integer> builder
189         = ImmutableSetMultimap.builder();
190     try {
191       builder.put("foo", null);
192       fail();
193     } catch (NullPointerException expected) {}
194     try {
195       builder.putAll("foo", Arrays.asList(1, null, 3));
196       fail();
197     } catch (NullPointerException expected) {}
198     try {
199       builder.putAll("foo", 4, null, 6);
200       fail();
201     } catch (NullPointerException expected) {}
202     try {
203       builder.putAll(toPut);
204       fail();
205     } catch (NullPointerException expected) {}
206   }
207 
208   public void testBuilderOrderKeysBy() {
209     ImmutableSetMultimap.Builder<String, Integer> builder
210         = ImmutableSetMultimap.builder();
211     builder.put("b", 3);
212     builder.put("d", 2);
213     builder.put("a", 5);
214     builder.orderKeysBy(Collections.reverseOrder());
215     builder.put("c", 4);
216     builder.put("a", 2);
217     builder.put("b", 6);
218     ImmutableSetMultimap<String, Integer> multimap = builder.build();
219     assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
220     assertThat(multimap.values()).has().exactly(2, 4, 3, 6, 5, 2).inOrder();
221     assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
222     assertThat(multimap.get("b")).has().exactly(3, 6).inOrder();
223     assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
224     assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
225     assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
226   }
227 
228   public void testBuilderOrderKeysByDuplicates() {
229     ImmutableSetMultimap.Builder<String, Integer> builder
230         = ImmutableSetMultimap.builder();
231     builder.put("bb", 3);
232     builder.put("d", 2);
233     builder.put("a", 5);
234     builder.orderKeysBy(new Ordering<String>() {
235       @Override
236       public int compare(String left, String right) {
237         return left.length() - right.length();
238       }
239     });
240     builder.put("cc", 4);
241     builder.put("a", 2);
242     builder.put("bb", 6);
243     ImmutableSetMultimap<String, Integer> multimap = builder.build();
244     assertThat(multimap.keySet()).has().exactly("d", "a", "bb", "cc").inOrder();
245     assertThat(multimap.values()).has().exactly(2, 5, 2, 3, 6, 4).inOrder();
246     assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
247     assertThat(multimap.get("bb")).has().exactly(3, 6).inOrder();
248     assertFalse(multimap.get("a") instanceof ImmutableSortedSet);
249     assertFalse(multimap.get("x") instanceof ImmutableSortedSet);
250     assertFalse(multimap.asMap().get("a") instanceof ImmutableSortedSet);
251   }
252 
253   public void testBuilderOrderValuesBy() {
254     ImmutableSetMultimap.Builder<String, Integer> builder
255         = ImmutableSetMultimap.builder();
256     builder.put("b", 3);
257     builder.put("d", 2);
258     builder.put("a", 5);
259     builder.orderValuesBy(Collections.reverseOrder());
260     builder.put("c", 4);
261     builder.put("a", 2);
262     builder.put("b", 6);
263     ImmutableSetMultimap<String, Integer> multimap = builder.build();
264     assertThat(multimap.keySet()).has().exactly("b", "d", "a", "c").inOrder();
265     assertThat(multimap.values()).has().exactly(6, 3, 2, 5, 2, 4).inOrder();
266     assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
267     assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
268     assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
269     assertEquals(Collections.reverseOrder(),
270         ((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
271     assertTrue(multimap.get("x") instanceof ImmutableSortedSet);
272     assertEquals(Collections.reverseOrder(),
273         ((ImmutableSortedSet<Integer>) multimap.get("x")).comparator());
274     assertTrue(multimap.asMap().get("a") instanceof ImmutableSortedSet);
275     assertEquals(Collections.reverseOrder(),
276         ((ImmutableSortedSet<Integer>) multimap.asMap().get("a")).comparator());
277   }
278 
279   public void testBuilderOrderKeysAndValuesBy() {
280     ImmutableSetMultimap.Builder<String, Integer> builder
281         = ImmutableSetMultimap.builder();
282     builder.put("b", 3);
283     builder.put("d", 2);
284     builder.put("a", 5);
285     builder.orderKeysBy(Collections.reverseOrder());
286     builder.orderValuesBy(Collections.reverseOrder());
287     builder.put("c", 4);
288     builder.put("a", 2);
289     builder.put("b", 6);
290     ImmutableSetMultimap<String, Integer> multimap = builder.build();
291     assertThat(multimap.keySet()).has().exactly("d", "c", "b", "a").inOrder();
292     assertThat(multimap.values()).has().exactly(2, 4, 6, 3, 5, 2).inOrder();
293     assertThat(multimap.get("a")).has().exactly(5, 2).inOrder();
294     assertThat(multimap.get("b")).has().exactly(6, 3).inOrder();
295     assertTrue(multimap.get("a") instanceof ImmutableSortedSet);
296     assertEquals(Collections.reverseOrder(),
297         ((ImmutableSortedSet<Integer>) multimap.get("a")).comparator());
298     assertTrue(multimap.get("x") instanceof ImmutableSortedSet);
299     assertEquals(Collections.reverseOrder(),
300         ((ImmutableSortedSet<Integer>) multimap.get("x")).comparator());
301     assertTrue(multimap.asMap().get("a") instanceof ImmutableSortedSet);
302     assertEquals(Collections.reverseOrder(),
303         ((ImmutableSortedSet<Integer>) multimap.asMap().get("a")).comparator());
304   }
305 
306   public void testCopyOf() {
307     HashMultimap<String, Integer> input = HashMultimap.create();
308     input.put("foo", 1);
309     input.put("bar", 2);
310     input.put("foo", 3);
311     Multimap<String, Integer> multimap = ImmutableSetMultimap.copyOf(input);
312     assertEquals(multimap, input);
313     assertEquals(input, multimap);
314   }
315 
316   public void testCopyOfWithDuplicates() {
317     ArrayListMultimap<Object, Object> input = ArrayListMultimap.create();
318     input.put("foo", 1);
319     input.put("bar", 2);
320     input.put("foo", 3);
321     input.put("foo", 1);
322     ImmutableSetMultimap<Object, Object> copy
323         = ImmutableSetMultimap.copyOf(input);
324     assertEquals(3, copy.size());
325   }
326 
327   public void testCopyOfEmpty() {
328     HashMultimap<String, Integer> input = HashMultimap.create();
329     Multimap<String, Integer> multimap = ImmutableSetMultimap.copyOf(input);
330     assertEquals(multimap, input);
331     assertEquals(input, multimap);
332   }
333 
334   public void testCopyOfImmutableSetMultimap() {
335     Multimap<String, Integer> multimap = createMultimap();
336     assertSame(multimap, ImmutableSetMultimap.copyOf(multimap));
337   }
338 
339   public void testCopyOfNullKey() {
340     HashMultimap<String, Integer> input = HashMultimap.create();
341     input.put(null, 1);
342     try {
343       ImmutableSetMultimap.copyOf(input);
344       fail();
345     } catch (NullPointerException expected) {}
346   }
347 
348   public void testCopyOfNullValue() {
349     HashMultimap<String, Integer> input = HashMultimap.create();
350     input.putAll("foo", Arrays.asList(1, null, 3));
351     try {
352       ImmutableSetMultimap.copyOf(input);
353       fail();
354     } catch (NullPointerException expected) {}
355   }
356 
357   public void testEmptyMultimapReads() {
358     Multimap<String, Integer> multimap = ImmutableSetMultimap.of();
359     assertFalse(multimap.containsKey("foo"));
360     assertFalse(multimap.containsValue(1));
361     assertFalse(multimap.containsEntry("foo", 1));
362     assertTrue(multimap.entries().isEmpty());
363     assertTrue(multimap.equals(HashMultimap.create()));
364     assertEquals(Collections.emptySet(), multimap.get("foo"));
365     assertEquals(0, multimap.hashCode());
366     assertTrue(multimap.isEmpty());
367     assertEquals(HashMultiset.create(), multimap.keys());
368     assertEquals(Collections.emptySet(), multimap.keySet());
369     assertEquals(0, multimap.size());
370     assertTrue(multimap.values().isEmpty());
371     assertEquals("{}", multimap.toString());
372   }
373 
374   public void testEmptyMultimapWrites() {
375     Multimap<String, Integer> multimap = ImmutableSetMultimap.of();
376     UnmodifiableCollectionTests.assertMultimapIsUnmodifiable(
377         multimap, "foo", 1);
378   }
379 
380   public void testMultimapReads() {
381     Multimap<String, Integer> multimap = createMultimap();
382     assertTrue(multimap.containsKey("foo"));
383     assertFalse(multimap.containsKey("cat"));
384     assertTrue(multimap.containsValue(1));
385     assertFalse(multimap.containsValue(5));
386     assertTrue(multimap.containsEntry("foo", 1));
387     assertFalse(multimap.containsEntry("cat", 1));
388     assertFalse(multimap.containsEntry("foo", 5));
389     assertFalse(multimap.entries().isEmpty());
390     assertEquals(3, multimap.size());
391     assertFalse(multimap.isEmpty());
392     assertEquals("{foo=[1, 3], bar=[2]}", multimap.toString());
393   }
394 
395   public void testMultimapWrites() {
396     Multimap<String, Integer> multimap = createMultimap();
397     UnmodifiableCollectionTests.assertMultimapIsUnmodifiable(
398         multimap, "bar", 2);
399   }
400 
401   public void testMultimapEquals() {
402     Multimap<String, Integer> multimap = createMultimap();
403     Multimap<String, Integer> hashMultimap = HashMultimap.create();
404     hashMultimap.putAll("foo", Arrays.asList(1, 3));
405     hashMultimap.put("bar", 2);
406 
407     new EqualsTester()
408         .addEqualityGroup(
409             multimap,
410             createMultimap(),
411             hashMultimap,
412             ImmutableSetMultimap.<String, Integer>builder()
413                 .put("bar", 2).put("foo", 1).put("foo", 3).build(),
414             ImmutableSetMultimap.<String, Integer>builder()
415                 .put("bar", 2).put("foo", 3).put("foo", 1).build())
416         .addEqualityGroup(ImmutableSetMultimap.<String, Integer>builder()
417             .put("foo", 2).put("foo", 3).put("foo", 1).build())
418         .addEqualityGroup(ImmutableSetMultimap.<String, Integer>builder()
419             .put("bar", 2).put("foo", 3).build())
420         .testEquals();
421   }
422 
423   public void testOf() {
424     assertMultimapEquals(
425         ImmutableSetMultimap.of("one", 1),
426         "one", 1);
427     assertMultimapEquals(
428         ImmutableSetMultimap.of("one", 1, "two", 2),
429         "one", 1, "two", 2);
430     assertMultimapEquals(
431         ImmutableSetMultimap.of("one", 1, "two", 2, "three", 3),
432         "one", 1, "two", 2, "three", 3);
433     assertMultimapEquals(
434         ImmutableSetMultimap.of("one", 1, "two", 2, "three", 3, "four", 4),
435         "one", 1, "two", 2, "three", 3, "four", 4);
436     assertMultimapEquals(
437         ImmutableSetMultimap.of(
438             "one", 1, "two", 2, "three", 3, "four", 4, "five", 5),
439         "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
440   }
441 
442   public void testInverse() {
443     assertEquals(
444         ImmutableSetMultimap.<Integer, String>of(),
445         ImmutableSetMultimap.<String, Integer>of().inverse());
446     assertEquals(
447         ImmutableSetMultimap.of(1, "one"),
448         ImmutableSetMultimap.of("one", 1).inverse());
449     assertEquals(
450         ImmutableSetMultimap.of(1, "one", 2, "two"),
451         ImmutableSetMultimap.of("one", 1, "two", 2).inverse());
452     assertEquals(
453         ImmutableSetMultimap.of('o', "of", 'f', "of", 't', "to", 'o', "to"),
454         ImmutableSetMultimap.of("of", 'o', "of", 'f', "to", 't', "to", 'o').inverse());
455   }
456 
457   public void testInverseMinimizesWork() {
458     ImmutableSetMultimap<String, Character> multimap =
459         ImmutableSetMultimap.of("of", 'o', "of", 'f', "to", 't', "to", 'o');
460     assertSame(multimap.inverse(), multimap.inverse());
461     assertSame(multimap, multimap.inverse().inverse());
462   }
463 
464   private static <K, V> void assertMultimapEquals(Multimap<K, V> multimap,
465       Object... alternatingKeysAndValues) {
466     assertEquals(multimap.size(), alternatingKeysAndValues.length / 2);
467     int i = 0;
468     for (Entry<K, V> entry : multimap.entries()) {
469       assertEquals(alternatingKeysAndValues[i++], entry.getKey());
470       assertEquals(alternatingKeysAndValues[i++], entry.getValue());
471     }
472   }
473 
474   private ImmutableSetMultimap<String, Integer> createMultimap() {
475     return ImmutableSetMultimap.<String, Integer>builder()
476         .put("foo", 1).put("bar", 2).put("foo", 3).build();
477   }
478 }
479