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
17package com.google.common.collect;
18
19import static java.util.Arrays.asList;
20import static org.junit.contrib.truth.Truth.ASSERT;
21
22import com.google.common.annotations.GwtCompatible;
23import com.google.common.annotations.GwtIncompatible;
24import com.google.common.testing.SerializableTester;
25
26import junit.framework.TestCase;
27
28import java.util.ArrayList;
29import java.util.Arrays;
30import java.util.Collection;
31import java.util.Collections;
32import java.util.ConcurrentModificationException;
33import java.util.Iterator;
34import java.util.Map;
35import java.util.Map.Entry;
36import java.util.NoSuchElementException;
37import 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)
46public abstract class AbstractMultimapTest extends TestCase {
47
48  private Multimap<String, Integer> multimap;
49
50  protected abstract Multimap<String, Integer> create();
51
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
60  @Override public void setUp() throws Exception {
61    super.setUp();
62    multimap = create();
63  }
64
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   */
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   */
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   */
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
111  protected boolean removedCollectionsAreModifiable() {
112    return false;
113  }
114
115  public void testSize0() {
116    assertSize(0);
117  }
118
119  public void testSize1() {
120    multimap.put("foo", 1);
121    assertSize(1);
122  }
123
124  public void testSize2Keys() {
125    multimap.put("foo", 1);
126    multimap.put("bar", 5);
127    assertSize(2);
128  }
129
130  public void testSize2Values() {
131    multimap.put("foo", 1);
132    multimap.put("foo", 7);
133    assertSize(2);
134  }
135
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
145  public void testIsEmptyYes() {
146    assertTrue(multimap.isEmpty());
147  }
148
149  public void testIsEmptyNo() {
150    multimap.put("foo", 1);
151    assertFalse(multimap.isEmpty());
152  }
153
154  public void testIsEmptyNull() {
155    multimap.put(nullKey(), nullValue());
156    assertFalse(multimap.isEmpty());
157  }
158
159  public void testIsEmptyRemoved() {
160    multimap.put("foo", 1);
161    multimap.remove("foo", 1);
162    assertTrue(multimap.isEmpty());
163  }
164
165  public void testContainsKeyTrue() {
166    multimap.put("foo", 1);
167    assertTrue(multimap.containsKey("foo"));
168  }
169
170  public void testContainsKeyFalse() {
171    multimap.put("foo", 1);
172    assertFalse(multimap.containsKey("bar"));
173    assertFalse(multimap.containsKey(nullKey()));
174  }
175
176  public void testContainsKeyNull() {
177    multimap.put(nullKey(), 1);
178    assertTrue(multimap.containsKey(nullKey()));
179  }
180
181  public void testContainsValueTrue() {
182    multimap.put("foo", 1);
183    assertTrue(multimap.containsValue(1));
184  }
185
186  public void testContainsValueFalse() {
187    multimap.put("foo", 1);
188    assertFalse(multimap.containsValue(2));
189    assertFalse(multimap.containsValue(nullValue()));
190  }
191
192  public void testContainsValueNull() {
193    multimap.put("foo", nullValue());
194    assertTrue(multimap.containsValue(nullValue()));
195  }
196
197  public void testContainsKeyValueTrue() {
198    multimap.put("foo", 1);
199    assertTrue(multimap.containsEntry("foo", 1));
200  }
201
202  public void testContainsKeyValueRemoved() {
203    multimap.put("foo", 1);
204    multimap.remove("foo", 1);
205    assertFalse(multimap.containsEntry("foo", 1));
206  }
207
208  public void testGet0() {
209    multimap.put("foo", 1);
210    Collection<Integer> values = multimap.get("bar");
211    assertEquals(0, values.size());
212  }
213
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
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
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
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
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
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
285  public void testPutAllEmptyCollection() {
286    Collection<Integer> collection = Lists.newArrayList();
287    multimap.putAll("foo", collection);
288    assertSize(0);
289    assertTrue(multimap.isEmpty());
290  }
291
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
310  public void testPutAllReturn_emptyCollection() {
311    assertFalse(multimap.putAll("foo", new ArrayList<Integer>()));
312    assertFalse(multimap.putAll(create()));
313  }
314
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
632  public void testAsMapToString() {
633    multimap.put("foo", 1);
634    assertEquals("{foo=[1]}", multimap.asMap().toString());
635  }
636
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
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
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
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
720  public void testKeysToString() {
721    multimap.put("foo", 7);
722    multimap.put("foo", 8);
723    assertEquals("[foo x 2]", multimap.keys().toString());
724  }
725
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
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
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
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
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
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
801  public void testValuesIteratorEmpty() {
802    int sum = 0;
803    for (int i : multimap.values()) {
804      sum += i;
805    }
806    assertEquals(0, sum);
807  }
808
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
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
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
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
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
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
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
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
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
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
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
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
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")
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
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")
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
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
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
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
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   */
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. */
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
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
1207  public void testKeySetRemoveAllNullFromEmpty() {
1208    try {
1209      multimap.keySet().removeAll(null);
1210      fail();
1211    } catch (NullPointerException expected) {}
1212  }
1213
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
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
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
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
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
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")
1339  public void testSerializable() {
1340    multimap = createSample();
1341    assertEquals(multimap, SerializableTester.reserialize(multimap));
1342  }
1343
1344  public void testEmptyToString() {
1345    Multimap<String, Integer> map = create();
1346    assertEquals("{}", map.toString());
1347    assertEquals("[]", map.entries().toString());
1348  }
1349
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
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
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