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