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