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.multiset;
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.assertThrows;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.io.IOException;
25  import java.io.Serializable;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.Collection;
29  import java.util.ConcurrentModificationException;
30  import java.util.HashSet;
31  import java.util.Iterator;
32  import java.util.List;
33  import java.util.NoSuchElementException;
34  import java.util.Set;
35  
36  import org.apache.commons.collections4.BulkTest;
37  import org.apache.commons.collections4.MultiSet;
38  import org.apache.commons.collections4.collection.AbstractCollectionTest;
39  import org.apache.commons.collections4.set.AbstractSetTest;
40  import org.apache.commons.lang3.ArrayUtils;
41  import org.apache.commons.lang3.StringUtils;
42  import org.junit.jupiter.api.Test;
43  
44  /**
45   * Abstract test class for {@link org.apache.commons.collections4.MultiSet MultiSet}
46   * methods and contracts.
47   * <p>
48   * To use, simply extend this class, and implement
49   * the {@link #makeObject} method.
50   * <p>
51   * If your multiset fails one of these tests by design,
52   * you may still use this base set of cases.  Simply override the
53   * test case (method) your multiset fails.
54   * <p>
55   * This abstract test class does wrap the concrete multiset implementation
56   * with such a decorator, see the overridden {@link #resetEmpty()} and
57   * {@link #resetFull()} methods.
58   * <p>
59   * In addition to the generic collection tests (prefix testCollection) inherited
60   * from AbstractCollectionTest, there are test methods that test the "normal" MultiSet
61   * interface (prefix testMultiSet). For MultiSet specific tests use the {@link #makeObject()} and
62   * {@link #makeFullCollection()} methods instead of {@link #resetEmpty()} and resetFull().
63   */
64  public abstract class AbstractMultiSetTest<T> extends AbstractCollectionTest<T> {
65  
66      public class TestMultiSetUniqueSet extends AbstractSetTest<T> {
67          public TestMultiSetUniqueSet() {
68              super(StringUtils.EMPTY);
69          }
70  
71          @Override
72          public T[] getFullElements() {
73              return AbstractMultiSetTest.this.getFullElements();
74          }
75  
76          @Override
77          protected int getIterationBehaviour() {
78              return AbstractMultiSetTest.this.getIterationBehaviour();
79          }
80  
81          @Override
82          public T[] getOtherElements() {
83              return AbstractMultiSetTest.this.getOtherElements();
84          }
85  
86          @Override
87          public boolean isAddSupported() {
88              return false;
89          }
90  
91          @Override
92          public boolean isNullSupported() {
93              return AbstractMultiSetTest.this.isNullSupported();
94          }
95  
96          @Override
97          public boolean isRemoveSupported() {
98              return AbstractMultiSetTest.this.isRemoveSupported();
99          }
100 
101         @Override
102         public boolean isTestSerialization() {
103             return false;
104         }
105 
106         @Override
107         public Set<T> makeFullCollection() {
108             return AbstractMultiSetTest.this.makeFullCollection().uniqueSet();
109         }
110 
111         @Override
112         public Set<T> makeObject() {
113             return AbstractMultiSetTest.this.makeObject().uniqueSet();
114         }
115 
116         @Override
117         public void resetEmpty() {
118             AbstractMultiSetTest.this.resetEmpty();
119             TestMultiSetUniqueSet.this.setCollection(AbstractMultiSetTest.this.getCollection().uniqueSet());
120             TestMultiSetUniqueSet.this.setConfirmed(new HashSet<>(AbstractMultiSetTest.this.getConfirmed()));
121         }
122 
123         @Override
124         public void resetFull() {
125             AbstractMultiSetTest.this.resetFull();
126             TestMultiSetUniqueSet.this.setCollection(AbstractMultiSetTest.this.getCollection().uniqueSet());
127             TestMultiSetUniqueSet.this.setConfirmed(new HashSet<>(AbstractMultiSetTest.this.getConfirmed()));
128         }
129 
130         @Override
131         public void verify() {
132             super.verify();
133         }
134     }
135 
136     /**
137      * JUnit constructor.
138      *
139      * @param testName  the test class name
140      */
141     public AbstractMultiSetTest(final String testName) {
142         super(testName);
143     }
144 
145     /**
146      * Bulk test {@link MultiSet#uniqueSet()}.  This method runs through all of
147      * the tests in {@link AbstractSetTest}.
148      * After modification operations, {@link #verify()} is invoked to ensure
149      * that the multiset and the other collection views are still valid.
150      *
151      * @return a {@link AbstractSetTest} instance for testing the multiset's unique set
152      */
153     public BulkTest bulkTestMultiSetUniqueSet() {
154         return new TestMultiSetUniqueSet();
155     }
156 
157     /**
158      * Returns the {@link #collection} field cast to a {@link MultiSet}.
159      *
160      * @return the collection field as a MultiSet
161      */
162     @Override
163     public MultiSet<T> getCollection() {
164         return (MultiSet<T>) super.getCollection();
165     }
166 
167     /**
168      * Returns an empty {@link ArrayList}.
169      */
170     @Override
171     public Collection<T> makeConfirmedCollection() {
172         final ArrayList<T> list = new ArrayList<>();
173         return list;
174     }
175 
176     /**
177      * Returns a full collection.
178      */
179     @Override
180     public Collection<T> makeConfirmedFullCollection() {
181         final Collection<T> coll = makeConfirmedCollection();
182         coll.addAll(Arrays.asList(getFullElements()));
183         return coll;
184     }
185 
186     /**
187      * {@inheritDoc}
188      */
189     @Override
190     public MultiSet<T> makeFullCollection() {
191         final MultiSet<T> multiset = makeObject();
192         multiset.addAll(Arrays.asList(getFullElements()));
193         return multiset;
194     }
195 
196     /**
197      * Return a new, empty multiset to used for testing.
198      *
199      * @return the multiset to be tested
200      */
201     @Override
202     public abstract MultiSet<T> makeObject();
203 
204     @Override
205     public void resetEmpty() {
206         this.setCollection(makeObject());
207         this.setConfirmed(makeConfirmedCollection());
208     }
209 
210     @Override
211     public void resetFull() {
212         this.setCollection(makeFullCollection());
213         this.setConfirmed(makeConfirmedFullCollection());
214     }
215 
216     /**
217      * Compare the current serialized form of the MultiSet
218      * against the canonical version in SCM.
219      */
220     @Test
221     public void testEmptyMultiSetCompatibility() throws IOException, ClassNotFoundException {
222         // test to make sure the canonical form has been preserved
223         final MultiSet<T> multiset = makeObject();
224         if (multiset instanceof Serializable && !skipSerializedCanonicalTests() && isTestSerialization()) {
225             final MultiSet<?> multiset2 = (MultiSet<?>) readExternalFormFromDisk(getCanonicalEmptyCollectionName(multiset));
226             assertTrue(multiset2.isEmpty(), "MultiSet is empty");
227             assertEquals(multiset, multiset2);
228         }
229     }
230 
231     /**
232      * Compare the current serialized form of the MultiSet
233      * against the canonical version in SCM.
234      */
235     @Test
236     public void testFullMultiSetCompatibility() throws IOException, ClassNotFoundException {
237         // test to make sure the canonical form has been preserved
238         final MultiSet<T> multiset = makeFullCollection();
239         if (multiset instanceof Serializable && !skipSerializedCanonicalTests() && isTestSerialization()) {
240             final MultiSet<?> multiset2 = (MultiSet<?>) readExternalFormFromDisk(getCanonicalFullCollectionName(multiset));
241             assertEquals(multiset.size(), multiset2.size(), "MultiSet is the right size");
242             assertEquals(multiset, multiset2);
243         }
244     }
245 
246     @Test
247     @SuppressWarnings("unchecked")
248     public void testMultiSetAdd() {
249         if (!isAddSupported()) {
250             return;
251         }
252 
253         final MultiSet<T> multiset = makeObject();
254         multiset.add((T) "A");
255         assertTrue(multiset.contains("A"), "Should contain 'A'");
256         assertEquals(1, multiset.getCount("A"), "Should have count of 1");
257         multiset.add((T) "A");
258         assertTrue(multiset.contains("A"), "Should contain 'A'");
259         assertEquals(2, multiset.getCount("A"), "Should have count of 2");
260         multiset.add((T) "B");
261         assertTrue(multiset.contains("A"));
262         assertTrue(multiset.contains("B"));
263     }
264 
265     @Test
266     @SuppressWarnings("unchecked")
267     public void testMultiSetContains() {
268         if (!isAddSupported()) {
269             return;
270         }
271 
272         final MultiSet<T> multiset = makeObject();
273 
274         assertFalse(multiset.contains("A"), "MultiSet does not have at least 1 'A'");
275         assertFalse(multiset.contains("B"), "MultiSet does not have at least 1 'B'");
276 
277         multiset.add((T) "A");  // multiset 1A
278         assertTrue(multiset.contains("A"), "MultiSet has at least 1 'A'");
279         assertFalse(multiset.contains("B"), "MultiSet does not have at least 1 'B'");
280 
281         multiset.add((T) "A");  // multiset 2A
282         assertTrue(multiset.contains("A"), "MultiSet has at least 1 'A'");
283         assertFalse(multiset.contains("B"), "MultiSet does not have at least 1 'B'");
284 
285         multiset.add((T) "B");  // multiset 2A,1B
286         assertTrue(multiset.contains("A"), "MultiSet has at least 1 'A'");
287         assertTrue(multiset.contains("B"), "MultiSet has at least 1 'B'");
288     }
289 
290     @Test
291     @SuppressWarnings("unchecked")
292     public void testMultiSetContainsAll() {
293         if (!isAddSupported()) {
294             return;
295         }
296 
297         final MultiSet<T> multiset = makeObject();
298         final List<String> known = new ArrayList<>();
299         final List<String> known1A = new ArrayList<>();
300         known1A.add("A");
301         final List<String> known2A = new ArrayList<>();
302         known2A.add("A");
303         known2A.add("A");
304         final List<String> known1B = new ArrayList<>();
305         known1B.add("B");
306         final List<String> known1A1B = new ArrayList<>();
307         known1A1B.add("A");
308         known1A1B.add("B");
309 
310         assertTrue(multiset.containsAll(known), "MultiSet containsAll of empty");
311         assertFalse(multiset.containsAll(known1A), "MultiSet does not containsAll of 1 'A'");
312         assertFalse(multiset.containsAll(known2A), "MultiSet does not containsAll of 2 'A'");
313         assertFalse(multiset.containsAll(known1B), "MultiSet does not containsAll of 1 'B'");
314         assertFalse(multiset.containsAll(known1A1B), "MultiSet does not containsAll of 1 'A' 1 'B'");
315 
316         multiset.add((T) "A");  // multiset 1A
317         assertTrue(multiset.containsAll(known), "MultiSet containsAll of empty");
318         assertTrue(multiset.containsAll(known1A), "MultiSet containsAll of 1 'A'");
319         assertTrue(multiset.containsAll(known2A), "MultiSet does not containsAll 'A'");
320         assertFalse(multiset.containsAll(known1B), "MultiSet does not containsAll of 1 'B'");
321         assertFalse(multiset.containsAll(known1A1B), "MultiSet does not containsAll of 1 'A' 1 'B'");
322 
323         multiset.add((T) "A");  // multiset 2A
324         assertTrue(multiset.containsAll(known), "MultiSet containsAll of empty");
325         assertTrue(multiset.containsAll(known1A), "MultiSet containsAll of 1 'A'");
326         assertTrue(multiset.containsAll(known2A), "MultiSet containsAll of 2 'A'");
327         assertFalse(multiset.containsAll(known1B), "MultiSet does not containsAll of 1 'B'");
328         assertFalse(multiset.containsAll(known1A1B), "MultiSet does not containsAll of 1 'A' 1 'B'");
329 
330         multiset.add((T) "A");  // multiset 3A
331         assertTrue(multiset.containsAll(known), "MultiSet containsAll of empty");
332         assertTrue(multiset.containsAll(known1A), "MultiSet containsAll of 1 'A'");
333         assertTrue(multiset.containsAll(known2A), "MultiSet containsAll of 2 'A'");
334         assertFalse(multiset.containsAll(known1B), "MultiSet does not containsAll of 1 'B'");
335         assertFalse(multiset.containsAll(known1A1B), "MultiSet does not containsAll of 1 'A' 1 'B'");
336 
337         multiset.add((T) "B");  // multiset 3A1B
338         assertTrue(multiset.containsAll(known), "MultiSet containsAll of empty");
339         assertTrue(multiset.containsAll(known1A), "MultiSet containsAll of 1 'A'");
340         assertTrue(multiset.containsAll(known2A), "MultiSet containsAll of 2 'A'");
341         assertTrue(multiset.containsAll(known1B), "MultiSet containsAll of 1 'B'");
342         assertTrue(multiset.containsAll(known1A1B), "MultiSet containsAll of 1 'A' 1 'B'");
343     }
344 
345     @Test
346     @SuppressWarnings("unchecked")
347     public void testMultiSetEntrySetUpdatedToZero() {
348         if (!isAddSupported()) {
349             return;
350         }
351         final MultiSet<T> multiset = makeObject();
352         multiset.add((T) "A");
353         multiset.add((T) "A");
354         final MultiSet.Entry<T> entry = multiset.entrySet().iterator().next();
355         assertEquals(2, entry.getCount());
356         multiset.remove("A");
357         assertEquals(1, entry.getCount());
358         multiset.remove("A");
359         assertEquals(0, entry.getCount());
360     }
361 
362     @Test
363     @SuppressWarnings("unchecked")
364     public void testMultiSetEquals() {
365         if (!isAddSupported()) {
366             return;
367         }
368 
369         final MultiSet<T> multiset = makeObject();
370         final MultiSet<T> multiset2 = makeObject();
371         assertTrue(multiset.equals(multiset2));
372         multiset.add((T) "A");
373         assertFalse(multiset.equals(multiset2));
374         multiset2.add((T) "A");
375         assertTrue(multiset.equals(multiset2));
376         multiset.add((T) "A");
377         multiset.add((T) "B");
378         multiset.add((T) "B");
379         multiset.add((T) "C");
380         multiset2.add((T) "A");
381         multiset2.add((T) "B");
382         multiset2.add((T) "B");
383         multiset2.add((T) "C");
384         assertTrue(multiset.equals(multiset2));
385     }
386 
387     @Test
388     @SuppressWarnings("unchecked")
389     public void testMultiSetEqualsHashMultiSet() {
390         if (!isAddSupported()) {
391             return;
392         }
393 
394         final MultiSet<T> multiset = makeObject();
395         final MultiSet<T> multiset2 = new HashMultiSet<>();
396         assertTrue(multiset.equals(multiset2));
397         multiset.add((T) "A");
398         assertFalse(multiset.equals(multiset2));
399         multiset2.add((T) "A");
400         assertTrue(multiset.equals(multiset2));
401         multiset.add((T) "A");
402         multiset.add((T) "B");
403         multiset.add((T) "B");
404         multiset.add((T) "C");
405         multiset2.add((T) "A");
406         multiset2.add((T) "B");
407         multiset2.add((T) "B");
408         multiset2.add((T) "C");
409         assertTrue(multiset.equals(multiset2));
410     }
411 
412     @Test
413     @SuppressWarnings("unchecked")
414     public void testMultiSetEqualsSelf() {
415         final MultiSet<T> multiset = makeObject();
416         assertEquals(multiset, multiset);
417 
418         if (!isAddSupported()) {
419             return;
420         }
421 
422         multiset.add((T) "elt");
423         assertEquals(multiset, multiset);
424         multiset.add((T) "elt"); // again
425         assertEquals(multiset, multiset);
426         multiset.add((T) "elt2");
427         assertEquals(multiset, multiset);
428     }
429 
430     @Test
431     @SuppressWarnings("unchecked")
432     public void testMultiSetHashCode() {
433         if (!isAddSupported()) {
434             return;
435         }
436 
437         final MultiSet<T> multiset = makeObject();
438         final MultiSet<T> multiset2 = makeObject();
439         assertEquals(0, multiset.hashCode());
440         assertEquals(0, multiset2.hashCode());
441         assertEquals(multiset.hashCode(), multiset2.hashCode());
442         multiset.add((T) "A");
443         multiset.add((T) "A");
444         multiset.add((T) "B");
445         multiset.add((T) "B");
446         multiset.add((T) "C");
447         multiset2.add((T) "A");
448         multiset2.add((T) "A");
449         multiset2.add((T) "B");
450         multiset2.add((T) "B");
451         multiset2.add((T) "C");
452         assertEquals(multiset.hashCode(), multiset2.hashCode());
453 
454         int total = 0;
455         total += "A".hashCode() ^ 2;
456         total += "B".hashCode() ^ 2;
457         total += "C".hashCode() ^ 1;
458         assertEquals(total, multiset.hashCode());
459         assertEquals(total, multiset2.hashCode());
460     }
461 
462     @Test
463     @SuppressWarnings("unchecked")
464     public void testMultiSetIterator() {
465         if (!isAddSupported()) {
466             return;
467         }
468 
469         final MultiSet<T> multiset = makeObject();
470         multiset.add((T) "A");
471         multiset.add((T) "A");
472         multiset.add((T) "B");
473         assertEquals(3, multiset.size(), "MultiSet should have 3 items");
474         final Iterator<T> i = multiset.iterator();
475 
476         boolean foundA = false;
477         while (i.hasNext()) {
478             final String element = (String) i.next();
479             // ignore the first A, remove the second via Iterator.remove()
480             if (element.equals("A")) {
481                 if (!foundA) {
482                     foundA = true;
483                 } else {
484                     i.remove();
485                 }
486             }
487         }
488 
489         assertTrue(multiset.contains("A"), "MultiSet should still contain 'A'");
490         assertEquals(2, multiset.size(), "MultiSet should have 2 items");
491         assertEquals(1, multiset.getCount("A"), "MultiSet should have 1 'A'");
492     }
493 
494     @Test
495     @SuppressWarnings("unchecked")
496     public void testMultiSetIteratorFail() {
497         if (!isAddSupported()) {
498             return;
499         }
500 
501         final MultiSet<T> multiset = makeObject();
502         multiset.add((T) "A");
503         multiset.add((T) "A");
504         multiset.add((T) "B");
505         final Iterator<T> it = multiset.iterator();
506         it.next();
507         multiset.remove("A");
508         assertThrows(ConcurrentModificationException.class, () -> it.next(),
509                 "Should throw ConcurrentModificationException");
510     }
511 
512     @Test
513     @SuppressWarnings("unchecked")
514     public void testMultiSetIteratorFailDoubleRemove() {
515         if (!isAddSupported()) {
516             return;
517         }
518 
519         final MultiSet<T> multiset = makeObject();
520         multiset.add((T) "A");
521         multiset.add((T) "A");
522         multiset.add((T) "B");
523         final Iterator<T> it = multiset.iterator();
524         it.next();
525         it.next();
526         assertEquals(3, multiset.size());
527         it.remove();
528         assertEquals(2, multiset.size());
529         assertThrows(IllegalStateException.class, () -> it.remove(),
530                 "Should throw IllegalStateException");
531         assertEquals(2, multiset.size());
532         it.next();
533         it.remove();
534         assertEquals(1, multiset.size());
535     }
536 
537     @Test
538     @SuppressWarnings("unchecked")
539     public void testMultiSetIteratorFailNoMore() {
540         if (!isAddSupported()) {
541             return;
542         }
543 
544         final MultiSet<T> multiset = makeObject();
545         multiset.add((T) "A");
546         multiset.add((T) "A");
547         multiset.add((T) "B");
548         final Iterator<T> it = multiset.iterator();
549         it.next();
550         it.next();
551         it.next();
552         assertThrows(NoSuchElementException.class, () -> it.next(),
553                 "Should throw NoSuchElementException");
554     }
555 
556     @Test
557     @SuppressWarnings("unchecked")
558     public void testMultiSetIteratorRemoveProtectsInvariants() {
559         if (!isAddSupported()) {
560             return;
561         }
562 
563         final MultiSet<T> multiset = makeObject();
564         multiset.add((T) "A");
565         multiset.add((T) "A");
566         assertEquals(2, multiset.size());
567         final Iterator<T> it = multiset.iterator();
568         assertEquals("A", it.next());
569         assertTrue(it.hasNext());
570         it.remove();
571         assertEquals(1, multiset.size());
572         assertTrue(it.hasNext());
573         assertEquals("A", it.next());
574         assertFalse(it.hasNext());
575         it.remove();
576         assertEquals(0, multiset.size());
577         assertFalse(it.hasNext());
578 
579         final Iterator<T> it2 = multiset.iterator();
580         assertFalse(it2.hasNext());
581     }
582 
583     @Test
584     @SuppressWarnings("unchecked")
585     public void testMultiSetRemove() {
586         if (!isRemoveSupported()) {
587             return;
588         }
589 
590         final MultiSet<T> multiset = makeObject();
591         multiset.add((T) "A");
592         assertEquals(1, multiset.getCount("A"), "Should have count of 1");
593         multiset.remove("A");
594         assertEquals(0, multiset.getCount("A"), "Should have count of 0");
595         multiset.add((T) "A");
596         multiset.add((T) "A");
597         multiset.add((T) "A");
598         multiset.add((T) "A");
599         assertEquals(4, multiset.getCount("A"), "Should have count of 4");
600         multiset.remove("A", 0);
601         assertEquals(4, multiset.getCount("A"), "Should have count of 4");
602         multiset.remove("A", 2);
603         assertEquals(2, multiset.getCount("A"), "Should have count of 2");
604         multiset.remove("A");
605         assertEquals(1, multiset.getCount("A"), "Should have count of 1");
606     }
607 
608     @Test
609     @SuppressWarnings("unchecked")
610     public void testMultiSetRemoveAll() {
611         if (!isRemoveSupported()) {
612             return;
613         }
614 
615         final MultiSet<T> multiset = makeObject();
616         multiset.add((T) "A", 2);
617         assertEquals(2, multiset.getCount("A"), "Should have count of 2");
618         multiset.add((T) "B");
619         multiset.add((T) "C");
620         assertEquals(4, multiset.size(), "Should have count of 4");
621         final List<String> delete = new ArrayList<>();
622         delete.add("A");
623         delete.add("B");
624         multiset.removeAll(delete);
625         assertEquals(0, multiset.getCount("A"), "Should have count of 0");
626         assertEquals(0, multiset.getCount("B"), "Should have count of 0");
627         assertEquals(1, multiset.getCount("C"), "Should have count of 1");
628         assertEquals(1, multiset.size(), "Should have count of 1");
629     }
630 
631     @Test
632     @SuppressWarnings("unchecked")
633     public void testMultiSetRetainAll() {
634         if (!isAddSupported()) {
635             return;
636         }
637 
638         final MultiSet<T> multiset = makeObject();
639         multiset.add((T) "A");
640         multiset.add((T) "A");
641         multiset.add((T) "A");
642         multiset.add((T) "B");
643         multiset.add((T) "B");
644         multiset.add((T) "C");
645         final List<String> retains = new ArrayList<>();
646         retains.add("B");
647         retains.add("C");
648         multiset.retainAll(retains);
649         assertEquals(3, multiset.size(), "Should have 3 total items");
650     }
651 
652     @Test
653     @SuppressWarnings("unchecked")
654     public void testMultiSetSize() {
655         if (!isAddSupported()) {
656             return;
657         }
658 
659         final MultiSet<T> multiset = makeObject();
660         assertEquals(0, multiset.size(), "Should have 0 total items");
661         multiset.add((T) "A");
662         assertEquals(1, multiset.size(), "Should have 1 total items");
663         multiset.add((T) "A");
664         assertEquals(2, multiset.size(), "Should have 2 total items");
665         multiset.add((T) "A");
666         assertEquals(3, multiset.size(), "Should have 3 total items");
667         multiset.add((T) "B");
668         assertEquals(4, multiset.size(), "Should have 4 total items");
669         multiset.add((T) "B");
670         assertEquals(5, multiset.size(), "Should have 5 total items");
671         multiset.remove("A", 2);
672         assertEquals(1, multiset.getCount("A"), "Should have 1 'A'");
673         assertEquals(3, multiset.size(), "Should have 3 total items");
674         multiset.remove("B");
675         assertEquals(2, multiset.size(), "Should have 2 total item");
676     }
677 
678     @Test
679     @SuppressWarnings("unchecked")
680     public void testMultiSetToArray() {
681         if (!isAddSupported()) {
682             return;
683         }
684 
685         final MultiSet<T> multiset = makeObject();
686         multiset.add((T) "A");
687         multiset.add((T) "A");
688         multiset.add((T) "B");
689         multiset.add((T) "B");
690         multiset.add((T) "C");
691         final Object[] array = multiset.toArray();
692         int a = 0, b = 0, c = 0;
693         for (final Object element : array) {
694             a += element.equals("A") ? 1 : 0;
695             b += element.equals("B") ? 1 : 0;
696             c += element.equals("C") ? 1 : 0;
697         }
698         assertEquals(2, a);
699         assertEquals(2, b);
700         assertEquals(1, c);
701     }
702 
703     @Test
704     @SuppressWarnings("unchecked")
705     public void testMultiSetToArrayPopulate() {
706         if (!isAddSupported()) {
707             return;
708         }
709 
710         final MultiSet<T> multiset = makeObject();
711         multiset.add((T) "A");
712         multiset.add((T) "A");
713         multiset.add((T) "B");
714         multiset.add((T) "B");
715         multiset.add((T) "C");
716         final String[] array = multiset.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
717         int a = 0, b = 0, c = 0;
718         for (final String element : array) {
719             a += element.equals("A") ? 1 : 0;
720             b += element.equals("B") ? 1 : 0;
721             c += element.equals("C") ? 1 : 0;
722         }
723         assertEquals(2, a);
724         assertEquals(2, b);
725         assertEquals(1, c);
726     }
727 
728 }