ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/Collection8Test.java
Revision: 1.9
Committed: Thu Nov 3 16:53:13 2016 UTC (7 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.8: +3 -0 lines
Log Message:
more assertions

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