Home | History | Annotate | Download | only in jsr166
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    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);
    175         public int runCount() { return runCount.get(); }
    176         public int doneCount() { return doneCount.get(); }
    177         public int runAndResetCount() { return runAndResetCount.get(); }
    178         public int setCount() { return setCount.get(); }
    179         public int setExceptionCount() { return setExceptionCount.get(); }
    180 
    181         PublicFutureTask(Runnable runnable) {
    182             this(runnable, seven);
    183         }
    184         PublicFutureTask(Runnable runnable, Object result) {
    185             this(runnable, result, new AtomicInteger(0));
    186         }
    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         }
    196         PublicFutureTask(Callable callable) {
    197             this(callable, new AtomicInteger(0));
    198         }
    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         }
    208         @Override public void done() {
    209             assertTrue(isDone());
    210             doneCount.incrementAndGet();
    211             super.done();
    212         }
    213         @Override public boolean runAndReset() {
    214             runAndResetCount.incrementAndGet();
    215             return super.runAndReset();
    216         }
    217         @Override public void set(Object x) {
    218             setCount.incrementAndGet();
    219             super.set(x);
    220         }
    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);
    229         public int get() { return count.get(); }
    230         public void realRun() {
    231             count.getAndIncrement();
    232         }
    233     }
    234 
    235     /**
    236      * creating a future with a null callable throws NullPointerException
    237      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    624     public void testTimedGet_Cancellation() {
    625         testTimedGet_Cancellation(false);
    626     }
    627     public void testTimedGet_Cancellation_interrupt() {
    628         testTimedGet_Cancellation(true);
    629     }
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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