ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/Collection8Test.java
Revision: 1.6
Committed: Sat Oct 29 22:47:55 2016 UTC (7 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.5: +6 -1 lines
Log Message:
null actions should throw NPE even when nothing to do

File Contents

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