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