1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.collections4.collection;
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.assertNotNull;
22 import static org.junit.jupiter.api.Assertions.assertNull;
23 import static org.junit.jupiter.api.Assertions.assertThrows;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25 import static org.junit.jupiter.api.Assertions.fail;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.ByteArrayOutputStream;
29 import java.io.ObjectInputStream;
30 import java.io.ObjectOutputStream;
31 import java.io.Serializable;
32 import java.lang.reflect.Array;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.ConcurrentModificationException;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.NoSuchElementException;
44 import java.util.Objects;
45 import java.util.function.Predicate;
46
47 import org.apache.commons.collections4.AbstractObjectTest;
48 import org.apache.commons.lang3.ArrayUtils;
49 import org.apache.commons.lang3.StringUtils;
50 import org.junit.jupiter.api.Test;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 public abstract class AbstractCollectionTest<E> extends AbstractObjectTest {
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 public static final int UNORDERED = 0x1;
158
159
160
161
162
163
164
165
166
167 protected static void assertNotCollectionContains(final Collection<?> coll, final Object element) {
168 try {
169 assertFalse(coll.contains(element));
170 } catch (final ClassCastException | NullPointerException e) {
171
172 }
173 }
174
175
176
177
178
179
180 protected static void assertNotCollectionContainsAll(final Collection<?> coll, final Collection<?> sub) {
181 try {
182 assertFalse(coll.containsAll(sub));
183 } catch (final ClassCastException | NullPointerException e) {
184
185 }
186 }
187
188
189
190
191
192
193 protected static void assertNotRemoveAllFromCollection(final Collection<?> coll, final Collection<?> sub) {
194 try {
195 assertFalse(coll.removeAll(sub));
196 } catch (final ClassCastException | NullPointerException e) {
197
198 }
199 }
200
201
202
203
204
205
206 protected static void assertNotRemoveFromCollection(final Collection<?> coll, final Object element) {
207 try {
208 assertFalse(coll.remove(element));
209 } catch (final ClassCastException | NullPointerException e) {
210
211 }
212 }
213
214
215
216
217
218
219
220
221
222
223
224 private static void assertUnorderedArrayEquals(final Object[] a1, final Object[] a2, final String msg) {
225 assertEquals(a1.length, a2.length, () -> msg + ": length");
226 final int size = a1.length;
227
228 final boolean[] matched = new boolean[size];
229 NEXT_OBJECT:
230 for (final Object o : a1) {
231 for (int i = 0; i < size; i++) {
232 if (matched[i]) {
233
234 continue;
235 }
236 if (Objects.equals(o, a2[i])) {
237
238 matched[i] = true;
239
240 continue NEXT_OBJECT;
241 }
242 }
243 fail(msg + ": array 2 does not have object: " + o);
244 }
245 }
246
247
248
249
250 private Collection<E> collection;
251
252
253
254
255
256
257
258
259
260 private Collection<E> confirmed;
261
262
263
264
265
266
267 public AbstractCollectionTest(final String testName) {
268 super(testName);
269 }
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293 public boolean areEqualElementsDistinguishable() {
294 return false;
295 }
296
297
298
299
300 public Map.Entry<E, E> cloneMapEntry(final Map.Entry<E, E> entry) {
301 final HashMap<E, E> map = new HashMap<>();
302 map.put(entry.getKey(), entry.getValue());
303 return map.entrySet().iterator().next();
304 }
305
306 public Collection<E> getCollection() {
307 return collection;
308 }
309
310 public Collection<E> getConfirmed() {
311 return confirmed;
312 }
313
314
315
316
317
318
319
320
321
322
323
324 @SuppressWarnings("unchecked")
325 public E[] getFullElements() {
326 if (isNullSupported()) {
327 final ArrayList<E> list = new ArrayList<>(Arrays.asList(getFullNonNullElements()));
328 list.add(4, null);
329 return (E[]) list.toArray();
330 }
331 return getFullNonNullElements().clone();
332 }
333
334
335
336
337
338
339
340
341
342 @SuppressWarnings("unchecked")
343 public E[] getFullNonNullElements() {
344 return (E[]) new Object[] {
345 StringUtils.EMPTY,
346 "One",
347 Integer.valueOf(2),
348 "Three",
349 Integer.valueOf(4),
350 "One",
351 Double.valueOf(5),
352 Float.valueOf(6),
353 "Seven",
354 "Eight",
355 "Nine",
356 Integer.valueOf(10),
357 Short.valueOf((short) 11),
358 Long.valueOf(12),
359 "Thirteen",
360 "14",
361 "15",
362 Byte.valueOf((byte) 16)
363 };
364 }
365
366
367
368
369
370
371
372 public Object[] getFullNonNullStringElements() {
373 return new Object[] {
374 "If", "the", "dull", "substance", "of", "my", "flesh", "were",
375 "thought", "Injurious", "distance", "could", "not", "stop", "my", "way",
376 };
377 }
378
379
380
381
382
383
384
385
386
387 protected int getIterationBehaviour(){
388 return 0;
389 }
390
391
392
393
394
395
396
397
398
399
400 public E[] getOtherElements() {
401 return getOtherNonNullElements();
402 }
403
404
405
406
407
408
409 @SuppressWarnings("unchecked")
410 public E[] getOtherNonNullElements() {
411 return (E[]) new Object[] {
412 Integer.valueOf(0),
413 Float.valueOf(0),
414 Double.valueOf(0),
415 "Zero",
416 Short.valueOf((short) 0),
417 Byte.valueOf((byte) 0),
418 Long.valueOf(0),
419 Character.valueOf('\u0000'),
420 "0"
421 };
422 }
423
424
425
426
427
428
429
430 public Object[] getOtherNonNullStringElements() {
431 return new Object[] {
432 "For", "then", "despite", "space", "I", "would", "be",
433 "brought", "From", "limits", "far", "remote", "where", "thou", "dost", "stay"
434 };
435 }
436
437
438
439
440
441
442
443
444
445 public boolean isAddSupported() {
446 return true;
447 }
448
449
450
451
452
453 @Override
454 public boolean isEqualsCheckable() {
455 return false;
456 }
457
458
459
460
461
462 public boolean isFailFastSupported() {
463 return false;
464 }
465
466
467
468
469
470 public boolean isNullSupported() {
471 return true;
472 }
473
474
475
476
477
478
479
480
481
482
483 public boolean isRemoveSupported() {
484 return true;
485 }
486
487
488
489
490
491
492
493
494 public abstract Collection<E> makeConfirmedCollection();
495
496
497
498
499
500
501
502
503
504 public abstract Collection<E> makeConfirmedFullCollection();
505
506
507
508
509
510
511
512
513
514 public Collection<E> makeFullCollection() {
515 final Collection<E> c = makeObject();
516 c.addAll(Arrays.asList(getFullElements()));
517 return c;
518 }
519
520
521
522
523 @Override
524 public abstract Collection<E> makeObject();
525
526
527
528
529
530
531 public void resetEmpty() {
532 this.setCollection(makeObject());
533 this.setConfirmed(makeConfirmedCollection());
534 }
535
536
537
538
539
540
541 public void resetFull() {
542 this.setCollection(makeFullCollection());
543 this.setConfirmed(makeConfirmedFullCollection());
544 }
545
546
547
548
549
550 public void setCollection(final Collection<E> collection) {
551 this.collection = collection;
552 }
553
554
555
556
557
558 public void setConfirmed(final Collection<E> confirmed) {
559 this.confirmed = confirmed;
560 }
561
562
563
564
565
566 @Test
567 public void testCollectionAdd() {
568 if (!isAddSupported()) {
569 return;
570 }
571
572 final E[] elements = getFullElements();
573 for (final E element : elements) {
574 resetEmpty();
575 final boolean r = getCollection().add(element);
576 getConfirmed().add(element);
577 verify();
578 assertTrue(r, "Empty collection changed after add");
579 assertEquals(1, getCollection().size(), "Collection size is 1 after first add");
580 }
581
582 resetEmpty();
583 int size = 0;
584 for (final E element : elements) {
585 final boolean r = getCollection().add(element);
586 getConfirmed().add(element);
587 verify();
588 if (r) {
589 size++;
590 }
591 assertEquals(size, getCollection().size(), "Collection size should grow after add");
592 assertTrue(getCollection().contains(element), "Collection should contain added element");
593 }
594 }
595
596
597
598
599 @Test
600 public void testCollectionAddAll() {
601 if (!isAddSupported()) {
602 return;
603 }
604
605 resetEmpty();
606 E[] elements = getFullElements();
607 boolean r = getCollection().addAll(Arrays.asList(elements));
608 getConfirmed().addAll(Arrays.asList(elements));
609 verify();
610 assertTrue(r, "Empty collection should change after addAll");
611 for (final E element : elements) {
612 assertTrue(getCollection().contains(element), "Collection should contain added element");
613 }
614
615 resetFull();
616 int size = getCollection().size();
617 elements = getOtherElements();
618 r = getCollection().addAll(Arrays.asList(elements));
619 getConfirmed().addAll(Arrays.asList(elements));
620 verify();
621 assertTrue(r, "Full collection should change after addAll");
622 for (final E element : elements) {
623 assertTrue(getCollection().contains(element),
624 "Full collection should contain added element");
625 }
626 assertEquals(size + elements.length, getCollection().size(), "Size should increase after addAll");
627
628 resetFull();
629 size = getCollection().size();
630 r = getCollection().addAll(Arrays.asList(getFullElements()));
631 getConfirmed().addAll(Arrays.asList(getFullElements()));
632 verify();
633 if (r) {
634 assertTrue(size < getCollection().size(), "Size should increase if addAll returns true");
635 } else {
636 assertEquals(size, getCollection().size(), "Size should not change if addAll returns false");
637 }
638 }
639
640
641
642
643 @Test
644 public void testCollectionClear() {
645 if (!isRemoveSupported()) {
646 return;
647 }
648
649 resetEmpty();
650 getCollection().clear();
651 verify();
652
653 resetFull();
654 getCollection().clear();
655 getConfirmed().clear();
656 verify();
657 }
658
659
660
661
662 @Test
663 public void testCollectionContains() {
664 Object[] elements;
665
666 resetEmpty();
667 elements = getFullElements();
668 for (int i = 0; i < elements.length; i++) {
669 assertFalse(getCollection().contains(elements[i]), "Empty collection shouldn't contain element[" + i + "]");
670 }
671
672 verify();
673
674 elements = getOtherElements();
675 for (int i = 0; i < elements.length; i++) {
676 assertFalse(getCollection().contains(elements[i]), "Empty collection shouldn't contain element[" + i + "]");
677 }
678
679 verify();
680
681 resetFull();
682 elements = getFullElements();
683 for (int i = 0; i < elements.length; i++) {
684 assertTrue(getCollection().contains(elements[i]),
685 "Full collection should contain element[" + i + "]");
686 }
687
688 verify();
689
690 resetFull();
691 elements = getOtherElements();
692 for (final Object element : elements) {
693 assertFalse(getCollection().contains(element), "Full collection shouldn't contain element");
694 }
695 }
696
697
698
699
700 @Test
701 public void testCollectionContainsAll() {
702 resetEmpty();
703 Collection<E> col = new HashSet<>();
704 assertTrue(getCollection().containsAll(col),
705 "Every Collection should contain all elements of an " + "empty Collection.");
706 col.addAll(Arrays.asList(getOtherElements()));
707 assertFalse(getCollection().containsAll(col),
708 "Empty Collection shouldn't contain all elements of " + "a non-empty Collection.");
709
710 verify();
711
712 resetFull();
713 assertFalse(getCollection().containsAll(col), "Full collection shouldn't contain other elements");
714
715 col.clear();
716 col.addAll(Arrays.asList(getFullElements()));
717 assertTrue(getCollection().containsAll(col),
718 "Full collection should containAll full elements");
719
720 verify();
721
722 final int min = getFullElements().length < 4 ? 0 : 2;
723 final int max = getFullElements().length == 1 ? 1 :
724 getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
725 col = Arrays.asList(getFullElements()).subList(min, max);
726 assertTrue(getCollection().containsAll(col),
727 "Full collection should containAll partial full elements");
728 assertTrue(getCollection().containsAll(getCollection()),
729 "Full collection should containAll itself");
730
731 verify();
732
733 col = new ArrayList<>(Arrays.asList(getFullElements()));
734 col.addAll(Arrays.asList(getFullElements()));
735 assertTrue(getCollection().containsAll(col),
736 "Full collection should containAll duplicate full elements");
737
738
739 verify();
740 }
741
742
743
744
745 @Test
746 public void testCollectionIsEmpty() {
747 resetEmpty();
748 assertTrue(getCollection().isEmpty(), "New Collection should be empty.");
749
750 verify();
751
752 resetFull();
753 assertFalse(getCollection().isEmpty(), "Full collection shouldn't be empty");
754
755 verify();
756 }
757
758
759
760
761 @Test
762 public void testCollectionIterator() {
763 resetEmpty();
764 Iterator<E> it1 = getCollection().iterator();
765 assertFalse(it1.hasNext(), "Iterator for empty Collection shouldn't have next.");
766 final Iterator<E> finalIt1 = it1;
767 assertThrows(NoSuchElementException.class, () -> finalIt1.next(),
768 "Iterator at end of Collection should throw NoSuchElementException when next is called.");
769
770 verify();
771
772 resetFull();
773 it1 = getCollection().iterator();
774 for (final E element : getCollection()) {
775 assertTrue(it1.hasNext(), "Iterator for full collection should haveNext");
776 it1.next();
777 }
778 assertFalse(it1.hasNext(), "Iterator should be finished");
779
780 final ArrayList<E> list = new ArrayList<>();
781 it1 = getCollection().iterator();
782 for (int i = 0; i < getCollection().size(); i++) {
783 final E next = it1.next();
784 assertTrue(getCollection().contains(next),
785 "Collection should contain element returned by its iterator");
786 list.add(next);
787 }
788 final Iterator<E> finalIt2 = it1;
789 assertThrows(NoSuchElementException.class, () -> finalIt2.next(),
790 "iterator.next() should raise NoSuchElementException after it finishes");
791
792 verify();
793 }
794
795
796
797
798 @Test
799 public void testCollectionIteratorFailFast() {
800 if (!isFailFastSupported()) {
801 return;
802 }
803
804 if (isAddSupported()) {
805 resetFull();
806 final Iterator<E> iter0 = getCollection().iterator();
807 final E o = getOtherElements()[0];
808 getCollection().add(o);
809 getConfirmed().add(o);
810 assertThrows(ConcurrentModificationException.class, () -> iter0.next(),
811 "next after add should raise ConcurrentModification");
812 verify();
813
814 resetFull();
815 final Iterator<E> iter = getCollection().iterator();
816 getCollection().addAll(Arrays.asList(getOtherElements()));
817 getConfirmed().addAll(Arrays.asList(getOtherElements()));
818 assertThrows(ConcurrentModificationException.class, () -> iter.next(),
819 "next after addAll should raise ConcurrentModification");
820 verify();
821 }
822
823 if (!isRemoveSupported()) {
824 return;
825 }
826
827 resetFull();
828 try {
829 final Iterator<E> iter = getCollection().iterator();
830 getCollection().clear();
831 iter.next();
832 fail("next after clear should raise ConcurrentModification");
833 } catch (final ConcurrentModificationException | NoSuchElementException e) {
834
835
836 }
837
838 resetFull();
839 final Iterator<E> iter0 = getCollection().iterator();
840 getCollection().remove(getFullElements()[0]);
841 assertThrows(ConcurrentModificationException.class, () -> iter0.next(),
842 "next after remove should raise ConcurrentModification");
843
844 resetFull();
845 final Iterator<E> iter1 = getCollection().iterator();
846 getCollection().removeIf(e -> false);
847 assertThrows(ConcurrentModificationException.class, () -> iter1.next(),
848 "next after removeIf should raise ConcurrentModification");
849
850 resetFull();
851 final Iterator<E> iter2 = getCollection().iterator();
852 final List<E> sublist = Arrays.asList(getFullElements()).subList(2, 5);
853 getCollection().removeAll(sublist);
854 assertThrows(ConcurrentModificationException.class, () -> iter2.next(),
855 "next after removeAll should raise ConcurrentModification");
856
857 resetFull();
858 final Iterator<E> iter3 = getCollection().iterator();
859 final List<E> sublist3 = Arrays.asList(getFullElements()).subList(2, 5);
860 getCollection().retainAll(sublist3);
861 assertThrows(ConcurrentModificationException.class, () -> iter3.next(),
862 "next after retainAll should raise ConcurrentModification");
863 }
864
865
866
867
868 @Test
869 @SuppressWarnings("unchecked")
870 public void testCollectionIteratorRemove() {
871 if (!isRemoveSupported()) {
872 return;
873 }
874
875 resetEmpty();
876 assertThrows(IllegalStateException.class, () -> getCollection().iterator().remove(),
877 "New iterator.remove should raise IllegalState");
878 verify();
879
880 final Iterator<E> iter0 = getCollection().iterator();
881 iter0.hasNext();
882 assertThrows(IllegalStateException.class, () -> iter0.remove(),
883 "New iterator.remove should raise IllegalState even after hasNext");
884 verify();
885
886 resetFull();
887 int size = getCollection().size();
888 Iterator<E> iter = getCollection().iterator();
889 while (iter.hasNext()) {
890 Object o = iter.next();
891
892
893 if (o instanceof Map.Entry) {
894 o = cloneMapEntry((Map.Entry<E, E>) o);
895 }
896 iter.remove();
897
898
899
900
901
902
903
904
905
906 if (!areEqualElementsDistinguishable()) {
907 getConfirmed().remove(o);
908 verify();
909 }
910
911 size--;
912 assertEquals(size, getCollection().size(),
913 "Collection should shrink by one after iterator.remove");
914 }
915 assertTrue(getCollection().isEmpty(), "Collection should be empty after iterator purge");
916
917 resetFull();
918 iter = getCollection().iterator();
919 iter.next();
920 iter.remove();
921 final Iterator<E> finalIter = iter;
922 assertThrows(IllegalStateException.class, () -> finalIter.remove(),
923 "Second iter.remove should raise IllegalState");
924 }
925
926
927
928
929 @Test
930 public void testCollectionRemove() {
931 if (!isRemoveSupported()) {
932 return;
933 }
934
935 resetEmpty();
936 final E[] elements = getFullElements();
937 for (final E element : elements) {
938 assertFalse(getCollection().remove(element), "Shouldn't remove nonexistent element");
939 verify();
940 }
941
942 final E[] other = getOtherElements();
943
944 resetFull();
945 for (final E element : other) {
946 assertFalse(getCollection().remove(element), "Shouldn't remove nonexistent other element");
947 verify();
948 }
949
950 final int size = getCollection().size();
951 for (final E element : elements) {
952 resetFull();
953 assertTrue(getCollection().remove(element),
954 "Collection should remove extant element: " + element);
955
956
957
958
959
960
961
962
963
964 if (!areEqualElementsDistinguishable()) {
965 getConfirmed().remove(element);
966 verify();
967 }
968
969 assertEquals(size - 1, getCollection().size(), "Collection should shrink after remove");
970 }
971 }
972
973
974
975
976 @Test
977 public void testCollectionRemoveAll() {
978 if (!isRemoveSupported()) {
979 return;
980 }
981
982 resetEmpty();
983 assertFalse(getCollection().removeAll(Collections.EMPTY_SET), "Empty collection removeAll should return false for empty input");
984 verify();
985
986 assertFalse(getCollection().removeAll(new ArrayList<>(getCollection())), "Empty collection removeAll should return false for nonempty input");
987 verify();
988
989 resetFull();
990 assertFalse(getCollection().removeAll(Collections.EMPTY_SET), "Full collection removeAll should return false for empty input");
991 verify();
992
993 assertFalse(getCollection().removeAll(Arrays.asList(getOtherElements())), "Full collection removeAll should return false for other elements");
994 verify();
995
996 assertTrue(getCollection().removeAll(new HashSet<>(getCollection())),
997 "Full collection removeAll should return true for full elements");
998 getConfirmed().removeAll(new HashSet<>(getConfirmed()));
999 verify();
1000
1001 resetFull();
1002 final int size = getCollection().size();
1003 final int min = getFullElements().length < 4 ? 0 : 2;
1004 final int max = getFullElements().length == 1 ? 1 :
1005 getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
1006 final Collection<E> all = Arrays.asList(getFullElements()).subList(min, max);
1007 assertTrue(getCollection().removeAll(all), "Full collection removeAll should work");
1008 getConfirmed().removeAll(all);
1009 verify();
1010
1011 assertTrue(getCollection().size() < size, "Collection should shrink after removeAll");
1012 for (final E element : all) {
1013 assertFalse(getCollection().contains(element), "Collection shouldn't contain removed element");
1014 }
1015 }
1016
1017
1018
1019
1020 @Test
1021 public void testCollectionRemoveIf() {
1022 if (!isRemoveSupported()) {
1023 return;
1024 }
1025
1026 resetEmpty();
1027 assertFalse(getCollection().removeIf(e -> false), "Empty collection removeIf should return false for a predicate that returns only false");
1028 verify();
1029
1030 assertFalse(getCollection().removeIf(e -> true), "Empty collection removeIf should return false for a predicate that returns only true");
1031 verify();
1032
1033 resetFull();
1034 assertFalse(getCollection().removeIf(e -> false), "Full collection removeIf should return false for a predicate that returns only false");
1035 verify();
1036
1037 assertTrue(getCollection().removeIf(e -> true), "Full collection removeIf should return true for a predicate that returns only true");
1038 getConfirmed().removeIf(e -> true);
1039 verify();
1040
1041 resetFull();
1042 final List<E> elements = Arrays.asList(getFullElements());
1043
1044 final int mid = getFullElements().length / 2;
1045 final E target = elements.get(mid);
1046
1047 final int size = getCollection().size();
1048 final int targetCount = Collections.frequency(elements, target);
1049
1050 final Predicate<E> filter = target::equals;
1051
1052 assertTrue(getCollection().removeIf(filter), "Full collection removeIf should work");
1053 getConfirmed().removeIf(filter);
1054 verify();
1055
1056 assertEquals(getCollection().size(), size - targetCount, "Collection should shrink after removeIf");
1057 assertFalse(getCollection().contains(target), "Collection shouldn't contain removed element");
1058 }
1059
1060
1061
1062
1063 @Test
1064 public void testCollectionRetainAll() {
1065 if (!isRemoveSupported()) {
1066 return;
1067 }
1068
1069 resetEmpty();
1070 final List<E> elements = Arrays.asList(getFullElements());
1071 final List<E> other = Arrays.asList(getOtherElements());
1072
1073 assertFalse(getCollection().retainAll(Collections.EMPTY_SET), "Empty retainAll() should return false");
1074 verify();
1075
1076 assertFalse(getCollection().retainAll(elements), "Empty retainAll() should return false");
1077 verify();
1078
1079 resetFull();
1080 assertTrue(getCollection().retainAll(Collections.EMPTY_SET),
1081 "Collection should change from retainAll empty");
1082 getConfirmed().retainAll(Collections.EMPTY_SET);
1083 verify();
1084
1085 resetFull();
1086 assertTrue(getCollection().retainAll(other), "Collection changed from retainAll other");
1087 getConfirmed().retainAll(other);
1088 verify();
1089
1090 resetFull();
1091 int size = getCollection().size();
1092 assertFalse(getCollection().retainAll(elements), "Collection shouldn't change from retainAll elements");
1093 verify();
1094 assertEquals(size, getCollection().size(), "Collection size shouldn't change");
1095
1096 if (getFullElements().length > 1) {
1097 resetFull();
1098 size = getCollection().size();
1099 final int min = getFullElements().length < 4 ? 0 : 2;
1100 final int max = getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
1101 assertTrue(getCollection().retainAll(elements.subList(min, max)),
1102 "Collection should changed by partial retainAll");
1103 getConfirmed().retainAll(elements.subList(min, max));
1104 verify();
1105
1106 for (final E element : getCollection()) {
1107 assertTrue(elements.subList(min, max).contains(element), "Collection only contains retained element");
1108 }
1109 }
1110
1111 resetFull();
1112 final HashSet<E> set = new HashSet<>(elements);
1113 size = getCollection().size();
1114 assertFalse(getCollection().retainAll(set),
1115 "Collection shouldn't change from retainAll without " + "duplicate elements");
1116 verify();
1117 assertEquals(size, getCollection().size(),
1118 "Collection size didn't change from nonduplicate " + "retainAll");
1119 }
1120
1121
1122
1123
1124 @Test
1125 public void testCollectionSize() {
1126 resetEmpty();
1127 assertEquals(0, getCollection().size(), "Size of new Collection is 0.");
1128
1129 resetFull();
1130 assertFalse(getCollection().isEmpty(), "Size of full collection should be greater than zero");
1131 }
1132
1133
1134
1135
1136 @Test
1137 public void testCollectionToArray() {
1138 resetEmpty();
1139 assertEquals(0, getCollection().toArray().length,
1140 "Empty Collection should return empty array for toArray");
1141
1142 resetFull();
1143 final Object[] array = getCollection().toArray();
1144 assertEquals(array.length, getCollection().size(),
1145 "Full collection toArray should be same size as collection");
1146 final Object[] confirmedArray = getConfirmed().toArray();
1147 assertEquals(confirmedArray.length, array.length, "length of array from confirmed collection should "
1148 + "match the length of the collection's array");
1149 final boolean[] matched = new boolean[array.length];
1150
1151 for (int i = 0; i < array.length; i++) {
1152 assertTrue(getCollection().contains(array[i]),
1153 "Collection should contain element in toArray");
1154
1155 boolean match = false;
1156
1157 for (int j = 0; j < array.length; j++) {
1158
1159 if (matched[j]) {
1160 continue;
1161 }
1162 if (Objects.equals(array[i], confirmedArray[j])) {
1163 matched[j] = true;
1164 match = true;
1165 break;
1166 }
1167 }
1168 if (!match) {
1169 fail("element " + i + " in returned array should be found "
1170 + "in the confirmed collection's array");
1171 }
1172 }
1173 for (final boolean element : matched) {
1174 assertTrue(element, "Collection should return all its elements in " + "toArray");
1175 }
1176 }
1177
1178
1179
1180
1181 @Test
1182 public void testCollectionToArray2() {
1183 resetEmpty();
1184 Object[] a = { new Object(), null, null };
1185 Object[] array = getCollection().toArray(a);
1186 assertEquals(array, a, "Given array shouldn't shrink");
1187 assertNull(a[0], "Last element should be set to null");
1188 verify();
1189
1190 resetFull();
1191 assertThrows(ArrayStoreException.class, () -> getCollection().toArray(new Void[0]),
1192 "toArray(new Void[0]) should raise ArrayStore");
1193 verify();
1194
1195
1196 assertThrows(NullPointerException.class, () -> getCollection().toArray((Object[]) null),
1197 "toArray(null) should raise NPE");
1198 verify();
1199
1200 array = getCollection().toArray(ArrayUtils.EMPTY_OBJECT_ARRAY);
1201 a = getCollection().toArray();
1202
1203 if ((getIterationBehaviour() & UNORDERED) != 0) {
1204 assertUnorderedArrayEquals(array, a, "toArray(Object[]) and toArray()");
1205 } else {
1206 assertEquals(Arrays.asList(array), Arrays.asList(a), "toArrays should be equal");
1207 }
1208
1209
1210 final HashSet<Class<?>> classes = new HashSet<>();
1211 for (final Object element : array) {
1212 classes.add(element == null ? null : element.getClass());
1213 }
1214 if (classes.size() > 1) {
1215 return;
1216 }
1217
1218 Class<?> cl = classes.iterator().next();
1219 if (Map.Entry.class.isAssignableFrom(cl)) {
1220 cl = Map.Entry.class;
1221 }
1222 a = (Object[]) Array.newInstance(cl, 0);
1223 array = getCollection().toArray(a);
1224 assertEquals(a.getClass(), array.getClass(),
1225 "toArray(Object[]) should return correct array type");
1226
1227 if ((getIterationBehaviour() & UNORDERED) != 0) {
1228 assertUnorderedArrayEquals(array, getCollection().toArray(), "type-specific toArray(T[]) and toArray()");
1229 } else {
1230 assertEquals(Arrays.asList(array),
1231 Arrays.asList(getCollection().toArray()),
1232 "type-specific toArrays should be equal");
1233 }
1234 verify();
1235 }
1236
1237
1238
1239
1240 @Test
1241 public void testCollectionToString() {
1242 resetEmpty();
1243 assertNotNull(getCollection().toString(), "toString shouldn't return null");
1244
1245 resetFull();
1246 assertNotNull(getCollection().toString(), "toString shouldn't return null");
1247 }
1248
1249 @Test
1250 @Override
1251 public void testSerializeDeserializeThenCompare() throws Exception {
1252 Object obj = makeObject();
1253 if (obj instanceof Serializable && isTestSerialization()) {
1254 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
1255 final ObjectOutputStream out = new ObjectOutputStream(buffer);
1256 out.writeObject(obj);
1257 out.close();
1258
1259 final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()));
1260 final Object dest = in.readObject();
1261 in.close();
1262 if (isEqualsCheckable()) {
1263 assertEquals(obj, dest, "obj != deserialize(serialize(obj)) - EMPTY Collection");
1264 }
1265 }
1266 obj = makeFullCollection();
1267 if (obj instanceof Serializable && isTestSerialization()) {
1268 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
1269 final ObjectOutputStream out = new ObjectOutputStream(buffer);
1270 out.writeObject(obj);
1271 out.close();
1272
1273 final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()));
1274 final Object dest = in.readObject();
1275 in.close();
1276 if (isEqualsCheckable()) {
1277 assertEquals(obj, dest, "obj != deserialize(serialize(obj)) - FULL Collection");
1278 }
1279 }
1280 }
1281
1282
1283
1284
1285
1286 @Test
1287 public void testUnsupportedAdd() {
1288 if (isAddSupported()) {
1289 return;
1290 }
1291
1292 resetEmpty();
1293 assertThrows(UnsupportedOperationException.class, () -> getCollection().add(getFullNonNullElements()[0]),
1294 "Empty collection should not support add.");
1295
1296
1297 verify();
1298
1299 assertThrows(UnsupportedOperationException.class, () -> getCollection().addAll(Arrays.asList(getFullElements())),
1300 "Empty collection should not support addAll.");
1301
1302
1303 verify();
1304
1305 resetFull();
1306 assertThrows(UnsupportedOperationException.class, () -> getCollection().add(getFullNonNullElements()[0]),
1307 "Full collection should not support add.");
1308
1309
1310 verify();
1311
1312 assertThrows(UnsupportedOperationException.class, () -> getCollection().addAll(Arrays.asList(getOtherElements())),
1313 "Full collection should not support addAll.");
1314
1315
1316 verify();
1317 }
1318
1319
1320
1321
1322
1323 @Test
1324 public void testUnsupportedRemove() {
1325 if (isRemoveSupported()) {
1326 return;
1327 }
1328
1329 resetEmpty();
1330 assertThrows(UnsupportedOperationException.class, () -> getCollection().clear(),
1331 "clear should raise UnsupportedOperationException");
1332 verify();
1333
1334 assertThrows(UnsupportedOperationException.class, () -> getCollection().remove(null),
1335 "remove should raise UnsupportedOperationException");
1336 verify();
1337
1338 assertThrows(UnsupportedOperationException.class, () -> getCollection().removeIf(e -> true),
1339 "removeIf should raise UnsupportedOperationException");
1340 verify();
1341
1342 assertThrows(UnsupportedOperationException.class, () -> getCollection().removeAll(null),
1343 "removeAll should raise UnsupportedOperationException");
1344 verify();
1345
1346 assertThrows(UnsupportedOperationException.class, () -> getCollection().retainAll(null),
1347 "retainAll should raise UnsupportedOperationException");
1348 verify();
1349
1350 resetFull();
1351 final Iterator<E> iterator = getCollection().iterator();
1352 iterator.next();
1353 assertThrows(UnsupportedOperationException.class, () -> iterator.remove(),
1354 "iterator.remove should raise UnsupportedOperationException");
1355 verify();
1356
1357 }
1358
1359
1360
1361
1362
1363 public void verify() {
1364 final int confirmedSize = getConfirmed().size();
1365 assertEquals(confirmedSize, getCollection().size(),
1366 "Collection size should match confirmed collection's");
1367 assertEquals(getConfirmed().isEmpty(), getCollection().isEmpty(),
1368 "Collection isEmpty() result should match confirmed collection's");
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380 final Object[] confirmedValues = new Object[confirmedSize];
1381
1382 Iterator<E> iter;
1383
1384 iter = getConfirmed().iterator();
1385 int pos = 0;
1386 while (iter.hasNext()) {
1387 confirmedValues[pos++] = iter.next();
1388 }
1389
1390
1391
1392 final boolean[] matched = new boolean[confirmedSize];
1393
1394
1395
1396 iter = getCollection().iterator();
1397 while (iter.hasNext()) {
1398 final Object o = iter.next();
1399 boolean match = false;
1400 for (int i = 0; i < confirmedSize; i++) {
1401 if (matched[i]) {
1402
1403 continue;
1404 }
1405 if (Objects.equals(o, confirmedValues[i])) {
1406
1407 matched[i] = true;
1408 match = true;
1409 break;
1410 }
1411 }
1412
1413 if (!match) {
1414 fail("Collection should not contain a value that the "
1415 + "confirmed collection does not have: " + o + "\nTest: " + getCollection()
1416 + "\nReal: " + getConfirmed());
1417 }
1418 }
1419
1420
1421 for (int i = 0; i < confirmedSize; i++) {
1422 if (!matched[i]) {
1423
1424 fail("Collection should contain all values that are in the confirmed collection"
1425 + "\nTest: " + getCollection() + "\nReal: " + getConfirmed());
1426 }
1427 }
1428 }
1429
1430 }