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.26 by jsr166, Sat Mar 11 17:33:32 2017 UTC vs.
Revision 1.36 by jsr166, Mon Dec 16 21:13:07 2019 UTC

# Line 13 | Line 13 | 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  
# Line 39 | Line 42 | public class ConcurrentLinkedDequeTest e
42       * Returns a new deque of given size containing consecutive
43       * Integers 0 ... n - 1.
44       */
45 <    private ConcurrentLinkedDeque<Integer> populatedDeque(int n) {
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)
# Line 312 | Line 315 | public class ConcurrentLinkedDequeTest e
315      }
316  
317      /**
318 <     * addAll(this) throws IAE
318 >     * addAll(this) throws IllegalArgumentException
319       */
320      public void testAddAllSelf() {
321          ConcurrentLinkedDeque q = populatedDeque(SIZE);
# Line 659 | Line 662 | public class ConcurrentLinkedDequeTest e
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());
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      /**
# Line 672 | Line 677 | public class ConcurrentLinkedDequeTest e
677          Integer[] ints = new Integer[SIZE];
678          Integer[] array = q.toArray(ints);
679          assertSame(ints, array);
680 <        for (int i = 0; i < ints.length; i++)
681 <            assertSame(ints[i], q.poll());
680 >        for (Integer o : ints)
681 >            assertSame(o, q.poll());
682 >        assertTrue(q.isEmpty());
683      }
684  
685      /**
# Line 682 | Line 688 | public class ConcurrentLinkedDequeTest e
688      public void testToArray_NullArg() {
689          ConcurrentLinkedDeque q = populatedDeque(SIZE);
690          try {
691 <            q.toArray(null);
691 >            q.toArray((Object[])null);
692              shouldThrow();
693          } catch (NullPointerException success) {}
694      }
# Line 862 | Line 868 | public class ConcurrentLinkedDequeTest e
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          Queue x = populatedDeque(SIZE);
# Line 905 | Line 911 | public class ConcurrentLinkedDequeTest e
911              } catch (NullPointerException success) {}
912          }
913      }
914 +
915 +    void runAsync(Runnable r1, Runnable r2) {
916 +        boolean b = randomBoolean();
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 +    /**
980 +     * Non-traversing Deque operations (that return null) are linearizable.
981 +     * Don't return null when the deque is observably never empty.
982 +     * https://bugs.openjdk.java.net/browse/JDK-8189387
983 +     * ant -Djsr166.expensiveTests=true -Djsr166.tckTestClass=ConcurrentLinkedDequeTest -Djsr166.methodFilter=testBug8189387 tck
984 +     */
985 +    public void testBug8189387() {
986 +        Object x = new Object();
987 +        for (int n = expensiveTests ? 100_000 : 10; n--> 0; ) {
988 +            ConcurrentLinkedDeque<Object> d = new ConcurrentLinkedDeque<>();
989 +            Runnable add = chooseRandomly(
990 +                () -> d.addFirst(x),
991 +                () -> d.offerFirst(x),
992 +                () -> d.addLast(x),
993 +                () -> d.offerLast(x));
994 +
995 +            Runnable get = chooseRandomly(
996 +                () -> assertFalse(d.isEmpty()),
997 +                () -> assertSame(x, d.peekFirst()),
998 +                () -> assertSame(x, d.peekLast()),
999 +                () -> assertSame(x, d.pollFirst()),
1000 +                () -> assertSame(x, d.pollLast()));
1001 +
1002 +            Runnable addRemove = chooseRandomly(
1003 +                () -> { d.addFirst(x); d.pollLast(); },
1004 +                () -> { d.offerFirst(x); d.removeFirst(); },
1005 +                () -> { d.offerLast(x); d.removeLast(); },
1006 +                () -> { d.addLast(x); d.pollFirst(); });
1007 +
1008 +            add.run();
1009 +            runAsync(get, addRemove);
1010 +        }
1011 +    }
1012   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines