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