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