ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/Collection8Test.java
Revision: 1.43
Committed: Thu Dec 15 01:21:22 2016 UTC (7 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.42: +0 -1 lines
Log Message:
remove debugging print

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