ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ConcurrentLinkedDequeTest.java
(Generate patch)

Comparing jsr166/src/test/tck/ConcurrentLinkedDequeTest.java (file contents):
Revision 1.1 by jsr166, Wed Aug 25 21:40:03 2010 UTC vs.
Revision 1.32 by jsr166, Mon May 28 21:19:50 2018 UTC

# Line 1 | Line 1
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/licenses/publicdomain
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 junit.framework.*;
10 < import java.util.*;
11 < import java.util.concurrent.*;
12 < import java.io.*;
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 <        junit.textui.TestRunner.run(suite());
26 >        main(suite(), args);
27      }
28  
29      public static Test suite() {
30 <        return new TestSuite(ConcurrentLinkedDequeTest.class);
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 <     * Create a deque of given size containing consecutive
43 <     * Integers 0 ... n.
42 >     * Returns a new deque of given size containing consecutive
43 >     * Integers 0 ... n - 1.
44       */
45 <    private ConcurrentLinkedDeque populatedDeque(int n) {
46 <        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
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  
# Line 48 | Line 67 | public class ConcurrentLinkedDequeTest e
67       */
68      public void testConstructor3() {
69          try {
70 <            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque((Collection)null);
70 >            new ConcurrentLinkedDeque((Collection)null);
71              shouldThrow();
72          } catch (NullPointerException success) {}
73      }
# Line 58 | Line 77 | public class ConcurrentLinkedDequeTest e
77       */
78      public void testConstructor4() {
79          try {
80 <            Integer[] ints = new Integer[SIZE];
62 <            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(Arrays.asList(ints));
80 >            new ConcurrentLinkedDeque(Arrays.asList(new Integer[SIZE]));
81              shouldThrow();
82          } catch (NullPointerException success) {}
83      }
# Line 68 | Line 86 | public class ConcurrentLinkedDequeTest e
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 <            Integer[] ints = new Integer[SIZE];
73 <            for (int i = 0; i < SIZE-1; ++i)
74 <                ints[i] = new Integer(i);
75 <            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(Arrays.asList(ints));
93 >            new ConcurrentLinkedDeque(Arrays.asList(ints));
94              shouldThrow();
95          } catch (NullPointerException success) {}
96      }
# Line 109 | Line 127 | public class ConcurrentLinkedDequeTest e
127      public void testSize() {
128          ConcurrentLinkedDeque q = populatedDeque(SIZE);
129          for (int i = 0; i < SIZE; ++i) {
130 <            assertEquals(SIZE-i, q.size());
130 >            assertEquals(SIZE - i, q.size());
131              q.remove();
132          }
133          for (int i = 0; i < SIZE; ++i) {
# Line 122 | Line 140 | public class ConcurrentLinkedDequeTest e
140       * push(null) throws NPE
141       */
142      public void testPushNull() {
143 +        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
144          try {
126            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
145              q.push(null);
146              shouldThrow();
147          } catch (NullPointerException success) {}
# Line 157 | Line 175 | public class ConcurrentLinkedDequeTest e
175       * offer(null) throws NPE
176       */
177      public void testOfferNull() {
178 +        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
179          try {
161            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
180              q.offer(null);
181              shouldThrow();
182          } catch (NullPointerException success) {}
# Line 168 | Line 186 | public class ConcurrentLinkedDequeTest e
186       * offerFirst(null) throws NPE
187       */
188      public void testOfferFirstNull() {
189 +        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
190          try {
172            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
191              q.offerFirst(null);
192              shouldThrow();
193          } catch (NullPointerException success) {}
# Line 179 | Line 197 | public class ConcurrentLinkedDequeTest e
197       * offerLast(null) throws NPE
198       */
199      public void testOfferLastNull() {
200 +        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
201          try {
183            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
202              q.offerLast(null);
203              shouldThrow();
204          } catch (NullPointerException success) {}
# Line 223 | Line 241 | public class ConcurrentLinkedDequeTest e
241       * add(null) throws NPE
242       */
243      public void testAddNull() {
244 +        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
245          try {
227            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
246              q.add(null);
247              shouldThrow();
248          } catch (NullPointerException success) {}
# Line 234 | Line 252 | public class ConcurrentLinkedDequeTest e
252       * addFirst(null) throws NPE
253       */
254      public void testAddFirstNull() {
255 +        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
256          try {
238            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
257              q.addFirst(null);
258              shouldThrow();
259          } catch (NullPointerException success) {}
# Line 245 | Line 263 | public class ConcurrentLinkedDequeTest e
263       * addLast(null) throws NPE
264       */
265      public void testAddLastNull() {
266 +        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
267          try {
249            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
268              q.addLast(null);
269              shouldThrow();
270          } catch (NullPointerException success) {}
# Line 289 | Line 307 | public class ConcurrentLinkedDequeTest e
307       * addAll(null) throws NPE
308       */
309      public void testAddAll1() {
310 +        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
311          try {
293            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
312              q.addAll(null);
313              shouldThrow();
314          } catch (NullPointerException success) {}
315      }
316  
317      /**
318 <     * addAll(this) throws IAE
318 >     * addAll(this) throws IllegalArgumentException
319       */
320      public void testAddAllSelf() {
321 +        ConcurrentLinkedDeque q = populatedDeque(SIZE);
322          try {
304            ConcurrentLinkedDeque q = populatedDeque(SIZE);
323              q.addAll(q);
324              shouldThrow();
325          } catch (IllegalArgumentException success) {}
# Line 311 | Line 329 | public class ConcurrentLinkedDequeTest e
329       * addAll of a collection with null elements throws NPE
330       */
331      public void testAddAll2() {
332 +        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
333          try {
334 <            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
316 <            Integer[] ints = new Integer[SIZE];
317 <            q.addAll(Arrays.asList(ints));
334 >            q.addAll(Arrays.asList(new Integer[SIZE]));
335              shouldThrow();
336          } catch (NullPointerException success) {}
337      }
# Line 324 | Line 341 | public class ConcurrentLinkedDequeTest e
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 {
328            ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
329            Integer[] ints = new Integer[SIZE];
330            for (int i = 0; i < SIZE-1; ++i)
331                ints[i] = new Integer(i);
349              q.addAll(Arrays.asList(ints));
350              shouldThrow();
351          } catch (NullPointerException success) {}
# Line 365 | Line 382 | public class ConcurrentLinkedDequeTest e
382       */
383      public void testPollLast() {
384          ConcurrentLinkedDeque q = populatedDeque(SIZE);
385 <        for (int i = SIZE-1; i >= 0; --i) {
385 >        for (int i = SIZE - 1; i >= 0; --i) {
386              assertEquals(i, q.pollLast());
387          }
388          assertNull(q.pollLast());
# Line 430 | Line 447 | public class ConcurrentLinkedDequeTest e
447       */
448      public void testRemoveElement() {
449          ConcurrentLinkedDeque q = populatedDeque(SIZE);
450 <        for (int i = 1; i < SIZE; i+=2) {
451 <            assertTrue(q.remove(new Integer(i)));
452 <        }
453 <        for (int i = 0; i < SIZE; i+=2) {
454 <            assertTrue(q.remove(new Integer(i)));
455 <            assertFalse(q.remove(new Integer(i+1)));
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      }
# Line 459 | Line 482 | public class ConcurrentLinkedDequeTest e
482       */
483      public void testPeekLast() {
484          ConcurrentLinkedDeque q = populatedDeque(SIZE);
485 <        for (int i = SIZE-1; i >= 0; --i) {
485 >        for (int i = SIZE - 1; i >= 0; --i) {
486              assertEquals(i, q.peekLast());
487              assertEquals(i, q.pollLast());
488              assertTrue(q.peekLast() == null ||
# Line 488 | Line 511 | public class ConcurrentLinkedDequeTest e
511       */
512      public void testLastElement() {
513          ConcurrentLinkedDeque q = populatedDeque(SIZE);
514 <        for (int i = SIZE-1; i >= 0; --i) {
514 >        for (int i = SIZE - 1; i >= 0; --i) {
515              assertEquals(i, q.getLast());
516              assertEquals(i, q.pollLast());
517          }
# Line 534 | Line 557 | public class ConcurrentLinkedDequeTest e
557       */
558      public void testRemoveFirstOccurrence() {
559          ConcurrentLinkedDeque q = populatedDeque(SIZE);
560 <        for (int i = 1; i < SIZE; i+=2) {
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) {
563 >        for (int i = 0; i < SIZE; i += 2) {
564              assertTrue(q.removeFirstOccurrence(new Integer(i)));
565 <            assertFalse(q.removeFirstOccurrence(new Integer(i+1)));
565 >            assertFalse(q.removeFirstOccurrence(new Integer(i + 1)));
566          }
567          assertTrue(q.isEmpty());
568      }
# Line 549 | Line 572 | public class ConcurrentLinkedDequeTest e
572       */
573      public void testRemoveLastOccurrence() {
574          ConcurrentLinkedDeque q = populatedDeque(SIZE);
575 <        for (int i = 1; i < SIZE; i+=2) {
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) {
578 >        for (int i = 0; i < SIZE; i += 2) {
579              assertTrue(q.removeLastOccurrence(new Integer(i)));
580 <            assertFalse(q.removeLastOccurrence(new Integer(i+1)));
580 >            assertFalse(q.removeLastOccurrence(new Integer(i + 1)));
581          }
582          assertTrue(q.isEmpty());
583      }
# Line 613 | Line 636 | public class ConcurrentLinkedDequeTest e
636                  assertTrue(changed);
637  
638              assertTrue(q.containsAll(p));
639 <            assertEquals(SIZE-i, q.size());
639 >            assertEquals(SIZE - i, q.size());
640              p.remove();
641          }
642      }
# Line 626 | Line 649 | public class ConcurrentLinkedDequeTest e
649              ConcurrentLinkedDeque q = populatedDeque(SIZE);
650              ConcurrentLinkedDeque p = populatedDeque(i);
651              assertTrue(q.removeAll(p));
652 <            assertEquals(SIZE-i, q.size());
652 >            assertEquals(SIZE - i, q.size());
653              for (int j = 0; j < i; ++j) {
654 <                Integer I = (Integer)(p.remove());
655 <                assertFalse(q.contains(I));
654 >                Integer x = (Integer)(p.remove());
655 >                assertFalse(q.contains(x));
656              }
657          }
658      }
659  
660      /**
661 <     * toArray() contains all elements
661 >     * toArray() contains all elements in FIFO order
662       */
663      public void testToArray() {
664          ConcurrentLinkedDeque q = populatedDeque(SIZE);
665 <        Object[] o = q.toArray();
666 <        Arrays.sort(o);
667 <        for (int i = 0; i < o.length; i++)
668 <            assertEquals(o[i], q.poll());
665 >        Object[] a = q.toArray();
666 >        assertSame(Object[].class, a.getClass());
667 >        for (Object o : a)
668 >            assertSame(o, q.poll());
669 >        assertTrue(q.isEmpty());
670      }
671  
672      /**
673 <     * toArray(a) contains all elements
673 >     * toArray(a) contains all elements in FIFO order
674       */
675      public void testToArray2() {
676 <        ConcurrentLinkedDeque q = populatedDeque(SIZE);
676 >        ConcurrentLinkedDeque<Integer> q = populatedDeque(SIZE);
677          Integer[] ints = new Integer[SIZE];
678 <        ints = (Integer[])q.toArray(ints);
679 <        Arrays.sort(ints);
680 <        for (int i = 0; i < ints.length; i++)
681 <            assertEquals(ints[i], q.poll());
678 >        Integer[] array = q.toArray(ints);
679 >        assertSame(ints, array);
680 >        for (Integer o : ints)
681 >            assertSame(o, q.poll());
682 >        assertTrue(q.isEmpty());
683      }
684  
685      /**
686 <     * toArray(null) throws NPE
686 >     * toArray(null) throws NullPointerException
687       */
688 <    public void testToArray_BadArg() {
688 >    public void testToArray_NullArg() {
689          ConcurrentLinkedDeque q = populatedDeque(SIZE);
690          try {
691 <            Object o[] = q.toArray(null);
691 >            q.toArray(null);
692              shouldThrow();
693          } catch (NullPointerException success) {}
694      }
695  
696      /**
697 <     * toArray() with incompatible array type throws ArrayStoreException
697 >     * toArray(incompatible array type) throws ArrayStoreException
698       */
699      public void testToArray1_BadArg() {
700          ConcurrentLinkedDeque q = populatedDeque(SIZE);
701          try {
702 <            Object o[] = q.toArray(new String[10]);
702 >            q.toArray(new String[10]);
703              shouldThrow();
704          } catch (ArrayStoreException success) {}
705      }
# Line 684 | Line 709 | public class ConcurrentLinkedDequeTest e
709       */
710      public void testIterator() {
711          ConcurrentLinkedDeque q = populatedDeque(SIZE);
687        int i = 0;
712          Iterator it = q.iterator();
713 <        while (it.hasNext()) {
713 >        int i;
714 >        for (i = 0; it.hasNext(); i++)
715              assertTrue(q.contains(it.next()));
691            ++i;
692        }
716          assertEquals(i, SIZE);
717 +        assertIteratorExhausted(it);
718 +    }
719 +
720 +    /**
721 +     * iterator of empty collection has no elements
722 +     */
723 +    public void testEmptyIterator() {
724 +        Deque c = new ConcurrentLinkedDeque();
725 +        assertIteratorExhausted(c.iterator());
726 +        assertIteratorExhausted(c.descendingIterator());
727      }
728  
729      /**
# Line 735 | Line 768 | public class ConcurrentLinkedDequeTest e
768          final Random rng = new Random();
769          for (int iters = 0; iters < 100; ++iters) {
770              int max = rng.nextInt(5) + 2;
771 <            int split = rng.nextInt(max-1) + 1;
771 >            int split = rng.nextInt(max - 1) + 1;
772              for (int j = 1; j <= max; ++j)
773                  q.add(new Integer(j));
774              Iterator it = q.iterator();
775              for (int j = 1; j <= split; ++j)
776                  assertEquals(it.next(), new Integer(j));
777              it.remove();
778 <            assertEquals(it.next(), new Integer(split+1));
778 >            assertEquals(it.next(), new Integer(split + 1));
779              for (int j = 1; j <= split; ++j)
780                  q.remove(new Integer(j));
781              it = q.iterator();
782 <            for (int j = split+1; j <= max; ++j) {
782 >            for (int j = split + 1; j <= max; ++j) {
783                  assertEquals(it.next(), new Integer(j));
784                  it.remove();
785              }
# Line 803 | Line 836 | public class ConcurrentLinkedDequeTest e
836          final Random rng = new Random();
837          for (int iters = 0; iters < 100; ++iters) {
838              int max = rng.nextInt(5) + 2;
839 <            int split = rng.nextInt(max-1) + 1;
839 >            int split = rng.nextInt(max - 1) + 1;
840              for (int j = max; j >= 1; --j)
841                  q.add(new Integer(j));
842              Iterator it = q.descendingIterator();
843              for (int j = 1; j <= split; ++j)
844                  assertEquals(it.next(), new Integer(j));
845              it.remove();
846 <            assertEquals(it.next(), new Integer(split+1));
846 >            assertEquals(it.next(), new Integer(split + 1));
847              for (int j = 1; j <= split; ++j)
848                  q.remove(new Integer(j));
849              it = q.descendingIterator();
850 <            for (int j = split+1; j <= max; ++j) {
850 >            for (int j = split + 1; j <= max; ++j) {
851                  assertEquals(it.next(), new Integer(j));
852                  it.remove();
853              }
# Line 830 | Line 863 | public class ConcurrentLinkedDequeTest e
863          ConcurrentLinkedDeque q = populatedDeque(SIZE);
864          String s = q.toString();
865          for (int i = 0; i < SIZE; ++i) {
866 <            assertTrue(s.indexOf(String.valueOf(i)) >= 0);
866 >            assertTrue(s.contains(String.valueOf(i)));
867          }
868      }
869  
870      /**
871 <     * A deserialized serialized deque has same elements in same order
871 >     * A deserialized/reserialized deque has same elements in same order
872       */
873      public void testSerialization() throws Exception {
874 <        ConcurrentLinkedDeque q = populatedDeque(SIZE);
875 <        ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
876 <        ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
877 <        out.writeObject(q);
878 <        out.close();
879 <
880 <        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
881 <        ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
882 <        ConcurrentLinkedDeque r = (ConcurrentLinkedDeque)in.readObject();
883 <        assertEquals(q.size(), r.size());
884 <        while (!q.isEmpty())
885 <            assertEquals(q.remove(), r.remove());
886 <    }
874 >        Queue x = populatedDeque(SIZE);
875 >        Queue y = serialClone(x);
876 >
877 >        assertNotSame(x, y);
878 >        assertEquals(x.size(), y.size());
879 >        assertEquals(x.toString(), y.toString());
880 >        assertTrue(Arrays.equals(x.toArray(), y.toArray()));
881 >        while (!x.isEmpty()) {
882 >            assertFalse(y.isEmpty());
883 >            assertEquals(x.remove(), y.remove());
884 >        }
885 >        assertTrue(y.isEmpty());
886 >    }
887 >
888 >    /**
889 >     * contains(null) always return false.
890 >     * remove(null) always throws NullPointerException.
891 >     */
892 >    public void testNeverContainsNull() {
893 >        Deque<?>[] qs = {
894 >            new ConcurrentLinkedDeque<Object>(),
895 >            populatedDeque(2),
896 >        };
897 >
898 >        for (Deque<?> q : qs) {
899 >            assertFalse(q.contains(null));
900 >            try {
901 >                assertFalse(q.remove(null));
902 >                shouldThrow();
903 >            } catch (NullPointerException success) {}
904 >            try {
905 >                assertFalse(q.removeFirstOccurrence(null));
906 >                shouldThrow();
907 >            } catch (NullPointerException success) {}
908 >            try {
909 >                assertFalse(q.removeLastOccurrence(null));
910 >                shouldThrow();
911 >            } catch (NullPointerException success) {}
912 >        }
913 >    }
914 >
915 >    void runAsync(Runnable r1, Runnable r2) {
916 >        boolean b = ThreadLocalRandom.current().nextBoolean();
917 >        CompletableFuture<Void> f1 = CompletableFuture.runAsync(b ? r1 : r2);
918 >        CompletableFuture<Void> f2 = CompletableFuture.runAsync(b ? r2 : r1);
919 >        f1.join();
920 >        f2.join();
921 >    }
922 >
923 >    /**
924 >     * Non-traversing Deque operations are linearizable.
925 >     * https://bugs.openjdk.java.net/browse/JDK-8188900
926 >     * ant -Djsr166.expensiveTests=true -Djsr166.tckTestClass=ConcurrentLinkedDequeTest -Djsr166.methodFilter=testBug8188900 tck
927 >     */
928 >    public void testBug8188900() {
929 >        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
930 >        final LongAdder nulls = new LongAdder(), zeros = new LongAdder();
931 >        for (int n = expensiveTests ? 100_000 : 10; n--> 0; ) {
932 >            ConcurrentLinkedDeque<Integer> d = new ConcurrentLinkedDeque<>();
933 >
934 >            boolean peek = rnd.nextBoolean();
935 >            Runnable getter = () -> {
936 >                Integer x = peek ? d.peekFirst() : d.pollFirst();
937 >                if (x == null) nulls.increment();
938 >                else if (x == 0) zeros.increment();
939 >                else
940 >                    throw new AssertionError(
941 >                        String.format(
942 >                            "unexpected value %d after %d nulls and %d zeros",
943 >                            x, nulls.sum(), zeros.sum()));
944 >            };
945 >
946 >            Runnable adder = () -> { d.addFirst(0); d.addLast(42); };
947 >
948 >            runAsync(getter, adder);
949 >        }
950 >    }
951 >
952 >    /**
953 >     * Reverse direction variant of testBug8188900
954 >     */
955 >    public void testBug8188900_reverse() {
956 >        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
957 >        final LongAdder nulls = new LongAdder(), zeros = new LongAdder();
958 >        for (int n = expensiveTests ? 100_000 : 10; n--> 0; ) {
959 >            ConcurrentLinkedDeque<Integer> d = new ConcurrentLinkedDeque<>();
960 >
961 >            boolean peek = rnd.nextBoolean();
962 >            Runnable getter = () -> {
963 >                Integer x = peek ? d.peekLast() : d.pollLast();
964 >                if (x == null) nulls.increment();
965 >                else if (x == 0) zeros.increment();
966 >                else
967 >                    throw new AssertionError(
968 >                        String.format(
969 >                            "unexpected value %d after %d nulls and %d zeros",
970 >                            x, nulls.sum(), zeros.sum()));
971 >            };
972 >
973 >            Runnable adder = () -> { d.addLast(0); d.addFirst(42); };
974 >
975 >            runAsync(getter, adder);
976 >        }
977 >    }
978 >
979 >    <T> T chooseRandomly(T... choices) {
980 >        return choices[ThreadLocalRandom.current().nextInt(choices.length)];
981 >    }
982 >
983 >    /**
984 >     * Non-traversing Deque operations (that return null) are linearizable.
985 >     * Don't return null when the deque is observably never empty.
986 >     * https://bugs.openjdk.java.net/browse/JDK-8189387
987 >     * ant -Djsr166.expensiveTests=true -Djsr166.tckTestClass=ConcurrentLinkedDequeTest -Djsr166.methodFilter=testBug8189387 tck
988 >     */
989 >    public void testBug8189387() {
990 >        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
991 >        Object x = new Object();
992 >        for (int n = expensiveTests ? 100_000 : 10; n--> 0; ) {
993 >            ConcurrentLinkedDeque<Object> d = new ConcurrentLinkedDeque<>();
994 >            Runnable add = chooseRandomly(
995 >                () -> d.addFirst(x),
996 >                () -> d.offerFirst(x),
997 >                () -> d.addLast(x),
998 >                () -> d.offerLast(x));
999 >
1000 >            Runnable get = chooseRandomly(
1001 >                () -> assertFalse(d.isEmpty()),
1002 >                () -> assertSame(x, d.peekFirst()),
1003 >                () -> assertSame(x, d.peekLast()),
1004 >                () -> assertSame(x, d.pollFirst()),
1005 >                () -> assertSame(x, d.pollLast()));
1006 >
1007 >            Runnable addRemove = chooseRandomly(
1008 >                () -> { d.addFirst(x); d.pollLast(); },
1009 >                () -> { d.offerFirst(x); d.removeFirst(); },
1010 >                () -> { d.offerLast(x); d.removeLast(); },
1011 >                () -> { d.addLast(x); d.pollFirst(); });
1012  
1013 +            add.run();
1014 +            runAsync(get, addRemove);
1015 +        }
1016 +    }
1017   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines