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