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