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