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.31 by jsr166, Sun Oct 22 21:52:58 2017 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 862 | Line 865 | public class ConcurrentLinkedDequeTest e
865      }
866  
867      /**
868 <     * A deserialized serialized deque has same elements in same order
868 >     * A deserialized/reserialized deque has same elements in same order
869       */
870      public void testSerialization() throws Exception {
871          Queue x = populatedDeque(SIZE);
# Line 905 | Line 908 | public class ConcurrentLinkedDequeTest e
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   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines