This repository has been archived by the owner on Dec 10, 2022. It is now read-only.
/
TestCollection.java
1079 lines (931 loc) · 36.6 KB
/
TestCollection.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
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
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright 2016 Carlos Ballesteros Velasco
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javatest.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* Tests base {@link java.util.Collection} methods and contracts.
* <p>
* You should create a concrete subclass of this class to test any custom
* {@link Collection} implementation. At minimum, you'll have to
* implement the {@link #makeCollection()} method. You might want to
* override some of the additional protected methods as well:<P>
*
* <B>Element Population Methods</B><P>
*
* Override these if your collection restricts what kind of elements are
* allowed (for instance, if <Code>null</Code> is not permitted):
* <UL>
* <Li>{@link #getFullElements()}
* <Li>{@link #getOtherElements()}
* </UL>
*
* <B>Supported Operation Methods</B><P>
*
* Override these if your collection doesn't support certain operations:
* <UL>
* <LI>{@link #isAddSuppoted()}
* <LI>{@link #isRemoveSupported()}
* <li>{@link #areEqualElementsDistinguishable()}
* </UL>
*
* <B>Fixture Methods</B><P>
*
* Fixtures are used to verify that the operation results in correct state
* for the collection. Basically, the operation is performed against your
* collection implementation, and an identical operation is performed against a
* <I>confirmed</I> collection implementation. A confirmed collection
* implementation is something like <Code>java.util.ArrayList</Code>, which is
* known to conform exactly to its collection interface's contract. After the
* operation takes place on both your collection implementation and the
* confirmed collection implementation, the two collections are compared to see
* if their state is identical. The comparison is usually much more involved
* than a simple <Code>equals</Code> test. This verification is used to ensure
* proper modifications are made along with ensuring that the collection does
* not change when read-only modifications are made.<P>
*
* The {@link #collection} field holds an instance of your collection
* implementation; the {@link #confirmed} field holds an instance of the
* confirmed collection implementation. The {@link #resetEmpty()} and
* {@link #resetFull()} methods set these fields to empty or full collections,
* so that tests can proceed from a known state.<P>
*
* After a modification operation to both {@link #collection} and
* {@link #confirmed}, the {@link #verify()} method is invoked to compare
* the results. You may want to override {@link #verify()} to perform
* additional verifications. For instance, when testing the collection
* views of a map, {@link TestMap} would override {@link #verify()} to make
* sure the map is changed after the collection view is changed.
*
* If you're extending this class directly, you will have to provide
* implementations for the following:
* <UL>
* <LI>{@link #makeConfirmedCollection()}
* <LI>{@link #makeConfirmedFullCollection()}
* </UL>
*
* Those methods should provide a confirmed collection implementation
* that's compatible with your collection implementation.<P>
*
* If you're extending {@link TestList}, {@link TestSet},
* or {@link TestBag}, you probably don't have to worry about the
* above methods, because those three classes already override the methods
* to provide standard JDK confirmed collections.<P>
*
* <B>Other notes</B><P>
*
* If your {@link Collection} fails one of these tests by design,
* you may still use this base set of cases. Simply override the
* test case (method) your {@link Collection} fails. For instance, the
* {@link #testIteratorFailFast()} method is provided since most collections
* have fail-fast iterators; however, that's not strictly required by the
* collection contract, so you may want to override that method to do
* nothing.<P>
*
* @author Rodney Waldhoff
* @author Paul Jack
* @author <a href="mailto:mas@apache.org">Michael A. Smith</a>
* @version $Id: TestCollection.java,v 1.9.2.1 2004/05/22 12:14:05 scolebourne Exp $
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public abstract class TestCollection extends TestObject {
//
// NOTE:
//
// Collection doesn't define any semantics for equals, and recommends you
// use reference-based default behavior of Object.equals. (And a test for
// that already exists in TestObject). Tests for equality of lists, sets
// and bags will have to be written in test subclasses. Thus, there is no
// tests on Collection.equals nor any for Collection.hashCode.
//
// These fields are used by reset() and verify(), and any test
// method that tests a modification.
/**
* A collection instance that will be used for testing.
*/
protected Collection collection;
/**
* Confirmed collection. This is an instance of a collection that is
* confirmed to conform exactly to the java.util.Collection contract.
* Modification operations are tested by performing a mod on your
* collection, performing the exact same mod on an equivalent confirmed
* collection, and then calling verify() to make sure your collection
* still matches the confirmed collection.
*/
protected Collection confirmed;
/**
* Resets the {@link #collection} and {@link #confirmed} fields to empty
* collections. Invoke this method before performing a modification
* test.
*/
protected void resetEmpty() {
this.collection = makeCollection();
this.confirmed = makeConfirmedCollection();
}
/**
* Resets the {@link #collection} and {@link #confirmed} fields to full
* collections. Invoke this method before performing a modification
* test.
*/
protected void resetFull() {
this.collection = makeFullCollection();
this.confirmed = makeConfirmedFullCollection();
}
/**
* Specifies whether equal elements in the collection are, in fact,
* distinguishable with information not readily available. That is, if a
* particular value is to be removed from the collection, then there is
* one and only one value that can be removed, even if there are other
* elements which are equal to it.
*
* <P>In most collection cases, elements are not distinguishable (equal is
* equal), thus this method defaults to return false. In some cases,
* however, they are. For example, the collection returned from the map's
* values() collection view are backed by the map, so while there may be
* two values that are equal, their associated keys are not. Since the
* keys are distinguishable, the values are.
*
* <P>This flag is used to skip some verifications for iterator.remove()
* where it is impossible to perform an equivalent modification on the
* confirmed collection because it is not possible to determine which
* value in the confirmed collection to actually remove. Tests that
* override the default (i.e. where equal elements are distinguishable),
* should provide additional tests on iterator.remove() to make sure the
* proper elements are removed when remove() is called on the iterator.
**/
protected boolean areEqualElementsDistinguishable() {
return false;
}
/**
* Verifies that {@link #collection} and {@link #confirmed} have
* identical state.
*/
protected void verify() {
int confirmedSize = confirmed.size();
assertEquals("Collection size should match confirmed collection's",
confirmedSize, collection.size());
assertEquals("Collection isEmpty() result should match confirmed " +
" collection's",
confirmed.isEmpty(), collection.isEmpty());
// verify the collections are the same by attempting to match each
// object in the collection and confirmed collection. To account for
// duplicates and differing orders, each confirmed element is copied
// into an array and a flag is maintained for each element to determine
// whether it has been matched once and only once. If all elements in
// the confirmed collection are matched once and only once and there
// aren't any elements left to be matched in the collection,
// verification is a success.
// copy each collection value into an array
Object[] confirmedValues = new Object[confirmedSize];
Iterator iter;
iter = confirmed.iterator();
int pos = 0;
while(iter.hasNext()) {
confirmedValues[pos++] = iter.next();
}
// allocate an array of boolean flags for tracking values that have
// been matched once and only once.
boolean[] matched = new boolean[confirmedSize];
// now iterate through the values of the collection and try to match
// the value with one in the confirmed array.
iter = collection.iterator();
while(iter.hasNext()) {
Object o = iter.next();
boolean match = false;
for(int i = 0; i < confirmedSize; i++) {
if(matched[i]) {
// skip values already matched
continue;
}
if(o == confirmedValues[i] ||
(o != null && o.equals(confirmedValues[i]))) {
// values matched
matched[i] = true;
match = true;
break;
}
}
// no match found!
if(!match) {
fail("Collection should not contain a value that the " +
"confirmed collection does not have.");
}
}
// make sure there aren't any unmatched values
for(int i = 0; i < confirmedSize; i++) {
if(!matched[i]) {
// the collection didn't match all the confirmed values
fail("Collection should contain all values that are in the " +
"confirmed collection");
}
}
}
/**
* Returns a confirmed empty collection.
* For instance, a {@link java.util.ArrayList} for lists or a
* {@link java.util.HashSet} for sets.
*
* @return a confirmed empty collection
*/
protected abstract Collection makeConfirmedCollection();
/**
* Returns a confirmed full collection.
* For instance, a {@link java.util.ArrayList} for lists or a
* {@link java.util.HashSet} for sets. The returned collection
* should contain the elements returned by {@link #getFullElements()}.
*
* @return a confirmed full collection
*/
protected abstract Collection makeConfirmedFullCollection();
/**
* Returns true if the collections produced by
* {@link #makeCollection()} and {@link #makeFullCollection()}
* support the <Code>add</Code> and <Code>addAll</Code>
* operations.<P>
* Default implementation returns true. Override if your collection
* class does not support add or addAll.
*/
protected boolean isAddSupported() {
return true;
}
/**
* Returns true if the collections produced by
* {@link #makeCollection()} and {@link #makeFullCollection()}
* support the <Code>remove</Code>, <Code>removeAll</Code>,
* <Code>retainAll</Code>, <Code>clear</Code> and
* <Code>iterator().remove()</Code> methods.
* Default implementation returns true. Override if your collection
* class does not support removal operations.
*/
protected boolean isRemoveSupported() {
return true;
}
/**
* Returns an array of objects that are contained in a collection
* produced by {@link #makeFullCollection()}. Every element in the
* returned array <I>must</I> be an element in a full collection.<P>
* The default implementation returns a heterogenous array of
* objects with some duplicates and with the null element.
* Override if you require specific testing elements. Note that if you
* override {@link #makeFullCollection()}, you <I>must</I> override
* this method to reflect the contents of a full collection.
*/
protected Object[] getFullElements() {
ArrayList list = new ArrayList();
list.addAll(Arrays.asList(getFullNonNullElements()));
list.add(4, null);
return list.toArray();
}
/**
* Returns an array of elements that are <I>not</I> contained in a
* full collection. Every element in the returned array must
* not exist in a collection returned by {@link #makeFullCollection()}.
* The default implementation returns a heterogenous array of elements
* without null. Note that some of the tests add these elements
* to an empty or full collection, so if your collection restricts
* certain kinds of elements, you should override this method.
*/
protected Object[] getOtherElements() {
return getOtherNonNullElements();
}
/**
* Returns a new, empty {@link Collection} to be used for testing.
*/
protected abstract Collection makeCollection();
/**
* Returns a full collection to be used for testing. The collection
* returned by this method should contain every element returned by
* {@link #getFullElements()}. The default implementation, in fact,
* simply invokes <Code>addAll</Code> on an empty collection with
* the results of {@link #getFullElements()}. Override this default
* if your collection doesn't support addAll.
*/
protected Collection makeFullCollection() {
Collection c = makeCollection();
c.addAll(Arrays.asList(getFullElements()));
return c;
}
/**
* Returns an empty collection for Object tests.
*/
@Override
public Object makeObject() {
return makeCollection();
}
/**
* Tests {@link Collection#add(Object)}.
*/
public void testCollectionAdd() {
if (!isAddSupported()) return;
Object[] elements = getFullElements();
for (int i = 0; i < elements.length; i++) {
resetEmpty();
boolean r = collection.add(elements[i]);
confirmed.add(elements[i]);
verify();
assertTrue("Empty collection changed after add", r);
assertTrue("Collection size is 1 after first add",
collection.size() == 1);
}
resetEmpty();
int size = 0;
for (int i = 0; i < elements.length; i++) {
boolean r = collection.add(elements[i]);
confirmed.add(elements[i]);
verify();
if (r) size++;
assertEquals("Collection size should grow after add",
size, collection.size());
assertTrue("Collection should contain added element",
collection.contains(elements[i]));
}
}
/**
* Tests {@link Collection#addAll(Collection)}.
*/
public void testCollectionAddAll() {
if (!isAddSupported()) return;
resetEmpty();
Object[] elements = getFullElements();
boolean r = collection.addAll(Arrays.asList(elements));
confirmed.addAll(Arrays.asList(elements));
verify();
assertTrue("Empty collection should change after addAll", r);
for (int i = 0; i < elements.length; i++) {
assertTrue("Collection should contain added element",
collection.contains(elements[i]));
}
resetFull();
int size = collection.size();
elements = getOtherElements();
r = collection.addAll(Arrays.asList(elements));
confirmed.addAll(Arrays.asList(elements));
verify();
assertTrue("Full collection should change after addAll", r);
for (int i = 0; i < elements.length; i++) {
assertTrue("Full collection should contain added element",
collection.contains(elements[i]));
}
assertEquals("Size should increase after addAll",
size + elements.length, collection.size());
resetFull();
size = collection.size();
r = collection.addAll(Arrays.asList(getFullElements()));
confirmed.addAll(Arrays.asList(getFullElements()));
verify();
if (r) {
assertTrue("Size should increase if addAll returns true",
size < collection.size());
} else {
assertEquals("Size should not change if addAll returns false",
size, collection.size());
}
}
/**
* If {@link #isAddSupported()} returns false, tests that add operations
* raise <Code>UnsupportedOperationException.
*/
public void testUnsupportedAdd() {
if (isAddSupported()) return;
resetEmpty();
try {
collection.add(new Object());
fail("Emtpy collection should not support add.");
} catch (UnsupportedOperationException e) {
// expected
}
// make sure things didn't change even if the expected exception was
// thrown.
verify();
try {
collection.addAll(Arrays.asList(getFullElements()));
fail("Emtpy collection should not support addAll.");
} catch (UnsupportedOperationException e) {
// expected
}
// make sure things didn't change even if the expected exception was
// thrown.
verify();
resetFull();
try {
collection.add(new Object());
fail("Full collection should not support add.");
} catch (UnsupportedOperationException e) {
// expected
}
// make sure things didn't change even if the expected exception was
// thrown.
verify();
try {
collection.addAll(Arrays.asList(getOtherElements()));
fail("Full collection should not support addAll.");
} catch (UnsupportedOperationException e) {
// expected
}
// make sure things didn't change even if the expected exception was
// thrown.
verify();
}
/**
* Test {@link Collection#clear()}.
*/
public void testCollectionClear() {
if (!isRemoveSupported()) return;
resetEmpty();
collection.clear(); // just to make sure it doesn't raise anything
verify();
resetFull();
collection.clear();
confirmed.clear();
verify();
}
/**
* Tests {@link Collection#contains(Object)}.
*/
public void testCollectionContains() {
Object[] elements;
resetEmpty();
elements = getFullElements();
for(int i = 0; i < elements.length; i++) {
assertTrue("Empty collection shouldn'y contain element",
!collection.contains(elements[i]));
}
// make sure calls to "contains" don't change anything
verify();
elements = getOtherElements();
for(int i = 0; i < elements.length; i++) {
assertTrue("Empty collection shouldn'y contain element",
!collection.contains(elements[i]));
}
// make sure calls to "contains" don't change anything
verify();
resetFull();
elements = getFullElements();
for(int i = 0; i < elements.length; i++) {
assertTrue("Full collection should contain element.",
collection.contains(elements[i]));
}
// make sure calls to "contains" don't change anything
verify();
resetFull();
elements = getOtherElements();
for(int i = 0; i < elements.length; i++) {
assertTrue("Full collection shouldn't contain element",
!collection.contains(elements[i]));
}
}
/**
* Tests {@link Collection#containsAll(Collection)}.
*/
@SuppressWarnings("ModifyingCollectionWithItself")
public void testCollectionContainsAll() {
resetEmpty();
Collection col = new HashSet();
assertTrue("Every Collection should contain all elements of an " +
"empty Collection.", collection.containsAll(col));
col.addAll(Arrays.asList(getOtherElements()));
assertTrue("Empty Collection shouldn't contain all elements of " +
"a non-empty Collection.", !collection.containsAll(col));
// make sure calls to "containsAll" don't change anything
verify();
resetFull();
assertTrue("Full collection shouldn't contain other elements",
!collection.containsAll(col));
col.clear();
col.addAll(Arrays.asList(getFullElements()));
assertTrue("Full collection should containAll full elements",
collection.containsAll(col));
// make sure calls to "containsAll" don't change anything
verify();
assertTrue("Full collection should containAll itself",
collection.containsAll(collection));
// make sure calls to "containsAll" don't change anything
verify();
col = new ArrayList();
col.addAll(Arrays.asList(getFullElements()));
col.addAll(Arrays.asList(getFullElements()));
assertTrue("Full collection should containAll duplicate full " +
"elements", collection.containsAll(col));
// make sure calls to "containsAll" don't change anything
verify();
}
/**
* Tests {@link Collection#isEmpty()}.
*/
public void testCollectionIsEmpty() {
resetEmpty();
assertEquals("New Collection should be empty.",
true, collection.isEmpty());
// make sure calls to "isEmpty() don't change anything
verify();
resetFull();
assertEquals("Full collection shouldn't be empty",
false, collection.isEmpty());
// make sure calls to "isEmpty() don't change anything
verify();
}
/**
* Tests the read-only functionality of {@link Collection#iterator()}.
*/
public void testCollectionIterator() {
resetEmpty();
Iterator it1 = collection.iterator();
assertEquals("Iterator for empty Collection shouldn't have next.",
false, it1.hasNext());
try {
it1.next();
fail("Iterator at end of Collection should throw " +
"NoSuchElementException when next is called.");
} catch(NoSuchElementException e) {
// expected
}
// make sure nothing has changed after non-modification
verify();
resetFull();
it1 = collection.iterator();
for (int i = 0; i < collection.size(); i++) {
assertTrue("Iterator for full collection should haveNext",
it1.hasNext());
it1.next();
}
assertTrue("Iterator should be finished", !it1.hasNext());
ArrayList list = new ArrayList();
it1 = collection.iterator();
for (int i = 0; i < collection.size(); i++) {
Object next = it1.next();
assertTrue("Collection should contain element returned by " +
"its iterator", collection.contains(next));
list.add(next);
}
try {
it1.next();
fail("iterator.next() should raise NoSuchElementException " +
"after it finishes");
} catch (NoSuchElementException e) {
// expected
}
// make sure nothing has changed after non-modification
verify();
}
/**
* Tests removals from {@link Collection#iterator()}.
*/
public void testCollectionIteratorRemove() {
if (!isRemoveSupported()) return;
resetEmpty();
try {
collection.iterator().remove();
fail("New iterator.remove should raise IllegalState");
} catch (IllegalStateException e) {
// expected
}
verify();
try {
Iterator iter = collection.iterator();
iter.hasNext();
iter.remove();
fail("New iterator.remove should raise IllegalState " +
"even after hasNext");
} catch (IllegalStateException e) {
// expected
}
verify();
resetFull();
int size = collection.size();
Iterator iter = collection.iterator();
while (iter.hasNext()) {
Object o = iter.next();
iter.remove();
// if the elements aren't distinguishable, we can just remove a
// matching element from the confirmed collection and verify
// contents are still the same. Otherwise, we don't have the
// ability to distinguish the elements and determine which to
// remove from the confirmed collection (in which case, we don't
// verify because we don't know how).
//
// see areEqualElementsDistinguishable()
if(!areEqualElementsDistinguishable()) {
confirmed.remove(o);
verify();
}
size--;
assertEquals("Collection should shrink by one after " +
"iterator.remove", size, collection.size());
}
assertTrue("Collection should be empty after iterator purge",
collection.isEmpty());
resetFull();
iter = collection.iterator();
iter.next();
iter.remove();
try {
iter.remove();
fail("Second iter.remove should raise IllegalState");
} catch (IllegalStateException e) {
// expected
}
}
/**
* Tests {@link Collection#remove(Object)}.
*/
public void testCollectionRemove() {
if (!isRemoveSupported()) return;
resetEmpty();
Object[] elements = getFullElements();
for (int i = 0; i < elements.length; i++) {
assertTrue("Shouldn't remove nonexistent element",
!collection.remove(elements[i]));
verify();
}
Object[] other = getOtherElements();
resetFull();
for (int i = 0; i < other.length; i++) {
assertTrue("Shouldn't remove nonexistent other element",
!collection.remove(other[i]));
verify();
}
int size = collection.size();
for (int i = 0; i < elements.length; i++) {
resetFull();
assertTrue("Collection should remove extant element",
collection.remove(elements[i]));
// if the elements aren't distinguishable, we can just remove a
// matching element from the confirmed collection and verify
// contents are still the same. Otherwise, we don't have the
// ability to distinguish the elements and determine which to
// remove from the confirmed collection (in which case, we don't
// verify because we don't know how).
//
// see areEqualElementsDistinguishable()
if(!areEqualElementsDistinguishable()) {
confirmed.remove(elements[i]);
verify();
}
assertEquals("Collection should shrink after remove",
size - 1, collection.size());
}
}
/**
* Tests {@link Collection#removeAll(Collection)}.
*/
public void testCollectionRemoveAll() {
if (!isRemoveSupported()) return;
resetEmpty();
assertTrue("Emtpy collection removeAll should return false for " +
"empty input",
!collection.removeAll(Collections.EMPTY_SET));
verify();
assertTrue("Emtpy collection removeAll should return false for " +
"nonempty input",
!collection.removeAll(new ArrayList(collection)));
verify();
resetFull();
assertTrue("Full collection removeAll should return false for " +
"empty input",
!collection.removeAll(Collections.EMPTY_SET));
verify();
assertTrue("Full collection removeAll should return false for " +
"other elements",
!collection.removeAll(Arrays.asList(getOtherElements())));
verify();
assertTrue("Full collection removeAll should return true for " +
"full elements",
collection.removeAll(new HashSet(collection)));
confirmed.removeAll(new HashSet(confirmed));
verify();
resetFull();
int size = collection.size();
Object[] s = getFullElements();
List l = new ArrayList();
l.add(s[2]); l.add(s[3]); l.add(s[3]);
assertTrue("Full collection removeAll should work",
collection.removeAll(l));
confirmed.removeAll(l);
verify();
assertTrue("Collection should shrink after removeAll",
collection.size() < size);
Iterator iter = l.iterator();
while (iter.hasNext()) {
assertTrue("Collection shouldn't contain removed element",
!collection.contains(iter.next()));
}
}
/**
* Tests {@link Collection#retainAll(Collection)}.
*/
public void testCollectionRetainAll() {
if (!isRemoveSupported()) return;
resetEmpty();
List elements = Arrays.asList(getFullElements());
List other = Arrays.asList(getOtherElements());
Set empty = new HashSet();
assertTrue("Empty retainAll() should return false",
!collection.retainAll(empty));
verify();
assertTrue("Empty retainAll() should return false",
!collection.retainAll(elements));
verify();
resetFull();
assertTrue("Collection should change from retainAll empty",
collection.retainAll(empty));
confirmed.retainAll(empty);
verify();
resetFull();
assertTrue("Collection changed from retainAll other",
collection.retainAll(other));
confirmed.retainAll(other);
verify();
resetFull();
int size = collection.size();
assertTrue("Collection shouldn't change from retainAll elements",
!collection.retainAll(elements));
verify();
assertEquals("Collection size shouldn't change", size,
collection.size());
resetFull();
HashSet set = new HashSet(elements);
size = collection.size();
assertTrue("Collection shouldn't change from retainAll without " +
"duplicate elements", !collection.retainAll(set));
verify();
assertEquals("Collection size didn't change from nonduplicate " +
"retainAll", size, collection.size());
}
/**
* Tests {@link Collection#size()}.
*/
public void testCollectionSize() {
resetEmpty();
assertEquals("Size of new Collection is 0.", 0, collection.size());
resetFull();
assertTrue("Size of full collection should be greater than zero",
collection.size() > 0);
}
/**
* Tests <Code>toString</Code> on a collection.
*/
public void testCollectionToString() {
resetEmpty();
assertTrue("toString shouldn't return null",
collection.toString() != null);
resetFull();
assertTrue("toString shouldn't return null",
collection.toString() != null);
}
/**
* If isRemoveSupported() returns false, tests to see that remove
* operations raise an UnsupportedOperationException.
*/
public void testUnsupportedRemove() {
if (isRemoveSupported()) return;
resetEmpty();
try {
collection.clear();
fail("clear should raise UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// expected
}
verify();
try {
collection.remove(null);
fail("remove should raise UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// expected
}
verify();
try {
collection.removeAll(null);
fail("removeAll should raise UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// expected
}
verify();
try {
collection.retainAll(null);
fail("removeAll should raise UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// expected
}
verify();
resetFull();
try {
Iterator iterator = collection.iterator();
iterator.next();
iterator.remove();
fail("iterator.remove should raise UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// expected
}
verify();
}
/**
* Returns a list of elements suitable for return by
* {@link #getFullElements()}. The array returned by this method
* does not include null, but does include a variety of objects
* of different types. Override getFullElements to return
* the results of this method if your collection does not support
* the null element.
*/
public static Object[] getFullNonNullElements() {
return new Object[] {
new String(""),
new String("One"),
new Integer(2),
"Three",
new Integer(4),
"One",
new Double(5),
new Float(6),
"Seven",
"Eight",