ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/Collection8Test.java
Revision: 1.61
Committed: Tue Jan 26 13:33:05 2021 UTC (3 years, 3 months ago) by dl
Branch: MAIN
CVS Tags: HEAD
Changes since 1.60: +60 -59 lines
Log Message:
Replace Integer with Item class

File Contents

# User Rev Content
1 jsr166 1.1 /*
2     * Written by Doug Lea and Martin Buchholz with assistance from
3     * members of JCP JSR-166 Expert Group and released to the public
4     * domain, as explained at
5     * http://creativecommons.org/publicdomain/zero/1.0/
6     */
7    
8 jsr166 1.16 import static java.util.concurrent.TimeUnit.HOURS;
9 jsr166 1.1 import static java.util.concurrent.TimeUnit.MILLISECONDS;
10    
11 jsr166 1.51 import java.util.ArrayDeque;
12 jsr166 1.1 import java.util.ArrayList;
13 jsr166 1.18 import java.util.Arrays;
14 jsr166 1.1 import java.util.Collection;
15     import java.util.Collections;
16 jsr166 1.42 import java.util.ConcurrentModificationException;
17 jsr166 1.5 import java.util.Deque;
18     import java.util.HashSet;
19     import java.util.Iterator;
20     import java.util.List;
21     import java.util.NoSuchElementException;
22     import java.util.Queue;
23 jsr166 1.48 import java.util.Set;
24 jsr166 1.5 import java.util.Spliterator;
25 jsr166 1.14 import java.util.concurrent.BlockingDeque;
26     import java.util.concurrent.BlockingQueue;
27 jsr166 1.32 import java.util.concurrent.ConcurrentLinkedQueue;
28 jsr166 1.2 import java.util.concurrent.CountDownLatch;
29 jsr166 1.1 import java.util.concurrent.Executors;
30     import java.util.concurrent.ExecutorService;
31     import java.util.concurrent.Future;
32 jsr166 1.26 import java.util.concurrent.Phaser;
33 jsr166 1.5 import java.util.concurrent.ThreadLocalRandom;
34 jsr166 1.1 import java.util.concurrent.atomic.AtomicBoolean;
35     import java.util.concurrent.atomic.AtomicLong;
36 jsr166 1.5 import java.util.concurrent.atomic.AtomicReference;
37 jsr166 1.1 import java.util.function.Consumer;
38 jsr166 1.5 import java.util.function.Predicate;
39 jsr166 1.26 import java.util.stream.Collectors;
40 jsr166 1.1
41     import junit.framework.Test;
42    
43     /**
44     * Contains tests applicable to all jdk8+ Collection implementations.
45     * An extension of CollectionTest.
46     */
47     public class Collection8Test extends JSR166TestCase {
48     final CollectionImplementation impl;
49    
50     /** Tests are parameterized by a Collection implementation. */
51     Collection8Test(CollectionImplementation impl, String methodName) {
52     super(methodName);
53     this.impl = impl;
54     }
55    
56     public static Test testSuite(CollectionImplementation impl) {
57     return parameterizedTestSuite(Collection8Test.class,
58     CollectionImplementation.class,
59     impl);
60     }
61    
62 jsr166 1.10 Object bomb() {
63     return new Object() {
64 jsr166 1.48 @Override public boolean equals(Object x) { throw new AssertionError(); }
65     @Override public int hashCode() { throw new AssertionError(); }
66     @Override public String toString() { throw new AssertionError(); }
67 jsr166 1.47 };
68 jsr166 1.10 }
69    
70 jsr166 1.5 /** Checks properties of empty collections. */
71 jsr166 1.24 public void testEmptyMeansEmpty() throws Throwable {
72 jsr166 1.5 Collection c = impl.emptyCollection();
73 jsr166 1.12 emptyMeansEmpty(c);
74    
75 jsr166 1.24 if (c instanceof java.io.Serializable) {
76     try {
77     emptyMeansEmpty(serialClonePossiblyFailing(c));
78     } catch (java.io.NotSerializableException ex) {
79     // excusable when we have a serializable wrapper around
80     // a non-serializable collection, as can happen with:
81     // Vector.subList() => wrapped AbstractList$RandomAccessSubList
82     if (testImplementationDetails
83     && (! c.getClass().getName().matches(
84     "java.util.Collections.*")))
85     throw ex;
86     }
87     }
88 jsr166 1.12
89     Collection clone = cloneableClone(c);
90     if (clone != null)
91     emptyMeansEmpty(clone);
92     }
93    
94 jsr166 1.14 void emptyMeansEmpty(Collection c) throws InterruptedException {
95 jsr166 1.5 assertTrue(c.isEmpty());
96 dl 1.61 mustEqual(0, c.size());
97     mustEqual("[]", c.toString());
98 jsr166 1.48 if (c instanceof List<?>) {
99     List x = (List) c;
100 dl 1.61 mustEqual(1, x.hashCode());
101     mustEqual(x, Collections.emptyList());
102     mustEqual(Collections.emptyList(), x);
103     mustEqual(-1, x.indexOf(impl.makeElement(86)));
104     mustEqual(-1, x.lastIndexOf(impl.makeElement(99)));
105 jsr166 1.49 assertThrows(
106     IndexOutOfBoundsException.class,
107     () -> x.get(0),
108     () -> x.set(0, impl.makeElement(42)));
109 jsr166 1.48 }
110     else if (c instanceof Set<?>) {
111 dl 1.61 mustEqual(0, c.hashCode());
112     mustEqual(c, Collections.emptySet());
113     mustEqual(Collections.emptySet(), c);
114 jsr166 1.48 }
115 jsr166 1.5 {
116     Object[] a = c.toArray();
117 dl 1.61 mustEqual(0, a.length);
118 jsr166 1.5 assertSame(Object[].class, a.getClass());
119     }
120     {
121     Object[] a = new Object[0];
122     assertSame(a, c.toArray(a));
123     }
124     {
125 dl 1.61 Item[] a = new Item[0];
126 jsr166 1.5 assertSame(a, c.toArray(a));
127     }
128     {
129 dl 1.61 Item[] a = { one, two, three};
130 jsr166 1.5 assertSame(a, c.toArray(a));
131     assertNull(a[0]);
132 dl 1.61 mustEqual(2, a[1]);
133     mustEqual(3, a[2]);
134 jsr166 1.5 }
135     assertIteratorExhausted(c.iterator());
136 jsr166 1.19 Consumer alwaysThrows = e -> { throw new AssertionError(); };
137 jsr166 1.5 c.forEach(alwaysThrows);
138     c.iterator().forEachRemaining(alwaysThrows);
139     c.spliterator().forEachRemaining(alwaysThrows);
140     assertFalse(c.spliterator().tryAdvance(alwaysThrows));
141 jsr166 1.9 if (c.spliterator().hasCharacteristics(Spliterator.SIZED))
142 dl 1.61 mustEqual(0, c.spliterator().estimateSize());
143 jsr166 1.10 assertFalse(c.contains(bomb()));
144     assertFalse(c.remove(bomb()));
145 jsr166 1.11 if (c instanceof Queue) {
146 jsr166 1.5 Queue q = (Queue) c;
147     assertNull(q.peek());
148     assertNull(q.poll());
149     }
150 jsr166 1.11 if (c instanceof Deque) {
151 jsr166 1.5 Deque d = (Deque) c;
152     assertNull(d.peekFirst());
153     assertNull(d.peekLast());
154     assertNull(d.pollFirst());
155     assertNull(d.pollLast());
156     assertIteratorExhausted(d.descendingIterator());
157 jsr166 1.9 d.descendingIterator().forEachRemaining(alwaysThrows);
158 jsr166 1.10 assertFalse(d.removeFirstOccurrence(bomb()));
159     assertFalse(d.removeLastOccurrence(bomb()));
160 jsr166 1.5 }
161 jsr166 1.14 if (c instanceof BlockingQueue) {
162     BlockingQueue q = (BlockingQueue) c;
163 jsr166 1.46 assertNull(q.poll(randomExpiredTimeout(), randomTimeUnit()));
164 jsr166 1.14 }
165     if (c instanceof BlockingDeque) {
166     BlockingDeque q = (BlockingDeque) c;
167 jsr166 1.46 assertNull(q.pollFirst(randomExpiredTimeout(), randomTimeUnit()));
168     assertNull(q.pollLast(randomExpiredTimeout(), randomTimeUnit()));
169 jsr166 1.14 }
170 jsr166 1.5 }
171    
172 jsr166 1.14 public void testNullPointerExceptions() throws InterruptedException {
173 jsr166 1.5 Collection c = impl.emptyCollection();
174 dl 1.61 Collection nullCollection = null;
175 jsr166 1.5 assertThrows(
176     NullPointerException.class,
177 dl 1.61 () -> c.addAll(nullCollection),
178     () -> c.containsAll(nullCollection),
179     () -> c.retainAll(nullCollection),
180     () -> c.removeAll(nullCollection),
181 jsr166 1.5 () -> c.removeIf(null),
182 jsr166 1.6 () -> c.forEach(null),
183     () -> c.iterator().forEachRemaining(null),
184     () -> c.spliterator().forEachRemaining(null),
185     () -> c.spliterator().tryAdvance(null),
186 jsr166 1.57 () -> c.toArray((Object[])null));
187 jsr166 1.5
188     if (!impl.permitsNulls()) {
189     assertThrows(
190     NullPointerException.class,
191     () -> c.add(null));
192     }
193 jsr166 1.14 if (!impl.permitsNulls() && c instanceof Queue) {
194 jsr166 1.5 Queue q = (Queue) c;
195     assertThrows(
196     NullPointerException.class,
197     () -> q.offer(null));
198     }
199 jsr166 1.14 if (!impl.permitsNulls() && c instanceof Deque) {
200 jsr166 1.5 Deque d = (Deque) c;
201     assertThrows(
202     NullPointerException.class,
203     () -> d.addFirst(null),
204     () -> d.addLast(null),
205     () -> d.offerFirst(null),
206     () -> d.offerLast(null),
207 jsr166 1.6 () -> d.push(null),
208     () -> d.descendingIterator().forEachRemaining(null));
209 jsr166 1.5 }
210 jsr166 1.15 if (c instanceof BlockingQueue) {
211 jsr166 1.14 BlockingQueue q = (BlockingQueue) c;
212     assertThrows(
213     NullPointerException.class,
214 jsr166 1.58 () -> q.offer(null, 1L, HOURS),
215     () -> q.put(null));
216 jsr166 1.14 }
217 jsr166 1.15 if (c instanceof BlockingDeque) {
218 jsr166 1.14 BlockingDeque q = (BlockingDeque) c;
219     assertThrows(
220     NullPointerException.class,
221 jsr166 1.58 () -> q.offerFirst(null, 1L, HOURS),
222     () -> q.offerLast(null, 1L, HOURS),
223     () -> q.putFirst(null),
224     () -> q.putLast(null));
225 jsr166 1.14 }
226 jsr166 1.5 }
227    
228     public void testNoSuchElementExceptions() {
229     Collection c = impl.emptyCollection();
230     assertThrows(
231     NoSuchElementException.class,
232     () -> c.iterator().next());
233    
234 jsr166 1.14 if (c instanceof Queue) {
235 jsr166 1.5 Queue q = (Queue) c;
236     assertThrows(
237     NoSuchElementException.class,
238     () -> q.element(),
239     () -> q.remove());
240     }
241 jsr166 1.14 if (c instanceof Deque) {
242 jsr166 1.5 Deque d = (Deque) c;
243     assertThrows(
244     NoSuchElementException.class,
245     () -> d.getFirst(),
246     () -> d.getLast(),
247     () -> d.removeFirst(),
248     () -> d.removeLast(),
249     () -> d.pop(),
250     () -> d.descendingIterator().next());
251     }
252 jsr166 1.48 if (c instanceof List) {
253     List x = (List) c;
254     assertThrows(
255     NoSuchElementException.class,
256     () -> x.iterator().next(),
257     () -> x.listIterator().next(),
258     () -> x.listIterator(0).next(),
259     () -> x.listIterator().previous(),
260     () -> x.listIterator(0).previous());
261     }
262 jsr166 1.5 }
263    
264     public void testRemoveIf() {
265     Collection c = impl.emptyCollection();
266 jsr166 1.22 boolean ordered =
267     c.spliterator().hasCharacteristics(Spliterator.ORDERED);
268 jsr166 1.5 ThreadLocalRandom rnd = ThreadLocalRandom.current();
269     int n = rnd.nextInt(6);
270     for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
271     AtomicReference threwAt = new AtomicReference(null);
272 jsr166 1.18 List orig = rnd.nextBoolean()
273     ? new ArrayList(c)
274     : Arrays.asList(c.toArray());
275    
276     // Merely creating an iterator can change ArrayBlockingQueue behavior
277     Iterator it = rnd.nextBoolean() ? c.iterator() : null;
278    
279     ArrayList survivors = new ArrayList();
280 jsr166 1.5 ArrayList accepts = new ArrayList();
281     ArrayList rejects = new ArrayList();
282 jsr166 1.18
283 jsr166 1.19 Predicate randomPredicate = e -> {
284 jsr166 1.5 assertNull(threwAt.get());
285     switch (rnd.nextInt(3)) {
286     case 0: accepts.add(e); return true;
287     case 1: rejects.add(e); return false;
288     case 2: threwAt.set(e); throw new ArithmeticException();
289     default: throw new AssertionError();
290     }
291     };
292     try {
293 jsr166 1.7 try {
294     boolean modified = c.removeIf(randomPredicate);
295 jsr166 1.18 assertNull(threwAt.get());
296 dl 1.61 mustEqual(modified, accepts.size() > 0);
297     mustEqual(modified, rejects.size() != n);
298     mustEqual(accepts.size() + rejects.size(), n);
299 jsr166 1.22 if (ordered) {
300 dl 1.61 mustEqual(rejects,
301 jsr166 1.22 Arrays.asList(c.toArray()));
302     } else {
303 dl 1.61 mustEqual(new HashSet(rejects),
304 jsr166 1.22 new HashSet(Arrays.asList(c.toArray())));
305     }
306 jsr166 1.18 } catch (ArithmeticException ok) {
307     assertNotNull(threwAt.get());
308     assertTrue(c.contains(threwAt.get()));
309     }
310     if (it != null && impl.isConcurrent())
311     // check for weakly consistent iterator
312     while (it.hasNext()) assertTrue(orig.contains(it.next()));
313     switch (rnd.nextInt(4)) {
314     case 0: survivors.addAll(c); break;
315     case 1: survivors.addAll(Arrays.asList(c.toArray())); break;
316 jsr166 1.28 case 2: c.forEach(survivors::add); break;
317 jsr166 1.18 case 3: for (Object e : c) survivors.add(e); break;
318     }
319     assertTrue(orig.containsAll(accepts));
320     assertTrue(orig.containsAll(rejects));
321     assertTrue(orig.containsAll(survivors));
322     assertTrue(orig.containsAll(c));
323     assertTrue(c.containsAll(rejects));
324 jsr166 1.7 assertTrue(c.containsAll(survivors));
325     assertTrue(survivors.containsAll(rejects));
326 jsr166 1.22 if (threwAt.get() == null) {
327 dl 1.61 mustEqual(n - accepts.size(), c.size());
328 jsr166 1.22 for (Object x : accepts) assertFalse(c.contains(x));
329     } else {
330     // Two acceptable behaviors: entire removeIf call is one
331     // transaction, or each element processed is one transaction.
332     assertTrue(n == c.size() || n == c.size() + accepts.size());
333     int k = 0;
334     for (Object x : accepts) if (c.contains(x)) k++;
335     assertTrue(k == accepts.size() || k == 0);
336     }
337 jsr166 1.7 } catch (Throwable ex) {
338 jsr166 1.5 System.err.println(impl.klazz());
339 jsr166 1.23 // c is at risk of corruption if we got here, so be lenient
340     try { System.err.printf("c=%s%n", c); }
341     catch (Throwable t) { t.printStackTrace(); }
342 jsr166 1.7 System.err.printf("n=%d%n", n);
343 jsr166 1.18 System.err.printf("orig=%s%n", orig);
344 jsr166 1.7 System.err.printf("accepts=%s%n", accepts);
345     System.err.printf("rejects=%s%n", rejects);
346 jsr166 1.8 System.err.printf("survivors=%s%n", survivors);
347 jsr166 1.18 System.err.printf("threwAt=%s%n", threwAt.get());
348 jsr166 1.7 throw ex;
349 jsr166 1.5 }
350     }
351    
352     /**
353 jsr166 1.39 * All elements removed in the middle of CONCURRENT traversal.
354     */
355     public void testElementRemovalDuringTraversal() {
356     Collection c = impl.emptyCollection();
357     ThreadLocalRandom rnd = ThreadLocalRandom.current();
358     int n = rnd.nextInt(6);
359     ArrayList copy = new ArrayList();
360     for (int i = 0; i < n; i++) {
361     Object x = impl.makeElement(i);
362     copy.add(x);
363     c.add(x);
364     }
365     ArrayList iterated = new ArrayList();
366     ArrayList spliterated = new ArrayList();
367     Spliterator s = c.spliterator();
368     Iterator it = c.iterator();
369     for (int i = rnd.nextInt(n + 1); --i >= 0; ) {
370     assertTrue(s.tryAdvance(spliterated::add));
371     if (rnd.nextBoolean()) assertTrue(it.hasNext());
372     iterated.add(it.next());
373     }
374     Consumer alwaysThrows = e -> { throw new AssertionError(); };
375     if (s.hasCharacteristics(Spliterator.CONCURRENT)) {
376     c.clear(); // TODO: many more removal methods
377     if (testImplementationDetails
378     && !(c instanceof java.util.concurrent.ArrayBlockingQueue)) {
379     if (rnd.nextBoolean())
380     assertFalse(s.tryAdvance(alwaysThrows));
381     else
382     s.forEachRemaining(alwaysThrows);
383     }
384     if (it.hasNext()) iterated.add(it.next());
385     if (rnd.nextBoolean()) assertIteratorExhausted(it);
386     }
387     assertTrue(copy.containsAll(iterated));
388     assertTrue(copy.containsAll(spliterated));
389     }
390    
391     /**
392     * Some elements randomly disappear in the middle of traversal.
393     */
394     public void testRandomElementRemovalDuringTraversal() {
395     Collection c = impl.emptyCollection();
396     ThreadLocalRandom rnd = ThreadLocalRandom.current();
397     int n = rnd.nextInt(6);
398     ArrayList copy = new ArrayList();
399     for (int i = 0; i < n; i++) {
400     Object x = impl.makeElement(i);
401     copy.add(x);
402     c.add(x);
403     }
404     ArrayList iterated = new ArrayList();
405     ArrayList spliterated = new ArrayList();
406     ArrayList removed = new ArrayList();
407     Spliterator s = c.spliterator();
408     Iterator it = c.iterator();
409     if (! (s.hasCharacteristics(Spliterator.CONCURRENT) ||
410     s.hasCharacteristics(Spliterator.IMMUTABLE)))
411     return;
412     for (int i = rnd.nextInt(n + 1); --i >= 0; ) {
413     assertTrue(s.tryAdvance(e -> {}));
414     if (rnd.nextBoolean()) assertTrue(it.hasNext());
415     it.next();
416     }
417     // TODO: many more removal methods
418     if (rnd.nextBoolean()) {
419     for (Iterator z = c.iterator(); z.hasNext(); ) {
420     Object e = z.next();
421     if (rnd.nextBoolean()) {
422     try {
423     z.remove();
424     } catch (UnsupportedOperationException ok) { return; }
425     removed.add(e);
426     }
427     }
428     } else {
429     Predicate randomlyRemove = e -> {
430     if (rnd.nextBoolean()) { removed.add(e); return true; }
431     else return false;
432     };
433     c.removeIf(randomlyRemove);
434     }
435     s.forEachRemaining(spliterated::add);
436     while (it.hasNext())
437     iterated.add(it.next());
438     assertTrue(copy.containsAll(iterated));
439     assertTrue(copy.containsAll(spliterated));
440     assertTrue(copy.containsAll(removed));
441     if (s.hasCharacteristics(Spliterator.CONCURRENT)) {
442     ArrayList iteratedAndRemoved = new ArrayList(iterated);
443     ArrayList spliteratedAndRemoved = new ArrayList(spliterated);
444     iteratedAndRemoved.retainAll(removed);
445     spliteratedAndRemoved.retainAll(removed);
446     assertTrue(iteratedAndRemoved.size() <= 1);
447     assertTrue(spliteratedAndRemoved.size() <= 1);
448     if (testImplementationDetails
449     && !(c instanceof java.util.concurrent.ArrayBlockingQueue))
450     assertTrue(spliteratedAndRemoved.isEmpty());
451     }
452     }
453    
454     /**
455 jsr166 1.5 * Various ways of traversing a collection yield same elements
456     */
457 jsr166 1.41 public void testTraversalEquivalence() {
458 jsr166 1.5 Collection c = impl.emptyCollection();
459     ThreadLocalRandom rnd = ThreadLocalRandom.current();
460     int n = rnd.nextInt(6);
461     for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
462     ArrayList iterated = new ArrayList();
463     ArrayList iteratedForEachRemaining = new ArrayList();
464 jsr166 1.13 ArrayList tryAdvanced = new ArrayList();
465 jsr166 1.5 ArrayList spliterated = new ArrayList();
466 jsr166 1.33 ArrayList splitonced = new ArrayList();
467 jsr166 1.13 ArrayList forEached = new ArrayList();
468 jsr166 1.32 ArrayList streamForEached = new ArrayList();
469     ConcurrentLinkedQueue parallelStreamForEached = new ConcurrentLinkedQueue();
470 jsr166 1.13 ArrayList removeIfed = new ArrayList();
471 jsr166 1.5 for (Object x : c) iterated.add(x);
472 jsr166 1.28 c.iterator().forEachRemaining(iteratedForEachRemaining::add);
473 jsr166 1.13 for (Spliterator s = c.spliterator();
474 jsr166 1.28 s.tryAdvance(tryAdvanced::add); ) {}
475     c.spliterator().forEachRemaining(spliterated::add);
476 jsr166 1.33 { // trySplit returns "strict prefix"
477     Spliterator s1 = c.spliterator(), s2 = s1.trySplit();
478     if (s2 != null) s2.forEachRemaining(splitonced::add);
479     s1.forEachRemaining(splitonced::add);
480     }
481 jsr166 1.28 c.forEach(forEached::add);
482 jsr166 1.32 c.stream().forEach(streamForEached::add);
483     c.parallelStream().forEach(parallelStreamForEached::add);
484 jsr166 1.13 c.removeIf(e -> { removeIfed.add(e); return false; });
485 jsr166 1.5 boolean ordered =
486     c.spliterator().hasCharacteristics(Spliterator.ORDERED);
487     if (c instanceof List || c instanceof Deque)
488     assertTrue(ordered);
489 jsr166 1.32 HashSet cset = new HashSet(c);
490 dl 1.61 mustEqual(cset, new HashSet(parallelStreamForEached));
491 jsr166 1.5 if (ordered) {
492 dl 1.61 mustEqual(iterated, iteratedForEachRemaining);
493     mustEqual(iterated, tryAdvanced);
494     mustEqual(iterated, spliterated);
495     mustEqual(iterated, splitonced);
496     mustEqual(iterated, forEached);
497     mustEqual(iterated, streamForEached);
498     mustEqual(iterated, removeIfed);
499 jsr166 1.5 } else {
500 dl 1.61 mustEqual(cset, new HashSet(iterated));
501     mustEqual(cset, new HashSet(iteratedForEachRemaining));
502     mustEqual(cset, new HashSet(tryAdvanced));
503     mustEqual(cset, new HashSet(spliterated));
504     mustEqual(cset, new HashSet(splitonced));
505     mustEqual(cset, new HashSet(forEached));
506     mustEqual(cset, new HashSet(streamForEached));
507     mustEqual(cset, new HashSet(removeIfed));
508 jsr166 1.5 }
509     if (c instanceof Deque) {
510     Deque d = (Deque) c;
511     ArrayList descending = new ArrayList();
512     ArrayList descendingForEachRemaining = new ArrayList();
513     for (Iterator it = d.descendingIterator(); it.hasNext(); )
514     descending.add(it.next());
515     d.descendingIterator().forEachRemaining(
516     e -> descendingForEachRemaining.add(e));
517     Collections.reverse(descending);
518     Collections.reverse(descendingForEachRemaining);
519 dl 1.61 mustEqual(iterated, descending);
520     mustEqual(iterated, descendingForEachRemaining);
521 jsr166 1.5 }
522     }
523    
524     /**
525 jsr166 1.42 * Iterator.forEachRemaining has same behavior as Iterator's
526     * default implementation.
527     */
528     public void testForEachRemainingConsistentWithDefaultImplementation() {
529     Collection c = impl.emptyCollection();
530     if (!testImplementationDetails
531     || c.getClass() == java.util.LinkedList.class)
532     return;
533     ThreadLocalRandom rnd = ThreadLocalRandom.current();
534     int n = 1 + rnd.nextInt(3);
535     for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
536     ArrayList iterated = new ArrayList();
537     ArrayList iteratedForEachRemaining = new ArrayList();
538     Iterator it1 = c.iterator();
539     Iterator it2 = c.iterator();
540     assertTrue(it1.hasNext());
541     assertTrue(it2.hasNext());
542     c.clear();
543     Object r1, r2;
544     try {
545     while (it1.hasNext()) iterated.add(it1.next());
546     r1 = iterated;
547     } catch (ConcurrentModificationException ex) {
548     r1 = ConcurrentModificationException.class;
549     assertFalse(impl.isConcurrent());
550     }
551     try {
552     it2.forEachRemaining(iteratedForEachRemaining::add);
553     r2 = iteratedForEachRemaining;
554     } catch (ConcurrentModificationException ex) {
555     r2 = ConcurrentModificationException.class;
556 jsr166 1.44 assertFalse(impl.isConcurrent());
557 jsr166 1.42 }
558 dl 1.61 mustEqual(r1, r2);
559 jsr166 1.42 }
560    
561     /**
562 jsr166 1.5 * Calling Iterator#remove() after Iterator#forEachRemaining
563 jsr166 1.21 * should (maybe) remove last element
564 jsr166 1.5 */
565     public void testRemoveAfterForEachRemaining() {
566     Collection c = impl.emptyCollection();
567     ThreadLocalRandom rnd = ThreadLocalRandom.current();
568 jsr166 1.53 ArrayList copy = new ArrayList();
569     boolean ordered = c.spliterator().hasCharacteristics(Spliterator.ORDERED);
570 jsr166 1.25 testCollection: {
571 jsr166 1.5 int n = 3 + rnd.nextInt(2);
572 jsr166 1.53 for (int i = 0; i < n; i++) {
573     Object x = impl.makeElement(i);
574     c.add(x);
575     copy.add(x);
576     }
577 jsr166 1.5 Iterator it = c.iterator();
578 jsr166 1.53 if (ordered) {
579     if (rnd.nextBoolean()) assertTrue(it.hasNext());
580 dl 1.61 mustEqual(impl.makeElement(0), it.next());
581 jsr166 1.53 if (rnd.nextBoolean()) assertTrue(it.hasNext());
582 dl 1.61 mustEqual(impl.makeElement(1), it.next());
583 jsr166 1.53 } else {
584     if (rnd.nextBoolean()) assertTrue(it.hasNext());
585     assertTrue(copy.contains(it.next()));
586     if (rnd.nextBoolean()) assertTrue(it.hasNext());
587     assertTrue(copy.contains(it.next()));
588     }
589 jsr166 1.54 if (rnd.nextBoolean()) assertTrue(it.hasNext());
590 jsr166 1.53 it.forEachRemaining(
591     e -> {
592     assertTrue(c.contains(e));
593     assertTrue(copy.contains(e));});
594 jsr166 1.21 if (testImplementationDetails) {
595     if (c instanceof java.util.concurrent.ArrayBlockingQueue) {
596     assertIteratorExhausted(it);
597     } else {
598 jsr166 1.25 try { it.remove(); }
599     catch (UnsupportedOperationException ok) {
600     break testCollection;
601     }
602 dl 1.61 mustEqual(n - 1, c.size());
603 jsr166 1.53 if (ordered) {
604     for (int i = 0; i < n - 1; i++)
605     assertTrue(c.contains(impl.makeElement(i)));
606     assertFalse(c.contains(impl.makeElement(n - 1)));
607     }
608 jsr166 1.21 }
609     }
610 jsr166 1.5 }
611     if (c instanceof Deque) {
612     Deque d = (Deque) impl.emptyCollection();
613 jsr166 1.53 assertTrue(ordered);
614 jsr166 1.5 int n = 3 + rnd.nextInt(2);
615     for (int i = 0; i < n; i++) d.add(impl.makeElement(i));
616     Iterator it = d.descendingIterator();
617     assertTrue(it.hasNext());
618 dl 1.61 mustEqual(impl.makeElement(n - 1), it.next());
619 jsr166 1.5 assertTrue(it.hasNext());
620 dl 1.61 mustEqual(impl.makeElement(n - 2), it.next());
621 jsr166 1.21 it.forEachRemaining(e -> assertTrue(c.contains(e)));
622     if (testImplementationDetails) {
623     it.remove();
624 dl 1.61 mustEqual(n - 1, d.size());
625 jsr166 1.21 for (int i = 1; i < n; i++)
626     assertTrue(d.contains(impl.makeElement(i)));
627     assertFalse(d.contains(impl.makeElement(0)));
628     }
629 jsr166 1.5 }
630     }
631    
632 jsr166 1.1 /**
633     * stream().forEach returns elements in the collection
634     */
635 jsr166 1.3 public void testStreamForEach() throws Throwable {
636 jsr166 1.1 final Collection c = impl.emptyCollection();
637     final Object x = impl.makeElement(1);
638     final Object y = impl.makeElement(2);
639     final ArrayList found = new ArrayList();
640 jsr166 1.20 Consumer<Object> spy = o -> found.add(o);
641 jsr166 1.1 c.stream().forEach(spy);
642     assertTrue(found.isEmpty());
643    
644     assertTrue(c.add(x));
645     c.stream().forEach(spy);
646 dl 1.61 mustEqual(Collections.singletonList(x), found);
647 jsr166 1.1 found.clear();
648    
649     assertTrue(c.add(y));
650     c.stream().forEach(spy);
651 dl 1.61 mustEqual(2, found.size());
652 jsr166 1.1 assertTrue(found.contains(x));
653     assertTrue(found.contains(y));
654     found.clear();
655    
656     c.clear();
657     c.stream().forEach(spy);
658     assertTrue(found.isEmpty());
659     }
660    
661 jsr166 1.3 public void testStreamForEachConcurrentStressTest() throws Throwable {
662     if (!impl.isConcurrent()) return;
663     final Collection c = impl.emptyCollection();
664     final long testDurationMillis = timeoutMillis();
665     final AtomicBoolean done = new AtomicBoolean(false);
666     final Object elt = impl.makeElement(1);
667     final Future<?> f1, f2;
668     final ExecutorService pool = Executors.newCachedThreadPool();
669     try (PoolCleaner cleaner = cleaner(pool, done)) {
670     final CountDownLatch threadsStarted = new CountDownLatch(2);
671     Runnable checkElt = () -> {
672     threadsStarted.countDown();
673     while (!done.get())
674 jsr166 1.20 c.stream().forEach(x -> assertSame(x, elt)); };
675 jsr166 1.3 Runnable addRemove = () -> {
676     threadsStarted.countDown();
677     while (!done.get()) {
678     assertTrue(c.add(elt));
679     assertTrue(c.remove(elt));
680     }};
681     f1 = pool.submit(checkElt);
682     f2 = pool.submit(addRemove);
683     Thread.sleep(testDurationMillis);
684     }
685     assertNull(f1.get(0L, MILLISECONDS));
686     assertNull(f2.get(0L, MILLISECONDS));
687     }
688    
689     /**
690     * collection.forEach returns elements in the collection
691     */
692     public void testForEach() throws Throwable {
693     final Collection c = impl.emptyCollection();
694     final Object x = impl.makeElement(1);
695     final Object y = impl.makeElement(2);
696     final ArrayList found = new ArrayList();
697 jsr166 1.20 Consumer<Object> spy = o -> found.add(o);
698 jsr166 1.3 c.forEach(spy);
699     assertTrue(found.isEmpty());
700    
701     assertTrue(c.add(x));
702     c.forEach(spy);
703 dl 1.61 mustEqual(Collections.singletonList(x), found);
704 jsr166 1.3 found.clear();
705    
706     assertTrue(c.add(y));
707     c.forEach(spy);
708 dl 1.61 mustEqual(2, found.size());
709 jsr166 1.3 assertTrue(found.contains(x));
710     assertTrue(found.contains(y));
711     found.clear();
712    
713     c.clear();
714     c.forEach(spy);
715     assertTrue(found.isEmpty());
716     }
717    
718 jsr166 1.38 /** TODO: promote to a common utility */
719     static <T> T chooseOne(T ... ts) {
720     return ts[ThreadLocalRandom.current().nextInt(ts.length)];
721     }
722    
723     /** TODO: more random adders and removers */
724     static <E> Runnable adderRemover(Collection<E> c, E e) {
725     return chooseOne(
726     () -> {
727     assertTrue(c.add(e));
728     assertTrue(c.contains(e));
729     assertTrue(c.remove(e));
730     assertFalse(c.contains(e));
731     },
732     () -> {
733     assertTrue(c.add(e));
734     assertTrue(c.contains(e));
735     assertTrue(c.removeIf(x -> x == e));
736     assertFalse(c.contains(e));
737     },
738     () -> {
739     assertTrue(c.add(e));
740     assertTrue(c.contains(e));
741     for (Iterator it = c.iterator();; )
742     if (it.next() == e) {
743     try { it.remove(); }
744     catch (UnsupportedOperationException ok) {
745     c.remove(e);
746     }
747     break;
748     }
749     assertFalse(c.contains(e));
750     });
751     }
752    
753 jsr166 1.26 /**
754 jsr166 1.45 * Concurrent Spliterators, once exhausted, stay exhausted.
755     */
756     public void testStickySpliteratorExhaustion() throws Throwable {
757     if (!impl.isConcurrent()) return;
758     if (!testImplementationDetails) return;
759     final ThreadLocalRandom rnd = ThreadLocalRandom.current();
760     final Consumer alwaysThrows = e -> { throw new AssertionError(); };
761     final Collection c = impl.emptyCollection();
762     final Spliterator s = c.spliterator();
763     if (rnd.nextBoolean()) {
764     assertFalse(s.tryAdvance(alwaysThrows));
765     } else {
766     s.forEachRemaining(alwaysThrows);
767     }
768     final Object one = impl.makeElement(1);
769     // Spliterator should not notice added element
770     c.add(one);
771     if (rnd.nextBoolean()) {
772     assertFalse(s.tryAdvance(alwaysThrows));
773     } else {
774     s.forEachRemaining(alwaysThrows);
775     }
776     }
777    
778     /**
779 jsr166 1.26 * Motley crew of threads concurrently randomly hammer the collection.
780     */
781     public void testDetectRaces() throws Throwable {
782 jsr166 1.1 if (!impl.isConcurrent()) return;
783 jsr166 1.26 final ThreadLocalRandom rnd = ThreadLocalRandom.current();
784 jsr166 1.1 final Collection c = impl.emptyCollection();
785 jsr166 1.34 final long testDurationMillis
786     = expensiveTests ? LONG_DELAY_MS : timeoutMillis();
787 jsr166 1.1 final AtomicBoolean done = new AtomicBoolean(false);
788 jsr166 1.26 final Object one = impl.makeElement(1);
789     final Object two = impl.makeElement(2);
790 jsr166 1.35 final Consumer checkSanity = x -> assertTrue(x == one || x == two);
791 jsr166 1.36 final Consumer<Object[]> checkArraySanity = array -> {
792 jsr166 1.37 // assertTrue(array.length <= 2); // duplicates are permitted
793 jsr166 1.36 for (Object x : array) assertTrue(x == one || x == two);
794     };
795 jsr166 1.29 final Object[] emptyArray =
796     (Object[]) java.lang.reflect.Array.newInstance(one.getClass(), 0);
797 jsr166 1.26 final List<Future<?>> futures;
798     final Phaser threadsStarted = new Phaser(1); // register this thread
799 jsr166 1.27 final Runnable[] frobbers = {
800 jsr166 1.32 () -> c.forEach(checkSanity),
801     () -> c.stream().forEach(checkSanity),
802     () -> c.parallelStream().forEach(checkSanity),
803 jsr166 1.26 () -> c.spliterator().trySplit(),
804     () -> {
805     Spliterator s = c.spliterator();
806 jsr166 1.32 s.tryAdvance(checkSanity);
807 jsr166 1.26 s.trySplit();
808     },
809     () -> {
810     Spliterator s = c.spliterator();
811 jsr166 1.32 do {} while (s.tryAdvance(checkSanity));
812 jsr166 1.29 },
813 jsr166 1.32 () -> { for (Object x : c) checkSanity.accept(x); },
814 jsr166 1.36 () -> checkArraySanity.accept(c.toArray()),
815     () -> checkArraySanity.accept(c.toArray(emptyArray)),
816 jsr166 1.29 () -> {
817 jsr166 1.38 Object[] a = new Object[5];
818     Object three = impl.makeElement(3);
819     Arrays.fill(a, 0, a.length, three);
820     Object[] x = c.toArray(a);
821     if (x == a)
822     for (int i = 0; i < a.length && a[i] != null; i++)
823     checkSanity.accept(a[i]);
824     // A careful reading of the spec does not support:
825     // for (i++; i < a.length; i++) assertSame(three, a[i]);
826     else
827     checkArraySanity.accept(x);
828     },
829     adderRemover(c, one),
830     adderRemover(c, two),
831 jsr166 1.27 };
832     final List<Runnable> tasks =
833     Arrays.stream(frobbers)
834 jsr166 1.26 .filter(task -> rnd.nextBoolean()) // random subset
835     .map(task -> (Runnable) () -> {
836     threadsStarted.arriveAndAwaitAdvance();
837     while (!done.get())
838     task.run();
839     })
840     .collect(Collectors.toList());
841 jsr166 1.2 final ExecutorService pool = Executors.newCachedThreadPool();
842     try (PoolCleaner cleaner = cleaner(pool, done)) {
843 jsr166 1.26 threadsStarted.bulkRegister(tasks.size());
844     futures = tasks.stream()
845 jsr166 1.28 .map(pool::submit)
846 jsr166 1.26 .collect(Collectors.toList());
847     threadsStarted.arriveAndDeregister();
848 jsr166 1.2 Thread.sleep(testDurationMillis);
849     }
850 jsr166 1.26 for (Future future : futures)
851     assertNull(future.get(0L, MILLISECONDS));
852 jsr166 1.1 }
853    
854 jsr166 1.30 /**
855     * Spliterators are either IMMUTABLE or truly late-binding or, if
856     * concurrent, use the same "late-binding style" of returning
857     * elements added between creation and first use.
858     */
859     public void testLateBindingStyle() {
860     if (!testImplementationDetails) return;
861 jsr166 1.31 if (impl.klazz() == ArrayList.class) return; // for jdk8
862 jsr166 1.30 // Immutable (snapshot) spliterators are exempt
863     if (impl.emptyCollection().spliterator()
864     .hasCharacteristics(Spliterator.IMMUTABLE))
865     return;
866     final Object one = impl.makeElement(1);
867     {
868     final Collection c = impl.emptyCollection();
869     final Spliterator split = c.spliterator();
870     c.add(one);
871     assertTrue(split.tryAdvance(e -> { assertSame(e, one); }));
872     assertFalse(split.tryAdvance(e -> { throw new AssertionError(); }));
873     assertTrue(c.contains(one));
874     }
875     {
876     final AtomicLong count = new AtomicLong(0);
877     final Collection c = impl.emptyCollection();
878     final Spliterator split = c.spliterator();
879     c.add(one);
880     split.forEachRemaining(
881     e -> { assertSame(e, one); count.getAndIncrement(); });
882 dl 1.61 mustEqual(1L, count.get());
883 jsr166 1.30 assertFalse(split.tryAdvance(e -> { throw new AssertionError(); }));
884     assertTrue(c.contains(one));
885     }
886     }
887    
888 jsr166 1.40 /**
889     * Spliterator.getComparator throws IllegalStateException iff the
890     * spliterator does not report SORTED.
891     */
892     public void testGetComparator_IllegalStateException() {
893     Collection c = impl.emptyCollection();
894     Spliterator s = c.spliterator();
895     boolean reportsSorted = s.hasCharacteristics(Spliterator.SORTED);
896     try {
897     s.getComparator();
898     assertTrue(reportsSorted);
899     } catch (IllegalStateException ex) {
900     assertFalse(reportsSorted);
901     }
902     }
903    
904 jsr166 1.51 public void testCollectionCopies() throws Exception {
905 jsr166 1.50 ThreadLocalRandom rnd = ThreadLocalRandom.current();
906     Collection c = impl.emptyCollection();
907 jsr166 1.51 for (int n = rnd.nextInt(4); n--> 0; )
908 jsr166 1.50 c.add(impl.makeElement(rnd.nextInt()));
909 dl 1.61 mustEqual(c, c);
910 jsr166 1.51 if (c instanceof List)
911     assertCollectionsEquals(c, new ArrayList(c));
912     else if (c instanceof Set)
913     assertCollectionsEquals(c, new HashSet(c));
914     else if (c instanceof Deque)
915     assertCollectionsEquivalent(c, new ArrayDeque(c));
916    
917     Collection clone = cloneableClone(c);
918     if (clone != null) {
919     assertSame(c.getClass(), clone.getClass());
920     assertCollectionsEquivalent(c, clone);
921 jsr166 1.50 }
922 jsr166 1.51 try {
923     Collection serialClone = serialClonePossiblyFailing(c);
924     assertSame(c.getClass(), serialClone.getClass());
925     assertCollectionsEquivalent(c, serialClone);
926     } catch (java.io.NotSerializableException acceptable) {}
927 jsr166 1.50 }
928    
929 jsr166 1.59 /**
930     * TODO: move out of limbo
931     * 8203662: remove increment of modCount from ArrayList and Vector replaceAll()
932     */
933     public void DISABLED_testReplaceAllIsNotStructuralModification() {
934 jsr166 1.52 Collection c = impl.emptyCollection();
935     if (!(c instanceof List))
936     return;
937     List list = (List) c;
938     ThreadLocalRandom rnd = ThreadLocalRandom.current();
939     for (int n = rnd.nextInt(2, 10); n--> 0; )
940     list.add(impl.makeElement(rnd.nextInt()));
941     ArrayList copy = new ArrayList(list);
942     int size = list.size(), half = size / 2;
943     Iterator it = list.iterator();
944     for (int i = 0; i < half; i++)
945 dl 1.61 mustEqual(it.next(), copy.get(i));
946 jsr166 1.52 list.replaceAll(n -> n);
947     // ConcurrentModificationException must not be thrown here.
948     for (int i = half; i < size; i++)
949 dl 1.61 mustEqual(it.next(), copy.get(i));
950 jsr166 1.52 }
951    
952 jsr166 1.4 // public void testCollection8DebugFail() {
953     // fail(impl.klazz().getSimpleName());
954     // }
955 jsr166 1.1 }