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.apache.commons.lang3.StringUtils;
42 import org.junit.jupiter.api.Test;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
138
139
140
141 public AbstractMultiSetTest(final String testName) {
142 super(testName);
143 }
144
145
146
147
148
149
150
151
152
153 public BulkTest bulkTestMultiSetUniqueSet() {
154 return new TestMultiSetUniqueSet();
155 }
156
157
158
159
160
161
162 @Override
163 public MultiSet<T> getCollection() {
164 return (MultiSet<T>) super.getCollection();
165 }
166
167
168
169
170 @Override
171 public Collection<T> makeConfirmedCollection() {
172 final ArrayList<T> list = new ArrayList<>();
173 return list;
174 }
175
176
177
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
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
198
199
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
218
219
220 @Test
221 public void testEmptyMultiSetCompatibility() throws IOException, ClassNotFoundException {
222
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
233
234
235 @Test
236 public void testFullMultiSetCompatibility() throws IOException, ClassNotFoundException {
237
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");
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");
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");
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");
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");
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");
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");
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");
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
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 }