/[cvs]/jsr166/src/test/tck/FutureTaskTest.java
ViewVC logotype

Contents of /jsr166/src/test/tck/FutureTaskTest.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.29 - (show annotations)
Mon Jun 20 04:31:59 2011 UTC (8 years, 2 months ago) by jsr166
Branch: MAIN
Changes since 1.28: +429 -214 lines
various test coverage improvements

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

dl@cs.oswego.edu
ViewVC Help
Powered by ViewVC 1.1.27