View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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   * Tests {@link java.util.Collection}.
54   * <p>
55   * You should create a concrete subclass of this class to test any custom
56   * {@link Collection} implementation.  At minimum, you'll have to
57   * implement the {@link #makeObject()}, {@link #makeConfirmedCollection()}
58   * and {@link #makeConfirmedFullCollection()} methods.
59   * You might want to override some of the additional public methods as well:
60   * <p>
61   * <strong>Element Population Methods</strong>
62   * <p>
63   * Override these if your collection restricts what kind of elements are
64   * allowed (for instance, if {@code null} is not permitted):
65   * <ul>
66   * <li>{@link #getFullElements()}
67   * <li>{@link #getOtherElements()}
68   * </ul>
69   * <p>
70   * <strong>Supported Operation Methods</strong>
71   * <p>
72   * Override these if your collection doesn't support certain operations:
73   * <ul>
74   * <li>{@link #isAddSupported()}
75   * <li>{@link #isRemoveSupported()}
76   * <li>{@link #areEqualElementsDistinguishable()}
77   * <li>{@link #isNullSupported()}
78   * <li>{@link #isFailFastSupported()}
79   * </ul>
80   * <p>
81   * <strong>Indicate Collection Behaviour</strong>
82   * <p>
83   * Override these if your collection makes specific behavior guarantees:
84   * <ul>
85   * <li>{@link #getIterationBehaviour()}</li>
86   * </ul>
87   * <p>
88   * <strong>Fixture Methods</strong>
89   * <p>
90   * Fixtures are used to verify that the operation results in correct state
91   * for the collection.  Basically, the operation is performed against your
92   * collection implementation, and an identical operation is performed against a
93   * <em>confirmed</em> collection implementation.  A confirmed collection
94   * implementation is something like {@link java.util.ArrayList}, which is
95   * known to conform exactly to its collection interface's contract.  After the
96   * operation takes place on both your collection implementation and the
97   * confirmed collection implementation, the two collections are compared to see
98   * if their state is identical.  The comparison is usually much more involved
99   * than a simple {@code equals} test.  This verification is used to ensure
100  * proper modifications are made along with ensuring that the collection does
101  * not change when read-only modifications are made.
102  * <p>
103  * The {@link #collection} field holds an instance of your collection
104  * implementation; the {@link #confirmed} field holds an instance of the
105  * confirmed collection implementation.  The {@link #resetEmpty()} and
106  * {@link #resetFull()} methods set these fields to empty or full collections,
107  * so that tests can proceed from a known state.
108  * <p>
109  * After a modification operation to both {@link #collection} and
110  * {@link #confirmed}, the {@link #verify()} method is invoked to compare
111  * the results.  You may want to override {@link #verify()} to perform
112  * additional verifications.  For instance, when testing the collection
113  * views of a map, {@link org.apache.commons.collections4.map.AbstractMapTest AbstractTestMap}
114  * would override {@link #verify()} to make
115  * sure the map is changed after the collection view is changed.
116  * <p>
117  * If you're extending this class directly, you will have to provide
118  * implementations for the following:
119  * <ul>
120  * <li>{@link #makeConfirmedCollection()}
121  * <li>{@link #makeConfirmedFullCollection()}
122  * </ul>
123  * <p>
124  * Those methods should provide a confirmed collection implementation
125  * that's compatible with your collection implementation.
126  * <p>
127  * If you're extending {@link org.apache.commons.collections4.list.AbstractListTest AbstractListTest},
128  * {@link org.apache.commons.collections4.set.AbstractSetTest AbstractTestSet},
129  * or {@link org.apache.commons.collections4.bag.AbstractBagTest AbstractBagTest},
130  * you probably don't have to worry about the
131  * above methods, because those three classes already override the methods
132  * to provide standard JDK confirmed collections.<P>
133  * <p>
134  * <strong>Other notes</strong>
135  * <p>
136  * If your {@link Collection} fails one of these tests by design,
137  * you may still use this base set of cases.  Simply override the
138  * test case (method) your {@link Collection} fails.
139  */
140 public abstract class AbstractCollectionTest<E> extends AbstractObjectTest {
141 
142     //
143     // NOTE:
144     //
145     // Collection doesn't define any semantics for equals, and recommends you
146     // use reference-based default behavior of Object.equals.  (And a test for
147     // that already exists in AbstractTestObject).  Tests for equality of lists, sets
148     // and bags will have to be written in test subclasses.  Thus, there is no
149     // tests on Collection.equals nor any for Collection.hashCode.
150     //
151 
152     /**
153      * Flag to indicate the collection makes no ordering guarantees for the iterator. If this is not used
154      * then the behavior is assumed to be ordered and the output order of the iterator is matched by
155      * the toArray method.
156      */
157     public static final int UNORDERED = 0x1;
158 
159     // These fields are used by reset() and verify(), and any test
160     // method that tests a modification.
161 
162     /**
163      * Handle the optional exceptions declared by {@link Collection#contains(Object)}
164      * @param coll
165      * @param element
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             //apparently not
172         }
173     }
174 
175     /**
176      * Handle the optional exceptions declared by {@link Collection#containsAll(Collection)}
177      * @param coll
178      * @param sub
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             //apparently not
185         }
186     }
187 
188     /**
189      * Handle optional exceptions of {@link Collection#removeAll(Collection)}
190      * @param coll
191      * @param sub
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             //apparently not
198         }
199     }
200 
201     /**
202      * Handle optional exceptions of {@link Collection#remove(Object)}
203      * @param coll
204      * @param element
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             //apparently not
211         }
212     }
213 
214     /**
215      * Assert the arrays contain the same elements, ignoring the order.
216      *
217      * <p>Note this does not test the arrays are deeply equal. Array elements are compared
218      * using {@link Object#equals(Object)}.
219      *
220      * @param a1 First array
221      * @param a2 Second array
222      * @param msg Failure message prefix
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         // Track values that have been matched once (and only once)
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                     // skip values already matched
234                     continue;
235                 }
236                 if (Objects.equals(o, a2[i])) {
237                     // values matched
238                     matched[i] = true;
239                     // continue to the outer loop
240                     continue NEXT_OBJECT;
241                 }
242             }
243             fail(msg + ": array 2 does not have object: " + o);
244         }
245     }
246 
247     /**
248      *  A collection instance that will be used for testing.
249      */
250     private Collection<E> collection;
251 
252     /**
253      *  Confirmed collection.  This is an instance of a collection that is
254      *  confirmed to conform exactly to the java.util.Collection contract.
255      *  Modification operations are tested by performing a mod on your
256      *  collection, performing the exact same mod on an equivalent confirmed
257      *  collection, and then calling verify() to make sure your collection
258      *  still matches the confirmed collection.
259      */
260     private Collection<E> confirmed;
261 
262     /**
263      *  Specifies whether equal elements in the collection are, in fact,
264      *  distinguishable with information not readily available.  That is, if a
265      *  particular value is to be removed from the collection, then there is
266      *  one and only one value that can be removed, even if there are other
267      *  elements which are equal to it.
268      *
269      *  <P>In most collection cases, elements are not distinguishable (equal is
270      *  equal), thus this method defaults to return false.  In some cases,
271      *  however, they are.  For example, the collection returned from the map's
272      *  values() collection view are backed by the map, so while there may be
273      *  two values that are equal, their associated keys are not.  Since the
274      *  keys are distinguishable, the values are.
275      *
276      *  <P>This flag is used to skip some verifications for iterator.remove()
277      *  where it is impossible to perform an equivalent modification on the
278      *  confirmed collection because it is not possible to determine which
279      *  value in the confirmed collection to actually remove.  Tests that
280      *  override the default (i.e. where equal elements are distinguishable),
281      *  should provide additional tests on iterator.remove() to make sure the
282      *  proper elements are removed when remove() is called on the iterator.
283      **/
284     public boolean areEqualElementsDistinguishable() {
285         return false;
286     }
287 
288     /**
289      * Creates a new Map Entry that is independent of the first and the map.
290      */
291     public Map.Entry<E, E> cloneMapEntry(final Map.Entry<E, E> entry) {
292         final HashMap<E, E> map = new HashMap<>();
293         map.put(entry.getKey(), entry.getValue());
294         return map.entrySet().iterator().next();
295     }
296 
297     public Collection<E> getCollection() {
298         return collection;
299     }
300 
301     public Collection<E> getConfirmed() {
302         return confirmed;
303     }
304 
305     /**
306      *  Returns an array of objects that are contained in a collection
307      *  produced by {@link #makeFullCollection()}.  Every element in the
308      *  returned array <em>must</em> be an element in a full collection.<P>
309      *  The default implementation returns a heterogeneous array of
310      *  objects with some duplicates. null is added if allowed.
311      *  Override if you require specific testing elements.  Note that if you
312      *  override {@link #makeFullCollection()}, you <em>must</em> override
313      *  this method to reflect the contents of a full collection.
314      */
315     @SuppressWarnings("unchecked")
316     public E[] getFullElements() {
317         if (isNullSupported()) {
318             final ArrayList<E> list = new ArrayList<>(Arrays.asList(getFullNonNullElements()));
319             list.add(4, null);
320             return (E[]) list.toArray();
321         }
322         return getFullNonNullElements().clone();
323     }
324 
325     /**
326      *  Returns a list of elements suitable for return by
327      *  {@link #getFullElements()}.  The array returned by this method
328      *  does not include null, but does include a variety of objects
329      *  of different types.  Override getFullElements to return
330      *  the results of this method if your collection does not support
331      *  the null element.
332      */
333     @SuppressWarnings("unchecked")
334     public E[] getFullNonNullElements() {
335         return (E[]) new Object[] {
336             StringUtils.EMPTY,
337             "One",
338             Integer.valueOf(2),
339             "Three",
340             Integer.valueOf(4),
341             "One",
342             Double.valueOf(5),
343             Float.valueOf(6),
344             "Seven",
345             "Eight",
346             "Nine",
347             Integer.valueOf(10),
348             Short.valueOf((short) 11),
349             Long.valueOf(12),
350             "Thirteen",
351             "14",
352             "15",
353             Byte.valueOf((byte) 16)
354         };
355     }
356 
357     /**
358      *  Returns a list of string elements suitable for return by
359      *  {@link #getFullElements()}.  Override getFullElements to return
360      *  the results of this method if your collection does not support
361      *  heterogeneous elements or the null element.
362      */
363     public Object[] getFullNonNullStringElements() {
364         return new Object[] {
365             "If", "the", "dull", "substance", "of", "my", "flesh", "were",
366             "thought", "Injurious", "distance", "could", "not", "stop", "my", "way",
367         };
368     }
369 
370     /**
371      * Return a flag specifying the iteration behavior of the collection.
372      * This is used to change the assertions used by specific tests.
373      * The default implementation returns 0 which indicates ordered iteration behavior.
374      *
375      * @return the iteration behavior
376      * @see #UNORDERED
377      */
378     protected int getIterationBehaviour() {
379         return 0;
380     }
381 
382     /**
383      *  Returns an array of elements that are <em>not</em> contained in a
384      *  full collection.  Every element in the returned array must
385      *  not exist in a collection returned by {@link #makeFullCollection()}.
386      *  The default implementation returns a heterogeneous array of elements
387      *  without null.  Note that some of the tests add these elements
388      *  to an empty or full collection, so if your collection restricts
389      *  certain kinds of elements, you should override this method.
390      */
391     public E[] getOtherElements() {
392         return getOtherNonNullElements();
393     }
394 
395     /**
396      *  Returns the default list of objects returned by
397      *  {@link #getOtherElements()}.  Includes many objects
398      *  of different types.
399      */
400     @SuppressWarnings("unchecked")
401     public E[] getOtherNonNullElements() {
402         return (E[]) new Object[] {
403             Integer.valueOf(0),
404             Float.valueOf(0),
405             Double.valueOf(0),
406             "Zero",
407             Short.valueOf((short) 0),
408             Byte.valueOf((byte) 0),
409             Long.valueOf(0),
410             Character.valueOf('\u0000'),
411             "0"
412         };
413     }
414 
415     /**
416      *  Returns a list of string elements suitable for return by
417      *  {@link #getOtherElements()}.  Override getOtherElements to return
418      *  the results of this method if your collection does not support
419      *  heterogeneous elements or the null element.
420      */
421     public Object[] getOtherNonNullStringElements() {
422         return new Object[] {
423             "For", "then", "despite", /* of */"space", "I", "would", "be",
424             "brought", "From", "limits", "far", "remote", "where", "thou", "dost", "stay"
425         };
426     }
427 
428     /**
429      *  Returns true if the collections produced by
430      *  {@link #makeObject()} and {@link #makeFullCollection()}
431      *  support the {@code add} and {@code addAll}
432      *  operations.<P>
433      *  Default implementation returns true.  Override if your collection
434      *  class does not support add or addAll.
435      */
436     public boolean isAddSupported() {
437         return true;
438     }
439 
440     /**
441      * Returns true to indicate that the collection supports equals() comparisons.
442      * This implementation returns false;
443      */
444     @Override
445     public boolean isEqualsCheckable() {
446         return false;
447     }
448 
449     /**
450      * Returns true to indicate that the collection supports fail fast iterators.
451      * The default implementation returns true;
452      */
453     public boolean isFailFastSupported() {
454         return false;
455     }
456 
457     /**
458      * Returns true to indicate that the collection supports holding null.
459      * The default implementation returns true;
460      */
461     public boolean isNullSupported() {
462         return true;
463     }
464 
465     /**
466      *  Returns true if the collections produced by
467      *  {@link #makeObject()} and {@link #makeFullCollection()}
468      *  support the {@code remove}, {@code removeAll},
469      *  {@code retainAll}, {@code clear} and
470      *  {@code iterator().remove()} methods.
471      *  Default implementation returns true.  Override if your collection
472      *  class does not support removal operations.
473      */
474     public boolean isRemoveSupported() {
475         return true;
476     }
477 
478     /**
479      *  Returns a confirmed empty collection.
480      *  For instance, an {@link java.util.ArrayList} for lists or a
481      *  {@link java.util.HashSet} for sets.
482      *
483      *  @return a confirmed empty collection
484      */
485     public abstract Collection<E> makeConfirmedCollection();
486 
487     /**
488      *  Returns a confirmed full collection.
489      *  For instance, an {@link java.util.ArrayList} for lists or a
490      *  {@link java.util.HashSet} for sets.  The returned collection
491      *  should contain the elements returned by {@link #getFullElements()}.
492      *
493      *  @return a confirmed full collection
494      */
495     public abstract Collection<E> makeConfirmedFullCollection();
496 
497     /**
498      *  Returns a full collection to be used for testing.  The collection
499      *  returned by this method should contain every element returned by
500      *  {@link #getFullElements()}.  The default implementation, in fact,
501      *  simply invokes {@code addAll} on an empty collection with
502      *  the results of {@link #getFullElements()}.  Override this default
503      *  if your collection doesn't support addAll.
504      */
505     public Collection<E> makeFullCollection() {
506         final Collection<E> c = makeObject();
507         c.addAll(Arrays.asList(getFullElements()));
508         return c;
509     }
510 
511     /**
512      * Return a new, empty {@link Collection} to be used for testing.
513      */
514     @Override
515     public abstract Collection<E> makeObject();
516 
517     /**
518      *  Resets the {@link #collection} and {@link #confirmed} fields to empty
519      *  collections.  Invoke this method before performing a modification
520      *  test.
521      */
522     public void resetEmpty() {
523         this.setCollection(makeObject());
524         this.setConfirmed(makeConfirmedCollection());
525     }
526 
527     /**
528      *  Resets the {@link #collection} and {@link #confirmed} fields to full
529      *  collections.  Invoke this method before performing a modification
530      *  test.
531      */
532     public void resetFull() {
533         this.setCollection(makeFullCollection());
534         this.setConfirmed(makeConfirmedFullCollection());
535     }
536 
537     /**
538      * Sets the collection.
539      * @param collection the Collection<E> to set
540      */
541     public void setCollection(final Collection<E> collection) {
542         this.collection = collection;
543     }
544 
545     /**
546      * Sets the confirmed.
547      * @param confirmed the Collection<E> to set
548      */
549     public void setConfirmed(final Collection<E> confirmed) {
550         this.confirmed = confirmed;
551     }
552 
553     // Tests
554     /**
555      *  Tests {@link Collection#add(Object)}.
556      */
557     @Test
558     public void testCollectionAdd() {
559         if (!isAddSupported()) {
560             return;
561         }
562 
563         final E[] elements = getFullElements();
564         for (final E element : elements) {
565             resetEmpty();
566             final boolean r = getCollection().add(element);
567             getConfirmed().add(element);
568             verify();
569             assertTrue(r, "Empty collection changed after add");
570             assertEquals(1, getCollection().size(), "Collection size is 1 after first add");
571         }
572 
573         resetEmpty();
574         int size = 0;
575         for (final E element : elements) {
576             final boolean r = getCollection().add(element);
577             getConfirmed().add(element);
578             verify();
579             if (r) {
580                 size++;
581             }
582             assertEquals(size, getCollection().size(), "Collection size should grow after add");
583             assertTrue(getCollection().contains(element), "Collection should contain added element");
584         }
585     }
586 
587     /**
588      *  Tests {@link Collection#addAll(Collection)}.
589      */
590     @Test
591     public void testCollectionAddAll() {
592         if (!isAddSupported()) {
593             return;
594         }
595 
596         resetEmpty();
597         E[] elements = getFullElements();
598         boolean r = getCollection().addAll(Arrays.asList(elements));
599         getConfirmed().addAll(Arrays.asList(elements));
600         verify();
601         assertTrue(r, "Empty collection should change after addAll");
602         for (final E element : elements) {
603             assertTrue(getCollection().contains(element), "Collection should contain added element");
604         }
605 
606         resetFull();
607         int size = getCollection().size();
608         elements = getOtherElements();
609         r = getCollection().addAll(Arrays.asList(elements));
610         getConfirmed().addAll(Arrays.asList(elements));
611         verify();
612         assertTrue(r, "Full collection should change after addAll");
613         for (final E element : elements) {
614             assertTrue(getCollection().contains(element),
615                     "Full collection should contain added element");
616         }
617         assertEquals(size + elements.length, getCollection().size(), "Size should increase after addAll");
618 
619         resetFull();
620         size = getCollection().size();
621         r = getCollection().addAll(Arrays.asList(getFullElements()));
622         getConfirmed().addAll(Arrays.asList(getFullElements()));
623         verify();
624         if (r) {
625             assertTrue(size < getCollection().size(), "Size should increase if addAll returns true");
626         } else {
627             assertEquals(size, getCollection().size(), "Size should not change if addAll returns false");
628         }
629     }
630 
631     /**
632      *  Test {@link Collection#clear()}.
633      */
634     @Test
635     public void testCollectionClear() {
636         if (!isRemoveSupported()) {
637             return;
638         }
639 
640         resetEmpty();
641         getCollection().clear(); // just to make sure it doesn't raise anything
642         verify();
643 
644         resetFull();
645         getCollection().clear();
646         getConfirmed().clear();
647         verify();
648     }
649 
650     /**
651      *  Tests {@link Collection#contains(Object)}.
652      */
653     @Test
654     public void testCollectionContains() {
655         Object[] elements;
656 
657         resetEmpty();
658         elements = getFullElements();
659         for (int i = 0; i < elements.length; i++) {
660             assertFalse(getCollection().contains(elements[i]), "Empty collection shouldn't contain element[" + i + "]");
661         }
662         // make sure calls to "contains" don't change anything
663         verify();
664 
665         elements = getOtherElements();
666         for (int i = 0; i < elements.length; i++) {
667             assertFalse(getCollection().contains(elements[i]), "Empty collection shouldn't contain element[" + i + "]");
668         }
669         // make sure calls to "contains" don't change anything
670         verify();
671 
672         resetFull();
673         elements = getFullElements();
674         for (int i = 0; i < elements.length; i++) {
675             assertTrue(getCollection().contains(elements[i]),
676                     "Full collection should contain element[" + i + "]");
677         }
678         // make sure calls to "contains" don't change anything
679         verify();
680 
681         resetFull();
682         elements = getOtherElements();
683         for (final Object element : elements) {
684             assertFalse(getCollection().contains(element), "Full collection shouldn't contain element");
685         }
686     }
687 
688     /**
689      *  Tests {@link Collection#containsAll(Collection)}.
690      */
691     @Test
692     public void testCollectionContainsAll() {
693         resetEmpty();
694         Collection<E> col = new HashSet<>();
695         assertTrue(getCollection().containsAll(col),
696                 "Every Collection should contain all elements of an " + "empty Collection.");
697         col.addAll(Arrays.asList(getOtherElements()));
698         assertFalse(getCollection().containsAll(col),
699                 "Empty Collection shouldn't contain all elements of " + "a non-empty Collection.");
700         // make sure calls to "containsAll" don't change anything
701         verify();
702 
703         resetFull();
704         assertFalse(getCollection().containsAll(col), "Full collection shouldn't contain other elements");
705 
706         col.clear();
707         col.addAll(Arrays.asList(getFullElements()));
708         assertTrue(getCollection().containsAll(col),
709                 "Full collection should containAll full elements");
710         // make sure calls to "containsAll" don't change anything
711         verify();
712 
713         final int min = getFullElements().length < 4 ? 0 : 2;
714         final int max = getFullElements().length == 1 ? 1 :
715                 getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
716         col = Arrays.asList(getFullElements()).subList(min, max);
717         assertTrue(getCollection().containsAll(col),
718                 "Full collection should containAll partial full elements");
719         assertTrue(getCollection().containsAll(getCollection()),
720                 "Full collection should containAll itself");
721         // make sure calls to "containsAll" don't change anything
722         verify();
723 
724         col = new ArrayList<>(Arrays.asList(getFullElements()));
725         col.addAll(Arrays.asList(getFullElements()));
726         assertTrue(getCollection().containsAll(col),
727                 "Full collection should containAll duplicate full elements");
728 
729         // make sure calls to "containsAll" don't change anything
730         verify();
731     }
732 
733     /**
734      *  Tests {@link Collection#isEmpty()}.
735      */
736     @Test
737     public void testCollectionIsEmpty() {
738         resetEmpty();
739         assertTrue(getCollection().isEmpty(), "New Collection should be empty.");
740         // make sure calls to "isEmpty() don't change anything
741         verify();
742 
743         resetFull();
744         assertFalse(getCollection().isEmpty(), "Full collection shouldn't be empty");
745         // make sure calls to "isEmpty() don't change anything
746         verify();
747     }
748 
749     /**
750      *  Tests the read-only functionality of {@link Collection#iterator()}.
751      */
752     @Test
753     public void testCollectionIterator() {
754         resetEmpty();
755         Iterator<E> it1 = getCollection().iterator();
756         assertFalse(it1.hasNext(), "Iterator for empty Collection shouldn't have next.");
757         final Iterator<E> finalIt1 = it1;
758         assertThrows(NoSuchElementException.class, () -> finalIt1.next(),
759                 "Iterator at end of Collection should throw NoSuchElementException when next is called.");
760         // make sure nothing has changed after non-modification
761         verify();
762 
763         resetFull();
764         it1 = getCollection().iterator();
765         for (final E element : getCollection()) {
766             assertTrue(it1.hasNext(), "Iterator for full collection should haveNext");
767             it1.next();
768         }
769         assertFalse(it1.hasNext(), "Iterator should be finished");
770 
771         final ArrayList<E> list = new ArrayList<>();
772         it1 = getCollection().iterator();
773         for (int i = 0; i < getCollection().size(); i++) {
774             final E next = it1.next();
775             assertTrue(getCollection().contains(next),
776                     "Collection should contain element returned by its iterator");
777             list.add(next);
778         }
779         final Iterator<E> finalIt2 = it1;
780         assertThrows(NoSuchElementException.class, () -> finalIt2.next(),
781                 "iterator.next() should raise NoSuchElementException after it finishes");
782         // make sure nothing has changed after non-modification
783         verify();
784     }
785 
786     /**
787      *  Tests that the collection's iterator is fail-fast.
788      */
789     @Test
790     public void testCollectionIteratorFailFast() {
791         if (!isFailFastSupported()) {
792             return;
793         }
794 
795         if (isAddSupported()) {
796             resetFull();
797             final Iterator<E> iter0 = getCollection().iterator();
798             final E o = getOtherElements()[0];
799             getCollection().add(o);
800             getConfirmed().add(o);
801             assertThrows(ConcurrentModificationException.class, () -> iter0.next(),
802                     "next after add should raise ConcurrentModification");
803             verify();
804 
805             resetFull();
806             final Iterator<E> iter = getCollection().iterator();
807             getCollection().addAll(Arrays.asList(getOtherElements()));
808             getConfirmed().addAll(Arrays.asList(getOtherElements()));
809             assertThrows(ConcurrentModificationException.class, () -> iter.next(),
810                     "next after addAll should raise ConcurrentModification");
811             verify();
812         }
813 
814         if (!isRemoveSupported()) {
815             return;
816         }
817 
818         resetFull();
819         final Iterator<E> iter = getCollection().iterator();
820         getCollection().clear();
821         try {
822             iter.next();
823             fail("next after clear should raise ConcurrentModification");
824         } catch (final ConcurrentModificationException | NoSuchElementException e) {
825             // ConcurrentModificationException: expected
826             // NoSuchElementException: (also legal given spec)
827         }
828 
829         resetFull();
830         final Iterator<E> iter0 = getCollection().iterator();
831         getCollection().remove(getFullElements()[0]);
832         assertThrows(ConcurrentModificationException.class, () -> iter0.next(),
833                 "next after remove should raise ConcurrentModification");
834 
835         resetFull();
836         final Iterator<E> iter1 = getCollection().iterator();
837         getCollection().removeIf(e -> false);
838         assertThrows(ConcurrentModificationException.class, () -> iter1.next(),
839                 "next after removeIf should raise ConcurrentModification");
840 
841         resetFull();
842         final Iterator<E> iter2 = getCollection().iterator();
843         final List<E> sublist = Arrays.asList(getFullElements()).subList(2, 5);
844         getCollection().removeAll(sublist);
845         assertThrows(ConcurrentModificationException.class, () -> iter2.next(),
846                 "next after removeAll should raise ConcurrentModification");
847 
848         resetFull();
849         final Iterator<E> iter3 = getCollection().iterator();
850         final List<E> sublist3 = Arrays.asList(getFullElements()).subList(2, 5);
851         getCollection().retainAll(sublist3);
852         assertThrows(ConcurrentModificationException.class, () -> iter3.next(),
853                 "next after retainAll should raise ConcurrentModification");
854     }
855 
856     /**
857      *  Tests removals from {@link Collection#iterator()}.
858      */
859     @Test
860     @SuppressWarnings("unchecked")
861     public void testCollectionIteratorRemove() {
862         if (!isRemoveSupported()) {
863             return;
864         }
865 
866         resetEmpty();
867         assertThrows(IllegalStateException.class, () -> getCollection().iterator().remove(),
868                 "New iterator.remove should raise IllegalState");
869         verify();
870 
871         final Iterator<E> iter0 = getCollection().iterator();
872         iter0.hasNext();
873         assertThrows(IllegalStateException.class, () -> iter0.remove(),
874                 "New iterator.remove should raise IllegalState even after hasNext");
875         verify();
876 
877         resetFull();
878         int size = getCollection().size();
879         Iterator<E> iter = getCollection().iterator();
880         while (iter.hasNext()) {
881             Object o = iter.next();
882             // TreeMap reuses the Map Entry, so the verify below fails
883             // Clone it here if necessary
884             if (o instanceof Map.Entry) {
885                 o = cloneMapEntry((Map.Entry<E, E>) o);
886             }
887             iter.remove();
888 
889             // if the elements aren't distinguishable, we can just remove a
890             // matching element from the confirmed collection and verify
891             // contents are still the same.  Otherwise, we don't have the
892             // ability to distinguish the elements and determine which to
893             // remove from the confirmed collection (in which case, we don't
894             // verify because we don't know how).
895             //
896             // see areEqualElementsDistinguishable()
897             if (!areEqualElementsDistinguishable()) {
898                 getConfirmed().remove(o);
899                 verify();
900             }
901 
902             size--;
903             assertEquals(size, getCollection().size(),
904                     "Collection should shrink by one after iterator.remove");
905         }
906         assertTrue(getCollection().isEmpty(), "Collection should be empty after iterator purge");
907 
908         resetFull();
909         iter = getCollection().iterator();
910         iter.next();
911         iter.remove();
912         final Iterator<E> finalIter = iter;
913         assertThrows(IllegalStateException.class, () -> finalIter.remove(),
914                 "Second iter.remove should raise IllegalState");
915     }
916 
917     /**
918      *  Tests {@link Collection#remove(Object)}.
919      */
920     @Test
921     public void testCollectionRemove() {
922         if (!isRemoveSupported()) {
923             return;
924         }
925 
926         resetEmpty();
927         final E[] elements = getFullElements();
928         for (final E element : elements) {
929             assertFalse(getCollection().remove(element), "Shouldn't remove nonexistent element");
930             verify();
931         }
932 
933         final E[] other = getOtherElements();
934 
935         resetFull();
936         for (final E element : other) {
937             assertFalse(getCollection().remove(element), "Shouldn't remove nonexistent other element");
938             verify();
939         }
940 
941         final int size = getCollection().size();
942         for (final E element : elements) {
943             resetFull();
944             assertTrue(getCollection().remove(element),
945                     "Collection should remove extant element: " + element);
946 
947             // if the elements aren't distinguishable, we can just remove a
948             // matching element from the confirmed collection and verify
949             // contents are still the same.  Otherwise, we don't have the
950             // ability to distinguish the elements and determine which to
951             // remove from the confirmed collection (in which case, we don't
952             // verify because we don't know how).
953             //
954             // see areEqualElementsDistinguishable()
955             if (!areEqualElementsDistinguishable()) {
956                 getConfirmed().remove(element);
957                 verify();
958             }
959 
960             assertEquals(size - 1, getCollection().size(), "Collection should shrink after remove");
961         }
962     }
963 
964     /**
965      *  Tests {@link Collection#removeAll(Collection)}.
966      */
967     @Test
968     public void testCollectionRemoveAll() {
969         if (!isRemoveSupported()) {
970             return;
971         }
972 
973         resetEmpty();
974         assertFalse(getCollection().removeAll(Collections.EMPTY_SET), "Empty collection removeAll should return false for empty input");
975         verify();
976 
977         assertFalse(getCollection().removeAll(new ArrayList<>(getCollection())), "Empty collection removeAll should return false for nonempty input");
978         verify();
979 
980         resetFull();
981         assertFalse(getCollection().removeAll(Collections.EMPTY_SET), "Full collection removeAll should return false for empty input");
982         verify();
983 
984         assertFalse(getCollection().removeAll(Arrays.asList(getOtherElements())), "Full collection removeAll should return false for other elements");
985         verify();
986 
987         assertTrue(getCollection().removeAll(new HashSet<>(getCollection())),
988                 "Full collection removeAll should return true for full elements");
989         getConfirmed().removeAll(new HashSet<>(getConfirmed()));
990         verify();
991 
992         resetFull();
993         final int size = getCollection().size();
994         final int min = getFullElements().length < 4 ? 0 : 2;
995         final int max = getFullElements().length == 1 ? 1 :
996                 getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
997         final Collection<E> all = Arrays.asList(getFullElements()).subList(min, max);
998         assertTrue(getCollection().removeAll(all), "Full collection removeAll should work");
999         getConfirmed().removeAll(all);
1000         verify();
1001 
1002         assertTrue(getCollection().size() < size, "Collection should shrink after removeAll");
1003         for (final E element : all) {
1004             assertFalse(getCollection().contains(element), "Collection shouldn't contain removed element");
1005         }
1006     }
1007 
1008     /**
1009      *  Tests {@link Collection#removeIf(Predicate)}.
1010      */
1011     @Test
1012     public void testCollectionRemoveIf() {
1013         if (!isRemoveSupported()) {
1014             return;
1015         }
1016 
1017         resetEmpty();
1018         assertFalse(getCollection().removeIf(e -> false), "Empty collection removeIf should return false for a predicate that returns only false");
1019         verify();
1020 
1021         assertFalse(getCollection().removeIf(e -> true), "Empty collection removeIf should return false for a predicate that returns only true");
1022         verify();
1023 
1024         resetFull();
1025         assertFalse(getCollection().removeIf(e -> false), "Full collection removeIf should return false for a predicate that returns only false");
1026         verify();
1027 
1028         assertTrue(getCollection().removeIf(e -> true), "Full collection removeIf should return true for a predicate that returns only true");
1029         getConfirmed().removeIf(e -> true);
1030         verify();
1031 
1032         resetFull();
1033         final List<E> elements = Arrays.asList(getFullElements());
1034 
1035         final int mid = getFullElements().length / 2;
1036         final E target = elements.get(mid);
1037 
1038         final int size = getCollection().size();
1039         final int targetCount = Collections.frequency(elements, target);
1040 
1041         final Predicate<E> filter = target::equals;
1042 
1043         assertTrue(getCollection().removeIf(filter), "Full collection removeIf should work");
1044         getConfirmed().removeIf(filter);
1045         verify();
1046 
1047         assertEquals(getCollection().size(), size - targetCount, "Collection should shrink after removeIf");
1048         assertFalse(getCollection().contains(target), "Collection shouldn't contain removed element");
1049     }
1050 
1051     /**
1052      *  Tests {@link Collection#retainAll(Collection)}.
1053      */
1054     @Test
1055     public void testCollectionRetainAll() {
1056         if (!isRemoveSupported()) {
1057             return;
1058         }
1059 
1060         resetEmpty();
1061         final List<E> elements = Arrays.asList(getFullElements());
1062         final List<E> other = Arrays.asList(getOtherElements());
1063 
1064         assertFalse(getCollection().retainAll(Collections.EMPTY_SET), "Empty retainAll() should return false");
1065         verify();
1066 
1067         assertFalse(getCollection().retainAll(elements), "Empty retainAll() should return false");
1068         verify();
1069 
1070         resetFull();
1071         assertTrue(getCollection().retainAll(Collections.EMPTY_SET),
1072                 "Collection should change from retainAll empty");
1073         getConfirmed().retainAll(Collections.EMPTY_SET);
1074         verify();
1075 
1076         resetFull();
1077         assertTrue(getCollection().retainAll(other), "Collection changed from retainAll other");
1078         getConfirmed().retainAll(other);
1079         verify();
1080 
1081         resetFull();
1082         int size = getCollection().size();
1083         assertFalse(getCollection().retainAll(elements), "Collection shouldn't change from retainAll elements");
1084         verify();
1085         assertEquals(size, getCollection().size(), "Collection size shouldn't change");
1086 
1087         if (getFullElements().length > 1) {
1088             resetFull();
1089             size = getCollection().size();
1090             final int min = getFullElements().length < 4 ? 0 : 2;
1091             final int max = getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
1092             assertTrue(getCollection().retainAll(elements.subList(min, max)),
1093                     "Collection should changed by partial retainAll");
1094             getConfirmed().retainAll(elements.subList(min, max));
1095             verify();
1096 
1097             for (final E element : getCollection()) {
1098                 assertTrue(elements.subList(min, max).contains(element), "Collection only contains retained element");
1099             }
1100         }
1101 
1102         resetFull();
1103         final HashSet<E> set = new HashSet<>(elements);
1104         size = getCollection().size();
1105         assertFalse(getCollection().retainAll(set),
1106                 "Collection shouldn't change from retainAll without " + "duplicate elements");
1107         verify();
1108         assertEquals(size, getCollection().size(),
1109                 "Collection size didn't change from nonduplicate " + "retainAll");
1110     }
1111 
1112     /**
1113      *  Tests {@link Collection#size()}.
1114      */
1115     @Test
1116     public void testCollectionSize() {
1117         resetEmpty();
1118         assertEquals(0, getCollection().size(), "Size of new Collection is 0.");
1119 
1120         resetFull();
1121         assertFalse(getCollection().isEmpty(), "Size of full collection should be greater than zero");
1122     }
1123 
1124     /**
1125      *  Tests {@link Collection#toArray()}.
1126      */
1127     @Test
1128     public void testCollectionToArray() {
1129         resetEmpty();
1130         assertEquals(0, getCollection().toArray().length,
1131                 "Empty Collection should return empty array for toArray");
1132 
1133         resetFull();
1134         final Object[] array = getCollection().toArray();
1135         assertEquals(array.length, getCollection().size(),
1136                 "Full collection toArray should be same size as collection");
1137         final Object[] confirmedArray = getConfirmed().toArray();
1138         assertEquals(confirmedArray.length, array.length, "length of array from confirmed collection should "
1139                 + "match the length of the collection's array");
1140         final boolean[] matched = new boolean[array.length];
1141 
1142         for (int i = 0; i < array.length; i++) {
1143             assertTrue(getCollection().contains(array[i]),
1144                     "Collection should contain element in toArray");
1145 
1146             boolean match = false;
1147             // find a match in the confirmed array
1148             for (int j = 0; j < array.length; j++) {
1149                 // skip already matched
1150                 if (matched[j]) {
1151                     continue;
1152                 }
1153                 if (Objects.equals(array[i], confirmedArray[j])) {
1154                     matched[j] = true;
1155                     match = true;
1156                     break;
1157                 }
1158             }
1159             if (!match) {
1160                 fail("element " + i + " in returned array should be found "
1161                         + "in the confirmed collection's array");
1162             }
1163         }
1164         for (final boolean element : matched) {
1165             assertTrue(element, "Collection should return all its elements in " + "toArray");
1166         }
1167     }
1168 
1169     /**
1170      *  Tests {@link Collection#toArray(Object[])}.
1171      */
1172     @Test
1173     public void testCollectionToArray2() {
1174         resetEmpty();
1175         Object[] a = { new Object(), null, null };
1176         Object[] array = getCollection().toArray(a);
1177         assertEquals(array, a, "Given array shouldn't shrink");
1178         assertNull(a[0], "Last element should be set to null");
1179         verify();
1180 
1181         resetFull();
1182         assertThrows(ArrayStoreException.class, () -> getCollection().toArray(new Void[0]),
1183                 "toArray(new Void[0]) should raise ArrayStore");
1184         verify();
1185 
1186         // Casting to Object[] allows compilation on Java 11.
1187         assertThrows(NullPointerException.class, () -> getCollection().toArray((Object[]) null),
1188                 "toArray(null) should raise NPE");
1189         verify();
1190 
1191         array = getCollection().toArray(ArrayUtils.EMPTY_OBJECT_ARRAY);
1192         a = getCollection().toArray();
1193 
1194         if ((getIterationBehaviour() & UNORDERED) != 0) {
1195             assertUnorderedArrayEquals(array, a, "toArray(Object[]) and toArray()");
1196         } else {
1197             assertEquals(Arrays.asList(array), Arrays.asList(a), "toArrays should be equal");
1198         }
1199         // Figure out if they're all the same class
1200         // TODO: It'd be nicer to detect a common superclass
1201         final HashSet<Class<?>> classes = new HashSet<>();
1202         for (final Object element : array) {
1203             classes.add(element == null ? null : element.getClass());
1204         }
1205         if (classes.size() > 1) {
1206             return;
1207         }
1208 
1209         Class<?> cl = classes.iterator().next();
1210         if (Map.Entry.class.isAssignableFrom(cl)) {  // check needed for protective cases like Predicated/Unmod map entrySet
1211             cl = Map.Entry.class;
1212         }
1213         a = (Object[]) Array.newInstance(cl, 0);
1214         array = getCollection().toArray(a);
1215         assertEquals(a.getClass(), array.getClass(),
1216                 "toArray(Object[]) should return correct array type");
1217 
1218         if ((getIterationBehaviour() & UNORDERED) != 0) {
1219             assertUnorderedArrayEquals(array, getCollection().toArray(), "type-specific toArray(T[]) and toArray()");
1220         } else {
1221             assertEquals(Arrays.asList(array),
1222                     Arrays.asList(getCollection().toArray()),
1223                     "type-specific toArrays should be equal");
1224         }
1225         verify();
1226     }
1227 
1228     /**
1229      *  Tests {@code toString} on a collection.
1230      */
1231     @Test
1232     public void testCollectionToString() {
1233         resetEmpty();
1234         assertNotNull(getCollection().toString(), "toString shouldn't return null");
1235 
1236         resetFull();
1237         assertNotNull(getCollection().toString(), "toString shouldn't return null");
1238     }
1239 
1240     @Test
1241     @Override
1242     public void testSerializeDeserializeThenCompare() throws Exception {
1243         Object obj = makeObject();
1244         if (obj instanceof Serializable && isTestSerialization()) {
1245             final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
1246             final ObjectOutputStream out = new ObjectOutputStream(buffer);
1247             out.writeObject(obj);
1248             out.close();
1249 
1250             final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()));
1251             final Object dest = in.readObject();
1252             in.close();
1253             if (isEqualsCheckable()) {
1254                 assertEquals(obj, dest, "obj != deserialize(serialize(obj)) - EMPTY Collection");
1255             }
1256         }
1257         obj = makeFullCollection();
1258         if (obj instanceof Serializable && isTestSerialization()) {
1259             final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
1260             final ObjectOutputStream out = new ObjectOutputStream(buffer);
1261             out.writeObject(obj);
1262             out.close();
1263 
1264             final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()));
1265             final Object dest = in.readObject();
1266             in.close();
1267             if (isEqualsCheckable()) {
1268                 assertEquals(obj, dest, "obj != deserialize(serialize(obj)) - FULL Collection");
1269             }
1270         }
1271     }
1272 
1273     /**
1274      *  If {@link #isAddSupported()} returns false, tests that add operations
1275      *  raise <code>UnsupportedOperationException.
1276      */
1277     @Test
1278     public void testUnsupportedAdd() {
1279         if (isAddSupported()) {
1280             return;
1281         }
1282 
1283         resetEmpty();
1284         assertThrows(UnsupportedOperationException.class, () -> getCollection().add(getFullNonNullElements()[0]),
1285                 "Empty collection should not support add.");
1286         // make sure things didn't change even if the expected exception was
1287         // thrown.
1288         verify();
1289 
1290         assertThrows(UnsupportedOperationException.class, () -> getCollection().addAll(Arrays.asList(getFullElements())),
1291                 "Empty collection should not support addAll.");
1292         // make sure things didn't change even if the expected exception was
1293         // thrown.
1294         verify();
1295 
1296         resetFull();
1297         assertThrows(UnsupportedOperationException.class, () -> getCollection().add(getFullNonNullElements()[0]),
1298                 "Full collection should not support add.");
1299         // make sure things didn't change even if the expected exception was
1300         // thrown.
1301         verify();
1302 
1303         assertThrows(UnsupportedOperationException.class, () -> getCollection().addAll(Arrays.asList(getOtherElements())),
1304                 "Full collection should not support addAll.");
1305         // make sure things didn't change even if the expected exception was
1306         // thrown.
1307         verify();
1308     }
1309 
1310     /**
1311      *  If isRemoveSupported() returns false, tests to see that remove
1312      *  operations raise an UnsupportedOperationException.
1313      */
1314     @Test
1315     public void testUnsupportedRemove() {
1316         if (isRemoveSupported()) {
1317             return;
1318         }
1319 
1320         resetEmpty();
1321         assertThrows(UnsupportedOperationException.class, () -> getCollection().clear(),
1322                 "clear should raise UnsupportedOperationException");
1323         verify();
1324 
1325         assertThrows(UnsupportedOperationException.class, () -> getCollection().remove(null),
1326                 "remove should raise UnsupportedOperationException");
1327         verify();
1328 
1329         assertThrows(UnsupportedOperationException.class, () -> getCollection().removeIf(e -> true),
1330                 "removeIf should raise UnsupportedOperationException");
1331         verify();
1332 
1333         assertThrows(UnsupportedOperationException.class, () -> getCollection().removeAll(null),
1334                 "removeAll should raise UnsupportedOperationException");
1335         verify();
1336 
1337         assertThrows(UnsupportedOperationException.class, () -> getCollection().retainAll(null),
1338                 "retainAll should raise UnsupportedOperationException");
1339         verify();
1340 
1341         resetFull();
1342         final Iterator<E> iterator = getCollection().iterator();
1343         iterator.next();
1344         assertThrows(UnsupportedOperationException.class, () -> iterator.remove(),
1345                 "iterator.remove should raise UnsupportedOperationException");
1346         verify();
1347 
1348     }
1349 
1350     /**
1351      *  Verifies that {@link #collection} and {@link #confirmed} have
1352      *  identical state.
1353      */
1354     public void verify() {
1355         final int confirmedSize = getConfirmed().size();
1356         assertEquals(confirmedSize, getCollection().size(),
1357                 "Collection size should match confirmed collection's");
1358         assertEquals(getConfirmed().isEmpty(), getCollection().isEmpty(),
1359                 "Collection isEmpty() result should match confirmed collection's");
1360 
1361         // verify the collections are the same by attempting to match each
1362         // object in the collection and confirmed collection.  To account for
1363         // duplicates and differing orders, each confirmed element is copied
1364         // into an array and a flag is maintained for each element to determine
1365         // whether it has been matched once and only once.  If all elements in
1366         // the confirmed collection are matched once and only once and there
1367         // aren't any elements left to be matched in the collection,
1368         // verification is a success.
1369 
1370         // copy each collection value into an array
1371         final Object[] confirmedValues = new Object[confirmedSize];
1372 
1373         Iterator<E> iter;
1374 
1375         iter = getConfirmed().iterator();
1376         int pos = 0;
1377         while (iter.hasNext()) {
1378             confirmedValues[pos++] = iter.next();
1379         }
1380 
1381         // allocate an array of boolean flags for tracking values that have
1382         // been matched once and only once.
1383         final boolean[] matched = new boolean[confirmedSize];
1384 
1385         // now iterate through the values of the collection and try to match
1386         // the value with one in the confirmed array.
1387         iter = getCollection().iterator();
1388         while (iter.hasNext()) {
1389             final Object o = iter.next();
1390             boolean match = false;
1391             for (int i = 0; i < confirmedSize; i++) {
1392                 if (matched[i]) {
1393                     // skip values already matched
1394                     continue;
1395                 }
1396                 if (Objects.equals(o, confirmedValues[i])) {
1397                     // values matched
1398                     matched[i] = true;
1399                     match = true;
1400                     break;
1401                 }
1402             }
1403             // no match found!
1404             if (!match) {
1405                 fail("Collection should not contain a value that the "
1406                         + "confirmed collection does not have: " + o + "\nTest: " + getCollection()
1407                         + "\nReal: " + getConfirmed());
1408             }
1409         }
1410 
1411         // make sure there aren't any unmatched values
1412         for (int i = 0; i < confirmedSize; i++) {
1413             if (!matched[i]) {
1414                 // the collection didn't match all the confirmed values
1415                 fail("Collection should contain all values that are in the confirmed collection"
1416                         + "\nTest: " + getCollection() + "\nReal: " + getConfirmed());
1417             }
1418         }
1419     }
1420 
1421 }