View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.multimap;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  import static org.junit.jupiter.api.Assumptions.assumeTrue;
26  
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.Collection;
30  import java.util.HashMap;
31  import java.util.HashSet;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Map.Entry;
36  import java.util.Set;
37  
38  import org.apache.commons.collections4.AbstractObjectTest;
39  import org.apache.commons.collections4.Bag;
40  import org.apache.commons.collections4.BulkTest;
41  import org.apache.commons.collections4.CollectionUtils;
42  import org.apache.commons.collections4.MapIterator;
43  import org.apache.commons.collections4.MultiSet;
44  import org.apache.commons.collections4.MultiValuedMap;
45  import org.apache.commons.collections4.SetValuedMap;
46  import org.apache.commons.collections4.bag.AbstractBagTest;
47  import org.apache.commons.collections4.bag.HashBag;
48  import org.apache.commons.collections4.collection.AbstractCollectionTest;
49  import org.apache.commons.collections4.map.AbstractMapTest;
50  import org.apache.commons.collections4.multiset.AbstractMultiSetTest;
51  import org.apache.commons.collections4.set.AbstractSetTest;
52  import org.apache.commons.lang3.StringUtils;
53  import org.junit.jupiter.api.Disabled;
54  import org.junit.jupiter.api.Test;
55  
56  /**
57   * Abstract test class for {@link MultiValuedMap} contract and methods.
58   * <p>
59   * To use, extend this class and implement the {@link #makeObject} method and if
60   * necessary override the {@link #makeFullMap()} method.
61   * </p>
62   */
63  public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTest {
64  
65      public class TestMultiValuedMapAsMap extends AbstractMapTest<K, Collection<V>> {
66  
67          public TestMultiValuedMapAsMap() {
68              super(StringUtils.EMPTY);
69          }
70  
71          @Override
72          public boolean areEqualElementsDistinguishable() {
73              // work-around for a problem with the EntrySet: the entries contain
74              // the wrapped collection, which will be automatically cleared
75              // when the associated key is removed from the map as the collection
76              // is not cached atm.
77              return true;
78          }
79  
80          @Override
81          protected int getIterationBehaviour() {
82              return AbstractMultiValuedMapTest.this.getIterationBehaviour();
83          }
84  
85          @Override
86          @SuppressWarnings("unchecked")
87          public Collection<V>[] getNewSampleValues() {
88              // See comment in getSampleValues() to understand why we are calling makeObject() and not
89              // getMap(). See COLLECTIONS-661 for more.
90              final boolean isSetValuedMap = AbstractMultiValuedMapTest.this.makeObject() instanceof SetValuedMap;
91              final int maxV = getSampleTotalValueCount();
92              final int maxK = getSampleKeySize();
93              final V[] sampleValues = (V[]) new Object[maxV];
94              for (int v = 0; v < maxV; v++) {
95                  // + something so that the key is different from an existing key.
96                  sampleValues[v] = makeValue(maxK + 9, v);
97              }
98              final int cpk = getSampleCountPerKey();
99              final Collection<V>[] colArr = new Collection[maxK];
100             for (int i = 0; i < maxK; i++) {
101                 final List<V> coll = new ArrayList<>(cpk);
102                 for (int j = 0; j < cpk; j++) {
103                     coll.add(sampleValues[i * cpk + j]);
104                 }
105                 colArr[i] = isSetValuedMap ? new HashSet<>(coll) : coll;
106             }
107             return colArr;
108         }
109 
110         @Override
111         @SuppressWarnings("unchecked")
112         public K[] getSampleKeys() {
113             final K[] samplekeys = AbstractMultiValuedMapTest.this.getSampleKeys();
114             final int maxK = getSampleKeySize();
115             final int cpk = getSampleCountPerKey();
116             final Object[] finalKeys = new Object[maxK];
117             for (int i = 0; i < maxK; i++) {
118                 finalKeys[i] = samplekeys[i * cpk];
119             }
120             return (K[]) finalKeys;
121         }
122 
123         @Override
124         @SuppressWarnings("unchecked")
125         public Collection<V>[] getSampleValues() {
126             // Calling getMap() instead of makeObject() would make more sense, but due to concurrency
127             // issues, this may lead to intermittent issues. See COLLECTIONS-661. A better solution
128             // would be to re-design the tests, or add a boolean method to the parent.
129             final boolean isSetValuedMap = AbstractMultiValuedMapTest.this.makeObject() instanceof SetValuedMap;
130             final V[] sampleValues = AbstractMultiValuedMapTest.this.getSampleValues();
131             final int maxK = getSampleKeySize();
132             final int cpk = getSampleCountPerKey();
133             final Collection<V>[] colArr = new Collection[maxK];
134             for (int i = 0; i < maxK; i++) {
135                 final List<V> coll = new ArrayList<>(cpk);
136                 for (int j = 0; j < cpk; j++) {
137                     coll.add(sampleValues[i * cpk + j]);
138                 }
139                 colArr[i] = isSetValuedMap ? new HashSet<>(coll) : coll;
140             }
141             return colArr;
142         }
143 
144         @Override
145         public boolean isAllowNullKey() {
146             return AbstractMultiValuedMapTest.this.isAllowNullKey();
147         }
148 
149         @Override
150         public boolean isPutAddSupported() {
151             return false;
152         }
153 
154         @Override
155         public boolean isPutChangeSupported() {
156             return false;
157         }
158 
159         @Override
160         public boolean isRemoveSupported() {
161             return AbstractMultiValuedMapTest.this.isRemoveSupported();
162         }
163 
164         @Override
165         public boolean isTestSerialization() {
166             return false;
167         }
168 
169         @Override
170         public Map<K, Collection<V>> makeFullMap() {
171             return AbstractMultiValuedMapTest.this.makeFullMap().asMap();
172         }
173 
174         @Override
175         public Map<K, Collection<V>> makeObject() {
176             return AbstractMultiValuedMapTest.this.makeObject().asMap();
177         }
178     }
179 
180     public class TestMultiValuedMapEntries extends AbstractCollectionTest<Entry<K, V>> {
181         public TestMultiValuedMapEntries() {
182             super(StringUtils.EMPTY);
183         }
184 
185         @SuppressWarnings("unchecked")
186         @Override
187         public Entry<K, V>[] getFullElements() {
188             return makeFullMap().entries().toArray(new Entry[0]);
189         }
190 
191         @Override
192         protected int getIterationBehaviour() {
193             return AbstractMultiValuedMapTest.this.getIterationBehaviour();
194         }
195 
196         @Override
197         public boolean isAddSupported() {
198             // Add not supported in entries view
199             return false;
200         }
201 
202         @Override
203         public boolean isNullSupported() {
204             return AbstractMultiValuedMapTest.this.isAllowNullKey();
205         }
206 
207         @Override
208         public boolean isRemoveSupported() {
209             return AbstractMultiValuedMapTest.this.isRemoveSupported();
210         }
211 
212         @Override
213         public boolean isTestSerialization() {
214             return false;
215         }
216 
217         @Override
218         public Collection<Entry<K, V>> makeConfirmedCollection() {
219             // never gets called, reset methods are overridden
220             return null;
221         }
222 
223         @Override
224         public Collection<Entry<K, V>> makeConfirmedFullCollection() {
225             // never gets called, reset methods are overridden
226             return null;
227         }
228 
229         @Override
230         public Collection<Entry<K, V>> makeFullCollection() {
231             return AbstractMultiValuedMapTest.this.makeFullMap().entries();
232         }
233 
234         @Override
235         public Collection<Entry<K, V>> makeObject() {
236             return AbstractMultiValuedMapTest.this.makeObject().entries();
237         }
238 
239         @Override
240         public void resetEmpty() {
241             AbstractMultiValuedMapTest.this.resetEmpty();
242             setCollection(AbstractMultiValuedMapTest.this.getMap().entries());
243             TestMultiValuedMapEntries.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().entries());
244         }
245 
246         @Override
247         public void resetFull() {
248             AbstractMultiValuedMapTest.this.resetFull();
249             setCollection(AbstractMultiValuedMapTest.this.getMap().entries());
250             TestMultiValuedMapEntries.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().entries());
251         }
252 
253     }
254 
255     public class TestMultiValuedMapKeys extends AbstractMultiSetTest<K> {
256 
257         public TestMultiValuedMapKeys() {
258             super(StringUtils.EMPTY);
259         }
260 
261         @Override
262         public K[] getFullElements() {
263             return getSampleKeys();
264         }
265 
266         @Override
267         protected int getIterationBehaviour() {
268             return AbstractMultiValuedMapTest.this.getIterationBehaviour();
269         }
270 
271         @Override
272         public boolean isAddSupported() {
273             return false;
274         }
275 
276         @Override
277         public boolean isNullSupported() {
278             return AbstractMultiValuedMapTest.this.isAllowNullKey();
279         }
280 
281         @Override
282         public boolean isRemoveSupported() {
283             return false;
284         }
285 
286         @Override
287         public boolean isTestSerialization() {
288             return false;
289         }
290 
291         @Override
292         public MultiSet<K> makeFullCollection() {
293             return AbstractMultiValuedMapTest.this.makeFullMap().keys();
294         }
295 
296         @Override
297         public MultiSet<K> makeObject() {
298             return AbstractMultiValuedMapTest.this.makeObject().keys();
299         }
300 
301         @Override
302         public void resetEmpty() {
303             AbstractMultiValuedMapTest.this.resetEmpty();
304             setCollection(AbstractMultiValuedMapTest.this.getMap().keys());
305             TestMultiValuedMapKeys.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().keys());
306         }
307 
308         @Override
309         public void resetFull() {
310             AbstractMultiValuedMapTest.this.resetFull();
311             setCollection(AbstractMultiValuedMapTest.this.getMap().keys());
312             TestMultiValuedMapKeys.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().keys());
313         }
314     }
315 
316     public class TestMultiValuedMapKeySet extends AbstractSetTest<K> {
317         public TestMultiValuedMapKeySet() {
318             super(StringUtils.EMPTY);
319         }
320 
321         @SuppressWarnings("unchecked")
322         @Override
323         public K[] getFullElements() {
324             return (K[]) AbstractMultiValuedMapTest.this.makeFullMap().keySet().toArray();
325         }
326 
327         @Override
328         protected int getIterationBehaviour() {
329             return AbstractMultiValuedMapTest.this.getIterationBehaviour();
330         }
331 
332         @Override
333         public boolean isAddSupported() {
334             return false;
335         }
336 
337         @Override
338         public boolean isNullSupported() {
339             return AbstractMultiValuedMapTest.this.isAllowNullKey();
340         }
341 
342         @Override
343         public boolean isRemoveSupported() {
344             return AbstractMultiValuedMapTest.this.isRemoveSupported();
345         }
346 
347         @Override
348         public boolean isTestSerialization() {
349             return false;
350         }
351 
352         @Override
353         public Set<K> makeFullCollection() {
354             return AbstractMultiValuedMapTest.this.makeFullMap().keySet();
355         }
356 
357         @Override
358         public Set<K> makeObject() {
359             return AbstractMultiValuedMapTest.this.makeObject().keySet();
360         }
361     }
362 
363     public class TestMultiValuedMapValues extends AbstractCollectionTest<V> {
364         public TestMultiValuedMapValues() {
365             super(StringUtils.EMPTY);
366         }
367 
368         @Override
369         public V[] getFullElements() {
370             return getSampleValues();
371         }
372 
373         @Override
374         protected int getIterationBehaviour() {
375             return AbstractMultiValuedMapTest.this.getIterationBehaviour();
376         }
377 
378         @Override
379         public boolean isAddSupported() {
380             return false;
381         }
382 
383         @Override
384         public boolean isNullSupported() {
385             return AbstractMultiValuedMapTest.this.isAllowNullKey();
386         }
387 
388         @Override
389         public boolean isRemoveSupported() {
390             return AbstractMultiValuedMapTest.this.isRemoveSupported();
391         }
392 
393         @Override
394         public boolean isTestSerialization() {
395             return false;
396         }
397 
398         @Override
399         public Collection<V> makeConfirmedCollection() {
400             // never gets called, reset methods are overridden
401             return null;
402         }
403 
404         @Override
405         public Collection<V> makeConfirmedFullCollection() {
406             // never gets called, reset methods are overridden
407             return null;
408         }
409 
410         @Override
411         public Collection<V> makeFullCollection() {
412             return AbstractMultiValuedMapTest.this.makeFullMap().values();
413         }
414 
415         @Override
416         public Collection<V> makeObject() {
417             return AbstractMultiValuedMapTest.this.makeObject().values();
418         }
419 
420         @Override
421         public void resetEmpty() {
422             AbstractMultiValuedMapTest.this.resetEmpty();
423             setCollection(AbstractMultiValuedMapTest.this.getMap().values());
424             TestMultiValuedMapValues.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().values());
425         }
426 
427         @Override
428         public void resetFull() {
429             AbstractMultiValuedMapTest.this.resetFull();
430             setCollection(AbstractMultiValuedMapTest.this.getMap().values());
431             TestMultiValuedMapValues.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().values());
432         }
433     }
434 
435     /** Map created by reset(). */
436     protected MultiValuedMap<K, V> map;
437 
438     /** MultiValuedHashMap created by reset(). */
439     protected MultiValuedMap<K, V> confirmed;
440 
441     public AbstractMultiValuedMapTest(final String testName) {
442         super(testName);
443     }
444 
445     protected void addSampleMappings(final MultiValuedMap<? super K, ? super V> map) {
446         final K[] keys = getSampleKeys();
447         final V[] values = getSampleValues();
448         for (int i = 0; i < keys.length; i++) {
449             map.put(keys[i], values[i]);
450         }
451     }
452 
453     public BulkTest bulkTestAsMap() {
454         return new TestMultiValuedMapAsMap();
455     }
456 
457     // Bulk Tests
458     /**
459      * Bulk test {@link MultiValuedMap#entries()}. This method runs through all
460      * of the tests in {@link AbstractCollectionTest}. After modification
461      * operations, {@link #verify()} is invoked to ensure that the map and the
462      * other collection views are still valid.
463      *
464      * @return a {@link AbstractCollectionTest} instance for testing the map's
465      *         values collection
466      */
467     public BulkTest bulkTestMultiValuedMapEntries() {
468         return new TestMultiValuedMapEntries();
469     }
470 
471     /**
472      * Bulk test {@link MultiValuedMap#keys()}. This method runs through all of
473      * the tests in {@link AbstractBagTest}. After modification operations,
474      * {@link #verify()} is invoked to ensure that the map and the other
475      * collection views are still valid.
476      *
477      * @return a {@link AbstractBagTest} instance for testing the map's values
478      *         collection
479      */
480     public BulkTest bulkTestMultiValuedMapKeys() {
481         return new TestMultiValuedMapKeys();
482     }
483 
484     /**
485      * Bulk test {@link MultiValuedMap#keySet()}. This method runs through all
486      * of the tests in {@link AbstractSetTest}. After modification operations,
487      * {@link #verify()} is invoked to ensure that the map and the other
488      * collection views are still valid.
489      *
490      * @return a {@link AbstractSetTest} instance for testing the map's key set
491      */
492     public BulkTest bulkTestMultiValuedMapKeySet() {
493         return new TestMultiValuedMapKeySet();
494     }
495 
496     /**
497      * Bulk test {@link MultiValuedMap#values()}. This method runs through all
498      * of the tests in {@link AbstractCollectionTest}. After modification
499      * operations, {@link #verify()} is invoked to ensure that the map and the
500      * other collection views are still valid.
501      *
502      * @return a {@link AbstractCollectionTest} instance for testing the map's
503      *         values collection
504      */
505     public BulkTest bulkTestMultiValuedMapValues() {
506         return new TestMultiValuedMapValues();
507     }
508 
509     @Override
510     public String getCompatibilityVersion() {
511         return "4.1"; // MultiValuedMap has been added in version 4.1
512     }
513 
514     public MultiValuedMap<K, V> getConfirmed() {
515         return confirmed;
516     }
517 
518     /**
519      * Gets a flag specifying the iteration behavior of the map.
520      * This is used to change the assertions used by specific tests.
521      * The default implementation returns 0 which indicates ordered iteration behavior.
522      *
523      * @return the iteration behavior
524      * @see AbstractCollectionTest#UNORDERED
525      */
526     protected int getIterationBehaviour() {
527         return 0;
528     }
529 
530     public MultiValuedMap<K, V> getMap() {
531         return map;
532     }
533 
534     public int getSampleCountPerKey() {
535         return 8;
536     }
537 
538     /**
539      * Returns the set of keys in the mappings used to test the map. This method
540      * must return an array with the same length as {@link #getSampleValues()}
541      * and all array elements must be different. The default implementation
542      * constructs a set of String keys, and includes a single null key if
543      * {@link #isAllowNullKey()} returns {@code true}.
544      */
545     @SuppressWarnings("unchecked")
546     public K[] getSampleKeys() {
547         final Object[] result = new Object[getSampleTotalValueCount()];
548         final int cpk = getSampleCountPerKey();
549         int k = 0;
550         for (int i = 0; i < result.length; i += cpk, k++) {
551             final K key = makeKey(k);
552             for (int j = 0; j < cpk; j++) {
553                 result[i + j] = key;
554             }
555         }
556         return (K[]) result;
557     }
558 
559     public int getSampleKeySize() {
560         return 256;
561     }
562 
563     public int getSampleTotalValueCount() {
564         return getSampleCountPerKey() * getSampleKeySize();
565     }
566 
567     /**
568      * Returns the set of values in the mappings used to test the map. This
569      * method must return an array with the same length as
570      * {@link #getSampleKeys()}. The default implementation constructs a set of
571      * String values
572      */
573     @SuppressWarnings("unchecked")
574     public V[] getSampleValues() {
575         final Object[] result = new Object[getSampleTotalValueCount()];
576         final int cpk = getSampleCountPerKey();
577         int k = 0;
578         for (int i = 0; i < result.length; i += cpk, k++) {
579             for (int j = 0; j < cpk; j++) {
580                 result[i + j] = makeValue(k, j);
581             }
582         }
583         return (V[]) result;
584     }
585 
586     /**
587      * Returns true if the maps produced by {@link #makeObject()} and
588      * {@link #makeFullMap()} support the {@code put} and
589      * {@code putAll} operations adding new mappings.
590      * <p>
591      * Default implementation returns true. Override if your collection class
592      * does not support put adding.
593      * </p>
594      */
595     public boolean isAddSupported() {
596         return true;
597     }
598 
599     /**
600      * Returns true if the maps produced by {@link #makeObject()} and
601      * {@link #makeFullMap()} supports null keys.
602      * <p>
603      * Default implementation returns true. Override if your collection class
604      * does not support null keys.
605      * </p>
606      */
607     public boolean isAllowNullKey() {
608         return true;
609     }
610 
611     /**
612      * Returns true if the maps produced by {@link #makeObject()} and
613      * {@link #makeFullMap()} supports set value.
614      * <p>
615      * Default implementation returns false. Override if your collection class
616      * supports set value.
617      * </p>
618      */
619     public boolean isHashSetValue() {
620         return false;
621     }
622 
623     /**
624      * Returns true if the maps produced by {@link #makeObject()} and
625      * {@link #makeFullMap()} support the {@code remove} and
626      * {@code clear} operations.
627      * <p>
628      * Default implementation returns true. Override if your collection class
629      * does not support removal operations.
630      * </p>
631      */
632     public boolean isRemoveSupported() {
633         return true;
634     }
635 
636     @Override
637     public boolean isTestSerialization() {
638         return true;
639     }
640 
641     /**
642      * Override to return a MultiValuedMap other than ArrayListValuedHashMap
643      * as the confirmed map.
644      *
645      * @return a MultiValuedMap that is known to be valid
646      */
647     public MultiValuedMap<K, V> makeConfirmedMap() {
648         return new ArrayListValuedHashMap<>();
649     }
650 
651     protected MultiValuedMap<K, V> makeFullMap() {
652         final MultiValuedMap<K, V> map = makeObject();
653         addSampleMappings(map);
654         return map;
655     }
656 
657     <E> E makeKey(final int key) {
658         return (E) new StringBuilder("k").append(key).toString();
659     }
660 
661     @Override
662     public abstract MultiValuedMap<K, V> makeObject();
663 
664     <E> E makeValue(final int key, final int value) {
665         return (E) new StringBuilder("v").append(key).append('_').append(value).toString();
666     }
667 
668     /**
669      * Resets the {@link #map} and {@link #confirmed} fields to empty.
670      */
671     public void resetEmpty() {
672         this.map = makeObject();
673         this.confirmed = makeConfirmedMap();
674     }
675 
676     /**
677      * Resets the {@link #map} and {@link #confirmed} fields to full.
678      */
679     public void resetFull() {
680         this.map = makeFullMap();
681         this.confirmed = makeConfirmedMap();
682         final K[] k = getSampleKeys();
683         final V[] v = getSampleValues();
684         for (int i = 0; i < k.length; i++) {
685             confirmed.put(k[i], v[i]);
686         }
687     }
688 
689 //    public void testKeyedIterator() {
690 //        final MultiValuedMap<K, V> map = makeFullMap();
691 //        final ArrayList<Object> actual = new ArrayList<Object>(IteratorUtils.toList(map.iterator("k0")));
692 //        final ArrayList<Object> expected = new ArrayList<Object>(Arrays.asList("v1_1", "v0_1"));
693 //        assertEquals(expected, actual);
694 //    }
695 
696     public void setConfirmed(final MultiValuedMap<K, V> map) {
697         this.confirmed = map;
698     }
699 
700     @Test
701     @SuppressWarnings("unchecked")
702     public void testAddMappingThroughGet() {
703         assumeTrue(isAddSupported());
704         resetEmpty();
705         final MultiValuedMap<K, V> map = getMap();
706         final Collection<V> col1 = map.get((K) "k0");
707         final Collection<V> col2 = map.get((K) "k0");
708         assertTrue(col1.isEmpty());
709         assertTrue(col2.isEmpty());
710         assertEquals(0, map.size());
711         col1.add((V) "v1_1");
712         col2.add((V) "v0_1");
713         assertTrue(map.containsKey("k0"));
714         assertTrue(map.containsMapping("k0", "v1_1"));
715         assertTrue(map.containsMapping("k0", "v0_1"));
716         assertTrue(map.containsValue("v1_1"));
717         assertTrue(map.containsValue("v0_1"));
718         assertTrue(col1.contains("v0_1"));
719         assertTrue(col2.contains("v1_1"));
720     }
721 
722     /*public void testRemoveViaGetCollectionRemove() {
723         if (!isRemoveSupported()) {
724             return;
725         }
726         final MultiValuedMap<K, V> map = makeFullMap();
727         Collection<V> values = map.get("k0");
728         values.remove("v1_1");
729         values.remove("v0_1");
730         assertFalse(map.containsKey("k0"));
731         assertEquals(4, map.size());
732     }*/
733 
734 //    public void testRemoveAllViaKeyedIterator() {
735 //        if (!isRemoveSupported()) {
736 //            return;
737 //        }
738 //        final MultiValuedMap<K, V> map = makeFullMap();
739 //        for (final Iterator<?> i = map.iterator("k0"); i.hasNext();) {
740 //            i.next();
741 //            i.remove();
742 //        }
743 //        assertNull(map.get("k0"));
744 //        assertEquals(4, map.size());
745 //    }
746 
747     @Test
748     public void testAsMapGet_Empty() {
749         resetEmpty();
750         final Map<K, Collection<V>> mapCol = getMap().asMap();
751         assertNull(mapCol.get("k0"));
752         assertEquals(0, mapCol.size());
753     }
754 
755     @Test
756     public void testAsMapGet_Full() {
757         resetFull();
758         final Map<K, Collection<V>> mapCol = getMap().asMap();
759         final int maxK = getSampleKeySize();
760         final int maxV = getSampleCountPerKey();
761         for (int k = 0; k < maxK; k++) {
762             final Collection<V> col = mapCol.get(makeKey(k));
763             for (int v = 0; v < maxV; v++) {
764                 assertTrue(col.contains(makeValue(k, v)));
765             }
766         }
767     }
768 
769     @Test
770     public void testAsMapRemove() {
771         assumeTrue(isRemoveSupported());
772         resetFull();
773         final Map<K, Collection<V>> mapCol = getMap().asMap();
774         final int maxK = getSampleKeySize();
775         int expectedSize = getMap().size();
776         for (int k = 0; k < maxK; k++) {
777             final K key = makeKey(k);
778             mapCol.remove(key);
779             assertFalse(getMap().containsKey(key));
780             expectedSize -= getSampleCountPerKey();
781             assertEquals(expectedSize, getMap().size());
782         }
783         assertFalse(getMap().containsKey("k0"));
784         assertEquals(0, getMap().size());
785     }
786 
787     @Test
788     public void testContainsValue() {
789         final MultiValuedMap<K, V> map = makeFullMap();
790         final int maxK = getSampleKeySize();
791         final int maxV = getSampleCountPerKey();
792         for (int k = 0; k < maxK; k++) {
793             for (int v = 0; v < maxV; v++) {
794                 assertTrue(map.containsValue(makeValue(k, v)));
795             }
796         }
797         assertFalse(map.containsValue("quatro"));
798     }
799 
800     @Test
801     @SuppressWarnings("unchecked")
802     public void testContainsValue_Key() {
803         final MultiValuedMap<K, V> map = makeFullMap();
804         final int maxK = getSampleKeySize();
805         final int maxV = getSampleCountPerKey();
806         for (int k = 0; k < maxK; k++) {
807             for (int v = 0; v < maxV; v++) {
808                 assertTrue(map.containsMapping(makeKey(k), makeValue(k, v)));            }
809         }
810         assertFalse(map.containsMapping("k1", "2"));
811         if (!isAddSupported()) {
812             return;
813         }
814         map.put((K) "A", (V) "AA");
815         assertTrue(map.containsMapping("A", "AA"));
816         assertFalse(map.containsMapping("A", "AB"));
817     }
818 
819     /**
820      * Manual serialization testing as this class cannot easily extend the AbstractTestMap
821      */
822     @Test
823     public void testEmptyMapCompatibility() throws Exception {
824         final MultiValuedMap<?, ?> map = makeObject();
825         final MultiValuedMap<?, ?> map2 =
826                 (MultiValuedMap<?, ?>) readExternalFormFromDisk(getCanonicalEmptyCollectionName(map));
827         assertEquals(0, map2.size(), "Map is empty");
828     }
829 
830     @Test
831     public void testEntriesCollectionIterator() {
832         final MultiValuedMap<K, V> map = makeFullMap();
833         final Collection<V> values = new ArrayList<>(map.values());
834         for (final Entry<K, V> entry : map.entries()) {
835             assertTrue(map.containsMapping(entry.getKey(), entry.getValue()));
836             assertTrue(values.contains(entry.getValue()));
837             if (isRemoveSupported()) {
838                 assertTrue(values.remove(entry.getValue()));
839             }
840         }
841         if (isRemoveSupported()) {
842             assertTrue(values.isEmpty());
843         }
844     }
845 
846     @SuppressWarnings({ "rawtypes", "unchecked" })
847     @Test
848     @Disabled("There is no code to create this test fixture?")
849     public void testFullMapCompatibility() throws Exception {
850         final MultiValuedMap map = makeFullMap();
851         final MultiValuedMap map2 =
852                 (MultiValuedMap) readExternalFormFromDisk(getCanonicalFullCollectionName(map));
853         assertEquals(map.size(), map2.size(), "Map is the right size");
854         for (final Object key : map.keySet()) {
855             assertTrue(CollectionUtils.isEqualCollection(map.get(key), map2.get(key)),
856                     "Map had inequal elements");
857             if (isRemoveSupported()) {
858                 map2.remove(key);
859             }
860         }
861         if (isRemoveSupported()) {
862             assertEquals(0, map2.size(), "Map had extra values");
863         }
864     }
865 
866 //    @SuppressWarnings("unchecked")
867 //    public void testIterator_Key() {
868 //        final MultiValuedMap<K, V> map = makeFullMap();
869 //        Iterator<V> it = map.iterator("k0");
870 //        assertTrue( it.hasNext());
871 //        Set<V> values = new HashSet<V>();
872 //        while (it.hasNext()) {
873 //            values.add(it.next());
874 //        }
875 //        assertTrue( values.contains("v0_1"));
876 //        assertTrue( values.contains("v1_1"));
877 //        assertFalse(map.iterator("A").hasNext());
878 //        assertFalse(map.iterator("A").hasNext());
879 //        if (!isAddSupported()) {
880 //            return;
881 //        }
882 //        map.put((K) "A", (V) "AA");
883 //        it = map.iterator("A");
884 //        assertTrue( it.hasNext());
885 //        it.next();
886 //        assertFalse(it.hasNext());
887 //    }
888 
889     @Test
890     @SuppressWarnings("unchecked")
891     public void testGet() {
892         final MultiValuedMap<K, V> map = makeFullMap();
893         final int maxK = getSampleKeySize();
894         final int maxV = getSampleCountPerKey();
895         for (int k = 0; k < maxK; k++) {
896             for (int v = 0; v < maxV; v++) {
897                 assertTrue(map.get((K) makeKey(k)).contains(makeValue(k, v)));
898             }
899         }
900     }
901 
902     @Test
903     public void testKeyContainsValue() {
904         final MultiValuedMap<K, V> map = makeFullMap();
905         final int maxK = getSampleKeySize();
906         final int maxV = getSampleCountPerKey();
907         for (int k = 0; k < maxK; k++) {
908             for (int v = 0; v < maxV; v++) {
909                 assertTrue(map.containsMapping(makeKey(k), makeValue(k, v)));
910             }
911         }
912         assertFalse(map.containsMapping("k", "v"));
913     }
914 
915     @Test
916     @SuppressWarnings({ "unchecked", "cast" })
917     public void testKeysBagContainsAll() {
918         final MultiValuedMap<K, V> map = makeFullMap();
919         final MultiSet<K> keyMultiSet = map.keys();
920 
921         final List<String> col = new ArrayList<>();
922         final int maxK = getSampleKeySize();
923         for (int k = 0; k < maxK; k++) {
924             col.add(makeKey(k));
925         }
926         for (int k = 0; k < maxK; k++) {
927             col.add(makeKey(k));
928         }
929         // Make sure we test Collection API
930         assertTrue(keyMultiSet.containsAll((Collection<K>) col));
931     }
932 
933     @Test
934     public void testKeysBagIterator() {
935         final MultiValuedMap<K, V> map = makeFullMap();
936         final Collection<K> col = new ArrayList<>(map.keys());
937         final Bag<K> bag = new HashBag<>(col);
938         final int maxK = getSampleKeySize();
939         for (int k = 0; k < maxK; k++) {
940             assertEquals(getSampleCountPerKey(), bag.getCount(makeKey(k)));
941         }
942         assertEquals(getSampleTotalValueCount(), bag.size());
943     }
944 
945     @Test
946     public void testKeySetSize() {
947         final MultiValuedMap<K, V> map = makeFullMap();
948         assertEquals(getSampleKeySize(), map.keySet().size());
949     }
950 
951     @Test
952     public void testKeysMultiSet() {
953         final MultiValuedMap<K, V> map = makeFullMap();
954         final MultiSet<K> keyMultiSet = map.keys();
955         final int maxK = getSampleKeySize();
956         for (int k = 0; k < maxK; k++) {
957             assertEquals(getSampleCountPerKey(), keyMultiSet.getCount(makeKey(k)));
958         }
959         assertEquals(0, keyMultiSet.getCount("conut"));
960         assertEquals(getSampleTotalValueCount(), keyMultiSet.size());
961     }
962 
963     @Test
964     @SuppressWarnings("unchecked")
965     public void testMapEquals() {
966         assumeTrue(isAddSupported());
967         final MultiValuedMap<K, V> one = makeObject();
968         final Integer value = Integer.valueOf(1);
969         one.put((K) "One", (V) value);
970         one.removeMapping("One", value);
971 
972         final MultiValuedMap<K, V> two = makeObject();
973         assertEquals(two, one);
974     }
975 
976     @Test
977     public void testMapIterator() {
978         resetEmpty();
979         MapIterator<K, V> mapIt  = getMap().mapIterator();
980         assertFalse(mapIt.hasNext());
981 
982         resetFull();
983         mapIt = getMap().mapIterator();
984         while (mapIt.hasNext()) {
985             final K key = mapIt.next();
986             final V value = mapIt.getValue();
987             assertTrue(getMap().containsMapping(key, value));
988         }
989     }
990 
991     @Test
992     public void testMapIteratorRemove() {
993         assumeTrue(isRemoveSupported());
994         resetFull();
995         final MapIterator<K, V> mapIt = getMap().mapIterator();
996         while (mapIt.hasNext()) {
997             mapIt.next();
998             mapIt.remove();
999         }
1000         assertTrue(getMap().isEmpty());
1001     }
1002 
1003     @Test
1004     @SuppressWarnings("unchecked")
1005     public void testMapIteratorUnsupportedSet() {
1006         resetFull();
1007         final MapIterator<K, V> mapIt = getMap().mapIterator();
1008         mapIt.next();
1009         assertThrows(UnsupportedOperationException.class, () -> mapIt.setValue((V) "some value"));
1010     }
1011 
1012     @Test
1013     public void testMultipleValues() {
1014         final MultiValuedMap<K, V> map = makeFullMap();
1015         final int maxK = getSampleKeySize();
1016         final int maxV = getSampleCountPerKey();
1017         for (int k = 0; k < maxK; k++) {
1018             final Collection<V> col = map.get(makeKey(k));
1019             for (int v = 0; v < maxV; v++) {
1020                 assertTrue(col.contains(makeValue(k, v)));
1021             }
1022         }
1023 
1024     }
1025 
1026     @Test
1027     public void testMultiValuedMapIterator() {
1028         final MultiValuedMap<K, V> map = makeFullMap();
1029         final MapIterator<K, V> it = map.mapIterator();
1030         assertThrows(IllegalStateException.class, () -> it.getKey());
1031         assertThrows(IllegalStateException.class, () -> it.getValue());
1032         if (isAddSupported()) {
1033             assertThrows(IllegalStateException.class, () -> it.setValue((V) "V"));
1034         }
1035         if (!isHashSetValue() && isAddSupported()) {
1036             assertTrue(it.hasNext());
1037             final MultiValuedMap<K, V> dejaVu = makeObject();
1038             while (it.hasNext()) {
1039                 final K next = it.next();
1040                 assertNotNull(next);
1041                 final K itKey = it.getKey();
1042                 assertEquals(next, itKey);
1043                 final V itValue = it.getValue();
1044                 dejaVu.put(itKey, itValue);
1045                 assertThrows(UnsupportedOperationException.class, () -> it.setValue((V) "threetrois"));
1046             }
1047             assertEquals(map, dejaVu);
1048             assertEquals(dejaVu, map);
1049             assertThrows(UnsupportedOperationException.class, () -> it.setValue((V) "threetrois"));
1050         }
1051     }
1052 
1053     @Test
1054     @SuppressWarnings("unchecked")
1055     public void testNoMappingReturnsEmptyCol() {
1056         final MultiValuedMap<K, V> map = makeFullMap();
1057         assertTrue(map.get((K) "whatever").isEmpty());
1058     }
1059 
1060     @Test
1061     @SuppressWarnings("unchecked")
1062     public void testPutAll_KeyIterable() {
1063         assumeTrue(isAddSupported());
1064         final MultiValuedMap<K, V> map = makeObject();
1065         Collection<V> coll = (Collection<V>) Arrays.asList("X", "Y", "Z");
1066 
1067         assertTrue(map.putAll((K) "A", coll));
1068         assertEquals(3, map.get((K) "A").size());
1069         assertTrue(map.containsMapping("A", "X"));
1070         assertTrue(map.containsMapping("A", "Y"));
1071         assertTrue(map.containsMapping("A", "Z"));
1072 
1073         assertThrows(NullPointerException.class, () -> map.putAll((K) "A", null),
1074                 "expecting NullPointerException");
1075 
1076         assertEquals(3, map.get((K) "A").size());
1077         assertTrue(map.containsMapping("A", "X"));
1078         assertTrue(map.containsMapping("A", "Y"));
1079         assertTrue(map.containsMapping("A", "Z"));
1080 
1081         assertFalse(map.putAll((K) "A", new ArrayList<>()));
1082         assertEquals(3, map.get((K) "A").size());
1083         assertTrue(map.containsMapping("A", "X"));
1084         assertTrue(map.containsMapping("A", "Y"));
1085         assertTrue(map.containsMapping("A", "Z"));
1086 
1087         coll = (Collection<V>) Arrays.asList("M");
1088         assertTrue(map.putAll((K) "A", coll));
1089         assertEquals(4, map.get((K) "A").size());
1090         assertTrue(map.containsMapping("A", "X"));
1091         assertTrue(map.containsMapping("A", "Y"));
1092         assertTrue(map.containsMapping("A", "Z"));
1093         assertTrue(map.containsMapping("A", "M"));
1094     }
1095 
1096     @Test
1097     @SuppressWarnings("unchecked")
1098     public void testPutAll_Map1() {
1099         assumeTrue(isAddSupported());
1100         final MultiValuedMap<K, V> original = makeObject();
1101         original.put((K) "key", (V) "object1");
1102         original.put((K) "key", (V) "object2");
1103 
1104         final MultiValuedMap<K, V> test = makeObject();
1105         test.put((K) "keyA", (V) "objectA");
1106         test.put((K) "key", (V) "object0");
1107         test.putAll(original);
1108 
1109         final MultiValuedMap<K, V> originalNull = null;
1110         assertThrows(NullPointerException.class, () -> test.putAll(originalNull),
1111                 "expecting NullPointerException");
1112 
1113         assertEquals(2, test.keySet().size());
1114         assertEquals(4, test.size());
1115         assertEquals(1, test.get((K) "keyA").size());
1116         assertEquals(3, test.get((K) "key").size());
1117         assertTrue(test.containsValue("objectA"));
1118         assertTrue(test.containsValue("object0"));
1119         assertTrue(test.containsValue("object1"));
1120         assertTrue(test.containsValue("object2"));
1121     }
1122 
1123     @Test
1124     @SuppressWarnings("unchecked")
1125     public void testPutAll_Map2() {
1126         assumeTrue(isAddSupported());
1127         final Map<K, V> original = new HashMap<>();
1128         original.put((K) "keyX", (V) "object1");
1129         original.put((K) "keyY", (V) "object2");
1130 
1131         final MultiValuedMap<K, V> test = makeObject();
1132         test.put((K) "keyA", (V) "objectA");
1133         test.put((K) "keyX", (V) "object0");
1134         test.putAll(original);
1135 
1136         final Map<K, V> originalNull = null;
1137         assertThrows(NullPointerException.class, () -> test.putAll(originalNull),
1138                 "expecting NullPointerException");
1139 
1140         assertEquals(3, test.keySet().size());
1141         assertEquals(4, test.size());
1142         assertEquals(1, test.get((K) "keyA").size());
1143         assertEquals(2, test.get((K) "keyX").size());
1144         assertEquals(1, test.get((K) "keyY").size());
1145         assertTrue(test.containsValue("objectA"));
1146         assertTrue(test.containsValue("object0"));
1147         assertTrue(test.containsValue("object1"));
1148         assertTrue(test.containsValue("object2"));
1149     }
1150 
1151     @Test
1152     @SuppressWarnings("unchecked")
1153     public void testRemove_KeyItem() {
1154         assumeTrue(isAddSupported());
1155         assumeTrue(isRemoveSupported());
1156         final MultiValuedMap<K, V> map = makeObject();
1157         map.put((K) "A", (V) "AA");
1158         map.put((K) "A", (V) "AB");
1159         map.put((K) "A", (V) "AC");
1160         assertFalse(map.removeMapping("C", "CA"));
1161         assertFalse(map.removeMapping("A", "AD"));
1162         assertTrue(map.removeMapping("A", "AC"));
1163         assertTrue(map.removeMapping("A", "AB"));
1164         assertTrue(map.removeMapping("A", "AA"));
1165         //assertEquals(new MultiValuedHashMap<K, V>(), map);
1166     }
1167 
1168     @Test
1169     @SuppressWarnings("unchecked")
1170     public void testRemoveAllViaEntriesIterator() {
1171         assumeTrue(isRemoveSupported());
1172         final MultiValuedMap<K, V> map = makeFullMap();
1173         for (final Iterator<?> i = map.entries().iterator(); i.hasNext();) {
1174             i.next();
1175             i.remove();
1176         }
1177         assertTrue(map.get((K) "k0").isEmpty());
1178         assertEquals(0, map.size());
1179     }
1180 
1181     @Test
1182     @SuppressWarnings("unchecked")
1183     public void testRemoveAllViaValuesIterator() {
1184         assumeTrue(isRemoveSupported());
1185         final MultiValuedMap<K, V> map = makeFullMap();
1186         for (final Iterator<?> i = map.values().iterator(); i.hasNext();) {
1187             i.next();
1188             i.remove();
1189         }
1190         assertTrue(map.get((K) "k0").isEmpty());
1191         assertTrue(map.isEmpty());
1192     }
1193 
1194     @Test
1195     public void testRemoveMappingThroughGet() {
1196         assumeTrue(isRemoveSupported());
1197         resetFull();
1198         final MultiValuedMap<K, V> map = getMap();
1199         final int cpk = getSampleCountPerKey();
1200         int expectedCount = getSampleTotalValueCount();
1201         assertEquals(expectedCount, map.size());
1202         for (int k = 0; k < getSampleKeySize(); k++) {
1203             final Object key = makeKey(k);
1204             @SuppressWarnings("unchecked")
1205             Collection<V> col = map.get((K) key);
1206             assertEquals(cpk, col.size());
1207             for (int i = 0; i < cpk; i++) {
1208                 final Object value = makeValue(k, i);
1209                 assertTrue(col.remove(value), () -> value.toString());
1210             }
1211             for (int i = 0; i < cpk; i++) {
1212                 assertFalse(col.remove(makeValue(k, i)));
1213             }
1214             assertFalse(map.containsKey(key));
1215             for (int i = 0; i < cpk; i++) {
1216                 assertFalse(map.containsMapping(key, i));
1217             }
1218             for (int i = 0; i < cpk; i++) {
1219                 assertFalse(map.containsValue(makeValue(k, i)));
1220             }
1221             expectedCount -= cpk;
1222             assertEquals(expectedCount, map.size());
1223             col = map.remove(key);
1224             assertNotNull(col);
1225             assertEquals(0, col.size());
1226         }
1227     }
1228 
1229     @Test
1230     public void testRemoveMappingThroughGetIterator() {
1231         assumeTrue(isRemoveSupported());
1232         resetFull();
1233         final MultiValuedMap<K, V> map = getMap();
1234         int expectedSize = map.size();
1235         final int maxK = getSampleKeySize();
1236         for (int k = 0; k < maxK; k++) {
1237             final String key = makeKey(k);
1238             final int cpk = getSampleCountPerKey();
1239             @SuppressWarnings("unchecked")
1240             final Iterator<V> it = map.get((K) key).iterator();
1241             while (it.hasNext()) {
1242                 it.next();
1243                 it.remove();
1244             }
1245             assertFalse(map.containsKey(key));
1246             for (int j = 0; j < cpk; j++) {
1247                 assertFalse(map.containsMapping(key, makeValue(k + 1, j)));
1248                 final Object value = makeValue(k, j);
1249                 assertFalse(map.containsMapping(key, value));
1250                 assertFalse(map.containsValue(value));
1251             }
1252             expectedSize -= cpk;
1253             assertEquals(expectedSize, map.size());
1254             final Collection<V> coll = map.remove("k0");
1255             assertNotNull(coll);
1256             assertEquals(0, coll.size());
1257         }
1258     }
1259 
1260     @Test
1261     public void testRemoveViaValuesRemove() {
1262         assumeTrue(isRemoveSupported());
1263         final MultiValuedMap<K, V> map = makeFullMap();
1264         final Collection<V> values = map.values();
1265         final int maxK = getSampleKeySize();
1266         final int maxV = getSampleCountPerKey();
1267         int expectedSize = map.size();
1268         for (int k = 0; k < maxK; k++) {
1269             for (int v = 0; v < maxV; v++) {
1270                 values.remove(makeValue(k, v));
1271             }
1272             assertFalse(map.containsKey(makeKey(k)));
1273             expectedSize -= maxV;
1274             assertEquals(expectedSize, map.size());
1275         }
1276         assertEquals(0, map.size());
1277     }
1278 
1279     @Test
1280     public void testSize() {
1281         assertEquals(getSampleTotalValueCount(), makeFullMap().size());
1282     }
1283 
1284     @Test
1285     @SuppressWarnings("unchecked")
1286     public void testSize_Key() {
1287         final MultiValuedMap<K, V> map = makeFullMap();
1288         final int maxK = getSampleKeySize();
1289         for (int k = 0; k < maxK; k++) {
1290             assertEquals(getSampleCountPerKey(), map.get((K) makeKey(k)).size());
1291         }
1292         if (!isAddSupported()) {
1293             return;
1294         }
1295         map.put((K) "A", (V) "AA");
1296         assertEquals(1, map.get((K) "A").size());
1297         // assertEquals(0, map.get("B").size());
1298         map.put((K) "B", (V) "BA");
1299         assertEquals(1, map.get((K) "A").size());
1300         assertEquals(1, map.get((K) "B").size());
1301         map.put((K) "B", (V) "BB");
1302         assertEquals(1, map.get((K) "A").size());
1303         assertEquals(2, map.get((K) "B").size());
1304         map.put((K) "B", (V) "BC");
1305         assertEquals(1, map.get((K) "A").size());
1306         assertEquals(3, map.get((K) "B").size());
1307         if (!isRemoveSupported()) {
1308             return;
1309         }
1310         map.remove("A");
1311         // assertEquals(0, map.get("A").size());
1312         assertEquals(3, map.get((K) "B").size());
1313         map.removeMapping("B", "BC");
1314         // assertEquals(0, map.get("A").size());
1315         assertEquals(2, map.get((K) "B").size());
1316     }
1317 
1318     @Test
1319     @SuppressWarnings("unchecked")
1320     public void testSizeWithPutRemove() {
1321         assumeTrue(isAddSupported());
1322         assumeTrue(isRemoveSupported());
1323         final MultiValuedMap<K, V> map = makeObject();
1324         assertEquals(0, map.size());
1325         map.put((K) "A", (V) "AA");
1326         assertEquals(1, map.size());
1327         map.put((K) "B", (V) "BA");
1328         assertEquals(2, map.size());
1329         map.put((K) "B", (V) "BB");
1330         assertEquals(3, map.size());
1331         map.put((K) "B", (V) "BC");
1332         assertEquals(4, map.size());
1333         map.remove("A");
1334         assertEquals(3, map.size());
1335         map.removeMapping("B", "BC");
1336         assertEquals(2, map.size());
1337     }
1338 
1339     @Test
1340     public void testToString() {
1341         assumeTrue(isAddSupported());
1342         final MultiValuedMap<K, V> map = makeObject();
1343         map.put((K) "A", (V) "X");
1344         map.put((K) "A", (V) "Y");
1345         map.put((K) "A", (V) "Z");
1346         map.put((K) "B", (V) "U");
1347         map.put((K) "B", (V) "V");
1348         map.put((K) "B", (V) "W");
1349         assertTrue("{A=[X, Y, Z], B=[U, V, W]}".equals(map.toString()) || "{B=[U, V, W], A=[X, Y, Z]}".equals(map.toString()));
1350 
1351         final MultiValuedMap<K, V> originalNull = null;
1352         assertThrows(NullPointerException.class, () -> map.putAll(originalNull), "expecting NullPointerException");
1353         assertTrue("{A=[X, Y, Z], B=[U, V, W]}".equals(map.toString()) || "{B=[U, V, W], A=[X, Y, Z]}".equals(map.toString()));
1354 
1355         map.remove("A");
1356         map.remove("B");
1357         assertEquals("{}", map.toString());
1358     }
1359 
1360     @Test
1361     @SuppressWarnings("unchecked")
1362     public void testValues() {
1363         final MultiValuedMap<K, V> map = makeFullMap();
1364         final HashSet<V> expected = new HashSet<>();
1365         final int maxK = getSampleKeySize();
1366         final int maxV = getSampleCountPerKey();
1367         for (int k = 0; k < maxK; k++) {
1368             for (int v = 0; v < maxV; v++) {
1369                 expected.add((V) makeValue(k, v));
1370             }
1371         }
1372         final Collection<V> c = map.values();
1373         assertEquals(getSampleTotalValueCount(), c.size());
1374         assertEquals(expected, new HashSet<>(c));
1375     }
1376 
1377 }