1 |
/* |
2 |
* Written by Doug Lea and Martin Buchholz with assistance from |
3 |
* members of JCP JSR-166 Expert Group and released to the public |
4 |
* domain, as explained at |
5 |
* http://creativecommons.org/publicdomain/zero/1.0/ |
6 |
*/ |
7 |
|
8 |
/* |
9 |
* @test |
10 |
* @summary Test drainTo failing due to c.add throwing |
11 |
* @library /lib/testlibrary/ |
12 |
*/ |
13 |
|
14 |
import java.util.ArrayList; |
15 |
import java.util.List; |
16 |
import java.util.concurrent.DelayQueue; |
17 |
import java.util.concurrent.Delayed; |
18 |
import java.util.concurrent.ArrayBlockingQueue; |
19 |
import java.util.concurrent.BlockingQueue; |
20 |
import java.util.concurrent.LinkedBlockingDeque; |
21 |
import java.util.concurrent.LinkedBlockingQueue; |
22 |
import java.util.concurrent.FutureTask; |
23 |
import java.util.concurrent.PriorityBlockingQueue; |
24 |
import java.util.concurrent.RunnableScheduledFuture; |
25 |
import java.util.concurrent.ScheduledThreadPoolExecutor; |
26 |
import java.util.concurrent.TimeUnit; |
27 |
import jdk.testlibrary.Utils; |
28 |
|
29 |
@SuppressWarnings({"unchecked", "rawtypes"}) |
30 |
public class DrainToFails { |
31 |
static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); |
32 |
final int CAPACITY = 10; |
33 |
final int SMALL = 2; |
34 |
|
35 |
void test(String[] args) throws Throwable { |
36 |
testDelayQueue(new DelayQueue()); |
37 |
testDelayQueue(new ScheduledThreadPoolExecutor(1).getQueue()); |
38 |
|
39 |
testUnbounded(new LinkedBlockingQueue()); |
40 |
testUnbounded(new LinkedBlockingDeque()); |
41 |
testUnbounded(new PriorityBlockingQueue()); |
42 |
|
43 |
testBounded(new LinkedBlockingQueue(CAPACITY)); |
44 |
testBounded(new LinkedBlockingDeque(CAPACITY)); |
45 |
testBounded(new ArrayBlockingQueue(CAPACITY)); |
46 |
} |
47 |
|
48 |
static class PDelay |
49 |
extends FutureTask<Void> |
50 |
implements Delayed, RunnableScheduledFuture<Void> { |
51 |
int pseudodelay; |
52 |
PDelay(int i) { |
53 |
super(new Runnable() { public void run() {}}, null); |
54 |
pseudodelay = i; |
55 |
} |
56 |
public int compareTo(PDelay other) { |
57 |
return Integer.compare(this.pseudodelay, other.pseudodelay); |
58 |
} |
59 |
public int compareTo(Delayed y) { |
60 |
return compareTo((PDelay)y); |
61 |
} |
62 |
public boolean equals(Object other) { |
63 |
return (other instanceof PDelay) && |
64 |
this.pseudodelay == ((PDelay)other).pseudodelay; |
65 |
} |
66 |
public long getDelay(TimeUnit ignore) { |
67 |
return Integer.MIN_VALUE + pseudodelay; |
68 |
} |
69 |
public String toString() { |
70 |
return String.valueOf(pseudodelay); |
71 |
} |
72 |
public boolean isPeriodic() { return false; } |
73 |
} |
74 |
|
75 |
void testDelayQueue(final BlockingQueue q) throws Throwable { |
76 |
System.err.println(q.getClass().getSimpleName()); |
77 |
for (int i = 0; i < CAPACITY; i++) |
78 |
q.add(new PDelay(i)); |
79 |
ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL); |
80 |
try { |
81 |
q.drainTo(q2, SMALL + 3); |
82 |
fail("should throw"); |
83 |
} catch (IllegalStateException success) { |
84 |
equal(SMALL, q2.size()); |
85 |
equal(new PDelay(0), q2.poll()); |
86 |
equal(new PDelay(1), q2.poll()); |
87 |
check(q2.isEmpty()); |
88 |
for (int i = SMALL; i < CAPACITY; i++) |
89 |
equal(new PDelay(i), q.poll()); |
90 |
equal(0, q.size()); |
91 |
} |
92 |
} |
93 |
|
94 |
void testUnbounded(final BlockingQueue q) throws Throwable { |
95 |
System.err.println(q.getClass().getSimpleName()); |
96 |
for (int i = 0; i < CAPACITY; i++) |
97 |
q.add(i); |
98 |
ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL); |
99 |
try { |
100 |
q.drainTo(q2, 7); |
101 |
fail("should throw"); |
102 |
} catch (IllegalStateException success) { |
103 |
assertContentsInOrder(q2, 0, 1); |
104 |
q2.clear(); |
105 |
equal(q.size(), CAPACITY - SMALL); |
106 |
equal(SMALL, q.peek()); |
107 |
} |
108 |
|
109 |
try { |
110 |
q.drainTo(q2); |
111 |
fail("should throw"); |
112 |
} catch (IllegalStateException success) { |
113 |
assertContentsInOrder(q2, 2, 3); |
114 |
equal(q.size(), CAPACITY - 2 * SMALL); |
115 |
for (int i = 2 * SMALL; i < CAPACITY; i++) |
116 |
equal(i, q.poll()); |
117 |
equal(0, q.size()); |
118 |
} |
119 |
} |
120 |
|
121 |
void testBounded(final BlockingQueue q) throws Throwable { |
122 |
System.err.println(q.getClass().getSimpleName()); |
123 |
for (int i = 0; i < CAPACITY; i++) |
124 |
q.add(i); |
125 |
List<Thread> putters = new ArrayList<>(); |
126 |
for (int i = 0; i < 4; i++) { |
127 |
Thread putter = new Thread(putter(q, 42 + i)); |
128 |
putters.add(putter); |
129 |
putter.setDaemon(true); |
130 |
putter.start(); |
131 |
} |
132 |
ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL); |
133 |
try { |
134 |
q.drainTo(q2, 7); |
135 |
fail("should throw"); |
136 |
} catch (IllegalStateException success) { |
137 |
while (q.size() < CAPACITY) |
138 |
Thread.yield(); |
139 |
assertContentsInOrder(q2, 0, 1); |
140 |
q2.clear(); |
141 |
} |
142 |
|
143 |
try { |
144 |
q.drainTo(q2); |
145 |
fail("should throw"); |
146 |
} catch (IllegalStateException success) { |
147 |
for (Thread putter : putters) { |
148 |
putter.join(LONG_DELAY_MS); |
149 |
check(! putter.isAlive()); |
150 |
} |
151 |
assertContentsInOrder(q2, 2, 3); |
152 |
for (int i = 2 * SMALL; i < CAPACITY; i++) |
153 |
equal(i, q.poll()); |
154 |
equal(4, q.size()); |
155 |
check(q.contains(42)); |
156 |
check(q.contains(43)); |
157 |
check(q.contains(44)); |
158 |
check(q.contains(45)); |
159 |
} |
160 |
} |
161 |
|
162 |
Runnable putter(BlockingQueue q, int elt) { |
163 |
return () -> { |
164 |
try { q.put(elt); } |
165 |
catch (Throwable t) { unexpected(t); }}; |
166 |
} |
167 |
|
168 |
void assertContentsInOrder(Iterable it, Object... contents) { |
169 |
int i = 0; |
170 |
for (Object e : it) |
171 |
equal(contents[i++], e); |
172 |
equal(contents.length, i); |
173 |
} |
174 |
|
175 |
//--------------------- Infrastructure --------------------------- |
176 |
volatile int passed = 0, failed = 0; |
177 |
void pass() {passed++;} |
178 |
void fail() {failed++; Thread.dumpStack();} |
179 |
void fail(String msg) {System.err.println(msg); fail();} |
180 |
void unexpected(Throwable t) {failed++; t.printStackTrace();} |
181 |
void check(boolean cond) {if (cond) pass(); else fail();} |
182 |
void equal(Object x, Object y) { |
183 |
if (x == null ? y == null : x.equals(y)) pass(); |
184 |
else fail(x + " not equal to " + y);} |
185 |
public static void main(String[] args) throws Throwable { |
186 |
new DrainToFails().instanceMain(args);} |
187 |
public void instanceMain(String[] args) throws Throwable { |
188 |
try {test(args);} catch (Throwable t) {unexpected(t);} |
189 |
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); |
190 |
if (failed > 0) throw new AssertionError("Some tests failed");} |
191 |
} |