• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 java.util.Arrays.asList;
20 import static org.junit.contrib.truth.Truth.ASSERT;
21 
22 import com.google.common.annotations.GwtCompatible;
23 import com.google.common.annotations.GwtIncompatible;
24 import com.google.common.testing.SerializableTester;
25 
26 import junit.framework.TestCase;
27 
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.ConcurrentModificationException;
33 import java.util.Iterator;
34 import java.util.Map;
35 import java.util.Map.Entry;
36 import java.util.NoSuchElementException;
37 import java.util.Set;
38 
39 /**
40  * Tests for {@code Multimap} implementations. Caution: when subclassing avoid
41  * accidental naming collisions with tests in this class!
42  *
43  * @author Jared Levy
44  */
45 @GwtCompatible(emulated = true)
46 public abstract class AbstractMultimapTest extends TestCase {
47 
48   private Multimap<String, Integer> multimap;
49 
create()50   protected abstract Multimap<String, Integer> create();
51 
createSample()52   protected Multimap<String, Integer> createSample() {
53     Multimap<String, Integer> sample = create();
54     sample.putAll("foo", asList(3, -1, 2, 4, 1));
55     sample.putAll("bar", asList(1, 2, 3, 1));
56     return sample;
57   }
58 
59   // public for GWT
setUp()60   @Override public void setUp() throws Exception {
61     super.setUp();
62     multimap = create();
63   }
64 
getMultimap()65   protected Multimap<String, Integer> getMultimap() {
66     return multimap;
67   }
68 
69   /**
70    * Returns the key to use as a null placeholder in tests. The default
71    * implementation returns {@code null}, but tests for multimaps that don't
72    * support null keys should override it.
73    */
nullKey()74   protected String nullKey() {
75     return null;
76   }
77 
78   /**
79    * Returns the value to use as a null placeholder in tests. The default
80    * implementation returns {@code null}, but tests for multimaps that don't
81    * support null values should override it.
82    */
nullValue()83   protected Integer nullValue() {
84     return null;
85   }
86 
87   /**
88    * Validate multimap size by calling {@code size()} and also by iterating
89    * through the entries. This tests cases where the {@code entries()} list is
90    * stored separately, such as the {@link LinkedHashMultimap}. It also
91    * verifies that the multimap contains every multimap entry.
92    */
assertSize(int expectedSize)93   protected void assertSize(int expectedSize) {
94     assertEquals(expectedSize, multimap.size());
95 
96     int size = 0;
97     for (Entry<String, Integer> entry : multimap.entries()) {
98       assertTrue(multimap.containsEntry(entry.getKey(), entry.getValue()));
99       size++;
100     }
101     assertEquals(expectedSize, size);
102 
103     int size2 = 0;
104     for (Entry<String, Collection<Integer>> entry2 :
105         multimap.asMap().entrySet()) {
106       size2 += entry2.getValue().size();
107     }
108     assertEquals(expectedSize, size2);
109   }
110 
removedCollectionsAreModifiable()111   protected boolean removedCollectionsAreModifiable() {
112     return false;
113   }
114 
testSize0()115   public void testSize0() {
116     assertSize(0);
117   }
118 
testSize1()119   public void testSize1() {
120     multimap.put("foo", 1);
121     assertSize(1);
122   }
123 
testSize2Keys()124   public void testSize2Keys() {
125     multimap.put("foo", 1);
126     multimap.put("bar", 5);
127     assertSize(2);
128   }
129 
testSize2Values()130   public void testSize2Values() {
131     multimap.put("foo", 1);
132     multimap.put("foo", 7);
133     assertSize(2);
134   }
135 
testSizeNull()136   public void testSizeNull() {
137     multimap.put("foo", 1);
138     multimap.put("bar", 5);
139     multimap.put(nullKey(), nullValue());
140     multimap.put("foo", nullValue());
141     multimap.put(nullKey(), 5);
142     assertSize(5);
143   }
144 
testIsEmptyYes()145   public void testIsEmptyYes() {
146     assertTrue(multimap.isEmpty());
147   }
148 
testIsEmptyNo()149   public void testIsEmptyNo() {
150     multimap.put("foo", 1);
151     assertFalse(multimap.isEmpty());
152   }
153 
testIsEmptyNull()154   public void testIsEmptyNull() {
155     multimap.put(nullKey(), nullValue());
156     assertFalse(multimap.isEmpty());
157   }
158 
testIsEmptyRemoved()159   public void testIsEmptyRemoved() {
160     multimap.put("foo", 1);
161     multimap.remove("foo", 1);
162     assertTrue(multimap.isEmpty());
163   }
164 
testContainsKeyTrue()165   public void testContainsKeyTrue() {
166     multimap.put("foo", 1);
167     assertTrue(multimap.containsKey("foo"));
168   }
169 
testContainsKeyFalse()170   public void testContainsKeyFalse() {
171     multimap.put("foo", 1);
172     assertFalse(multimap.containsKey("bar"));
173     assertFalse(multimap.containsKey(nullKey()));
174   }
175 
testContainsKeyNull()176   public void testContainsKeyNull() {
177     multimap.put(nullKey(), 1);
178     assertTrue(multimap.containsKey(nullKey()));
179   }
180 
testContainsValueTrue()181   public void testContainsValueTrue() {
182     multimap.put("foo", 1);
183     assertTrue(multimap.containsValue(1));
184   }
185 
testContainsValueFalse()186   public void testContainsValueFalse() {
187     multimap.put("foo", 1);
188     assertFalse(multimap.containsValue(2));
189     assertFalse(multimap.containsValue(nullValue()));
190   }
191 
testContainsValueNull()192   public void testContainsValueNull() {
193     multimap.put("foo", nullValue());
194     assertTrue(multimap.containsValue(nullValue()));
195   }
196 
testContainsKeyValueTrue()197   public void testContainsKeyValueTrue() {
198     multimap.put("foo", 1);
199     assertTrue(multimap.containsEntry("foo", 1));
200   }
201 
testContainsKeyValueRemoved()202   public void testContainsKeyValueRemoved() {
203     multimap.put("foo", 1);
204     multimap.remove("foo", 1);
205     assertFalse(multimap.containsEntry("foo", 1));
206   }
207 
testGet0()208   public void testGet0() {
209     multimap.put("foo", 1);
210     Collection<Integer> values = multimap.get("bar");
211     assertEquals(0, values.size());
212   }
213 
testGet1()214   public void testGet1() {
215     multimap.put("foo", 1);
216     multimap.put("bar", 3);
217     Collection<Integer> values = multimap.get("bar");
218     assertEquals(1, values.size());
219     assertTrue(values.contains(3));
220     assertFalse(values.contains(5));
221   }
222 
testGet2()223   public void testGet2() {
224     multimap.put("foo", 1);
225     multimap.put("foo", 3);
226     Collection<Integer> values = multimap.get("foo");
227     assertEquals(2, values.size());
228     assertTrue(values.contains(1));
229     assertTrue(values.contains(3));
230   }
231 
testGetNull()232   public void testGetNull() {
233     multimap.put(nullKey(), nullValue());
234     multimap.put(nullKey(), 3);
235     Collection<Integer> values = multimap.get(nullKey());
236     assertEquals(2, values.size());
237     assertTrue(values.contains(nullValue()));
238     assertTrue(values.contains(3));
239   }
240 
testPutAllIterable()241   public void testPutAllIterable() {
242     Iterable<Integer> iterable = new Iterable<Integer>() {
243       @Override
244       public Iterator<Integer> iterator() {
245         return Lists.newArrayList(1, 3).iterator();
246       }
247     };
248     multimap.putAll("foo", iterable);
249     assertTrue(multimap.containsEntry("foo", 1));
250     assertTrue(multimap.containsEntry("foo", 3));
251     assertSize(2);
252 
253     Iterable<Integer> emptyIterable = new Iterable<Integer>() {
254       @Override
255       public Iterator<Integer> iterator() {
256         return Iterators.emptyIterator();
257       }
258     };
259     multimap.putAll("bar", emptyIterable);
260     assertSize(2);
261     assertEquals(Collections.singleton("foo"), multimap.keySet());
262   }
263 
testPutAllCollection()264   public void testPutAllCollection() {
265     Collection<Integer> collection = Lists.newArrayList(1, 3);
266     multimap.putAll("foo", collection);
267     assertTrue(multimap.containsEntry("foo", 1));
268     assertTrue(multimap.containsEntry("foo", 3));
269     assertSize(2);
270 
271     Collection<Integer> emptyCollection = Lists.newArrayList();
272     multimap.putAll("bar", emptyCollection);
273     assertSize(2);
274     assertEquals(Collections.singleton("foo"), multimap.keySet());
275   }
276 
testPutAllCollectionNull()277   public void testPutAllCollectionNull() {
278     Collection<Integer> collection = Lists.newArrayList(1, nullValue());
279     multimap.putAll(nullKey(), collection);
280     assertTrue(multimap.containsEntry(nullKey(), 1));
281     assertTrue(multimap.containsEntry(nullKey(), nullValue()));
282     assertSize(2);
283   }
284 
testPutAllEmptyCollection()285   public void testPutAllEmptyCollection() {
286     Collection<Integer> collection = Lists.newArrayList();
287     multimap.putAll("foo", collection);
288     assertSize(0);
289     assertTrue(multimap.isEmpty());
290   }
291 
testPutAllMultimap()292   public void testPutAllMultimap() {
293     multimap.put("foo", 2);
294     multimap.put("cow", 5);
295     multimap.put(nullKey(), 2);
296     Multimap<String, Integer> multimap2 = create();
297     multimap2.put("foo", 1);
298     multimap2.put("bar", 3);
299     multimap2.put(nullKey(), nullValue());
300     multimap.putAll(multimap2);
301     assertTrue(multimap.containsEntry("foo", 2));
302     assertTrue(multimap.containsEntry("cow", 5));
303     assertTrue(multimap.containsEntry("foo", 1));
304     assertTrue(multimap.containsEntry("bar", 3));
305     assertTrue(multimap.containsEntry(nullKey(), nullValue()));
306     assertTrue(multimap.containsEntry(nullKey(), 2));
307     assertSize(6);
308   }
309 
testPutAllReturn_emptyCollection()310   public void testPutAllReturn_emptyCollection() {
311     assertFalse(multimap.putAll("foo", new ArrayList<Integer>()));
312     assertFalse(multimap.putAll(create()));
313   }
314 
testPutAllReturn_nonEmptyCollection()315   public void testPutAllReturn_nonEmptyCollection() {
316     assertTrue(multimap.putAll("foo", asList(1, 2, 3)));
317     assertTrue(multimap.putAll("foo", asList(4, 5, 6)));
318     assertFalse(multimap.putAll(create()));
319 
320     Multimap<String, Integer> other = create();
321     other.putAll("bar", asList(7, 8, 9));
322     assertTrue(multimap.putAll(other));
323   }
324 
checkRemovedCollection(Collection<Integer> collection)325   private void checkRemovedCollection(Collection<Integer> collection) {
326     if (removedCollectionsAreModifiable()) {
327       collection.add(9876);
328       collection.remove(9876);
329       assertFalse(collection.contains(9876));
330     } else {
331       try {
332         collection.add(9876);
333         fail();
334       } catch (UnsupportedOperationException expected) {
335       }
336     }
337   }
338 
testReplaceValues()339   public void testReplaceValues() {
340     multimap.put("foo", 1);
341     multimap.put("bar", 3);
342     Collection<Integer> values = asList(2, nullValue());
343     Collection<Integer> oldValues = multimap.replaceValues("foo", values);
344     assertTrue(multimap.containsEntry("foo", 2));
345     assertTrue(multimap.containsEntry("foo", nullValue()));
346     assertTrue(multimap.containsEntry("bar", 3));
347     assertSize(3);
348     assertTrue(oldValues.contains(1));
349     assertEquals(1, oldValues.size());
350     checkRemovedCollection(oldValues);
351   }
352 
testReplaceValuesEmpty()353   public void testReplaceValuesEmpty() {
354     multimap.put("foo", 1);
355     multimap.put("bar", 3);
356     Collection<Integer> values = asList();
357     Collection<Integer> oldValues = multimap.replaceValues("foo", values);
358     assertFalse(multimap.containsKey("foo"));
359     assertTrue(multimap.containsEntry("bar", 3));
360     assertSize(1);
361     assertTrue(oldValues.contains(1));
362     assertEquals(1, oldValues.size());
363     checkRemovedCollection(oldValues);
364   }
365 
testReplaceValuesNull()366   public void testReplaceValuesNull() {
367     multimap.put(nullKey(), 1);
368     multimap.put("bar", 3);
369     Collection<Integer> values = asList(2, nullValue());
370     Collection<Integer> oldValues = multimap.replaceValues(nullKey(), values);
371     assertTrue(multimap.containsEntry(nullKey(), 2));
372     assertTrue(multimap.containsEntry(nullKey(), nullValue()));
373     assertTrue(multimap.containsEntry("bar", 3));
374     assertSize(3);
375     assertTrue(oldValues.contains(1));
376     assertEquals(1, oldValues.size());
377     checkRemovedCollection(oldValues);
378   }
379 
testReplaceValuesNotPresent()380   public void testReplaceValuesNotPresent() {
381     multimap.put("bar", 3);
382     Collection<Integer> values = asList(2, 4);
383     Collection<Integer> oldValues = multimap.replaceValues("foo", values);
384     assertTrue(multimap.containsEntry("foo", 2));
385     assertTrue(multimap.containsEntry("foo", 4));
386     assertTrue(multimap.containsEntry("bar", 3));
387     assertSize(3);
388     assertNotNull(oldValues);
389     assertTrue(oldValues.isEmpty());
390     checkRemovedCollection(oldValues);
391   }
392 
testReplaceValuesDuplicates()393   public void testReplaceValuesDuplicates() {
394     Collection<Integer> values = Lists.newArrayList(1, 2, 3, 2, 1);
395     multimap.put("bar", 3);
396     Collection<Integer> oldValues = multimap.replaceValues("bar", values);
397     Collection<Integer> replacedValues = multimap.get("bar");
398     assertSize(multimap.size());
399     assertEquals(replacedValues.size(), multimap.size());
400     assertEquals(1, oldValues.size());
401     assertTrue(oldValues.contains(3));
402     checkRemovedCollection(oldValues);
403   }
404 
testRemove()405   public void testRemove() {
406     multimap.put("foo", 1);
407     multimap.put("foo", 3);
408 
409     assertTrue(multimap.remove("foo", 1));
410     assertFalse(multimap.containsEntry("foo", 1));
411     assertTrue(multimap.containsEntry("foo", 3));
412     assertSize(1);
413 
414     assertFalse(multimap.remove("bar", 3));
415     assertTrue(multimap.containsEntry("foo", 3));
416     assertSize(1);
417 
418     assertFalse(multimap.remove("foo", 2));
419     assertTrue(multimap.containsEntry("foo", 3));
420     assertSize(1);
421 
422     assertTrue(multimap.remove("foo", 3));
423     assertFalse(multimap.containsKey("foo"));
424     assertSize(0);
425   }
426 
testRemoveNull()427   public void testRemoveNull() {
428     multimap.put(nullKey(), 1);
429     multimap.put(nullKey(), 3);
430     multimap.put(nullKey(), nullValue());
431 
432     assertTrue(multimap.remove(nullKey(), 1));
433     assertFalse(multimap.containsEntry(nullKey(), 1));
434     assertTrue(multimap.containsEntry(nullKey(), 3));
435     assertTrue(multimap.containsEntry(nullKey(), nullValue()));
436     assertSize(2);
437 
438     assertTrue(multimap.remove(nullKey(), nullValue()));
439     assertFalse(multimap.containsEntry(nullKey(), 1));
440     assertTrue(multimap.containsEntry(nullKey(), 3));
441     assertFalse(multimap.containsEntry(nullKey(), nullValue()));
442     assertSize(1);
443   }
444 
testRemoveAll()445   public void testRemoveAll() {
446     multimap.put("foo", 1);
447     multimap.put("foo", 3);
448     Collection<Integer> removed = multimap.removeAll("foo");
449     assertFalse(multimap.containsKey("foo"));
450     assertSize(0);
451     assertTrue(removed.contains(1));
452     assertTrue(removed.contains(3));
453     assertEquals(2, removed.size());
454     checkRemovedCollection(removed);
455   }
456 
testRemoveAllNull()457   public void testRemoveAllNull() {
458     multimap.put(nullKey(), 1);
459     multimap.put(nullKey(), nullValue());
460     Collection<Integer> removed = multimap.removeAll(nullKey());
461     assertFalse(multimap.containsKey(nullKey()));
462     assertSize(0);
463     assertTrue(removed.contains(1));
464     assertTrue(removed.contains(nullValue()));
465     assertEquals(2, removed.size());
466     checkRemovedCollection(removed);
467   }
468 
testRemoveAllNotPresent()469   public void testRemoveAllNotPresent() {
470     multimap.put("foo", 1);
471     multimap.put("foo", 3);
472     Collection<Integer> removed = multimap.removeAll("bar");
473     assertSize(2);
474     assertNotNull(removed);
475     assertTrue(removed.isEmpty());
476     checkRemovedCollection(removed);
477   }
478 
testClear()479   public void testClear() {
480     multimap.put("foo", 1);
481     multimap.put("bar", 3);
482     multimap.clear();
483     assertEquals(0, multimap.keySet().size());
484     assertSize(0);
485   }
486 
testKeySet()487   public void testKeySet() {
488     multimap.put("foo", 1);
489     multimap.put("foo", nullValue());
490     multimap.put(nullKey(), 3);
491     Set<String> keys = multimap.keySet();
492     assertEquals(2, keys.size());
493     assertTrue(keys.contains("foo"));
494     assertTrue(keys.contains(nullKey()));
495     assertTrue(keys.containsAll(Lists.newArrayList("foo", nullKey())));
496     assertFalse(keys.containsAll(Lists.newArrayList("foo", "bar")));
497   }
498 
testValues()499   public void testValues() {
500     multimap.put("foo", 1);
501     multimap.put("foo", nullValue());
502     multimap.put(nullKey(), 3);
503     Collection<Integer> values = multimap.values();
504     assertEquals(3, values.size());
505     assertTrue(values.contains(1));
506     assertTrue(values.contains(3));
507     assertTrue(values.contains(nullValue()));
508     assertFalse(values.contains(5));
509   }
510 
testValuesClear()511   public void testValuesClear() {
512     multimap.put("foo", 1);
513     multimap.put("foo", nullValue());
514     multimap.put(nullKey(), 3);
515     Collection<Integer> values = multimap.values();
516     values.clear();
517     assertTrue(multimap.isEmpty());
518     assertTrue(values.isEmpty());
519     assertFalse(multimap.containsEntry("foo", 1));
520   }
521 
testValuesRemoveAllNullFromEmpty()522   public void testValuesRemoveAllNullFromEmpty() {
523     try {
524       multimap.values().removeAll(null);
525       // Returning successfully is not ideal, but tolerated.
526     } catch (NullPointerException expected) {}
527   }
528 
testValuesRetainAllNullFromEmpty()529   public void testValuesRetainAllNullFromEmpty() {
530     try {
531       multimap.values().retainAll(null);
532       // Returning successfully is not ideal, but tolerated.
533     } catch (NullPointerException expected) {}
534   }
535 
536   // the entries collection is more thoroughly tested in MultimapCollectionTest
537   @SuppressWarnings("unchecked") // varargs
testEntries()538   public void testEntries() {
539     multimap.put("foo", 1);
540     multimap.put("foo", nullValue());
541     multimap.put(nullKey(), 3);
542     Collection<Entry<String, Integer>> entries = multimap.entries();
543     ASSERT.that(entries).hasContentsAnyOrder(
544         Maps.immutableEntry("foo", 1),
545         Maps.immutableEntry("foo", nullValue()),
546         Maps.immutableEntry(nullKey(), 3));
547   }
548 
testNoSuchElementException()549   public void testNoSuchElementException() {
550     Iterator<Entry<String, Integer>> entries =
551         multimap.entries().iterator();
552     try {
553       entries.next();
554       fail();
555     } catch (NoSuchElementException expected) {}
556   }
557 
testAsMap()558   public void testAsMap() {
559     multimap.put("foo", 1);
560     multimap.put("foo", nullValue());
561     multimap.put(nullKey(), 3);
562     Map<String, Collection<Integer>> map = multimap.asMap();
563 
564     assertEquals(2, map.size());
565     ASSERT.that(map.get("foo")).hasContentsAnyOrder(1, nullValue());
566     ASSERT.that(map.get(nullKey())).hasContentsAnyOrder(3);
567     assertNull(map.get("bar"));
568     assertTrue(map.containsKey("foo"));
569     assertTrue(map.containsKey(nullKey()));
570     assertFalse(multimap.containsKey("bar"));
571 
572     ASSERT.that(map.remove("foo")).hasContentsAnyOrder(1, nullValue());
573     assertFalse(multimap.containsKey("foo"));
574     assertEquals(1, multimap.size());
575     assertNull(map.remove("bar"));
576     multimap.get(nullKey()).add(5);
577     assertTrue(multimap.containsEntry(nullKey(), 5));
578     assertEquals(2, multimap.size());
579     multimap.get(nullKey()).clear();
580     assertTrue(multimap.isEmpty());
581     assertEquals(0, multimap.size());
582 
583     try {
584       map.put("bar", asList(4, 8));
585       fail("Expected UnsupportedOperationException");
586     } catch (UnsupportedOperationException expected) {}
587 
588     multimap.put("bar", 5);
589     assertSize(1);
590     map.clear();
591     assertSize(0);
592   }
593 
testAsMapEntries()594   public void testAsMapEntries() {
595     multimap.put("foo", 1);
596     multimap.put("foo", nullValue());
597     multimap.put(nullKey(), 3);
598     Collection<Entry<String, Collection<Integer>>> entries =
599         multimap.asMap().entrySet();
600     assertEquals(2, entries.size());
601 
602     assertTrue(entries.contains(
603         Maps.immutableEntry("foo", multimap.get("foo"))));
604     assertFalse(entries.contains(
605         Maps.immutableEntry("bar", multimap.get("foo"))));
606     assertFalse(entries.contains(
607         Maps.immutableEntry("bar", null)));
608     assertFalse(entries.contains(
609         Maps.immutableEntry("foo", null)));
610     assertFalse(entries.contains(
611         Maps.immutableEntry("foo", asList(1, 4))));
612     assertFalse(entries.contains("foo"));
613 
614     Iterator<Entry<String, Collection<Integer>>> iterator =
615         entries.iterator();
616     for (int i = 0; i < 2; i++) {
617       assertTrue(iterator.hasNext());
618       Entry<String, Collection<Integer>> entry = iterator.next();
619       if ("foo".equals(entry.getKey())) {
620         assertEquals(2, entry.getValue().size());
621         assertTrue(entry.getValue().contains(1));
622         assertTrue(entry.getValue().contains(nullValue()));
623       } else {
624         assertEquals(nullKey(), entry.getKey());
625         assertEquals(1, entry.getValue().size());
626         assertTrue(entry.getValue().contains(3));
627       }
628     }
629     assertFalse(iterator.hasNext());
630   }
631 
testAsMapToString()632   public void testAsMapToString() {
633     multimap.put("foo", 1);
634     assertEquals("{foo=[1]}", multimap.asMap().toString());
635   }
636 
testKeys()637   public void testKeys() {
638     multimap.put("foo", 1);
639     multimap.put("foo", 5);
640     multimap.put("foo", nullValue());
641     multimap.put(nullKey(), 3);
642     Multiset<String> multiset = multimap.keys();
643     assertEquals(3, multiset.count("foo"));
644     assertEquals(1, multiset.count(nullKey()));
645     ASSERT.that(multiset.elementSet()).hasContentsAnyOrder("foo", nullKey());
646     assertEquals(2, multiset.entrySet().size());
647     assertEquals(4, multiset.size());
648 
649     Set<Multiset.Entry<String>> entries = multimap.keys().entrySet();
650     assertTrue(entries.contains(Multisets.immutableEntry("foo", 3)));
651     assertFalse(entries.contains(Multisets.immutableEntry("foo", 2)));
652     assertFalse(entries.contains(Maps.immutableEntry("foo", 3)));
653 
654     Multiset<String> foo3null1 =
655         HashMultiset.create(asList("foo", "foo", nullKey(), "foo"));
656     assertEquals(foo3null1, multiset);
657     assertEquals(multiset, foo3null1);
658     assertFalse(multiset.equals(
659         HashMultiset.create(asList("foo", "foo", nullKey(), nullKey()))));
660     assertEquals(foo3null1.hashCode(), multiset.hashCode());
661     assertEquals(foo3null1.entrySet(), multiset.entrySet());
662     assertEquals(multiset.entrySet(), foo3null1.entrySet());
663     assertEquals(foo3null1.entrySet().hashCode(),
664         multiset.entrySet().hashCode());
665 
666     assertEquals(0, multiset.remove("bar", 1));
667     assertEquals(1, multiset.remove(nullKey(), 4));
668     assertFalse(multimap.containsKey(nullKey()));
669     assertSize(3);
670     assertEquals("foo", entries.iterator().next().getElement());
671 
672     assertEquals(3, multiset.remove("foo", 1));
673     assertTrue(multimap.containsKey("foo"));
674     assertSize(2);
675     assertEquals(2, multiset.setCount("foo", 0));
676     assertEquals(0, multiset.setCount("bar", 0));
677   }
678 
testKeysAdd()679   public void testKeysAdd() {
680     multimap.put("foo", 1);
681     Multiset<String> multiset = multimap.keys();
682 
683     try {
684       multiset.add("bar");
685       fail();
686     } catch (UnsupportedOperationException expected) {}
687 
688     try {
689       multiset.add("bar", 2);
690       fail();
691     } catch (UnsupportedOperationException expected) {}
692   }
693 
testKeysContainsAll()694   public void testKeysContainsAll() {
695     multimap.put("foo", 1);
696     multimap.put("foo", 5);
697     multimap.put("foo", nullValue());
698     multimap.put(nullKey(), 3);
699     Multiset<String> multiset = multimap.keys();
700 
701     assertTrue(multiset.containsAll(asList("foo", nullKey())));
702     assertFalse(multiset.containsAll(asList("foo", "bar")));
703   }
704 
testKeysClear()705   public void testKeysClear() {
706     multimap.put("foo", 1);
707     multimap.put("foo", 5);
708     multimap.put("foo", nullValue());
709     multimap.put(nullKey(), 3);
710     Multiset<String> multiset = multimap.keys();
711 
712     multiset.clear();
713     assertTrue(multiset.isEmpty());
714     assertTrue(multimap.isEmpty());
715     assertSize(0);
716     assertFalse(multimap.containsKey("foo"));
717     assertFalse(multimap.containsKey(nullKey()));
718   }
719 
testKeysToString()720   public void testKeysToString() {
721     multimap.put("foo", 7);
722     multimap.put("foo", 8);
723     assertEquals("[foo x 2]", multimap.keys().toString());
724   }
725 
testKeysEntrySetIterator()726   public void testKeysEntrySetIterator() {
727     multimap.put("foo", 7);
728     multimap.put("foo", 8);
729     Iterator<Multiset.Entry<String>> iterator
730         = multimap.keys().entrySet().iterator();
731     assertTrue(iterator.hasNext());
732     assertEquals(Multisets.immutableEntry("foo", 2), iterator.next());
733     iterator.remove();
734     assertFalse(iterator.hasNext());
735     assertSize(0);
736   }
737 
testKeysEntrySetToString()738   public void testKeysEntrySetToString() {
739     multimap.put("foo", 7);
740     multimap.put("foo", 8);
741     assertEquals("[foo x 2]", multimap.keys().entrySet().toString());
742   }
743 
testKeysEntrySetRemove()744   public void testKeysEntrySetRemove() {
745     multimap.putAll("foo", asList(1, 2, 3));
746     multimap.putAll("bar", asList(4, 5));
747     Set<Multiset.Entry<String>> entries = multimap.keys().entrySet();
748     assertTrue(entries.remove(Multisets.immutableEntry("bar", 2)));
749     assertEquals("[foo x 3]", multimap.keys().entrySet().toString());
750 
751     // doesn't exist in entries, should have no effect
752     assertFalse(entries.remove(Multisets.immutableEntry("foo", 2)));
753     assertEquals("[foo x 3]", multimap.keys().entrySet().toString());
754     assertEquals("Multimap size after keys().entrySet().remove(entry)",
755         3, multimap.size());
756   }
757 
testEqualsTrue()758   public void testEqualsTrue() {
759     multimap.put("foo", 1);
760     multimap.put("foo", nullValue());
761     multimap.put(nullKey(), 3);
762     assertEquals(multimap, multimap);
763 
764     Multimap<String, Integer> multimap2 = create();
765     multimap2.put(nullKey(), 3);
766     multimap2.put("foo", 1);
767     multimap2.put("foo", nullValue());
768 
769     assertEquals(multimap, multimap2);
770     assertEquals(multimap.hashCode(), multimap2.hashCode());
771   }
772 
testEqualsFalse()773   public void testEqualsFalse() {
774     multimap.put("foo", 1);
775     multimap.put("foo", 3);
776     multimap.put("bar", 3);
777 
778     Multimap<String, Integer> multimap2 = create();
779     multimap2.put("bar", 3);
780     multimap2.put("bar", 1);
781     assertFalse(multimap.equals(multimap2));
782 
783     multimap2.put("foo", 3);
784     assertFalse(multimap.equals(multimap2));
785 
786     assertFalse(multimap.equals(nullValue()));
787     assertFalse(multimap.equals("foo"));
788   }
789 
testValuesIterator()790   public void testValuesIterator() {
791     multimap.put("foo", 1);
792     multimap.put("foo", 2);
793     multimap.put(nullKey(), 4);
794     int sum = 0;
795     for (int i : multimap.values()) {
796       sum += i;
797     }
798     assertEquals(7, sum);
799   }
800 
testValuesIteratorEmpty()801   public void testValuesIteratorEmpty() {
802     int sum = 0;
803     for (int i : multimap.values()) {
804       sum += i;
805     }
806     assertEquals(0, sum);
807   }
808 
testGetAddQuery()809   public void testGetAddQuery() {
810     multimap.put("foo", 1);
811     multimap.put("foo", 3);
812     multimap.put("bar", 4);
813     Collection<Integer> values = multimap.get("foo");
814     multimap.put("foo", 5);
815     multimap.put("bar", 6);
816 
817     /* Verify that values includes effect of put. */
818     assertEquals(3, values.size());
819     assertTrue(values.contains(1));
820     assertTrue(values.contains(5));
821     assertFalse(values.contains(6));
822     ASSERT.that(values).hasContentsAnyOrder(1, 3, 5);
823     assertTrue(values.containsAll(asList(3, 5)));
824     assertFalse(values.isEmpty());
825     assertEquals(multimap.get("foo"), values);
826     assertEquals(multimap.get("foo").hashCode(), values.hashCode());
827     assertEquals(multimap.get("foo").toString(), values.toString());
828   }
829 
testGetAddAll()830   public void testGetAddAll() {
831     multimap.put("foo", 1);
832     multimap.put("foo", 3);
833     multimap.get("foo").addAll(asList(5, 7));
834     multimap.get("bar").addAll(asList(6, 8));
835     multimap.get("cow").addAll(Arrays.<Integer>asList());
836     assertSize(6);
837     ASSERT.that(multimap.get("foo")).hasContentsAnyOrder(1, 3, 5, 7);
838     ASSERT.that(multimap.get("bar")).hasContentsAnyOrder(6, 8);
839     ASSERT.that(multimap.get("cow")).isEmpty();
840   }
841 
testGetRemoveAddQuery()842   public void testGetRemoveAddQuery() {
843     multimap.put("foo", 1);
844     multimap.put("foo", 3);
845     multimap.put("bar", 4);
846     Collection<Integer> values = multimap.get("foo");
847     Iterator<Integer> iterator = values.iterator();
848     multimap.remove("foo", 1);
849     multimap.remove("foo", 3);
850 
851     /* Verify that values includes effect of remove */
852     assertEquals(0, values.size());
853     assertFalse(values.contains(1));
854     assertFalse(values.contains(6));
855     assertTrue(values.isEmpty());
856     assertEquals(multimap.get("foo"), values);
857     assertEquals(multimap.get("foo").hashCode(), values.hashCode());
858     assertEquals(multimap.get("foo").toString(), values.toString());
859 
860     multimap.put("foo", 5);
861 
862     /* Verify that values includes effect of put. */
863     assertEquals(1, values.size());
864     assertFalse(values.contains(1));
865     assertTrue(values.contains(5));
866     assertFalse(values.contains(6));
867     assertEquals(5, values.iterator().next().intValue());
868     assertFalse(values.isEmpty());
869     assertEquals(multimap.get("foo"), values);
870     assertEquals(multimap.get("foo").hashCode(), values.hashCode());
871     assertEquals(multimap.get("foo").toString(), values.toString());
872 
873     try {
874       iterator.hasNext();
875     } catch (ConcurrentModificationException expected) {}
876   }
877 
testModifyCollectionFromGet()878   public void testModifyCollectionFromGet() {
879     multimap.put("foo", 1);
880     multimap.put("foo", 3);
881     multimap.put("bar", 4);
882     Collection<Integer> values = multimap.get("foo");
883 
884     assertTrue(values.add(5));
885     assertSize(4);
886     assertEquals(3, multimap.get("foo").size());
887     assertTrue(multimap.containsEntry("foo", 5));
888 
889     values.clear();
890     assertSize(1);
891     assertFalse(multimap.containsKey("foo"));
892 
893     assertTrue(values.addAll(asList(7, 9)));
894     assertSize(3);
895     assertEquals(2, multimap.get("foo").size());
896     assertTrue(multimap.containsEntry("foo", 7));
897     assertTrue(multimap.containsEntry("foo", 9));
898     assertFalse(values.addAll(Collections.<Integer>emptyList()));
899     assertSize(3);
900 
901     assertTrue(values.remove(7));
902     assertSize(2);
903     assertEquals(1, multimap.get("foo").size());
904     assertFalse(multimap.containsEntry("foo", 7));
905     assertTrue(multimap.containsEntry("foo", 9));
906     assertFalse(values.remove(77));
907     assertSize(2);
908 
909     assertTrue(values.add(11));
910     assertTrue(values.add(13));
911     assertTrue(values.add(15));
912     assertTrue(values.add(17));
913 
914     assertTrue(values.removeAll(asList(11, 15)));
915     assertSize(4);
916     ASSERT.that(multimap.get("foo")).hasContentsAnyOrder(9, 13, 17);
917     assertFalse(values.removeAll(asList(21, 25)));
918     assertSize(4);
919 
920     assertTrue(values.retainAll(asList(13, 17, 19)));
921     assertSize(3);
922     ASSERT.that(multimap.get("foo")).hasContentsAnyOrder(13, 17);
923     assertFalse(values.retainAll(asList(13, 17, 19)));
924     assertSize(3);
925 
926     values.remove(13);
927     values.remove(17);
928     assertTrue(multimap.get("foo").isEmpty());
929     assertSize(1);
930     assertFalse(multimap.containsKey("foo"));
931   }
932 
testGetIterator()933   public void testGetIterator() {
934     multimap.put("foo", 1);
935     multimap.put("foo", 3);
936     multimap.put("foo", 5);
937     multimap.put("bar", 4);
938     Collection<Integer> values = multimap.get("foo");
939 
940     Iterator<Integer> iterator = values.iterator();
941     assertTrue(iterator.hasNext());
942     Integer v1 = iterator.next();
943     assertTrue(iterator.hasNext());
944     Integer v2 = iterator.next();
945     iterator.remove();
946     assertTrue(iterator.hasNext());
947     Integer v3 = iterator.next();
948     assertFalse(iterator.hasNext());
949 
950     ASSERT.that(asList(v1, v2, v3)).hasContentsAnyOrder(1, 3, 5);
951     assertSize(3);
952     assertTrue(multimap.containsEntry("foo", v1));
953     assertFalse(multimap.containsEntry("foo", v2));
954     assertTrue(multimap.containsEntry("foo", v3));
955 
956     iterator = values.iterator();
957     assertTrue(iterator.hasNext());
958     Integer n1 = iterator.next();
959     iterator.remove();
960     assertTrue(iterator.hasNext());
961     Integer n3 = iterator.next();
962     iterator.remove();
963     assertFalse(iterator.hasNext());
964 
965     ASSERT.that(asList(n1, n3)).hasContentsAnyOrder(v1, v3);
966     assertSize(1);
967     assertFalse(multimap.containsKey("foo"));
968   }
969 
testGetClear()970   public void testGetClear() {
971     multimap.put("foo", 1);
972     multimap.put("bar", 3);
973     Collection<Integer> values = multimap.get("foo");
974     multimap.clear();
975     assertTrue(values.isEmpty());
976   }
977 
testGetPutAllCollection()978   public void testGetPutAllCollection() {
979     Collection<Integer> values = multimap.get("foo");
980     Collection<Integer> collection = Lists.newArrayList(1, 3);
981     multimap.putAll("foo", collection);
982     ASSERT.that(values).hasContentsAnyOrder(1, 3);
983   }
984 
testGetPutAllMultimap()985   public void testGetPutAllMultimap() {
986     multimap.put("foo", 2);
987     multimap.put("cow", 5);
988     multimap.put(nullKey(), 2);
989     Collection<Integer> valuesFoo = multimap.get("foo");
990     Collection<Integer> valuesBar = multimap.get("bar");
991     Collection<Integer> valuesCow = multimap.get("cow");
992     Collection<Integer> valuesNull = multimap.get(nullKey());
993     Multimap<String, Integer> multimap2 = create();
994     multimap2.put("foo", 1);
995     multimap2.put("bar", 3);
996     multimap2.put(nullKey(), nullValue());
997     multimap.putAll(multimap2);
998 
999     ASSERT.that(valuesFoo).hasContentsAnyOrder(1, 2);
1000     ASSERT.that(valuesBar).hasContentsAnyOrder(3);
1001     ASSERT.that(valuesCow).hasContentsAnyOrder(5);
1002     ASSERT.that(valuesNull).hasContentsAnyOrder(nullValue(), 2);
1003   }
1004 
testGetRemove()1005   public void testGetRemove() {
1006     multimap.put("foo", 1);
1007     multimap.put("foo", 3);
1008     Collection<Integer> values = multimap.get("foo");
1009     multimap.remove("foo", 1);
1010     ASSERT.that(values).hasContentsAnyOrder(3);
1011   }
1012 
testGetRemoveAll()1013   public void testGetRemoveAll() {
1014     multimap.put("foo", 1);
1015     multimap.put("foo", 3);
1016     Collection<Integer> values = multimap.get("foo");
1017     multimap.removeAll("foo");
1018     assertTrue(values.isEmpty());
1019   }
1020 
testGetReplaceValues()1021   public void testGetReplaceValues() {
1022     multimap.put("foo", 1);
1023     multimap.put("foo", 3);
1024     Collection<Integer> values = multimap.get("foo");
1025     multimap.replaceValues("foo", asList(1, 5));
1026     ASSERT.that(values).hasContentsAnyOrder(1, 5);
1027 
1028     multimap.replaceValues("foo", new ArrayList<Integer>());
1029     assertTrue(multimap.isEmpty());
1030     assertSize(0);
1031     assertTrue(values.isEmpty());
1032   }
1033 
testEntriesUpdate()1034   public void testEntriesUpdate() {
1035     multimap.put("foo", 1);
1036     Collection<Entry<String, Integer>> entries = multimap.entries();
1037     Iterator<Entry<String, Integer>> iterator = entries.iterator();
1038 
1039     assertTrue(iterator.hasNext());
1040     Entry<String, Integer> entry = iterator.next();
1041     assertEquals("foo", entry.getKey());
1042     assertEquals(1, entry.getValue().intValue());
1043     iterator.remove();
1044     assertFalse(iterator.hasNext());
1045     assertTrue(multimap.isEmpty());
1046     assertSize(0);
1047 
1048     try {
1049       entries.add(Maps.immutableEntry("bar", 2));
1050       fail("UnsupportedOperationException expected");
1051     } catch (UnsupportedOperationException expected) {}
1052     assertSize(0);
1053     assertFalse(multimap.containsEntry("bar", 2));
1054 
1055     multimap.put("bar", 2);
1056     assertSize(1);
1057     assertTrue(entries.contains(Maps.immutableEntry("bar", 2)));
1058 
1059     entries.clear();
1060     assertTrue(multimap.isEmpty());
1061     assertSize(0);
1062   }
1063 
testEntriesRemove()1064   public void testEntriesRemove() {
1065     multimap.put("foo", 1);
1066     multimap.put("foo", nullValue());
1067     multimap.put(nullKey(), 3);
1068     Collection<Entry<String, Integer>> entries = multimap.entries();
1069 
1070     assertTrue(entries.remove(Maps.immutableEntry("foo", nullValue())));
1071     assertSize(2);
1072     assertFalse(multimap.containsEntry("foo", nullValue()));
1073 
1074     assertFalse(entries.remove(Maps.immutableEntry("foo", 3)));
1075     assertFalse(entries.remove(3.5));
1076     assertSize(2);
1077   }
1078 
1079   @SuppressWarnings("unchecked")
testEntriesRemoveAll()1080   public void testEntriesRemoveAll() {
1081     multimap.put("foo", 1);
1082     multimap.put("foo", 2);
1083     multimap.put("bar", 3);
1084 
1085     assertFalse(multimap.entries().removeAll(
1086         Collections.singleton(Maps.immutableEntry("foo", 3))));
1087     assertSize(3);
1088 
1089     assertTrue(multimap.entries().removeAll(asList(
1090         Maps.immutableEntry("foo", 3), Maps.immutableEntry("bar", 3))));
1091     assertSize(2);
1092     assertFalse(multimap.containsKey("bar"));
1093   }
1094 
testEntriesRemoveAllNullFromEmpty()1095   public void testEntriesRemoveAllNullFromEmpty() {
1096     try {
1097       multimap.entries().removeAll(null);
1098       // Returning successfully is not ideal, but tolerated.
1099     } catch (NullPointerException expected) {}
1100   }
1101 
1102   @SuppressWarnings("unchecked")
testEntriesRetainAll()1103   public void testEntriesRetainAll() {
1104     multimap.put("foo", 1);
1105     multimap.put("foo", 2);
1106     multimap.put("bar", 3);
1107 
1108     assertFalse(multimap.entries().retainAll(asList(
1109         Maps.immutableEntry("foo", 1), Maps.immutableEntry("foo", 2),
1110         Maps.immutableEntry("foo", 3), Maps.immutableEntry("bar", 3))));
1111     assertSize(3);
1112 
1113     assertTrue(multimap.entries().retainAll(asList(
1114         Maps.immutableEntry("foo", 3), Maps.immutableEntry("bar", 3))));
1115     assertSize(1);
1116     assertTrue(multimap.containsEntry("bar", 3));
1117   }
1118 
testEntriesRetainAllNullFromEmpty()1119   public void testEntriesRetainAllNullFromEmpty() {
1120     try {
1121       multimap.entries().retainAll(null);
1122       // Returning successfully is not ideal, but tolerated.
1123     } catch (NullPointerException expected) {}
1124   }
1125 
testEntriesIterator()1126   public void testEntriesIterator() {
1127     multimap.put("foo", 3);
1128     Iterator<Entry<String, Integer>> iterator
1129         = multimap.entries().iterator();
1130     assertTrue(iterator.hasNext());
1131     assertEquals(Maps.immutableEntry("foo", 3), iterator.next());
1132     iterator.remove();
1133     assertFalse(iterator.hasNext());
1134     assertSize(0);
1135   }
1136 
testEntriesToString()1137   public void testEntriesToString() {
1138     multimap.put("foo", 3);
1139     Collection<Entry<String, Integer>> entries = multimap.entries();
1140     assertEquals("[foo=3]", entries.toString());
1141   }
1142 
testEntriesToArray()1143   public void testEntriesToArray() {
1144     multimap.put("foo", 3);
1145     Collection<Entry<String, Integer>> entries = multimap.entries();
1146     Entry<?, ?>[] array = new Entry<?, ?>[3];
1147     assertSame(array, entries.toArray(array));
1148     assertEquals(Maps.immutableEntry("foo", 3), array[0]);
1149     assertNull(array[1]);
1150   }
1151 
1152   /**
1153    * Test calling setValue() on an entry returned by multimap.entries().
1154    */
testEntrySetValue()1155   public void testEntrySetValue() {
1156     multimap.put("foo", 1);
1157     multimap.put("bar", 1);
1158     Collection<Entry<String, Integer>> entries = multimap.entries();
1159     Iterator<Entry<String, Integer>> iterator = entries.iterator();
1160     Entry<String, Integer> entrya = iterator.next();
1161     Entry<String, Integer> entryb = iterator.next();
1162     try {
1163       entrya.setValue(3);
1164       fail();
1165     } catch (UnsupportedOperationException expected) {}
1166     assertTrue(multimap.containsEntry("foo", 1));
1167     assertTrue(multimap.containsEntry("bar", 1));
1168     assertFalse(multimap.containsEntry("foo", 2));
1169     assertFalse(multimap.containsEntry("bar", 2));
1170     assertEquals(1, (int) entrya.getValue());
1171     assertEquals(1, (int) entryb.getValue());
1172   }
1173 
1174   /** Verify that the entries remain valid after iterating past them. */
testEntriesCopy()1175   public void testEntriesCopy() {
1176     multimap.put("foo", 1);
1177     multimap.put("foo", 2);
1178     multimap.put("bar", 3);
1179 
1180     Set<Entry<String, Integer>> copy = Sets.newHashSet(multimap.entries());
1181     assertEquals(3, copy.size());
1182     assertTrue(copy.contains(Maps.immutableEntry("foo", 1)));
1183     assertTrue(copy.contains(Maps.immutableEntry("foo", 2)));
1184     assertTrue(copy.contains(Maps.immutableEntry("bar", 3)));
1185     assertFalse(copy.contains(Maps.immutableEntry("bar", 1)));
1186 
1187     multimap.removeAll("foo");
1188     assertEquals(3, copy.size());
1189     assertTrue(copy.contains(Maps.immutableEntry("foo", 1)));
1190     assertTrue(copy.contains(Maps.immutableEntry("foo", 2)));
1191     assertTrue(copy.contains(Maps.immutableEntry("bar", 3)));
1192     assertFalse(copy.contains(Maps.immutableEntry("bar", 1)));
1193   }
1194 
testKeySetRemove()1195   public void testKeySetRemove() {
1196     multimap.put("foo", 1);
1197     multimap.put("foo", nullValue());
1198     multimap.put(nullKey(), 3);
1199     Set<String> keys = multimap.keySet();
1200     assertTrue(keys.remove("foo"));
1201     assertFalse(keys.remove("bar"));
1202     assertSize(1);
1203     assertFalse(multimap.containsKey("foo"));
1204     assertTrue(multimap.containsEntry(nullKey(), 3));
1205   }
1206 
testKeySetRemoveAllNullFromEmpty()1207   public void testKeySetRemoveAllNullFromEmpty() {
1208     try {
1209       multimap.keySet().removeAll(null);
1210       fail();
1211     } catch (NullPointerException expected) {}
1212   }
1213 
testKeySetRetainAllNullFromEmpty()1214   public void testKeySetRetainAllNullFromEmpty() {
1215     try {
1216       multimap.keySet().retainAll(null);
1217       // Returning successfully is not ideal, but tolerated.
1218     } catch (NullPointerException expected) {}
1219   }
1220 
testKeySetIterator()1221   public void testKeySetIterator() {
1222     multimap.put("foo", 1);
1223     multimap.put("foo", nullValue());
1224     multimap.put(nullKey(), 3);
1225 
1226     Iterator<String> iterator = multimap.keySet().iterator();
1227     while (iterator.hasNext()) {
1228       String key = iterator.next();
1229       if ("foo".equals(key)) {
1230         iterator.remove();
1231       }
1232     }
1233     assertSize(1);
1234     assertFalse(multimap.containsKey("foo"));
1235     assertTrue(multimap.containsEntry(nullKey(), 3));
1236 
1237     iterator = multimap.keySet().iterator();
1238     assertEquals(nullKey(), iterator.next());
1239     iterator.remove();
1240     assertTrue(multimap.isEmpty());
1241     assertSize(0);
1242   }
1243 
testKeySetClear()1244   public void testKeySetClear() {
1245     multimap.put("foo", 1);
1246     multimap.put("foo", nullValue());
1247     multimap.put(nullKey(), 3);
1248 
1249     multimap.keySet().clear();
1250     assertTrue(multimap.isEmpty());
1251     assertSize(0);
1252   }
1253 
testValuesIteratorRemove()1254   public void testValuesIteratorRemove() {
1255     multimap.put("foo", 1);
1256     multimap.put("foo", 2);
1257     multimap.put(nullKey(), 4);
1258 
1259     Iterator<Integer> iterator = multimap.values().iterator();
1260     while (iterator.hasNext()) {
1261       int value = iterator.next();
1262       if ((value % 2) == 0) {
1263         iterator.remove();
1264       }
1265     }
1266 
1267     assertSize(1);
1268     assertTrue(multimap.containsEntry("foo", 1));
1269   }
1270 
testAsMapEntriesUpdate()1271   public void testAsMapEntriesUpdate() {
1272     multimap.put("foo", 1);
1273     multimap.put("foo", 3);
1274     Collection<Entry<String, Collection<Integer>>> entries =
1275         multimap.asMap().entrySet();
1276     Entry<String, Collection<Integer>> entry = entries.iterator().next();
1277     Collection<Integer> values = entry.getValue();
1278 
1279     multimap.put("foo", 5);
1280     assertEquals(3, values.size());
1281     assertTrue(values.contains(5));
1282 
1283     values.add(7);
1284     assertSize(4);
1285     assertTrue(multimap.containsValue(7));
1286 
1287     multimap.put("bar", 4);
1288     assertEquals(2, entries.size());
1289     assertSize(5);
1290 
1291     assertTrue(entries.remove(entry));
1292     assertSize(1);
1293     assertFalse(multimap.containsKey("foo"));
1294     assertTrue(multimap.containsKey("bar"));
1295     assertFalse(entries.remove("foo"));
1296     assertFalse(entries.remove(
1297         Maps.immutableEntry("foo", Collections.singleton(2))));
1298     assertSize(1);
1299 
1300     Iterator<Entry<String, Collection<Integer>>> iterator =
1301         entries.iterator();
1302     assertTrue(iterator.hasNext());
1303     iterator.next();
1304     iterator.remove();
1305     assertFalse(iterator.hasNext());
1306     assertSize(0);
1307     assertTrue(multimap.isEmpty());
1308 
1309     multimap.put("bar", 8);
1310     assertSize(1);
1311     entries.clear();
1312     assertSize(0);
1313   }
1314 
testToStringNull()1315   public void testToStringNull() {
1316     multimap.put("foo", 3);
1317     multimap.put("foo", -1);
1318     multimap.put(nullKey(), nullValue());
1319     multimap.put("bar", 1);
1320     multimap.put("foo", 2);
1321     multimap.put(nullKey(), 0);
1322     multimap.put("bar", 2);
1323     multimap.put("bar", nullValue());
1324     multimap.put("foo", nullValue());
1325     multimap.put("foo", 4);
1326     multimap.put(nullKey(), -1);
1327     multimap.put("bar", 3);
1328     multimap.put("bar", 1);
1329     multimap.put("foo", 1);
1330 
1331     // This test is brittle. The original test was meant to validate the
1332     // contents of the string itself, but key and value ordering tend
1333     // to change under unpredictable circumstances. Instead, we're just ensuring
1334     // that the string not return null and, implicitly, not throw an exception.
1335     assertNotNull(multimap.toString());
1336   }
1337 
1338   @GwtIncompatible("SerializableTester")
testSerializable()1339   public void testSerializable() {
1340     multimap = createSample();
1341     assertEquals(multimap, SerializableTester.reserialize(multimap));
1342   }
1343 
testEmptyToString()1344   public void testEmptyToString() {
1345     Multimap<String, Integer> map = create();
1346     assertEquals("{}", map.toString());
1347     assertEquals("[]", map.entries().toString());
1348   }
1349 
testEmptyGetToString()1350   public void testEmptyGetToString() {
1351     Multimap<String, Integer> map = create();
1352     map.get("foo"); // shouldn't have any side-effect
1353     assertEquals("{}", map.toString());
1354     assertEquals("[]", map.entries().toString());
1355   }
1356 
testGetRemoveToString()1357   public void testGetRemoveToString() {
1358     Multimap<String, Integer> map = create();
1359     map.put("bar", 1);
1360     map.put("foo", 2);
1361     map.put("bar", 3);
1362     map.get("foo").remove(2);
1363     map.get("bar").remove(1);
1364     assertEquals("{bar=[3]}", map.toString());
1365     assertEquals("[bar=3]", map.entries().toString());
1366   }
1367 
testRemoveToString()1368   public void testRemoveToString() {
1369     Multimap<String, Integer> map = create();
1370     map.put("foo", 1);
1371     map.put("foo", 2);
1372     map.remove("foo", 1);
1373     assertEquals("[foo=2]", map.entries().toString());
1374   }
1375 }
1376