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