ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ConcurrentLinkedDequeTest.java
Revision: 1.31
Committed: Sun Oct 22 21:52:58 2017 UTC (6 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.30: +51 -22 lines
Log Message:
8189387: ConcurrentLinkedDeque linearizability continued ...

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9 import java.util.Arrays;
10 import java.util.Collection;
11 import java.util.Deque;
12 import java.util.Iterator;
13 import java.util.NoSuchElementException;
14 import java.util.Queue;
15 import java.util.Random;
16 import java.util.concurrent.CompletableFuture;
17 import java.util.concurrent.ConcurrentLinkedDeque;
18 import java.util.concurrent.ThreadLocalRandom;
19 import java.util.concurrent.atomic.LongAdder;
20
21 import junit.framework.Test;
22
23 public class ConcurrentLinkedDequeTest extends JSR166TestCase {
24
25 public static void main(String[] args) {
26 main(suite(), args);
27 }
28
29 public static Test suite() {
30 class Implementation implements CollectionImplementation {
31 public Class<?> klazz() { return ConcurrentLinkedDeque.class; }
32 public Collection emptyCollection() { return new ConcurrentLinkedDeque(); }
33 public Object makeElement(int i) { return i; }
34 public boolean isConcurrent() { return true; }
35 public boolean permitsNulls() { return false; }
36 }
37 return newTestSuite(ConcurrentLinkedDequeTest.class,
38 CollectionTest.testSuite(new Implementation()));
39 }
40
41 /**
42 * Returns a new deque of given size containing consecutive
43 * Integers 0 ... n - 1.
44 */
45 private static ConcurrentLinkedDeque<Integer> populatedDeque(int n) {
46 ConcurrentLinkedDeque<Integer> q = new ConcurrentLinkedDeque<>();
47 assertTrue(q.isEmpty());
48 for (int i = 0; i < n; ++i)
49 assertTrue(q.offer(new Integer(i)));
50 assertFalse(q.isEmpty());
51 assertEquals(n, q.size());
52 assertEquals((Integer) 0, q.peekFirst());
53 assertEquals((Integer) (n - 1), q.peekLast());
54 return q;
55 }
56
57 /**
58 * new deque is empty
59 */
60 public void testConstructor1() {
61 assertTrue(new ConcurrentLinkedDeque().isEmpty());
62 assertEquals(0, new ConcurrentLinkedDeque().size());
63 }
64
65 /**
66 * Initializing from null Collection throws NPE
67 */
68 public void testConstructor3() {
69 try {
70 new ConcurrentLinkedDeque((Collection)null);
71 shouldThrow();
72 } catch (NullPointerException success) {}
73 }
74
75 /**
76 * Initializing from Collection of null elements throws NPE
77 */
78 public void testConstructor4() {
79 try {
80 new ConcurrentLinkedDeque(Arrays.asList(new Integer[SIZE]));
81 shouldThrow();
82 } catch (NullPointerException success) {}
83 }
84
85 /**
86 * Initializing from Collection with some null elements throws NPE
87 */
88 public void testConstructor5() {
89 Integer[] ints = new Integer[SIZE];
90 for (int i = 0; i < SIZE - 1; ++i)
91 ints[i] = new Integer(i);
92 try {
93 new ConcurrentLinkedDeque(Arrays.asList(ints));
94 shouldThrow();
95 } catch (NullPointerException success) {}
96 }
97
98 /**
99 * Deque contains all elements of collection used to initialize
100 */
101 public void testConstructor6() {
102 Integer[] ints = new Integer[SIZE];
103 for (int i = 0; i < SIZE; ++i)
104 ints[i] = new Integer(i);
105 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(Arrays.asList(ints));
106 for (int i = 0; i < SIZE; ++i)
107 assertEquals(ints[i], q.poll());
108 }
109
110 /**
111 * isEmpty is true before add, false after
112 */
113 public void testEmpty() {
114 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
115 assertTrue(q.isEmpty());
116 q.add(one);
117 assertFalse(q.isEmpty());
118 q.add(two);
119 q.remove();
120 q.remove();
121 assertTrue(q.isEmpty());
122 }
123
124 /**
125 * size() changes when elements added and removed
126 */
127 public void testSize() {
128 ConcurrentLinkedDeque q = populatedDeque(SIZE);
129 for (int i = 0; i < SIZE; ++i) {
130 assertEquals(SIZE - i, q.size());
131 q.remove();
132 }
133 for (int i = 0; i < SIZE; ++i) {
134 assertEquals(i, q.size());
135 q.add(new Integer(i));
136 }
137 }
138
139 /**
140 * push(null) throws NPE
141 */
142 public void testPushNull() {
143 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
144 try {
145 q.push(null);
146 shouldThrow();
147 } catch (NullPointerException success) {}
148 }
149
150 /**
151 * peekFirst() returns element inserted with push
152 */
153 public void testPush() {
154 ConcurrentLinkedDeque q = populatedDeque(3);
155 q.pollLast();
156 q.push(four);
157 assertSame(four, q.peekFirst());
158 }
159
160 /**
161 * pop() removes first element, or throws NSEE if empty
162 */
163 public void testPop() {
164 ConcurrentLinkedDeque q = populatedDeque(SIZE);
165 for (int i = 0; i < SIZE; ++i) {
166 assertEquals(i, q.pop());
167 }
168 try {
169 q.pop();
170 shouldThrow();
171 } catch (NoSuchElementException success) {}
172 }
173
174 /**
175 * offer(null) throws NPE
176 */
177 public void testOfferNull() {
178 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
179 try {
180 q.offer(null);
181 shouldThrow();
182 } catch (NullPointerException success) {}
183 }
184
185 /**
186 * offerFirst(null) throws NPE
187 */
188 public void testOfferFirstNull() {
189 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
190 try {
191 q.offerFirst(null);
192 shouldThrow();
193 } catch (NullPointerException success) {}
194 }
195
196 /**
197 * offerLast(null) throws NPE
198 */
199 public void testOfferLastNull() {
200 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
201 try {
202 q.offerLast(null);
203 shouldThrow();
204 } catch (NullPointerException success) {}
205 }
206
207 /**
208 * offer(x) succeeds
209 */
210 public void testOffer() {
211 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
212 assertTrue(q.offer(zero));
213 assertTrue(q.offer(one));
214 assertSame(zero, q.peekFirst());
215 assertSame(one, q.peekLast());
216 }
217
218 /**
219 * offerFirst(x) succeeds
220 */
221 public void testOfferFirst() {
222 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
223 assertTrue(q.offerFirst(zero));
224 assertTrue(q.offerFirst(one));
225 assertSame(one, q.peekFirst());
226 assertSame(zero, q.peekLast());
227 }
228
229 /**
230 * offerLast(x) succeeds
231 */
232 public void testOfferLast() {
233 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
234 assertTrue(q.offerLast(zero));
235 assertTrue(q.offerLast(one));
236 assertSame(zero, q.peekFirst());
237 assertSame(one, q.peekLast());
238 }
239
240 /**
241 * add(null) throws NPE
242 */
243 public void testAddNull() {
244 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
245 try {
246 q.add(null);
247 shouldThrow();
248 } catch (NullPointerException success) {}
249 }
250
251 /**
252 * addFirst(null) throws NPE
253 */
254 public void testAddFirstNull() {
255 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
256 try {
257 q.addFirst(null);
258 shouldThrow();
259 } catch (NullPointerException success) {}
260 }
261
262 /**
263 * addLast(null) throws NPE
264 */
265 public void testAddLastNull() {
266 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
267 try {
268 q.addLast(null);
269 shouldThrow();
270 } catch (NullPointerException success) {}
271 }
272
273 /**
274 * add(x) succeeds
275 */
276 public void testAdd() {
277 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
278 assertTrue(q.add(zero));
279 assertTrue(q.add(one));
280 assertSame(zero, q.peekFirst());
281 assertSame(one, q.peekLast());
282 }
283
284 /**
285 * addFirst(x) succeeds
286 */
287 public void testAddFirst() {
288 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
289 q.addFirst(zero);
290 q.addFirst(one);
291 assertSame(one, q.peekFirst());
292 assertSame(zero, q.peekLast());
293 }
294
295 /**
296 * addLast(x) succeeds
297 */
298 public void testAddLast() {
299 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
300 q.addLast(zero);
301 q.addLast(one);
302 assertSame(zero, q.peekFirst());
303 assertSame(one, q.peekLast());
304 }
305
306 /**
307 * addAll(null) throws NPE
308 */
309 public void testAddAll1() {
310 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
311 try {
312 q.addAll(null);
313 shouldThrow();
314 } catch (NullPointerException success) {}
315 }
316
317 /**
318 * addAll(this) throws IllegalArgumentException
319 */
320 public void testAddAllSelf() {
321 ConcurrentLinkedDeque q = populatedDeque(SIZE);
322 try {
323 q.addAll(q);
324 shouldThrow();
325 } catch (IllegalArgumentException success) {}
326 }
327
328 /**
329 * addAll of a collection with null elements throws NPE
330 */
331 public void testAddAll2() {
332 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
333 try {
334 q.addAll(Arrays.asList(new Integer[SIZE]));
335 shouldThrow();
336 } catch (NullPointerException success) {}
337 }
338
339 /**
340 * addAll of a collection with any null elements throws NPE after
341 * possibly adding some elements
342 */
343 public void testAddAll3() {
344 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
345 Integer[] ints = new Integer[SIZE];
346 for (int i = 0; i < SIZE - 1; ++i)
347 ints[i] = new Integer(i);
348 try {
349 q.addAll(Arrays.asList(ints));
350 shouldThrow();
351 } catch (NullPointerException success) {}
352 }
353
354 /**
355 * Deque contains all elements, in traversal order, of successful addAll
356 */
357 public void testAddAll5() {
358 Integer[] empty = new Integer[0];
359 Integer[] ints = new Integer[SIZE];
360 for (int i = 0; i < SIZE; ++i)
361 ints[i] = new Integer(i);
362 ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
363 assertFalse(q.addAll(Arrays.asList(empty)));
364 assertTrue(q.addAll(Arrays.asList(ints)));
365 for (int i = 0; i < SIZE; ++i)
366 assertEquals(ints[i], q.poll());
367 }
368
369 /**
370 * pollFirst() succeeds unless empty
371 */
372 public void testPollFirst() {
373 ConcurrentLinkedDeque q = populatedDeque(SIZE);
374 for (int i = 0; i < SIZE; ++i) {
375 assertEquals(i, q.pollFirst());
376 }
377 assertNull(q.pollFirst());
378 }
379
380 /**
381 * pollLast() succeeds unless empty
382 */
383 public void testPollLast() {
384 ConcurrentLinkedDeque q = populatedDeque(SIZE);
385 for (int i = SIZE - 1; i >= 0; --i) {
386 assertEquals(i, q.pollLast());
387 }
388 assertNull(q.pollLast());
389 }
390
391 /**
392 * poll() succeeds unless empty
393 */
394 public void testPoll() {
395 ConcurrentLinkedDeque q = populatedDeque(SIZE);
396 for (int i = 0; i < SIZE; ++i) {
397 assertEquals(i, q.poll());
398 }
399 assertNull(q.poll());
400 }
401
402 /**
403 * peek() returns next element, or null if empty
404 */
405 public void testPeek() {
406 ConcurrentLinkedDeque q = populatedDeque(SIZE);
407 for (int i = 0; i < SIZE; ++i) {
408 assertEquals(i, q.peek());
409 assertEquals(i, q.poll());
410 assertTrue(q.peek() == null ||
411 !q.peek().equals(i));
412 }
413 assertNull(q.peek());
414 }
415
416 /**
417 * element() returns first element, or throws NSEE if empty
418 */
419 public void testElement() {
420 ConcurrentLinkedDeque q = populatedDeque(SIZE);
421 for (int i = 0; i < SIZE; ++i) {
422 assertEquals(i, q.element());
423 assertEquals(i, q.poll());
424 }
425 try {
426 q.element();
427 shouldThrow();
428 } catch (NoSuchElementException success) {}
429 }
430
431 /**
432 * remove() removes next element, or throws NSEE if empty
433 */
434 public void testRemove() {
435 ConcurrentLinkedDeque q = populatedDeque(SIZE);
436 for (int i = 0; i < SIZE; ++i) {
437 assertEquals(i, q.remove());
438 }
439 try {
440 q.remove();
441 shouldThrow();
442 } catch (NoSuchElementException success) {}
443 }
444
445 /**
446 * remove(x) removes x and returns true if present
447 */
448 public void testRemoveElement() {
449 ConcurrentLinkedDeque q = populatedDeque(SIZE);
450 for (int i = 1; i < SIZE; i += 2) {
451 assertTrue(q.contains(i));
452 assertTrue(q.remove(i));
453 assertFalse(q.contains(i));
454 assertTrue(q.contains(i - 1));
455 }
456 for (int i = 0; i < SIZE; i += 2) {
457 assertTrue(q.contains(i));
458 assertTrue(q.remove(i));
459 assertFalse(q.contains(i));
460 assertFalse(q.remove(i + 1));
461 assertFalse(q.contains(i + 1));
462 }
463 assertTrue(q.isEmpty());
464 }
465
466 /**
467 * peekFirst() returns next element, or null if empty
468 */
469 public void testPeekFirst() {
470 ConcurrentLinkedDeque q = populatedDeque(SIZE);
471 for (int i = 0; i < SIZE; ++i) {
472 assertEquals(i, q.peekFirst());
473 assertEquals(i, q.pollFirst());
474 assertTrue(q.peekFirst() == null ||
475 !q.peekFirst().equals(i));
476 }
477 assertNull(q.peekFirst());
478 }
479
480 /**
481 * peekLast() returns next element, or null if empty
482 */
483 public void testPeekLast() {
484 ConcurrentLinkedDeque q = populatedDeque(SIZE);
485 for (int i = SIZE - 1; i >= 0; --i) {
486 assertEquals(i, q.peekLast());
487 assertEquals(i, q.pollLast());
488 assertTrue(q.peekLast() == null ||
489 !q.peekLast().equals(i));
490 }
491 assertNull(q.peekLast());
492 }
493
494 /**
495 * getFirst() returns first element, or throws NSEE if empty
496 */
497 public void testFirstElement() {
498 ConcurrentLinkedDeque q = populatedDeque(SIZE);
499 for (int i = 0; i < SIZE; ++i) {
500 assertEquals(i, q.getFirst());
501 assertEquals(i, q.pollFirst());
502 }
503 try {
504 q.getFirst();
505 shouldThrow();
506 } catch (NoSuchElementException success) {}
507 }
508
509 /**
510 * getLast() returns last element, or throws NSEE if empty
511 */
512 public void testLastElement() {
513 ConcurrentLinkedDeque q = populatedDeque(SIZE);
514 for (int i = SIZE - 1; i >= 0; --i) {
515 assertEquals(i, q.getLast());
516 assertEquals(i, q.pollLast());
517 }
518 try {
519 q.getLast();
520 shouldThrow();
521 } catch (NoSuchElementException success) {}
522 assertNull(q.peekLast());
523 }
524
525 /**
526 * removeFirst() removes first element, or throws NSEE if empty
527 */
528 public void testRemoveFirst() {
529 ConcurrentLinkedDeque q = populatedDeque(SIZE);
530 for (int i = 0; i < SIZE; ++i) {
531 assertEquals(i, q.removeFirst());
532 }
533 try {
534 q.removeFirst();
535 shouldThrow();
536 } catch (NoSuchElementException success) {}
537 assertNull(q.peekFirst());
538 }
539
540 /**
541 * removeLast() removes last element, or throws NSEE if empty
542 */
543 public void testRemoveLast() {
544 ConcurrentLinkedDeque q = populatedDeque(SIZE);
545 for (int i = SIZE - 1; i >= 0; --i) {
546 assertEquals(i, q.removeLast());
547 }
548 try {
549 q.removeLast();
550 shouldThrow();
551 } catch (NoSuchElementException success) {}
552 assertNull(q.peekLast());
553 }
554
555 /**
556 * removeFirstOccurrence(x) removes x and returns true if present
557 */
558 public void testRemoveFirstOccurrence() {
559 ConcurrentLinkedDeque q = populatedDeque(SIZE);
560 for (int i = 1; i < SIZE; i += 2) {
561 assertTrue(q.removeFirstOccurrence(new Integer(i)));
562 }
563 for (int i = 0; i < SIZE; i += 2) {
564 assertTrue(q.removeFirstOccurrence(new Integer(i)));
565 assertFalse(q.removeFirstOccurrence(new Integer(i + 1)));
566 }
567 assertTrue(q.isEmpty());
568 }
569
570 /**
571 * removeLastOccurrence(x) removes x and returns true if present
572 */
573 public void testRemoveLastOccurrence() {
574 ConcurrentLinkedDeque q = populatedDeque(SIZE);
575 for (int i = 1; i < SIZE; i += 2) {
576 assertTrue(q.removeLastOccurrence(new Integer(i)));
577 }
578 for (int i = 0; i < SIZE; i += 2) {
579 assertTrue(q.removeLastOccurrence(new Integer(i)));
580 assertFalse(q.removeLastOccurrence(new Integer(i + 1)));
581 }
582 assertTrue(q.isEmpty());
583 }
584
585 /**
586 * contains(x) reports true when elements added but not yet removed
587 */
588 public void testContains() {
589 ConcurrentLinkedDeque q = populatedDeque(SIZE);
590 for (int i = 0; i < SIZE; ++i) {
591 assertTrue(q.contains(new Integer(i)));
592 q.poll();
593 assertFalse(q.contains(new Integer(i)));
594 }
595 }
596
597 /**
598 * clear() removes all elements
599 */
600 public void testClear() {
601 ConcurrentLinkedDeque q = populatedDeque(SIZE);
602 q.clear();
603 assertTrue(q.isEmpty());
604 assertEquals(0, q.size());
605 q.add(one);
606 assertFalse(q.isEmpty());
607 q.clear();
608 assertTrue(q.isEmpty());
609 }
610
611 /**
612 * containsAll(c) is true when c contains a subset of elements
613 */
614 public void testContainsAll() {
615 ConcurrentLinkedDeque q = populatedDeque(SIZE);
616 ConcurrentLinkedDeque p = new ConcurrentLinkedDeque();
617 for (int i = 0; i < SIZE; ++i) {
618 assertTrue(q.containsAll(p));
619 assertFalse(p.containsAll(q));
620 p.add(new Integer(i));
621 }
622 assertTrue(p.containsAll(q));
623 }
624
625 /**
626 * retainAll(c) retains only those elements of c and reports true if change
627 */
628 public void testRetainAll() {
629 ConcurrentLinkedDeque q = populatedDeque(SIZE);
630 ConcurrentLinkedDeque p = populatedDeque(SIZE);
631 for (int i = 0; i < SIZE; ++i) {
632 boolean changed = q.retainAll(p);
633 if (i == 0)
634 assertFalse(changed);
635 else
636 assertTrue(changed);
637
638 assertTrue(q.containsAll(p));
639 assertEquals(SIZE - i, q.size());
640 p.remove();
641 }
642 }
643
644 /**
645 * removeAll(c) removes only those elements of c and reports true if changed
646 */
647 public void testRemoveAll() {
648 for (int i = 1; i < SIZE; ++i) {
649 ConcurrentLinkedDeque q = populatedDeque(SIZE);
650 ConcurrentLinkedDeque p = populatedDeque(i);
651 assertTrue(q.removeAll(p));
652 assertEquals(SIZE - i, q.size());
653 for (int j = 0; j < i; ++j) {
654 Integer x = (Integer)(p.remove());
655 assertFalse(q.contains(x));
656 }
657 }
658 }
659
660 /**
661 * toArray() contains all elements in FIFO order
662 */
663 public void testToArray() {
664 ConcurrentLinkedDeque q = populatedDeque(SIZE);
665 Object[] o = q.toArray();
666 for (int i = 0; i < o.length; i++)
667 assertSame(o[i], q.poll());
668 }
669
670 /**
671 * toArray(a) contains all elements in FIFO order
672 */
673 public void testToArray2() {
674 ConcurrentLinkedDeque<Integer> q = populatedDeque(SIZE);
675 Integer[] ints = new Integer[SIZE];
676 Integer[] array = q.toArray(ints);
677 assertSame(ints, array);
678 for (int i = 0; i < ints.length; i++)
679 assertSame(ints[i], q.poll());
680 }
681
682 /**
683 * toArray(null) throws NullPointerException
684 */
685 public void testToArray_NullArg() {
686 ConcurrentLinkedDeque q = populatedDeque(SIZE);
687 try {
688 q.toArray(null);
689 shouldThrow();
690 } catch (NullPointerException success) {}
691 }
692
693 /**
694 * toArray(incompatible array type) throws ArrayStoreException
695 */
696 public void testToArray1_BadArg() {
697 ConcurrentLinkedDeque q = populatedDeque(SIZE);
698 try {
699 q.toArray(new String[10]);
700 shouldThrow();
701 } catch (ArrayStoreException success) {}
702 }
703
704 /**
705 * Iterator iterates through all elements
706 */
707 public void testIterator() {
708 ConcurrentLinkedDeque q = populatedDeque(SIZE);
709 Iterator it = q.iterator();
710 int i;
711 for (i = 0; it.hasNext(); i++)
712 assertTrue(q.contains(it.next()));
713 assertEquals(i, SIZE);
714 assertIteratorExhausted(it);
715 }
716
717 /**
718 * iterator of empty collection has no elements
719 */
720 public void testEmptyIterator() {
721 Deque c = new ConcurrentLinkedDeque();
722 assertIteratorExhausted(c.iterator());
723 assertIteratorExhausted(c.descendingIterator());
724 }
725
726 /**
727 * Iterator ordering is FIFO
728 */
729 public void testIteratorOrdering() {
730 final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
731 q.add(one);
732 q.add(two);
733 q.add(three);
734
735 int k = 0;
736 for (Iterator it = q.iterator(); it.hasNext();) {
737 assertEquals(++k, it.next());
738 }
739
740 assertEquals(3, k);
741 }
742
743 /**
744 * Modifications do not cause iterators to fail
745 */
746 public void testWeaklyConsistentIteration() {
747 final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
748 q.add(one);
749 q.add(two);
750 q.add(three);
751
752 for (Iterator it = q.iterator(); it.hasNext();) {
753 q.remove();
754 it.next();
755 }
756
757 assertEquals("deque should be empty again", 0, q.size());
758 }
759
760 /**
761 * iterator.remove() removes current element
762 */
763 public void testIteratorRemove() {
764 final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
765 final Random rng = new Random();
766 for (int iters = 0; iters < 100; ++iters) {
767 int max = rng.nextInt(5) + 2;
768 int split = rng.nextInt(max - 1) + 1;
769 for (int j = 1; j <= max; ++j)
770 q.add(new Integer(j));
771 Iterator it = q.iterator();
772 for (int j = 1; j <= split; ++j)
773 assertEquals(it.next(), new Integer(j));
774 it.remove();
775 assertEquals(it.next(), new Integer(split + 1));
776 for (int j = 1; j <= split; ++j)
777 q.remove(new Integer(j));
778 it = q.iterator();
779 for (int j = split + 1; j <= max; ++j) {
780 assertEquals(it.next(), new Integer(j));
781 it.remove();
782 }
783 assertFalse(it.hasNext());
784 assertTrue(q.isEmpty());
785 }
786 }
787
788 /**
789 * Descending iterator iterates through all elements
790 */
791 public void testDescendingIterator() {
792 ConcurrentLinkedDeque q = populatedDeque(SIZE);
793 int i = 0;
794 Iterator it = q.descendingIterator();
795 while (it.hasNext()) {
796 assertTrue(q.contains(it.next()));
797 ++i;
798 }
799 assertEquals(i, SIZE);
800 assertFalse(it.hasNext());
801 try {
802 it.next();
803 shouldThrow();
804 } catch (NoSuchElementException success) {}
805 }
806
807 /**
808 * Descending iterator ordering is reverse FIFO
809 */
810 public void testDescendingIteratorOrdering() {
811 final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
812 for (int iters = 0; iters < 100; ++iters) {
813 q.add(new Integer(3));
814 q.add(new Integer(2));
815 q.add(new Integer(1));
816 int k = 0;
817 for (Iterator it = q.descendingIterator(); it.hasNext();) {
818 assertEquals(++k, it.next());
819 }
820
821 assertEquals(3, k);
822 q.remove();
823 q.remove();
824 q.remove();
825 }
826 }
827
828 /**
829 * descendingIterator.remove() removes current element
830 */
831 public void testDescendingIteratorRemove() {
832 final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
833 final Random rng = new Random();
834 for (int iters = 0; iters < 100; ++iters) {
835 int max = rng.nextInt(5) + 2;
836 int split = rng.nextInt(max - 1) + 1;
837 for (int j = max; j >= 1; --j)
838 q.add(new Integer(j));
839 Iterator it = q.descendingIterator();
840 for (int j = 1; j <= split; ++j)
841 assertEquals(it.next(), new Integer(j));
842 it.remove();
843 assertEquals(it.next(), new Integer(split + 1));
844 for (int j = 1; j <= split; ++j)
845 q.remove(new Integer(j));
846 it = q.descendingIterator();
847 for (int j = split + 1; j <= max; ++j) {
848 assertEquals(it.next(), new Integer(j));
849 it.remove();
850 }
851 assertFalse(it.hasNext());
852 assertTrue(q.isEmpty());
853 }
854 }
855
856 /**
857 * toString() contains toStrings of elements
858 */
859 public void testToString() {
860 ConcurrentLinkedDeque q = populatedDeque(SIZE);
861 String s = q.toString();
862 for (int i = 0; i < SIZE; ++i) {
863 assertTrue(s.contains(String.valueOf(i)));
864 }
865 }
866
867 /**
868 * A deserialized/reserialized deque has same elements in same order
869 */
870 public void testSerialization() throws Exception {
871 Queue x = populatedDeque(SIZE);
872 Queue y = serialClone(x);
873
874 assertNotSame(x, y);
875 assertEquals(x.size(), y.size());
876 assertEquals(x.toString(), y.toString());
877 assertTrue(Arrays.equals(x.toArray(), y.toArray()));
878 while (!x.isEmpty()) {
879 assertFalse(y.isEmpty());
880 assertEquals(x.remove(), y.remove());
881 }
882 assertTrue(y.isEmpty());
883 }
884
885 /**
886 * contains(null) always return false.
887 * remove(null) always throws NullPointerException.
888 */
889 public void testNeverContainsNull() {
890 Deque<?>[] qs = {
891 new ConcurrentLinkedDeque<Object>(),
892 populatedDeque(2),
893 };
894
895 for (Deque<?> q : qs) {
896 assertFalse(q.contains(null));
897 try {
898 assertFalse(q.remove(null));
899 shouldThrow();
900 } catch (NullPointerException success) {}
901 try {
902 assertFalse(q.removeFirstOccurrence(null));
903 shouldThrow();
904 } catch (NullPointerException success) {}
905 try {
906 assertFalse(q.removeLastOccurrence(null));
907 shouldThrow();
908 } catch (NullPointerException success) {}
909 }
910 }
911
912 void runAsync(Runnable r1, Runnable r2) {
913 boolean b = ThreadLocalRandom.current().nextBoolean();
914 CompletableFuture<Void> f1 = CompletableFuture.runAsync(b ? r1 : r2);
915 CompletableFuture<Void> f2 = CompletableFuture.runAsync(b ? r2 : r1);
916 f1.join();
917 f2.join();
918 }
919
920 /**
921 * Non-traversing Deque operations are linearizable.
922 * https://bugs.openjdk.java.net/browse/JDK-8188900
923 * ant -Djsr166.expensiveTests=true -Djsr166.tckTestClass=ConcurrentLinkedDequeTest -Djsr166.methodFilter=testBug8188900 tck
924 */
925 public void testBug8188900() {
926 final ThreadLocalRandom rnd = ThreadLocalRandom.current();
927 final LongAdder nulls = new LongAdder(), zeros = new LongAdder();
928 for (int n = expensiveTests ? 100_000 : 10; n--> 0; ) {
929 ConcurrentLinkedDeque<Integer> d = new ConcurrentLinkedDeque<>();
930
931 boolean peek = rnd.nextBoolean();
932 Runnable getter = () -> {
933 Integer x = peek ? d.peekFirst() : d.pollFirst();
934 if (x == null) nulls.increment();
935 else if (x == 0) zeros.increment();
936 else
937 throw new AssertionError(
938 String.format(
939 "unexpected value %d after %d nulls and %d zeros",
940 x, nulls.sum(), zeros.sum()));
941 };
942
943 Runnable adder = () -> { d.addFirst(0); d.addLast(42); };
944
945 runAsync(getter, adder);
946 }
947 }
948
949 /**
950 * Reverse direction variant of testBug8188900
951 */
952 public void testBug8188900_reverse() {
953 final ThreadLocalRandom rnd = ThreadLocalRandom.current();
954 final LongAdder nulls = new LongAdder(), zeros = new LongAdder();
955 for (int n = expensiveTests ? 100_000 : 10; n--> 0; ) {
956 ConcurrentLinkedDeque<Integer> d = new ConcurrentLinkedDeque<>();
957
958 boolean peek = rnd.nextBoolean();
959 Runnable getter = () -> {
960 Integer x = peek ? d.peekLast() : d.pollLast();
961 if (x == null) nulls.increment();
962 else if (x == 0) zeros.increment();
963 else
964 throw new AssertionError(
965 String.format(
966 "unexpected value %d after %d nulls and %d zeros",
967 x, nulls.sum(), zeros.sum()));
968 };
969
970 Runnable adder = () -> { d.addLast(0); d.addFirst(42); };
971
972 runAsync(getter, adder);
973 }
974 }
975
976 <T> T chooseRandomly(T... choices) {
977 return choices[ThreadLocalRandom.current().nextInt(choices.length)];
978 }
979
980 /**
981 * Non-traversing Deque operations (that return null) are linearizable.
982 * Don't return null when the deque is observably never empty.
983 * https://bugs.openjdk.java.net/browse/JDK-8189387
984 * ant -Djsr166.expensiveTests=true -Djsr166.tckTestClass=ConcurrentLinkedDequeTest -Djsr166.methodFilter=testBug8189387 tck
985 */
986 public void testBug8189387() {
987 final ThreadLocalRandom rnd = ThreadLocalRandom.current();
988 Object x = new Object();
989 for (int n = expensiveTests ? 100_000 : 10; n--> 0; ) {
990 ConcurrentLinkedDeque<Object> d = new ConcurrentLinkedDeque<>();
991 Runnable add = chooseRandomly(
992 () -> d.addFirst(x),
993 () -> d.offerFirst(x),
994 () -> d.addLast(x),
995 () -> d.offerLast(x));
996
997 Runnable get = chooseRandomly(
998 () -> assertFalse(d.isEmpty()),
999 () -> assertSame(x, d.peekFirst()),
1000 () -> assertSame(x, d.peekLast()),
1001 () -> assertSame(x, d.pollFirst()),
1002 () -> assertSame(x, d.pollLast()));
1003
1004 Runnable addRemove = chooseRandomly(
1005 () -> { d.addFirst(x); d.pollLast(); },
1006 () -> { d.offerFirst(x); d.removeFirst(); },
1007 () -> { d.offerLast(x); d.removeLast(); },
1008 () -> { d.addLast(x); d.pollFirst(); });
1009
1010 add.run();
1011 runAsync(get, addRemove);
1012 }
1013 }
1014 }