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