ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/Collection8Test.java
Revision: 1.8
Committed: Thu Nov 3 15:31:25 2016 UTC (7 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.7: +2 -1 lines
Log Message:
improve testRemoveIf

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.8 assertFalse(survivors.contains(null));
186 jsr166 1.7 try {
187     boolean modified = c.removeIf(randomPredicate);
188     if (!modified) {
189     assertNull(threwAt.get());
190     assertEquals(n, rejects.size());
191     assertEquals(0, accepts.size());
192     }
193     } catch (ArithmeticException ok) {}
194     survivors.removeAll(accepts);
195     assertEquals(n - accepts.size(), c.size());
196     assertTrue(c.containsAll(survivors));
197     assertTrue(survivors.containsAll(rejects));
198     for (Object x : accepts) assertFalse(c.contains(x));
199     if (threwAt.get() == null)
200     assertEquals(accepts.size() + rejects.size(), n);
201     } catch (Throwable ex) {
202 jsr166 1.5 System.err.println(impl.klazz());
203 jsr166 1.7 System.err.printf("c=%s%n", c);
204     System.err.printf("n=%d%n", n);
205     System.err.printf("accepts=%s%n", accepts);
206     System.err.printf("rejects=%s%n", rejects);
207 jsr166 1.8 System.err.printf("survivors=%s%n", survivors);
208 jsr166 1.7 System.err.printf("threw=%s%n", threwAt.get());
209     throw ex;
210 jsr166 1.5 }
211     }
212    
213     /**
214     * Various ways of traversing a collection yield same elements
215     */
216     public void testIteratorEquivalence() {
217     Collection c = impl.emptyCollection();
218     ThreadLocalRandom rnd = ThreadLocalRandom.current();
219     int n = rnd.nextInt(6);
220     for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
221     ArrayList iterated = new ArrayList();
222     ArrayList iteratedForEachRemaining = new ArrayList();
223     ArrayList spliterated = new ArrayList();
224     ArrayList foreached = new ArrayList();
225     for (Object x : c) iterated.add(x);
226     c.iterator().forEachRemaining(e -> iteratedForEachRemaining.add(e));
227     c.spliterator().forEachRemaining(e -> spliterated.add(e));
228     c.forEach(e -> foreached.add(e));
229     boolean ordered =
230     c.spliterator().hasCharacteristics(Spliterator.ORDERED);
231     if (c instanceof List || c instanceof Deque)
232     assertTrue(ordered);
233     if (ordered) {
234     assertEquals(iterated, iteratedForEachRemaining);
235     assertEquals(iterated, spliterated);
236     assertEquals(iterated, foreached);
237     } else {
238     HashSet cset = new HashSet(c);
239     assertEquals(cset, new HashSet(iterated));
240     assertEquals(cset, new HashSet(iteratedForEachRemaining));
241     assertEquals(cset, new HashSet(spliterated));
242     assertEquals(cset, new HashSet(foreached));
243     }
244     if (c instanceof Deque) {
245     Deque d = (Deque) c;
246     ArrayList descending = new ArrayList();
247     ArrayList descendingForEachRemaining = new ArrayList();
248     for (Iterator it = d.descendingIterator(); it.hasNext(); )
249     descending.add(it.next());
250     d.descendingIterator().forEachRemaining(
251     e -> descendingForEachRemaining.add(e));
252     Collections.reverse(descending);
253     Collections.reverse(descendingForEachRemaining);
254     assertEquals(iterated, descending);
255     assertEquals(iterated, descendingForEachRemaining);
256     }
257     }
258    
259     /**
260     * Calling Iterator#remove() after Iterator#forEachRemaining
261     * should remove last element
262     */
263     public void testRemoveAfterForEachRemaining() {
264     Collection c = impl.emptyCollection();
265     ThreadLocalRandom rnd = ThreadLocalRandom.current();
266     {
267     int n = 3 + rnd.nextInt(2);
268     for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
269     Iterator it = c.iterator();
270     assertTrue(it.hasNext());
271     assertEquals(impl.makeElement(0), it.next());
272     assertTrue(it.hasNext());
273     assertEquals(impl.makeElement(1), it.next());
274     it.forEachRemaining((e) -> {});
275     it.remove();
276     assertEquals(n - 1, c.size());
277     for (int i = 0; i < n - 1; i++)
278     assertTrue(c.contains(impl.makeElement(i)));
279     assertFalse(c.contains(impl.makeElement(n - 1)));
280     }
281     if (c instanceof Deque) {
282     Deque d = (Deque) impl.emptyCollection();
283     int n = 3 + rnd.nextInt(2);
284     for (int i = 0; i < n; i++) d.add(impl.makeElement(i));
285     Iterator it = d.descendingIterator();
286     assertTrue(it.hasNext());
287     assertEquals(impl.makeElement(n - 1), it.next());
288     assertTrue(it.hasNext());
289     assertEquals(impl.makeElement(n - 2), it.next());
290     it.forEachRemaining((e) -> {});
291     it.remove();
292     assertEquals(n - 1, d.size());
293     for (int i = 1; i < n; i++)
294     assertTrue(d.contains(impl.makeElement(i)));
295     assertFalse(d.contains(impl.makeElement(0)));
296     }
297     }
298    
299 jsr166 1.1 /**
300     * stream().forEach returns elements in the collection
301     */
302 jsr166 1.3 public void testStreamForEach() throws Throwable {
303 jsr166 1.1 final Collection c = impl.emptyCollection();
304     final AtomicLong count = new AtomicLong(0L);
305     final Object x = impl.makeElement(1);
306     final Object y = impl.makeElement(2);
307     final ArrayList found = new ArrayList();
308     Consumer<Object> spy = (o) -> { found.add(o); };
309     c.stream().forEach(spy);
310     assertTrue(found.isEmpty());
311    
312     assertTrue(c.add(x));
313     c.stream().forEach(spy);
314     assertEquals(Collections.singletonList(x), found);
315     found.clear();
316    
317     assertTrue(c.add(y));
318     c.stream().forEach(spy);
319     assertEquals(2, found.size());
320     assertTrue(found.contains(x));
321     assertTrue(found.contains(y));
322     found.clear();
323    
324     c.clear();
325     c.stream().forEach(spy);
326     assertTrue(found.isEmpty());
327     }
328    
329 jsr166 1.3 public void testStreamForEachConcurrentStressTest() throws Throwable {
330     if (!impl.isConcurrent()) return;
331     final Collection c = impl.emptyCollection();
332     final long testDurationMillis = timeoutMillis();
333     final AtomicBoolean done = new AtomicBoolean(false);
334     final Object elt = impl.makeElement(1);
335     final Future<?> f1, f2;
336     final ExecutorService pool = Executors.newCachedThreadPool();
337     try (PoolCleaner cleaner = cleaner(pool, done)) {
338     final CountDownLatch threadsStarted = new CountDownLatch(2);
339     Runnable checkElt = () -> {
340     threadsStarted.countDown();
341     while (!done.get())
342     c.stream().forEach((x) -> { assertSame(x, elt); }); };
343     Runnable addRemove = () -> {
344     threadsStarted.countDown();
345     while (!done.get()) {
346     assertTrue(c.add(elt));
347     assertTrue(c.remove(elt));
348     }};
349     f1 = pool.submit(checkElt);
350     f2 = pool.submit(addRemove);
351     Thread.sleep(testDurationMillis);
352     }
353     assertNull(f1.get(0L, MILLISECONDS));
354     assertNull(f2.get(0L, MILLISECONDS));
355     }
356    
357     /**
358     * collection.forEach returns elements in the collection
359     */
360     public void testForEach() throws Throwable {
361     final Collection c = impl.emptyCollection();
362     final AtomicLong count = new AtomicLong(0L);
363     final Object x = impl.makeElement(1);
364     final Object y = impl.makeElement(2);
365     final ArrayList found = new ArrayList();
366     Consumer<Object> spy = (o) -> { found.add(o); };
367     c.forEach(spy);
368     assertTrue(found.isEmpty());
369    
370     assertTrue(c.add(x));
371     c.forEach(spy);
372     assertEquals(Collections.singletonList(x), found);
373     found.clear();
374    
375     assertTrue(c.add(y));
376     c.forEach(spy);
377     assertEquals(2, found.size());
378     assertTrue(found.contains(x));
379     assertTrue(found.contains(y));
380     found.clear();
381    
382     c.clear();
383     c.forEach(spy);
384     assertTrue(found.isEmpty());
385     }
386    
387 jsr166 1.1 public void testForEachConcurrentStressTest() throws Throwable {
388     if (!impl.isConcurrent()) return;
389     final Collection c = impl.emptyCollection();
390 jsr166 1.2 final long testDurationMillis = timeoutMillis();
391 jsr166 1.1 final AtomicBoolean done = new AtomicBoolean(false);
392     final Object elt = impl.makeElement(1);
393 jsr166 1.2 final Future<?> f1, f2;
394     final ExecutorService pool = Executors.newCachedThreadPool();
395     try (PoolCleaner cleaner = cleaner(pool, done)) {
396     final CountDownLatch threadsStarted = new CountDownLatch(2);
397     Runnable checkElt = () -> {
398     threadsStarted.countDown();
399     while (!done.get())
400 jsr166 1.3 c.forEach((x) -> { assertSame(x, elt); }); };
401 jsr166 1.2 Runnable addRemove = () -> {
402     threadsStarted.countDown();
403     while (!done.get()) {
404     assertTrue(c.add(elt));
405     assertTrue(c.remove(elt));
406     }};
407     f1 = pool.submit(checkElt);
408     f2 = pool.submit(addRemove);
409     Thread.sleep(testDurationMillis);
410     }
411     assertNull(f1.get(0L, MILLISECONDS));
412     assertNull(f2.get(0L, MILLISECONDS));
413 jsr166 1.1 }
414    
415 jsr166 1.4 // public void testCollection8DebugFail() {
416     // fail(impl.klazz().getSimpleName());
417     // }
418 jsr166 1.1 }