Parent Directory
|
Revision Log
Revision 1.37 - (view) (download)
1 : | dl | 1.1 | /* |
2 : | dl | 1.10 | * 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 : | jsr166 | 1.24 | * http://creativecommons.org/publicdomain/zero/1.0/ |
5 : | jsr166 | 1.12 | * Other contributors include Andrew Wright, Jeffrey Hayes, |
6 : | * Pat Fisher, Mike Judd. | ||
7 : | dl | 1.1 | */ |
8 : | |||
9 : | import junit.framework.*; | ||
10 : | jsr166 | 1.26 | import java.util.concurrent.Callable; |
11 : | import java.util.concurrent.CancellationException; | ||
12 : | import java.util.concurrent.CountDownLatch; | ||
13 : | import java.util.concurrent.ExecutionException; | ||
14 : | import java.util.concurrent.Future; | ||
15 : | import java.util.concurrent.FutureTask; | ||
16 : | import java.util.concurrent.TimeoutException; | ||
17 : | jsr166 | 1.29 | import java.util.concurrent.atomic.AtomicInteger; |
18 : | jsr166 | 1.15 | import static java.util.concurrent.TimeUnit.MILLISECONDS; |
19 : | jsr166 | 1.22 | import static java.util.concurrent.TimeUnit.SECONDS; |
20 : | dl | 1.4 | import java.util.*; |
21 : | dl | 1.1 | |
22 : | dl | 1.4 | public class FutureTaskTest extends JSR166TestCase { |
23 : | dl | 1.1 | |
24 : | public static void main(String[] args) { | ||
25 : | jsr166 | 1.19 | junit.textui.TestRunner.run(suite()); |
26 : | dl | 1.1 | } |
27 : | public static Test suite() { | ||
28 : | jsr166 | 1.16 | return new TestSuite(FutureTaskTest.class); |
29 : | dl | 1.1 | } |
30 : | |||
31 : | jsr166 | 1.29 | void checkIsDone(Future<?> f) { |
32 : | assertTrue(f.isDone()); | ||
33 : | assertFalse(f.cancel(false)); | ||
34 : | assertFalse(f.cancel(true)); | ||
35 : | if (f instanceof PublicFutureTask) { | ||
36 : | PublicFutureTask pf = (PublicFutureTask) f; | ||
37 : | assertEquals(1, pf.doneCount()); | ||
38 : | assertFalse(pf.runAndReset()); | ||
39 : | assertEquals(1, pf.doneCount()); | ||
40 : | jsr166 | 1.37 | Object r = null; Object exInfo = null; |
41 : | try { | ||
42 : | r = f.get(); | ||
43 : | } catch (CancellationException t) { | ||
44 : | exInfo = CancellationException.class; | ||
45 : | } catch (ExecutionException t) { | ||
46 : | exInfo = t.getCause(); | ||
47 : | } catch (Throwable t) { | ||
48 : | threadUnexpectedException(t); | ||
49 : | } | ||
50 : | jsr166 | 1.29 | |
51 : | // Check that run and runAndReset have no effect. | ||
52 : | int savedRunCount = pf.runCount(); | ||
53 : | pf.run(); | ||
54 : | pf.runAndReset(); | ||
55 : | assertEquals(savedRunCount, pf.runCount()); | ||
56 : | jsr166 | 1.37 | try { |
57 : | assertSame(r, f.get()); | ||
58 : | } catch (CancellationException t) { | ||
59 : | assertSame(exInfo, CancellationException.class); | ||
60 : | } catch (ExecutionException t) { | ||
61 : | assertSame(exInfo, t.getCause()); | ||
62 : | } catch (Throwable t) { | ||
63 : | threadUnexpectedException(t); | ||
64 : | } | ||
65 : | jsr166 | 1.29 | assertTrue(f.isDone()); |
66 : | } | ||
67 : | } | ||
68 : | |||
69 : | jsr166 | 1.22 | void checkNotDone(Future<?> f) { |
70 : | assertFalse(f.isDone()); | ||
71 : | assertFalse(f.isCancelled()); | ||
72 : | jsr166 | 1.29 | if (f instanceof PublicFutureTask) { |
73 : | PublicFutureTask pf = (PublicFutureTask) f; | ||
74 : | assertEquals(0, pf.doneCount()); | ||
75 : | assertEquals(0, pf.setCount()); | ||
76 : | assertEquals(0, pf.setExceptionCount()); | ||
77 : | } | ||
78 : | } | ||
79 : | |||
80 : | void checkIsRunning(Future<?> f) { | ||
81 : | checkNotDone(f); | ||
82 : | if (f instanceof FutureTask) { | ||
83 : | FutureTask ft = (FutureTask<?>) f; | ||
84 : | // Check that run methods do nothing | ||
85 : | ft.run(); | ||
86 : | jsr166 | 1.37 | if (f instanceof PublicFutureTask) { |
87 : | PublicFutureTask pf = (PublicFutureTask) f; | ||
88 : | int savedRunCount = pf.runCount(); | ||
89 : | pf.run(); | ||
90 : | assertFalse(pf.runAndReset()); | ||
91 : | assertEquals(savedRunCount, pf.runCount()); | ||
92 : | } | ||
93 : | jsr166 | 1.29 | checkNotDone(f); |
94 : | } | ||
95 : | jsr166 | 1.22 | } |
96 : | |||
97 : | <T> void checkCompletedNormally(Future<T> f, T expected) { | ||
98 : | jsr166 | 1.29 | checkIsDone(f); |
99 : | jsr166 | 1.22 | assertFalse(f.isCancelled()); |
100 : | |||
101 : | try { | ||
102 : | assertSame(expected, f.get()); | ||
103 : | } catch (Throwable fail) { threadUnexpectedException(fail); } | ||
104 : | try { | ||
105 : | assertSame(expected, f.get(5L, SECONDS)); | ||
106 : | } catch (Throwable fail) { threadUnexpectedException(fail); } | ||
107 : | } | ||
108 : | |||
109 : | void checkCancelled(Future<?> f) { | ||
110 : | jsr166 | 1.29 | checkIsDone(f); |
111 : | jsr166 | 1.22 | assertTrue(f.isCancelled()); |
112 : | |||
113 : | try { | ||
114 : | f.get(); | ||
115 : | shouldThrow(); | ||
116 : | } catch (CancellationException success) { | ||
117 : | } catch (Throwable fail) { threadUnexpectedException(fail); } | ||
118 : | |||
119 : | try { | ||
120 : | f.get(5L, SECONDS); | ||
121 : | shouldThrow(); | ||
122 : | } catch (CancellationException success) { | ||
123 : | } catch (Throwable fail) { threadUnexpectedException(fail); } | ||
124 : | jsr166 | 1.29 | } |
125 : | jsr166 | 1.22 | |
126 : | jsr166 | 1.29 | void tryToConfuseDoneTask(PublicFutureTask pf) { |
127 : | pf.set(new Object()); | ||
128 : | pf.setException(new Error()); | ||
129 : | for (boolean mayInterruptIfRunning : new boolean[] { true, false }) { | ||
130 : | pf.cancel(true); | ||
131 : | } | ||
132 : | jsr166 | 1.22 | } |
133 : | |||
134 : | void checkCompletedAbnormally(Future<?> f, Throwable t) { | ||
135 : | jsr166 | 1.29 | checkIsDone(f); |
136 : | jsr166 | 1.22 | assertFalse(f.isCancelled()); |
137 : | |||
138 : | try { | ||
139 : | f.get(); | ||
140 : | shouldThrow(); | ||
141 : | } catch (ExecutionException success) { | ||
142 : | assertSame(t, success.getCause()); | ||
143 : | } catch (Throwable fail) { threadUnexpectedException(fail); } | ||
144 : | |||
145 : | try { | ||
146 : | f.get(5L, SECONDS); | ||
147 : | shouldThrow(); | ||
148 : | } catch (ExecutionException success) { | ||
149 : | assertSame(t, success.getCause()); | ||
150 : | } catch (Throwable fail) { threadUnexpectedException(fail); } | ||
151 : | } | ||
152 : | |||
153 : | dl | 1.4 | /** |
154 : | * Subclass to expose protected methods | ||
155 : | */ | ||
156 : | dl | 1.7 | static class PublicFutureTask extends FutureTask { |
157 : | jsr166 | 1.29 | private final AtomicInteger runCount; |
158 : | private final AtomicInteger doneCount = new AtomicInteger(0); | ||
159 : | private final AtomicInteger runAndResetCount = new AtomicInteger(0); | ||
160 : | private final AtomicInteger setCount = new AtomicInteger(0); | ||
161 : | private final AtomicInteger setExceptionCount = new AtomicInteger(0); | ||
162 : | public int runCount() { return runCount.get(); } | ||
163 : | public int doneCount() { return doneCount.get(); } | ||
164 : | public int runAndResetCount() { return runAndResetCount.get(); } | ||
165 : | public int setCount() { return setCount.get(); } | ||
166 : | public int setExceptionCount() { return setExceptionCount.get(); } | ||
167 : | |||
168 : | PublicFutureTask(Runnable runnable) { | ||
169 : | this(runnable, seven); | ||
170 : | } | ||
171 : | PublicFutureTask(Runnable runnable, Object result) { | ||
172 : | this(runnable, result, new AtomicInteger(0)); | ||
173 : | } | ||
174 : | private PublicFutureTask(final Runnable runnable, Object result, | ||
175 : | final AtomicInteger runCount) { | ||
176 : | super(new Runnable() { | ||
177 : | jsr166 | 1.31 | public void run() { |
178 : | runCount.getAndIncrement(); | ||
179 : | runnable.run(); | ||
180 : | }}, result); | ||
181 : | jsr166 | 1.29 | this.runCount = runCount; |
182 : | } | ||
183 : | PublicFutureTask(Callable callable) { | ||
184 : | this(callable, new AtomicInteger(0)); | ||
185 : | } | ||
186 : | private PublicFutureTask(final Callable callable, | ||
187 : | final AtomicInteger runCount) { | ||
188 : | super(new Callable() { | ||
189 : | public Object call() throws Exception { | ||
190 : | runCount.getAndIncrement(); | ||
191 : | return callable.call(); | ||
192 : | }}); | ||
193 : | this.runCount = runCount; | ||
194 : | } | ||
195 : | jsr166 | 1.30 | @Override public void done() { |
196 : | jsr166 | 1.29 | assertTrue(isDone()); |
197 : | doneCount.incrementAndGet(); | ||
198 : | super.done(); | ||
199 : | } | ||
200 : | jsr166 | 1.30 | @Override public boolean runAndReset() { |
201 : | jsr166 | 1.29 | runAndResetCount.incrementAndGet(); |
202 : | return super.runAndReset(); | ||
203 : | } | ||
204 : | jsr166 | 1.30 | @Override public void set(Object x) { |
205 : | jsr166 | 1.29 | setCount.incrementAndGet(); |
206 : | super.set(x); | ||
207 : | } | ||
208 : | jsr166 | 1.30 | @Override public void setException(Throwable t) { |
209 : | jsr166 | 1.29 | setExceptionCount.incrementAndGet(); |
210 : | super.setException(t); | ||
211 : | } | ||
212 : | } | ||
213 : | |||
214 : | class Counter extends CheckedRunnable { | ||
215 : | final AtomicInteger count = new AtomicInteger(0); | ||
216 : | public int get() { return count.get(); } | ||
217 : | public void realRun() { | ||
218 : | count.getAndIncrement(); | ||
219 : | } | ||
220 : | dl | 1.4 | } |
221 : | dl | 1.1 | |
222 : | dl | 1.5 | /** |
223 : | jsr166 | 1.29 | * creating a future with a null callable throws NullPointerException |
224 : | dl | 1.5 | */ |
225 : | public void testConstructor() { | ||
226 : | dl | 1.3 | try { |
227 : | jsr166 | 1.29 | new FutureTask(null); |
228 : | jsr166 | 1.17 | shouldThrow(); |
229 : | jsr166 | 1.15 | } catch (NullPointerException success) {} |
230 : | dl | 1.3 | } |
231 : | |||
232 : | dl | 1.5 | /** |
233 : | jsr166 | 1.29 | * creating a future with null runnable throws NullPointerException |
234 : | dl | 1.5 | */ |
235 : | public void testConstructor2() { | ||
236 : | dl | 1.3 | try { |
237 : | jsr166 | 1.29 | new FutureTask(null, Boolean.TRUE); |
238 : | jsr166 | 1.17 | shouldThrow(); |
239 : | jsr166 | 1.15 | } catch (NullPointerException success) {} |
240 : | dl | 1.3 | } |
241 : | |||
242 : | dl | 1.5 | /** |
243 : | dl | 1.6 | * isDone is true when a task completes |
244 : | dl | 1.5 | */ |
245 : | public void testIsDone() { | ||
246 : | jsr166 | 1.29 | PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); |
247 : | assertFalse(task.isDone()); | ||
248 : | jsr166 | 1.16 | task.run(); |
249 : | assertTrue(task.isDone()); | ||
250 : | jsr166 | 1.22 | checkCompletedNormally(task, Boolean.TRUE); |
251 : | jsr166 | 1.29 | assertEquals(1, task.runCount()); |
252 : | dl | 1.4 | } |
253 : | |||
254 : | dl | 1.5 | /** |
255 : | dl | 1.9 | * runAndReset of a non-cancelled task succeeds |
256 : | dl | 1.5 | */ |
257 : | dl | 1.9 | public void testRunAndReset() { |
258 : | dl | 1.7 | PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); |
259 : | jsr166 | 1.29 | for (int i = 0; i < 3; i++) { |
260 : | assertTrue(task.runAndReset()); | ||
261 : | checkNotDone(task); | ||
262 : | assertEquals(i+1, task.runCount()); | ||
263 : | assertEquals(i+1, task.runAndResetCount()); | ||
264 : | assertEquals(0, task.setCount()); | ||
265 : | assertEquals(0, task.setExceptionCount()); | ||
266 : | } | ||
267 : | dl | 1.4 | } |
268 : | |||
269 : | dl | 1.5 | /** |
270 : | dl | 1.9 | * runAndReset after cancellation fails |
271 : | dl | 1.5 | */ |
272 : | jsr166 | 1.29 | public void testRunAndResetAfterCancel() { |
273 : | for (boolean mayInterruptIfRunning : new boolean[] { true, false }) { | ||
274 : | PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); | ||
275 : | assertTrue(task.cancel(mayInterruptIfRunning)); | ||
276 : | for (int i = 0; i < 3; i++) { | ||
277 : | assertFalse(task.runAndReset()); | ||
278 : | assertEquals(0, task.runCount()); | ||
279 : | assertEquals(i+1, task.runAndResetCount()); | ||
280 : | assertEquals(0, task.setCount()); | ||
281 : | assertEquals(0, task.setExceptionCount()); | ||
282 : | } | ||
283 : | tryToConfuseDoneTask(task); | ||
284 : | checkCancelled(task); | ||
285 : | } | ||
286 : | dl | 1.4 | } |
287 : | |||
288 : | dl | 1.5 | /** |
289 : | dl | 1.11 | * setting value causes get to return it |
290 : | dl | 1.5 | */ |
291 : | jsr166 | 1.15 | public void testSet() throws Exception { |
292 : | dl | 1.7 | PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); |
293 : | dl | 1.4 | task.set(one); |
294 : | jsr166 | 1.29 | for (int i = 0; i < 3; i++) { |
295 : | assertSame(one, task.get()); | ||
296 : | assertSame(one, task.get(LONG_DELAY_MS, MILLISECONDS)); | ||
297 : | assertEquals(1, task.setCount()); | ||
298 : | } | ||
299 : | tryToConfuseDoneTask(task); | ||
300 : | jsr166 | 1.22 | checkCompletedNormally(task, one); |
301 : | jsr166 | 1.29 | assertEquals(0, task.runCount()); |
302 : | dl | 1.4 | } |
303 : | |||
304 : | dl | 1.5 | /** |
305 : | dl | 1.6 | * setException causes get to throw ExecutionException |
306 : | dl | 1.5 | */ |
307 : | jsr166 | 1.29 | public void testSetException_get() throws Exception { |
308 : | dl | 1.4 | Exception nse = new NoSuchElementException(); |
309 : | dl | 1.7 | PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); |
310 : | dl | 1.4 | task.setException(nse); |
311 : | jsr166 | 1.29 | |
312 : | try { | ||
313 : | task.get(); | ||
314 : | shouldThrow(); | ||
315 : | } catch (ExecutionException success) { | ||
316 : | assertSame(nse, success.getCause()); | ||
317 : | checkCompletedAbnormally(task, nse); | ||
318 : | } | ||
319 : | |||
320 : | dl | 1.4 | try { |
321 : | jsr166 | 1.29 | task.get(LONG_DELAY_MS, MILLISECONDS); |
322 : | jsr166 | 1.17 | shouldThrow(); |
323 : | jsr166 | 1.15 | } catch (ExecutionException success) { |
324 : | jsr166 | 1.29 | assertSame(nse, success.getCause()); |
325 : | jsr166 | 1.22 | checkCompletedAbnormally(task, nse); |
326 : | dl | 1.4 | } |
327 : | jsr166 | 1.29 | |
328 : | assertEquals(1, task.setExceptionCount()); | ||
329 : | assertEquals(0, task.setCount()); | ||
330 : | tryToConfuseDoneTask(task); | ||
331 : | checkCompletedAbnormally(task, nse); | ||
332 : | assertEquals(0, task.runCount()); | ||
333 : | dl | 1.4 | } |
334 : | |||
335 : | dl | 1.5 | /** |
336 : | jsr166 | 1.29 | * cancel(false) before run succeeds |
337 : | dl | 1.5 | */ |
338 : | dl | 1.1 | public void testCancelBeforeRun() { |
339 : | jsr166 | 1.29 | PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); |
340 : | dl | 1.1 | assertTrue(task.cancel(false)); |
341 : | jsr166 | 1.16 | task.run(); |
342 : | jsr166 | 1.32 | assertEquals(0, task.runCount()); |
343 : | jsr166 | 1.29 | assertEquals(0, task.setCount()); |
344 : | assertEquals(0, task.setExceptionCount()); | ||
345 : | jsr166 | 1.32 | assertTrue(task.isCancelled()); |
346 : | assertTrue(task.isDone()); | ||
347 : | jsr166 | 1.29 | tryToConfuseDoneTask(task); |
348 : | jsr166 | 1.32 | assertEquals(0, task.runCount()); |
349 : | jsr166 | 1.22 | checkCancelled(task); |
350 : | dl | 1.1 | } |
351 : | |||
352 : | dl | 1.5 | /** |
353 : | jsr166 | 1.29 | * cancel(true) before run succeeds |
354 : | dl | 1.5 | */ |
355 : | dl | 1.1 | public void testCancelBeforeRun2() { |
356 : | jsr166 | 1.29 | PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); |
357 : | dl | 1.1 | assertTrue(task.cancel(true)); |
358 : | jsr166 | 1.16 | task.run(); |
359 : | jsr166 | 1.32 | assertEquals(0, task.runCount()); |
360 : | jsr166 | 1.29 | assertEquals(0, task.setCount()); |
361 : | assertEquals(0, task.setExceptionCount()); | ||
362 : | jsr166 | 1.32 | assertTrue(task.isCancelled()); |
363 : | assertTrue(task.isDone()); | ||
364 : | jsr166 | 1.29 | tryToConfuseDoneTask(task); |
365 : | jsr166 | 1.32 | assertEquals(0, task.runCount()); |
366 : | jsr166 | 1.22 | checkCancelled(task); |
367 : | dl | 1.1 | } |
368 : | |||
369 : | dl | 1.5 | /** |
370 : | jsr166 | 1.29 | * cancel(false) of a completed task fails |
371 : | dl | 1.5 | */ |
372 : | dl | 1.1 | public void testCancelAfterRun() { |
373 : | jsr166 | 1.29 | PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); |
374 : | jsr166 | 1.16 | task.run(); |
375 : | dl | 1.1 | assertFalse(task.cancel(false)); |
376 : | jsr166 | 1.32 | assertEquals(1, task.runCount()); |
377 : | jsr166 | 1.29 | assertEquals(1, task.setCount()); |
378 : | assertEquals(0, task.setExceptionCount()); | ||
379 : | tryToConfuseDoneTask(task); | ||
380 : | checkCompletedNormally(task, Boolean.TRUE); | ||
381 : | assertEquals(1, task.runCount()); | ||
382 : | } | ||
383 : | |||
384 : | /** | ||
385 : | * cancel(true) of a completed task fails | ||
386 : | */ | ||
387 : | public void testCancelAfterRun2() { | ||
388 : | PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); | ||
389 : | task.run(); | ||
390 : | assertFalse(task.cancel(true)); | ||
391 : | jsr166 | 1.32 | assertEquals(1, task.runCount()); |
392 : | jsr166 | 1.29 | assertEquals(1, task.setCount()); |
393 : | assertEquals(0, task.setExceptionCount()); | ||
394 : | tryToConfuseDoneTask(task); | ||
395 : | jsr166 | 1.22 | checkCompletedNormally(task, Boolean.TRUE); |
396 : | jsr166 | 1.29 | assertEquals(1, task.runCount()); |
397 : | dl | 1.1 | } |
398 : | |||
399 : | dl | 1.5 | /** |
400 : | jsr166 | 1.29 | * cancel(true) interrupts a running task that subsequently succeeds |
401 : | dl | 1.5 | */ |
402 : | jsr166 | 1.29 | public void testCancelInterrupt() { |
403 : | final CountDownLatch pleaseCancel = new CountDownLatch(1); | ||
404 : | final PublicFutureTask task = | ||
405 : | new PublicFutureTask(new CheckedRunnable() { | ||
406 : | public void realRun() { | ||
407 : | pleaseCancel.countDown(); | ||
408 : | try { | ||
409 : | delay(LONG_DELAY_MS); | ||
410 : | shouldThrow(); | ||
411 : | } catch (InterruptedException success) {} | ||
412 : | jsr166 | 1.15 | }}); |
413 : | |||
414 : | jsr166 | 1.22 | Thread t = newStartedThread(task); |
415 : | jsr166 | 1.29 | await(pleaseCancel); |
416 : | jsr166 | 1.15 | assertTrue(task.cancel(true)); |
417 : | jsr166 | 1.29 | assertTrue(task.isCancelled()); |
418 : | jsr166 | 1.32 | assertTrue(task.isDone()); |
419 : | jsr166 | 1.29 | awaitTermination(t); |
420 : | assertEquals(1, task.runCount()); | ||
421 : | assertEquals(1, task.setCount()); | ||
422 : | assertEquals(0, task.setExceptionCount()); | ||
423 : | tryToConfuseDoneTask(task); | ||
424 : | jsr166 | 1.22 | checkCancelled(task); |
425 : | jsr166 | 1.29 | } |
426 : | |||
427 : | /** | ||
428 : | jsr166 | 1.33 | * cancel(true) tries to interrupt a running task, but |
429 : | * Thread.interrupt throws (simulating a restrictive security | ||
430 : | * manager) | ||
431 : | jsr166 | 1.32 | */ |
432 : | public void testCancelInterrupt_ThrowsSecurityException() { | ||
433 : | final CountDownLatch pleaseCancel = new CountDownLatch(1); | ||
434 : | final CountDownLatch cancelled = new CountDownLatch(1); | ||
435 : | final PublicFutureTask task = | ||
436 : | new PublicFutureTask(new CheckedRunnable() { | ||
437 : | public void realRun() { | ||
438 : | pleaseCancel.countDown(); | ||
439 : | await(cancelled); | ||
440 : | assertFalse(Thread.interrupted()); | ||
441 : | }}); | ||
442 : | |||
443 : | jsr166 | 1.33 | final Thread t = new Thread(task) { |
444 : | // Simulate a restrictive security manager. | ||
445 : | @Override public void interrupt() { | ||
446 : | throw new SecurityException(); | ||
447 : | }}; | ||
448 : | t.setDaemon(true); | ||
449 : | t.start(); | ||
450 : | |||
451 : | jsr166 | 1.32 | await(pleaseCancel); |
452 : | try { | ||
453 : | jsr166 | 1.33 | task.cancel(true); |
454 : | shouldThrow(); | ||
455 : | } catch (SecurityException expected) {} | ||
456 : | |||
457 : | // We failed to deliver the interrupt, but the world retains | ||
458 : | // its sanity, as if we had done task.cancel(false) | ||
459 : | jsr166 | 1.32 | assertTrue(task.isCancelled()); |
460 : | assertTrue(task.isDone()); | ||
461 : | assertEquals(1, task.runCount()); | ||
462 : | assertEquals(1, task.doneCount()); | ||
463 : | assertEquals(0, task.setCount()); | ||
464 : | assertEquals(0, task.setExceptionCount()); | ||
465 : | cancelled.countDown(); | ||
466 : | awaitTermination(t); | ||
467 : | assertEquals(1, task.setCount()); | ||
468 : | assertEquals(0, task.setExceptionCount()); | ||
469 : | tryToConfuseDoneTask(task); | ||
470 : | checkCancelled(task); | ||
471 : | } | ||
472 : | |||
473 : | /** | ||
474 : | jsr166 | 1.29 | * cancel(true) interrupts a running task that subsequently throws |
475 : | */ | ||
476 : | public void testCancelInterrupt_taskFails() { | ||
477 : | final CountDownLatch pleaseCancel = new CountDownLatch(1); | ||
478 : | final PublicFutureTask task = | ||
479 : | new PublicFutureTask(new Runnable() { | ||
480 : | public void run() { | ||
481 : | try { | ||
482 : | pleaseCancel.countDown(); | ||
483 : | delay(LONG_DELAY_MS); | ||
484 : | jsr166 | 1.35 | shouldThrow(); |
485 : | } catch (Throwable t) { | ||
486 : | assertTrue(t instanceof InterruptedException); | ||
487 : | } | ||
488 : | throw new RuntimeException(); | ||
489 : | jsr166 | 1.29 | }}); |
490 : | |||
491 : | Thread t = newStartedThread(task); | ||
492 : | await(pleaseCancel); | ||
493 : | assertTrue(task.cancel(true)); | ||
494 : | assertTrue(task.isCancelled()); | ||
495 : | awaitTermination(t); | ||
496 : | assertEquals(1, task.runCount()); | ||
497 : | assertEquals(0, task.setCount()); | ||
498 : | assertEquals(1, task.setExceptionCount()); | ||
499 : | tryToConfuseDoneTask(task); | ||
500 : | jsr166 | 1.22 | checkCancelled(task); |
501 : | dl | 1.1 | } |
502 : | |||
503 : | dl | 1.5 | /** |
504 : | dl | 1.6 | * cancel(false) does not interrupt a running task |
505 : | dl | 1.5 | */ |
506 : | jsr166 | 1.29 | public void testCancelNoInterrupt() { |
507 : | final CountDownLatch pleaseCancel = new CountDownLatch(1); | ||
508 : | jsr166 | 1.22 | final CountDownLatch cancelled = new CountDownLatch(1); |
509 : | jsr166 | 1.29 | final PublicFutureTask task = |
510 : | new PublicFutureTask(new CheckedCallable<Boolean>() { | ||
511 : | public Boolean realCall() { | ||
512 : | pleaseCancel.countDown(); | ||
513 : | await(cancelled); | ||
514 : | jsr166 | 1.22 | assertFalse(Thread.interrupted()); |
515 : | dl | 1.1 | return Boolean.TRUE; |
516 : | jsr166 | 1.15 | }}); |
517 : | |||
518 : | jsr166 | 1.22 | Thread t = newStartedThread(task); |
519 : | jsr166 | 1.29 | await(pleaseCancel); |
520 : | jsr166 | 1.15 | assertTrue(task.cancel(false)); |
521 : | jsr166 | 1.29 | assertTrue(task.isCancelled()); |
522 : | jsr166 | 1.22 | cancelled.countDown(); |
523 : | jsr166 | 1.29 | awaitTermination(t); |
524 : | assertEquals(1, task.runCount()); | ||
525 : | assertEquals(1, task.setCount()); | ||
526 : | assertEquals(0, task.setExceptionCount()); | ||
527 : | tryToConfuseDoneTask(task); | ||
528 : | jsr166 | 1.22 | checkCancelled(task); |
529 : | dl | 1.1 | } |
530 : | |||
531 : | dl | 1.5 | /** |
532 : | jsr166 | 1.23 | * run in one thread causes get in another thread to retrieve value |
533 : | dl | 1.5 | */ |
534 : | jsr166 | 1.29 | public void testGetRun() { |
535 : | final CountDownLatch pleaseRun = new CountDownLatch(2); | ||
536 : | jsr166 | 1.23 | |
537 : | final PublicFutureTask task = | ||
538 : | new PublicFutureTask(new CheckedCallable<Object>() { | ||
539 : | jsr166 | 1.29 | public Object realCall() { |
540 : | return two; | ||
541 : | jsr166 | 1.23 | }}); |
542 : | |||
543 : | jsr166 | 1.29 | Thread t1 = newStartedThread(new CheckedRunnable() { |
544 : | jsr166 | 1.23 | public void realRun() throws Exception { |
545 : | jsr166 | 1.29 | pleaseRun.countDown(); |
546 : | assertSame(two, task.get()); | ||
547 : | jsr166 | 1.23 | }}); |
548 : | |||
549 : | jsr166 | 1.29 | Thread t2 = newStartedThread(new CheckedRunnable() { |
550 : | jsr166 | 1.15 | public void realRun() throws Exception { |
551 : | jsr166 | 1.29 | pleaseRun.countDown(); |
552 : | assertSame(two, task.get(2*LONG_DELAY_MS, MILLISECONDS)); | ||
553 : | jsr166 | 1.15 | }}); |
554 : | jsr166 | 1.12 | |
555 : | jsr166 | 1.29 | await(pleaseRun); |
556 : | jsr166 | 1.23 | checkNotDone(task); |
557 : | jsr166 | 1.29 | assertTrue(t1.isAlive()); |
558 : | assertTrue(t2.isAlive()); | ||
559 : | jsr166 | 1.22 | task.run(); |
560 : | jsr166 | 1.29 | checkCompletedNormally(task, two); |
561 : | assertEquals(1, task.runCount()); | ||
562 : | assertEquals(1, task.setCount()); | ||
563 : | assertEquals(0, task.setExceptionCount()); | ||
564 : | awaitTermination(t1); | ||
565 : | awaitTermination(t2); | ||
566 : | tryToConfuseDoneTask(task); | ||
567 : | checkCompletedNormally(task, two); | ||
568 : | dl | 1.1 | } |
569 : | |||
570 : | dl | 1.5 | /** |
571 : | jsr166 | 1.29 | * set in one thread causes get in another thread to retrieve value |
572 : | jsr166 | 1.23 | */ |
573 : | jsr166 | 1.29 | public void testGetSet() { |
574 : | final CountDownLatch pleaseSet = new CountDownLatch(2); | ||
575 : | jsr166 | 1.23 | |
576 : | final PublicFutureTask task = | ||
577 : | new PublicFutureTask(new CheckedCallable<Object>() { | ||
578 : | public Object realCall() throws InterruptedException { | ||
579 : | jsr166 | 1.29 | return two; |
580 : | jsr166 | 1.23 | }}); |
581 : | |||
582 : | jsr166 | 1.29 | Thread t1 = newStartedThread(new CheckedRunnable() { |
583 : | public void realRun() throws Exception { | ||
584 : | pleaseSet.countDown(); | ||
585 : | assertSame(two, task.get()); | ||
586 : | }}); | ||
587 : | |||
588 : | Thread t2 = newStartedThread(new CheckedRunnable() { | ||
589 : | jsr166 | 1.23 | public void realRun() throws Exception { |
590 : | jsr166 | 1.29 | pleaseSet.countDown(); |
591 : | assertSame(two, task.get(2*LONG_DELAY_MS, MILLISECONDS)); | ||
592 : | jsr166 | 1.23 | }}); |
593 : | |||
594 : | jsr166 | 1.29 | await(pleaseSet); |
595 : | jsr166 | 1.23 | checkNotDone(task); |
596 : | jsr166 | 1.29 | assertTrue(t1.isAlive()); |
597 : | assertTrue(t2.isAlive()); | ||
598 : | task.set(two); | ||
599 : | assertEquals(0, task.runCount()); | ||
600 : | assertEquals(1, task.setCount()); | ||
601 : | assertEquals(0, task.setExceptionCount()); | ||
602 : | tryToConfuseDoneTask(task); | ||
603 : | checkCompletedNormally(task, two); | ||
604 : | awaitTermination(t1); | ||
605 : | awaitTermination(t2); | ||
606 : | jsr166 | 1.23 | } |
607 : | |||
608 : | /** | ||
609 : | jsr166 | 1.21 | * Cancelling a task causes timed get in another thread to throw |
610 : | * CancellationException | ||
611 : | dl | 1.5 | */ |
612 : | jsr166 | 1.29 | public void testTimedGet_Cancellation() { |
613 : | jsr166 | 1.36 | testTimedGet_Cancellation(false); |
614 : | } | ||
615 : | public void testTimedGet_Cancellation_interrupt() { | ||
616 : | testTimedGet_Cancellation(true); | ||
617 : | } | ||
618 : | public void testTimedGet_Cancellation(final boolean mayInterruptIfRunning) { | ||
619 : | final CountDownLatch pleaseCancel = new CountDownLatch(3); | ||
620 : | final CountDownLatch cancelled = new CountDownLatch(1); | ||
621 : | final Callable<Object> callable = | ||
622 : | new CheckedCallable<Object>() { | ||
623 : | public Object realCall() throws InterruptedException { | ||
624 : | pleaseCancel.countDown(); | ||
625 : | if (mayInterruptIfRunning) { | ||
626 : | try { | ||
627 : | delay(2*LONG_DELAY_MS); | ||
628 : | } catch (InterruptedException success) {} | ||
629 : | } else { | ||
630 : | await(cancelled); | ||
631 : | } | ||
632 : | return two; | ||
633 : | }}; | ||
634 : | final PublicFutureTask task = new PublicFutureTask(callable); | ||
635 : | jsr166 | 1.29 | |
636 : | jsr166 | 1.36 | Thread t1 = new ThreadShouldThrow(CancellationException.class) { |
637 : | jsr166 | 1.29 | public void realRun() throws Exception { |
638 : | pleaseCancel.countDown(); | ||
639 : | task.get(); | ||
640 : | }}; | ||
641 : | jsr166 | 1.36 | Thread t2 = new ThreadShouldThrow(CancellationException.class) { |
642 : | jsr166 | 1.29 | public void realRun() throws Exception { |
643 : | pleaseCancel.countDown(); | ||
644 : | task.get(2*LONG_DELAY_MS, MILLISECONDS); | ||
645 : | }}; | ||
646 : | jsr166 | 1.36 | t1.start(); |
647 : | t2.start(); | ||
648 : | Thread t3 = newStartedThread(task); | ||
649 : | await(pleaseCancel); | ||
650 : | checkIsRunning(task); | ||
651 : | task.cancel(mayInterruptIfRunning); | ||
652 : | checkCancelled(task); | ||
653 : | awaitTermination(t1); | ||
654 : | awaitTermination(t2); | ||
655 : | cancelled.countDown(); | ||
656 : | awaitTermination(t3); | ||
657 : | assertEquals(1, task.runCount()); | ||
658 : | assertEquals(1, task.setCount()); | ||
659 : | assertEquals(0, task.setExceptionCount()); | ||
660 : | tryToConfuseDoneTask(task); | ||
661 : | checkCancelled(task); | ||
662 : | dl | 1.1 | } |
663 : | jsr166 | 1.12 | |
664 : | dl | 1.5 | /** |
665 : | dl | 1.6 | * A runtime exception in task causes get to throw ExecutionException |
666 : | dl | 1.5 | */ |
667 : | jsr166 | 1.15 | public void testGet_ExecutionException() throws InterruptedException { |
668 : | jsr166 | 1.29 | final ArithmeticException e = new ArithmeticException(); |
669 : | final PublicFutureTask task = new PublicFutureTask(new Callable() { | ||
670 : | jsr166 | 1.16 | public Object call() { |
671 : | jsr166 | 1.29 | throw e; |
672 : | jsr166 | 1.15 | }}); |
673 : | |||
674 : | jsr166 | 1.22 | task.run(); |
675 : | jsr166 | 1.29 | assertEquals(1, task.runCount()); |
676 : | assertEquals(0, task.setCount()); | ||
677 : | assertEquals(1, task.setExceptionCount()); | ||
678 : | jsr166 | 1.15 | try { |
679 : | jsr166 | 1.22 | task.get(); |
680 : | jsr166 | 1.17 | shouldThrow(); |
681 : | jsr166 | 1.16 | } catch (ExecutionException success) { |
682 : | jsr166 | 1.29 | assertSame(e, success.getCause()); |
683 : | tryToConfuseDoneTask(task); | ||
684 : | jsr166 | 1.22 | checkCompletedAbnormally(task, success.getCause()); |
685 : | dl | 1.1 | } |
686 : | } | ||
687 : | jsr166 | 1.12 | |
688 : | dl | 1.5 | /** |
689 : | jsr166 | 1.20 | * A runtime exception in task causes timed get to throw ExecutionException |
690 : | dl | 1.5 | */ |
691 : | jsr166 | 1.15 | public void testTimedGet_ExecutionException2() throws Exception { |
692 : | jsr166 | 1.29 | final ArithmeticException e = new ArithmeticException(); |
693 : | final PublicFutureTask task = new PublicFutureTask(new Callable() { | ||
694 : | jsr166 | 1.16 | public Object call() { |
695 : | jsr166 | 1.29 | throw e; |
696 : | jsr166 | 1.15 | }}); |
697 : | |||
698 : | jsr166 | 1.22 | task.run(); |
699 : | jsr166 | 1.16 | try { |
700 : | jsr166 | 1.29 | task.get(LONG_DELAY_MS, MILLISECONDS); |
701 : | jsr166 | 1.17 | shouldThrow(); |
702 : | jsr166 | 1.16 | } catch (ExecutionException success) { |
703 : | jsr166 | 1.29 | assertSame(e, success.getCause()); |
704 : | tryToConfuseDoneTask(task); | ||
705 : | jsr166 | 1.22 | checkCompletedAbnormally(task, success.getCause()); |
706 : | jsr166 | 1.15 | } |
707 : | dl | 1.1 | } |
708 : | jsr166 | 1.12 | |
709 : | dl | 1.5 | /** |
710 : | jsr166 | 1.29 | * get is interruptible |
711 : | dl | 1.5 | */ |
712 : | jsr166 | 1.29 | public void testGet_interruptible() { |
713 : | final CountDownLatch pleaseInterrupt = new CountDownLatch(1); | ||
714 : | jsr166 | 1.22 | final FutureTask task = new FutureTask(new NoOpCallable()); |
715 : | jsr166 | 1.29 | Thread t = newStartedThread(new CheckedRunnable() { |
716 : | jsr166 | 1.15 | public void realRun() throws Exception { |
717 : | jsr166 | 1.29 | Thread.currentThread().interrupt(); |
718 : | try { | ||
719 : | task.get(); | ||
720 : | shouldThrow(); | ||
721 : | } catch (InterruptedException success) {} | ||
722 : | assertFalse(Thread.interrupted()); | ||
723 : | |||
724 : | pleaseInterrupt.countDown(); | ||
725 : | try { | ||
726 : | task.get(); | ||
727 : | shouldThrow(); | ||
728 : | } catch (InterruptedException success) {} | ||
729 : | assertFalse(Thread.interrupted()); | ||
730 : | jsr166 | 1.15 | }}); |
731 : | |||
732 : | jsr166 | 1.29 | await(pleaseInterrupt); |
733 : | jsr166 | 1.15 | t.interrupt(); |
734 : | jsr166 | 1.28 | awaitTermination(t); |
735 : | jsr166 | 1.22 | checkNotDone(task); |
736 : | dl | 1.1 | } |
737 : | |||
738 : | dl | 1.5 | /** |
739 : | jsr166 | 1.29 | * timed get is interruptible |
740 : | dl | 1.5 | */ |
741 : | jsr166 | 1.29 | public void testTimedGet_interruptible() { |
742 : | final CountDownLatch pleaseInterrupt = new CountDownLatch(1); | ||
743 : | jsr166 | 1.22 | final FutureTask task = new FutureTask(new NoOpCallable()); |
744 : | jsr166 | 1.29 | Thread t = newStartedThread(new CheckedRunnable() { |
745 : | jsr166 | 1.15 | public void realRun() throws Exception { |
746 : | jsr166 | 1.29 | Thread.currentThread().interrupt(); |
747 : | try { | ||
748 : | task.get(2*LONG_DELAY_MS, MILLISECONDS); | ||
749 : | shouldThrow(); | ||
750 : | } catch (InterruptedException success) {} | ||
751 : | assertFalse(Thread.interrupted()); | ||
752 : | |||
753 : | pleaseInterrupt.countDown(); | ||
754 : | try { | ||
755 : | task.get(2*LONG_DELAY_MS, MILLISECONDS); | ||
756 : | shouldThrow(); | ||
757 : | } catch (InterruptedException success) {} | ||
758 : | assertFalse(Thread.interrupted()); | ||
759 : | jsr166 | 1.15 | }}); |
760 : | |||
761 : | jsr166 | 1.29 | await(pleaseInterrupt); |
762 : | jsr166 | 1.15 | t.interrupt(); |
763 : | jsr166 | 1.28 | awaitTermination(t); |
764 : | jsr166 | 1.22 | checkNotDone(task); |
765 : | dl | 1.1 | } |
766 : | jsr166 | 1.12 | |
767 : | dl | 1.5 | /** |
768 : | dl | 1.6 | * A timed out timed get throws TimeoutException |
769 : | dl | 1.5 | */ |
770 : | jsr166 | 1.15 | public void testGet_TimeoutException() throws Exception { |
771 : | jsr166 | 1.29 | FutureTask task = new FutureTask(new NoOpCallable()); |
772 : | long startTime = System.nanoTime(); | ||
773 : | jsr166 | 1.16 | try { |
774 : | jsr166 | 1.29 | task.get(timeoutMillis(), MILLISECONDS); |
775 : | jsr166 | 1.17 | shouldThrow(); |
776 : | jsr166 | 1.29 | } catch (TimeoutException success) { |
777 : | assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); | ||
778 : | } | ||
779 : | } | ||
780 : | |||
781 : | /** | ||
782 : | * timed get with null TimeUnit throws NullPointerException | ||
783 : | */ | ||
784 : | public void testGet_NullTimeUnit() throws Exception { | ||
785 : | FutureTask task = new FutureTask(new NoOpCallable()); | ||
786 : | long[] timeouts = { Long.MIN_VALUE, 0L, Long.MAX_VALUE }; | ||
787 : | |||
788 : | for (long timeout : timeouts) { | ||
789 : | try { | ||
790 : | task.get(timeout, null); | ||
791 : | shouldThrow(); | ||
792 : | } catch (NullPointerException success) {} | ||
793 : | } | ||
794 : | |||
795 : | task.run(); | ||
796 : | |||
797 : | for (long timeout : timeouts) { | ||
798 : | try { | ||
799 : | task.get(timeout, null); | ||
800 : | shouldThrow(); | ||
801 : | } catch (NullPointerException success) {} | ||
802 : | } | ||
803 : | dl | 1.1 | } |
804 : | jsr166 | 1.12 | |
805 : | dl | 1.1 | } |
Doug Lea | ViewVC Help |
Powered by ViewVC 1.0.8 |