ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/Collection8Test.java
Revision: 1.7
Committed: Mon Oct 31 20:08:40 2016 UTC (7 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.6: +22 -19 lines
Log Message:
testRemoveIf: better diagnostics on failure

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     import static java.util.concurrent.TimeUnit.MILLISECONDS;
9    
10     import java.util.ArrayList;
11     import java.util.Collection;
12     import java.util.Collections;
13 jsr166 1.5 import java.util.Deque;
14     import java.util.HashSet;
15     import java.util.Iterator;
16     import java.util.List;
17     import java.util.NoSuchElementException;
18     import java.util.Queue;
19     import java.util.Spliterator;
20 jsr166 1.2 import java.util.concurrent.CountDownLatch;
21 jsr166 1.1 import java.util.concurrent.Executors;
22     import java.util.concurrent.ExecutorService;
23     import java.util.concurrent.Future;
24 jsr166 1.5 import java.util.concurrent.ThreadLocalRandom;
25 jsr166 1.1 import java.util.concurrent.atomic.AtomicBoolean;
26     import java.util.concurrent.atomic.AtomicLong;
27 jsr166 1.5 import java.util.concurrent.atomic.AtomicReference;
28 jsr166 1.1 import java.util.function.Consumer;
29 jsr166 1.5 import java.util.function.Predicate;
30 jsr166 1.1
31     import junit.framework.Test;
32    
33     /**
34     * Contains tests applicable to all jdk8+ Collection implementations.
35     * An extension of CollectionTest.
36     */
37     public class Collection8Test extends JSR166TestCase {
38     final CollectionImplementation impl;
39    
40     /** Tests are parameterized by a Collection implementation. */
41     Collection8Test(CollectionImplementation impl, String methodName) {
42     super(methodName);
43     this.impl = impl;
44     }
45    
46     public static Test testSuite(CollectionImplementation impl) {
47     return parameterizedTestSuite(Collection8Test.class,
48     CollectionImplementation.class,
49     impl);
50     }
51    
52 jsr166 1.5 /** Checks properties of empty collections. */
53     public void testEmptyMeansEmpty() {
54     Collection c = impl.emptyCollection();
55     assertTrue(c.isEmpty());
56     assertEquals(0, c.size());
57     assertEquals("[]", c.toString());
58     {
59     Object[] a = c.toArray();
60     assertEquals(0, a.length);
61     assertSame(Object[].class, a.getClass());
62     }
63     {
64     Object[] a = new Object[0];
65     assertSame(a, c.toArray(a));
66     }
67     {
68     Integer[] a = new Integer[0];
69     assertSame(a, c.toArray(a));
70     }
71     {
72     Integer[] a = { 1, 2, 3};
73     assertSame(a, c.toArray(a));
74     assertNull(a[0]);
75     assertSame(2, a[1]);
76     assertSame(3, a[2]);
77     }
78     assertIteratorExhausted(c.iterator());
79     Consumer alwaysThrows = (e) -> { throw new AssertionError(); };
80     c.forEach(alwaysThrows);
81     c.iterator().forEachRemaining(alwaysThrows);
82     c.spliterator().forEachRemaining(alwaysThrows);
83     assertFalse(c.spliterator().tryAdvance(alwaysThrows));
84     if (Queue.class.isAssignableFrom(impl.klazz())) {
85     Queue q = (Queue) c;
86     assertNull(q.peek());
87     assertNull(q.poll());
88     }
89     if (Deque.class.isAssignableFrom(impl.klazz())) {
90     Deque d = (Deque) c;
91     assertNull(d.peekFirst());
92     assertNull(d.peekLast());
93     assertNull(d.pollFirst());
94     assertNull(d.pollLast());
95     assertIteratorExhausted(d.descendingIterator());
96     }
97     }
98    
99     public void testNullPointerExceptions() {
100     Collection c = impl.emptyCollection();
101     assertThrows(
102     NullPointerException.class,
103     () -> c.addAll(null),
104     () -> c.containsAll(null),
105     () -> c.retainAll(null),
106     () -> c.removeAll(null),
107     () -> c.removeIf(null),
108 jsr166 1.6 () -> c.forEach(null),
109     () -> c.iterator().forEachRemaining(null),
110     () -> c.spliterator().forEachRemaining(null),
111     () -> c.spliterator().tryAdvance(null),
112 jsr166 1.5 () -> c.toArray(null));
113    
114     if (!impl.permitsNulls()) {
115     assertThrows(
116     NullPointerException.class,
117     () -> c.add(null));
118     }
119     if (!impl.permitsNulls()
120     && Queue.class.isAssignableFrom(impl.klazz())) {
121     Queue q = (Queue) c;
122     assertThrows(
123     NullPointerException.class,
124     () -> q.offer(null));
125     }
126     if (!impl.permitsNulls()
127     && Deque.class.isAssignableFrom(impl.klazz())) {
128     Deque d = (Deque) c;
129     assertThrows(
130     NullPointerException.class,
131     () -> d.addFirst(null),
132     () -> d.addLast(null),
133     () -> d.offerFirst(null),
134     () -> d.offerLast(null),
135 jsr166 1.6 () -> d.push(null),
136     () -> d.descendingIterator().forEachRemaining(null));
137 jsr166 1.5 }
138     }
139    
140     public void testNoSuchElementExceptions() {
141     Collection c = impl.emptyCollection();
142     assertThrows(
143     NoSuchElementException.class,
144     () -> c.iterator().next());
145    
146     if (Queue.class.isAssignableFrom(impl.klazz())) {
147     Queue q = (Queue) c;
148     assertThrows(
149     NoSuchElementException.class,
150     () -> q.element(),
151     () -> q.remove());
152     }
153     if (Deque.class.isAssignableFrom(impl.klazz())) {
154     Deque d = (Deque) c;
155     assertThrows(
156     NoSuchElementException.class,
157     () -> d.getFirst(),
158     () -> d.getLast(),
159     () -> d.removeFirst(),
160     () -> d.removeLast(),
161     () -> d.pop(),
162     () -> d.descendingIterator().next());
163     }
164     }
165    
166     public void testRemoveIf() {
167     Collection c = impl.emptyCollection();
168     ThreadLocalRandom rnd = ThreadLocalRandom.current();
169     int n = rnd.nextInt(6);
170     for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
171     AtomicReference threwAt = new AtomicReference(null);
172     ArrayList survivors = new ArrayList(c);
173     ArrayList accepts = new ArrayList();
174     ArrayList rejects = new ArrayList();
175     Predicate randomPredicate = (e) -> {
176     assertNull(threwAt.get());
177     switch (rnd.nextInt(3)) {
178     case 0: accepts.add(e); return true;
179     case 1: rejects.add(e); return false;
180     case 2: threwAt.set(e); throw new ArithmeticException();
181     default: throw new AssertionError();
182     }
183     };
184     try {
185 jsr166 1.7 try {
186     boolean modified = c.removeIf(randomPredicate);
187     if (!modified) {
188     assertNull(threwAt.get());
189     assertEquals(n, rejects.size());
190     assertEquals(0, accepts.size());
191     }
192     } catch (ArithmeticException ok) {}
193     survivors.removeAll(accepts);
194     assertEquals(n - accepts.size(), c.size());
195     assertTrue(c.containsAll(survivors));
196     assertTrue(survivors.containsAll(rejects));
197     for (Object x : accepts) assertFalse(c.contains(x));
198     if (threwAt.get() == null)
199     assertEquals(accepts.size() + rejects.size(), n);
200     } catch (Throwable ex) {
201 jsr166 1.5 System.err.println(impl.klazz());
202 jsr166 1.7 System.err.printf("c=%s%n", c);
203     System.err.printf("n=%d%n", n);
204     System.err.printf("accepts=%s%n", accepts);
205     System.err.printf("rejects=%s%n", rejects);
206 jsr166 1.5 System.err.println(survivors);
207 jsr166 1.7 System.err.printf("threw=%s%n", threwAt.get());
208     throw ex;
209 jsr166 1.5 }
210     }
211    
212     /**
213     * Various ways of traversing a collection yield same elements
214     */
215     public void testIteratorEquivalence() {
216     Collection c = impl.emptyCollection();
217     ThreadLocalRandom rnd = ThreadLocalRandom.current();
218     int n = rnd.nextInt(6);
219     for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
220     ArrayList iterated = new ArrayList();
221     ArrayList iteratedForEachRemaining = new ArrayList();
222     ArrayList spliterated = new ArrayList();
223     ArrayList foreached = new ArrayList();
224     for (Object x : c) iterated.add(x);
225     c.iterator().forEachRemaining(e -> iteratedForEachRemaining.add(e));
226     c.spliterator().forEachRemaining(e -> spliterated.add(e));
227     c.forEach(e -> foreached.add(e));
228     boolean ordered =
229     c.spliterator().hasCharacteristics(Spliterator.ORDERED);
230     if (c instanceof List || c instanceof Deque)
231     assertTrue(ordered);
232     if (ordered) {
233     assertEquals(iterated, iteratedForEachRemaining);
234     assertEquals(iterated, spliterated);
235     assertEquals(iterated, foreached);
236     } else {
237     HashSet cset = new HashSet(c);
238     assertEquals(cset, new HashSet(iterated));
239     assertEquals(cset, new HashSet(iteratedForEachRemaining));
240     assertEquals(cset, new HashSet(spliterated));
241     assertEquals(cset, new HashSet(foreached));
242     }
243     if (c instanceof Deque) {
244     Deque d = (Deque) c;
245     ArrayList descending = new ArrayList();
246     ArrayList descendingForEachRemaining = new ArrayList();
247     for (Iterator it = d.descendingIterator(); it.hasNext(); )
248     descending.add(it.next());
249     d.descendingIterator().forEachRemaining(
250     e -> descendingForEachRemaining.add(e));
251     Collections.reverse(descending);
252     Collections.reverse(descendingForEachRemaining);
253     assertEquals(iterated, descending);
254     assertEquals(iterated, descendingForEachRemaining);
255     }
256     }
257    
258     /**
259     * Calling Iterator#remove() after Iterator#forEachRemaining
260     * should remove last element
261     */
262     public void testRemoveAfterForEachRemaining() {
263     Collection c = impl.emptyCollection();
264     ThreadLocalRandom rnd = ThreadLocalRandom.current();
265     {
266     int n = 3 + rnd.nextInt(2);
267     for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
268     Iterator it = c.iterator();
269     assertTrue(it.hasNext());
270     assertEquals(impl.makeElement(0), it.next());
271     assertTrue(it.hasNext());
272     assertEquals(impl.makeElement(1), it.next());
273     it.forEachRemaining((e) -> {});
274     it.remove();
275     assertEquals(n - 1, c.size());
276     for (int i = 0; i < n - 1; i++)
277     assertTrue(c.contains(impl.makeElement(i)));
278     assertFalse(c.contains(impl.makeElement(n - 1)));
279     }
280     if (c instanceof Deque) {
281     Deque d = (Deque) impl.emptyCollection();
282     int n = 3 + rnd.nextInt(2);
283     for (int i = 0; i < n; i++) d.add(impl.makeElement(i));
284     Iterator it = d.descendingIterator();
285     assertTrue(it.hasNext());
286     assertEquals(impl.makeElement(n - 1), it.next());
287     assertTrue(it.hasNext());
288     assertEquals(impl.makeElement(n - 2), it.next());
289     it.forEachRemaining((e) -> {});
290     it.remove();
291     assertEquals(n - 1, d.size());
292     for (int i = 1; i < n; i++)
293     assertTrue(d.contains(impl.makeElement(i)));
294     assertFalse(d.contains(impl.makeElement(0)));
295     }
296     }
297    
298 jsr166 1.1 /**
299     * stream().forEach returns elements in the collection
300     */
301 jsr166 1.3 public void testStreamForEach() throws Throwable {
302 jsr166 1.1 final Collection c = impl.emptyCollection();
303     final AtomicLong count = new AtomicLong(0L);
304     final Object x = impl.makeElement(1);
305     final Object y = impl.makeElement(2);
306     final ArrayList found = new ArrayList();
307     Consumer<Object> spy = (o) -> { found.add(o); };
308     c.stream().forEach(spy);
309     assertTrue(found.isEmpty());
310    
311     assertTrue(c.add(x));
312     c.stream().forEach(spy);
313     assertEquals(Collections.singletonList(x), found);
314     found.clear();
315    
316     assertTrue(c.add(y));
317     c.stream().forEach(spy);
318     assertEquals(2, found.size());
319     assertTrue(found.contains(x));
320     assertTrue(found.contains(y));
321     found.clear();
322    
323     c.clear();
324     c.stream().forEach(spy);
325     assertTrue(found.isEmpty());
326     }
327    
328 jsr166 1.3 public void testStreamForEachConcurrentStressTest() throws Throwable {
329     if (!impl.isConcurrent()) return;
330     final Collection c = impl.emptyCollection();
331     final long testDurationMillis = timeoutMillis();
332     final AtomicBoolean done = new AtomicBoolean(false);
333     final Object elt = impl.makeElement(1);
334     final Future<?> f1, f2;
335     final ExecutorService pool = Executors.newCachedThreadPool();
336     try (PoolCleaner cleaner = cleaner(pool, done)) {
337     final CountDownLatch threadsStarted = new CountDownLatch(2);
338     Runnable checkElt = () -> {
339     threadsStarted.countDown();
340     while (!done.get())
341     c.stream().forEach((x) -> { assertSame(x, elt); }); };
342     Runnable addRemove = () -> {
343     threadsStarted.countDown();
344     while (!done.get()) {
345     assertTrue(c.add(elt));
346     assertTrue(c.remove(elt));
347     }};
348     f1 = pool.submit(checkElt);
349     f2 = pool.submit(addRemove);
350     Thread.sleep(testDurationMillis);
351     }
352     assertNull(f1.get(0L, MILLISECONDS));
353     assertNull(f2.get(0L, MILLISECONDS));
354     }
355    
356     /**
357     * collection.forEach returns elements in the collection
358     */
359     public void testForEach() throws Throwable {
360     final Collection c = impl.emptyCollection();
361     final AtomicLong count = new AtomicLong(0L);
362     final Object x = impl.makeElement(1);
363     final Object y = impl.makeElement(2);
364     final ArrayList found = new ArrayList();
365     Consumer<Object> spy = (o) -> { found.add(o); };
366     c.forEach(spy);
367     assertTrue(found.isEmpty());
368    
369     assertTrue(c.add(x));
370     c.forEach(spy);
371     assertEquals(Collections.singletonList(x), found);
372     found.clear();
373    
374     assertTrue(c.add(y));
375     c.forEach(spy);
376     assertEquals(2, found.size());
377     assertTrue(found.contains(x));
378     assertTrue(found.contains(y));
379     found.clear();
380    
381     c.clear();
382     c.forEach(spy);
383     assertTrue(found.isEmpty());
384     }
385    
386 jsr166 1.1 public void testForEachConcurrentStressTest() throws Throwable {
387     if (!impl.isConcurrent()) return;
388     final Collection c = impl.emptyCollection();
389 jsr166 1.2 final long testDurationMillis = timeoutMillis();
390 jsr166 1.1 final AtomicBoolean done = new AtomicBoolean(false);
391     final Object elt = impl.makeElement(1);
392 jsr166 1.2 final Future<?> f1, f2;
393     final ExecutorService pool = Executors.newCachedThreadPool();
394     try (PoolCleaner cleaner = cleaner(pool, done)) {
395     final CountDownLatch threadsStarted = new CountDownLatch(2);
396     Runnable checkElt = () -> {
397     threadsStarted.countDown();
398     while (!done.get())
399 jsr166 1.3 c.forEach((x) -> { assertSame(x, elt); }); };
400 jsr166 1.2 Runnable addRemove = () -> {
401     threadsStarted.countDown();
402     while (!done.get()) {
403     assertTrue(c.add(elt));
404     assertTrue(c.remove(elt));
405     }};
406     f1 = pool.submit(checkElt);
407     f2 = pool.submit(addRemove);
408     Thread.sleep(testDurationMillis);
409     }
410     assertNull(f1.get(0L, MILLISECONDS));
411     assertNull(f2.get(0L, MILLISECONDS));
412 jsr166 1.1 }
413    
414 jsr166 1.4 // public void testCollection8DebugFail() {
415     // fail(impl.klazz().getSimpleName());
416     // }
417 jsr166 1.1 }