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 |
|
|
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 |
|
/** |
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 |
|
/** |
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 |
|
} |
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); |
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 |
+ |
<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 |
|
} |