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  */
  33 
  34 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  35 
  36 import java.util.Arrays;
  37 import java.util.HashSet;
  38 import java.util.concurrent.Callable;
  39 import java.util.concurrent.CancellationException;
  40 import java.util.concurrent.ExecutionException;
  41 import java.util.concurrent.ForkJoinPool;
  42 import java.util.concurrent.ForkJoinTask;
  43 import java.util.concurrent.RecursiveAction;
  44 import java.util.concurrent.TimeoutException;
  45 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
  46 
  47 import junit.framework.Test;
  48 import junit.framework.TestSuite;
  49 
  50 public class ForkJoinTaskTest extends JSR166TestCase {
  51 
  52     public static void main(String[] args) {
  53         main(suite(), args);
  54     }
  55 
  56     public static Test suite() {
  57         return new TestSuite(ForkJoinTaskTest.class);
  58     }
  59 
  60     // Runs with "mainPool" use > 1 thread. singletonPool tests use 1
  61     static final int mainPoolSize =
  62         Math.max(2, Runtime.getRuntime().availableProcessors());
  63 
  64     private static ForkJoinPool mainPool() {
  65         return new ForkJoinPool(mainPoolSize);
  66     }
  67 
  68     private static ForkJoinPool singletonPool() {
  69         return new ForkJoinPool(1);
  70     }
  71 
  72     private static ForkJoinPool asyncSingletonPool() {
  73         return new ForkJoinPool(1,
  74                                 ForkJoinPool.defaultForkJoinWorkerThreadFactory,
  75                                 null, true);
  76     }
  77 
  78     private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) {
  79         try (PoolCleaner cleaner = cleaner(pool)) {
  80             assertFalse(a.isDone());
  81             assertFalse(a.isCompletedNormally());
  82             assertFalse(a.isCompletedAbnormally());
  83             assertFalse(a.isCancelled());
  84             assertNull(a.getException());
  85             assertNull(a.getRawResult());
  86 
  87             assertNull(pool.invoke(a));
  88 
  89             assertTrue(a.isDone());
  90             assertTrue(a.isCompletedNormally());
  91             assertFalse(a.isCompletedAbnormally());
  92             assertFalse(a.isCancelled());
  93             assertNull(a.getException());
  94             assertNull(a.getRawResult());
  95         }
  96     }
  97 
  98     void checkNotDone(ForkJoinTask a) {
  99         assertFalse(a.isDone());
 100         assertFalse(a.isCompletedNormally());
 101         assertFalse(a.isCompletedAbnormally());
 102         assertFalse(a.isCancelled());
 103         assertNull(a.getException());
 104         assertNull(a.getRawResult());
 105 
 106         try {
 107             a.get(randomExpiredTimeout(), randomTimeUnit());
 108             shouldThrow();
 109         } catch (TimeoutException success) {
 110         } catch (Throwable fail) { threadUnexpectedException(fail); }
 111     }
 112 
 113     <T> void checkCompletedNormally(ForkJoinTask<T> a) {
 114         checkCompletedNormally(a, null);
 115     }
 116 
 117     <T> void checkCompletedNormally(ForkJoinTask<T> a, T expectedValue) {
 118         assertTrue(a.isDone());
 119         assertFalse(a.isCancelled());
 120         assertTrue(a.isCompletedNormally());
 121         assertFalse(a.isCompletedAbnormally());
 122         assertNull(a.getException());
 123         assertSame(expectedValue, a.getRawResult());
 124 
 125         {
 126             Thread.currentThread().interrupt();
 127             long startTime = System.nanoTime();
 128             assertSame(expectedValue, a.join());
 129             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 130             Thread.interrupted();
 131         }
 132 
 133         {
 134             Thread.currentThread().interrupt();
 135             long startTime = System.nanoTime();
 136             a.quietlyJoin();        // should be no-op
 137             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 138             Thread.interrupted();
 139         }
 140 
 141         assertFalse(a.cancel(false));
 142         assertFalse(a.cancel(true));
 143 
 144         T v1 = null, v2 = null;
 145         try {
 146             v1 = a.get();
 147             v2 = a.get(randomTimeout(), randomTimeUnit());
 148         } catch (Throwable fail) { threadUnexpectedException(fail); }
 149         assertSame(expectedValue, v1);
 150         assertSame(expectedValue, v2);
 151     }
 152 
 153     void checkCancelled(ForkJoinTask a) {
 154         assertTrue(a.isDone());
 155         assertTrue(a.isCancelled());
 156         assertFalse(a.isCompletedNormally());
 157         assertTrue(a.isCompletedAbnormally());
 158         assertTrue(a.getException() instanceof CancellationException);
 159         assertNull(a.getRawResult());
 160         assertTrue(a.cancel(false));
 161         assertTrue(a.cancel(true));
 162 
 163         try {
 164             Thread.currentThread().interrupt();
 165             a.join();
 166             shouldThrow();
 167         } catch (CancellationException success) {
 168         } catch (Throwable fail) { threadUnexpectedException(fail); }
 169         Thread.interrupted();
 170 
 171         {
 172             long startTime = System.nanoTime();
 173             a.quietlyJoin();        // should be no-op
 174             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 175         }
 176 
 177         try {
 178             a.get();
 179             shouldThrow();
 180         } catch (CancellationException success) {
 181         } catch (Throwable fail) { threadUnexpectedException(fail); }
 182 
 183         try {
 184             a.get(randomTimeout(), randomTimeUnit());
 185             shouldThrow();
 186         } catch (CancellationException success) {
 187         } catch (Throwable fail) { threadUnexpectedException(fail); }
 188     }
 189 
 190     void checkCompletedAbnormally(ForkJoinTask a, Throwable t) {
 191         assertTrue(a.isDone());
 192         assertFalse(a.isCancelled());
 193         assertFalse(a.isCompletedNormally());
 194         assertTrue(a.isCompletedAbnormally());
 195         assertSame(t.getClass(), a.getException().getClass());
 196         assertNull(a.getRawResult());
 197         assertFalse(a.cancel(false));
 198         assertFalse(a.cancel(true));
 199 
 200         try {
 201             Thread.currentThread().interrupt();
 202             a.join();
 203             shouldThrow();
 204         } catch (Throwable expected) {
 205             assertSame(t.getClass(), expected.getClass());
 206         }
 207         Thread.interrupted();
 208 
 209         {
 210             long startTime = System.nanoTime();
 211             a.quietlyJoin();        // should be no-op
 212             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 213         }
 214 
 215         try {
 216             a.get();
 217             shouldThrow();
 218         } catch (ExecutionException success) {
 219             assertSame(t.getClass(), success.getCause().getClass());
 220         } catch (Throwable fail) { threadUnexpectedException(fail); }
 221 
 222         try {
 223             a.get(randomTimeout(), randomTimeUnit());
 224             shouldThrow();
 225         } catch (ExecutionException success) {
 226             assertSame(t.getClass(), success.getCause().getClass());
 227         } catch (Throwable fail) { threadUnexpectedException(fail); }
 228     }
 229 
 230     /*
 231      * Testing coverage notes:
 232      *
 233      * To test extension methods and overrides, most tests use
 234      * BinaryAsyncAction extension class that processes joins
 235      * differently than supplied Recursive forms.
 236      */
 237 
 238     public static final class FJException extends RuntimeException {
 239         FJException() { super(); }
 240     }
 241 
 242     abstract static class BinaryAsyncAction extends ForkJoinTask<Void> {
 243         private volatile int controlState;
 244 
 245         static final AtomicIntegerFieldUpdater<BinaryAsyncAction> controlStateUpdater =
 246             AtomicIntegerFieldUpdater.newUpdater(BinaryAsyncAction.class,
 247                                                  "controlState");
 248 
 249         private volatile BinaryAsyncAction parent;
 250 
 251         private volatile BinaryAsyncAction sibling;
 252 
 253         protected BinaryAsyncAction() {
 254         }
 255 
 256         public final Void getRawResult() { return null; }
 257         protected final void setRawResult(Void mustBeNull) { }
 258 
 259         public final void linkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
 260             x.parent = y.parent = this;
 261             x.sibling = y;
 262             y.sibling = x;
 263         }
 264 
 265         protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
 266         }
 267 
 268         protected boolean onException() {
 269             return true;
 270         }
 271 
 272         public void linkAndForkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
 273             linkSubtasks(x, y);
 274             y.fork();
 275             x.fork();
 276         }
 277 
 278         private void completeThis() {
 279             super.complete(null);
 280         }
 281 
 282         private void completeThisExceptionally(Throwable ex) {
 283             super.completeExceptionally(ex);
 284         }
 285 
 286         public boolean cancel(boolean mayInterruptIfRunning) {
 287             if (super.cancel(mayInterruptIfRunning)) {
 288                 completeExceptionally(new FJException());
 289                 return true;
 290             }
 291             return false;
 292         }
 293 
 294         public final void complete() {
 295             BinaryAsyncAction a = this;
 296             for (;;) {
 297                 BinaryAsyncAction s = a.sibling;
 298                 BinaryAsyncAction p = a.parent;
 299                 a.sibling = null;
 300                 a.parent = null;
 301                 a.completeThis();
 302                 if (p == null || p.compareAndSetControlState(0, 1))
 303                     break;
 304                 try {
 305                     p.onComplete(a, s);
 306                 } catch (Throwable rex) {
 307                     p.completeExceptionally(rex);
 308                     return;
 309                 }
 310                 a = p;
 311             }
 312         }
 313 
 314         public final void completeExceptionally(Throwable ex) {
 315             for (BinaryAsyncAction a = this;;) {
 316                 a.completeThisExceptionally(ex);
 317                 BinaryAsyncAction s = a.sibling;
 318                 if (s != null && !s.isDone())
 319                     s.completeExceptionally(ex);
 320                 if ((a = a.parent) == null)
 321                     break;
 322             }
 323         }
 324 
 325         public final BinaryAsyncAction getParent() {
 326             return parent;
 327         }
 328 
 329         public BinaryAsyncAction getSibling() {
 330             return sibling;
 331         }
 332 
 333         public void reinitialize() {
 334             parent = sibling = null;
 335             super.reinitialize();
 336         }
 337 
 338         protected final int getControlState() {
 339             return controlState;
 340         }
 341 
 342         protected final boolean compareAndSetControlState(int expect,
 343                                                           int update) {
 344             return controlStateUpdater.compareAndSet(this, expect, update);
 345         }
 346 
 347         protected final void setControlState(int value) {
 348             controlState = value;
 349         }
 350 
 351         protected final void incrementControlState() {
 352             controlStateUpdater.incrementAndGet(this);
 353         }
 354 
 355         protected final void decrementControlState() {
 356             controlStateUpdater.decrementAndGet(this);
 357         }
 358 
 359     }
 360 
 361     static final class AsyncFib extends BinaryAsyncAction {
 362         int number;
 363         public AsyncFib(int n) {
 364             this.number = n;
 365         }
 366 
 367         public final boolean exec() {
 368             AsyncFib f = this;
 369             int n = f.number;
 370             while (n > 1) {
 371                 AsyncFib p = f;
 372                 AsyncFib r = new AsyncFib(n - 2);
 373                 f = new AsyncFib(--n);
 374                 p.linkSubtasks(r, f);
 375                 r.fork();
 376             }
 377             f.complete();
 378             return false;
 379         }
 380 
 381         protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
 382             number = ((AsyncFib)x).number + ((AsyncFib)y).number;
 383         }
 384     }
 385 
 386     static final class FailingAsyncFib extends BinaryAsyncAction {
 387         int number;
 388         public FailingAsyncFib(int n) {
 389             this.number = n;
 390         }
 391 
 392         public final boolean exec() {
 393             FailingAsyncFib f = this;
 394             int n = f.number;
 395             while (n > 1) {
 396                 FailingAsyncFib p = f;
 397                 FailingAsyncFib r = new FailingAsyncFib(n - 2);
 398                 f = new FailingAsyncFib(--n);
 399                 p.linkSubtasks(r, f);
 400                 r.fork();
 401             }
 402             f.complete();
 403             return false;
 404         }
 405 
 406         protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
 407             completeExceptionally(new FJException());
 408         }
 409     }
 410 
 411     /**
 412      * invoke returns when task completes normally.
 413      * isCompletedAbnormally and isCancelled return false for normally
 414      * completed tasks; getRawResult returns null.
 415      */
 416     public void testInvoke() {
 417         RecursiveAction a = new CheckedRecursiveAction() {
 418             protected void realCompute() {
 419                 AsyncFib f = new AsyncFib(8);
 420                 assertNull(f.invoke());
 421                 assertEquals(21, f.number);
 422                 checkCompletedNormally(f);
 423             }};
 424         testInvokeOnPool(mainPool(), a);
 425     }
 426 
 427     /**
 428      * quietlyInvoke task returns when task completes normally.
 429      * isCompletedAbnormally and isCancelled return false for normally
 430      * completed tasks
 431      */
 432     public void testQuietlyInvoke() {
 433         RecursiveAction a = new CheckedRecursiveAction() {
 434             protected void realCompute() {
 435                 AsyncFib f = new AsyncFib(8);
 436                 f.quietlyInvoke();
 437                 assertEquals(21, f.number);
 438                 checkCompletedNormally(f);
 439             }};
 440         testInvokeOnPool(mainPool(), a);
 441     }
 442 
 443     /**
 444      * join of a forked task returns when task completes
 445      */
 446     public void testForkJoin() {
 447         RecursiveAction a = new CheckedRecursiveAction() {
 448             protected void realCompute() {
 449                 AsyncFib f = new AsyncFib(8);
 450                 assertSame(f, f.fork());
 451                 assertNull(f.join());
 452                 assertEquals(21, f.number);
 453                 checkCompletedNormally(f);
 454             }};
 455         testInvokeOnPool(mainPool(), a);
 456     }
 457 
 458     /**
 459      * get of a forked task returns when task completes
 460      */
 461     public void testForkGet() {
 462         RecursiveAction a = new CheckedRecursiveAction() {
 463             protected void realCompute() throws Exception {
 464                 AsyncFib f = new AsyncFib(8);
 465                 assertSame(f, f.fork());
 466                 assertNull(f.get());
 467                 assertEquals(21, f.number);
 468                 checkCompletedNormally(f);
 469             }};
 470         testInvokeOnPool(mainPool(), a);
 471     }
 472 
 473     /**
 474      * timed get of a forked task returns when task completes
 475      */
 476     public void testForkTimedGet() {
 477         RecursiveAction a = new CheckedRecursiveAction() {
 478             protected void realCompute() throws Exception {
 479                 AsyncFib f = new AsyncFib(8);
 480                 assertSame(f, f.fork());
 481                 assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
 482                 assertEquals(21, f.number);
 483                 checkCompletedNormally(f);
 484             }};
 485         testInvokeOnPool(mainPool(), a);
 486     }
 487 
 488     /**
 489      * timed get with null time unit throws NPE
 490      */
 491     public void testForkTimedGetNPE() {
 492         RecursiveAction a = new CheckedRecursiveAction() {
 493             protected void realCompute() throws Exception {
 494                 AsyncFib f = new AsyncFib(8);
 495                 assertSame(f, f.fork());
 496                 try {
 497                     f.get(randomTimeout(), null);
 498                     shouldThrow();
 499                 } catch (NullPointerException success) {}
 500             }};
 501         testInvokeOnPool(mainPool(), a);
 502     }
 503 
 504     /**
 505      * quietlyJoin of a forked task returns when task completes
 506      */
 507     public void testForkQuietlyJoin() {
 508         RecursiveAction a = new CheckedRecursiveAction() {
 509             protected void realCompute() {
 510                 AsyncFib f = new AsyncFib(8);
 511                 assertSame(f, f.fork());
 512                 f.quietlyJoin();
 513                 assertEquals(21, f.number);
 514                 checkCompletedNormally(f);
 515             }};
 516         testInvokeOnPool(mainPool(), a);
 517     }
 518 
 519     /**
 520      * helpQuiesce returns when tasks are complete.
 521      * getQueuedTaskCount returns 0 when quiescent
 522      */
 523     public void testForkHelpQuiesce() {
 524         RecursiveAction a = new CheckedRecursiveAction() {
 525             protected void realCompute() {
 526                 AsyncFib f = new AsyncFib(8);
 527                 assertSame(f, f.fork());
 528                 helpQuiesce();
 529                 assertEquals(21, f.number);
 530                 assertEquals(0, getQueuedTaskCount());
 531                 checkCompletedNormally(f);
 532             }};
 533         testInvokeOnPool(mainPool(), a);
 534     }
 535 
 536     /**
 537      * invoke task throws exception when task completes abnormally
 538      */
 539     public void testAbnormalInvoke() {
 540         RecursiveAction a = new CheckedRecursiveAction() {
 541             protected void realCompute() {
 542                 FailingAsyncFib f = new FailingAsyncFib(8);
 543                 try {
 544                     f.invoke();
 545                     shouldThrow();
 546                 } catch (FJException success) {
 547                     checkCompletedAbnormally(f, success);
 548                 }
 549             }};
 550         testInvokeOnPool(mainPool(), a);
 551     }
 552 
 553     /**
 554      * quietlyInvoke task returns when task completes abnormally
 555      */
 556     public void testAbnormalQuietlyInvoke() {
 557         RecursiveAction a = new CheckedRecursiveAction() {
 558             protected void realCompute() {
 559                 FailingAsyncFib f = new FailingAsyncFib(8);
 560                 f.quietlyInvoke();
 561                 assertTrue(f.getException() instanceof FJException);
 562                 checkCompletedAbnormally(f, f.getException());
 563             }};
 564         testInvokeOnPool(mainPool(), a);
 565     }
 566 
 567     /**
 568      * join of a forked task throws exception when task completes abnormally
 569      */
 570     public void testAbnormalForkJoin() {
 571         RecursiveAction a = new CheckedRecursiveAction() {
 572             protected void realCompute() {
 573                 FailingAsyncFib f = new FailingAsyncFib(8);
 574                 assertSame(f, f.fork());
 575                 try {
 576                     f.join();
 577                     shouldThrow();
 578                 } catch (FJException success) {
 579                     checkCompletedAbnormally(f, success);
 580                 }
 581             }};
 582         testInvokeOnPool(mainPool(), a);
 583     }
 584 
 585     /**
 586      * get of a forked task throws exception when task completes abnormally
 587      */
 588     public void testAbnormalForkGet() {
 589         RecursiveAction a = new CheckedRecursiveAction() {
 590             protected void realCompute() throws Exception {
 591                 FailingAsyncFib f = new FailingAsyncFib(8);
 592                 assertSame(f, f.fork());
 593                 try {
 594                     f.get();
 595                     shouldThrow();
 596                 } catch (ExecutionException success) {
 597                     Throwable cause = success.getCause();
 598                     assertTrue(cause instanceof FJException);
 599                     checkCompletedAbnormally(f, cause);
 600                 }
 601             }};
 602         testInvokeOnPool(mainPool(), a);
 603     }
 604 
 605     /**
 606      * timed get of a forked task throws exception when task completes abnormally
 607      */
 608     public void testAbnormalForkTimedGet() {
 609         RecursiveAction a = new CheckedRecursiveAction() {
 610             protected void realCompute() throws Exception {
 611                 FailingAsyncFib f = new FailingAsyncFib(8);
 612                 assertSame(f, f.fork());
 613                 try {
 614                     f.get(LONG_DELAY_MS, MILLISECONDS);
 615                     shouldThrow();
 616                 } catch (ExecutionException success) {
 617                     Throwable cause = success.getCause();
 618                     assertTrue(cause instanceof FJException);
 619                     checkCompletedAbnormally(f, cause);
 620                 }
 621             }};
 622         testInvokeOnPool(mainPool(), a);
 623     }
 624 
 625     /**
 626      * quietlyJoin of a forked task returns when task completes abnormally
 627      */
 628     public void testAbnormalForkQuietlyJoin() {
 629         RecursiveAction a = new CheckedRecursiveAction() {
 630             protected void realCompute() {
 631                 FailingAsyncFib f = new FailingAsyncFib(8);
 632                 assertSame(f, f.fork());
 633                 f.quietlyJoin();
 634                 assertTrue(f.getException() instanceof FJException);
 635                 checkCompletedAbnormally(f, f.getException());
 636             }};
 637         testInvokeOnPool(mainPool(), a);
 638     }
 639 
 640     /**
 641      * invoke task throws exception when task cancelled
 642      */
 643     public void testCancelledInvoke() {
 644         RecursiveAction a = new CheckedRecursiveAction() {
 645             protected void realCompute() {
 646                 AsyncFib f = new AsyncFib(8);
 647                 assertTrue(f.cancel(true));
 648                 try {
 649                     f.invoke();
 650                     shouldThrow();
 651                 } catch (CancellationException success) {
 652                     checkCancelled(f);
 653                 }
 654             }};
 655         testInvokeOnPool(mainPool(), a);
 656     }
 657 
 658     /**
 659      * join of a forked task throws exception when task cancelled
 660      */
 661     public void testCancelledForkJoin() {
 662         RecursiveAction a = new CheckedRecursiveAction() {
 663             protected void realCompute() {
 664                 AsyncFib f = new AsyncFib(8);
 665                 assertTrue(f.cancel(true));
 666                 assertSame(f, f.fork());
 667                 try {
 668                     f.join();
 669                     shouldThrow();
 670                 } catch (CancellationException success) {
 671                     checkCancelled(f);
 672                 }
 673             }};
 674         testInvokeOnPool(mainPool(), a);
 675     }
 676 
 677     /**
 678      * get of a forked task throws exception when task cancelled
 679      */
 680     public void testCancelledForkGet() {
 681         RecursiveAction a = new CheckedRecursiveAction() {
 682             protected void realCompute() throws Exception {
 683                 AsyncFib f = new AsyncFib(8);
 684                 assertTrue(f.cancel(true));
 685                 assertSame(f, f.fork());
 686                 try {
 687                     f.get();
 688                     shouldThrow();
 689                 } catch (CancellationException success) {
 690                     checkCancelled(f);
 691                 }
 692             }};
 693         testInvokeOnPool(mainPool(), a);
 694     }
 695 
 696     /**
 697      * timed get of a forked task throws exception when task cancelled
 698      */
 699     public void testCancelledForkTimedGet() throws Exception {
 700         RecursiveAction a = new CheckedRecursiveAction() {
 701             protected void realCompute() throws Exception {
 702                 AsyncFib f = new AsyncFib(8);
 703                 assertTrue(f.cancel(true));
 704                 assertSame(f, f.fork());
 705                 try {
 706                     f.get(LONG_DELAY_MS, MILLISECONDS);
 707                     shouldThrow();
 708                 } catch (CancellationException success) {
 709                     checkCancelled(f);
 710                 }
 711             }};
 712         testInvokeOnPool(mainPool(), a);
 713     }
 714 
 715     /**
 716      * quietlyJoin of a forked task returns when task cancelled
 717      */
 718     public void testCancelledForkQuietlyJoin() {
 719         RecursiveAction a = new CheckedRecursiveAction() {
 720             protected void realCompute() {
 721                 AsyncFib f = new AsyncFib(8);
 722                 assertTrue(f.cancel(true));
 723                 assertSame(f, f.fork());
 724                 f.quietlyJoin();
 725                 checkCancelled(f);
 726             }};
 727         testInvokeOnPool(mainPool(), a);
 728     }
 729 
 730     /**
 731      * getPool of executing task returns its pool
 732      */
 733     public void testGetPool() {
 734         final ForkJoinPool mainPool = mainPool();
 735         RecursiveAction a = new CheckedRecursiveAction() {
 736             protected void realCompute() {
 737                 assertSame(mainPool, getPool());
 738             }};
 739         testInvokeOnPool(mainPool, a);
 740     }
 741 
 742     /**
 743      * getPool of non-FJ task returns null
 744      */
 745     public void testGetPool2() {
 746         RecursiveAction a = new CheckedRecursiveAction() {
 747             protected void realCompute() {
 748                 assertNull(getPool());
 749             }};
 750         assertNull(a.invoke());
 751     }
 752 
 753     /**
 754      * inForkJoinPool of executing task returns true
 755      */
 756     public void testInForkJoinPool() {
 757         RecursiveAction a = new CheckedRecursiveAction() {
 758             protected void realCompute() {
 759                 assertTrue(inForkJoinPool());
 760             }};
 761         testInvokeOnPool(mainPool(), a);
 762     }
 763 
 764     /**
 765      * inForkJoinPool of non-FJ task returns false
 766      */
 767     public void testInForkJoinPool2() {
 768         RecursiveAction a = new CheckedRecursiveAction() {
 769             protected void realCompute() {
 770                 assertFalse(inForkJoinPool());
 771             }};
 772         assertNull(a.invoke());
 773     }
 774 
 775     /**
 776      * setRawResult(null) succeeds
 777      */
 778     public void testSetRawResult() {
 779         RecursiveAction a = new CheckedRecursiveAction() {
 780             protected void realCompute() {
 781                 setRawResult(null);
 782                 assertNull(getRawResult());
 783             }};
 784         assertNull(a.invoke());
 785     }
 786 
 787     /**
 788      * invoke task throws exception after invoking completeExceptionally
 789      */
 790     public void testCompleteExceptionally() {
 791         RecursiveAction a = new CheckedRecursiveAction() {
 792             protected void realCompute() {
 793                 AsyncFib f = new AsyncFib(8);
 794                 f.completeExceptionally(new FJException());
 795                 try {
 796                     f.invoke();
 797                     shouldThrow();
 798                 } catch (FJException success) {
 799                     checkCompletedAbnormally(f, success);
 800                 }
 801             }};
 802         testInvokeOnPool(mainPool(), a);
 803     }
 804 
 805     /**
 806      * completeExceptionally(null) surprisingly has the same effect as
 807      * completeExceptionally(new RuntimeException())
 808      */
 809     public void testCompleteExceptionally_null() {
 810         RecursiveAction a = new CheckedRecursiveAction() {
 811             protected void realCompute() {
 812                 AsyncFib f = new AsyncFib(8);
 813                 f.completeExceptionally(null);
 814                 try {
 815                     f.invoke();
 816                     shouldThrow();
 817                 } catch (RuntimeException success) {
 818                     assertSame(success.getClass(), RuntimeException.class);
 819                     assertNull(success.getCause());
 820                     checkCompletedAbnormally(f, success);
 821                 }
 822             }};
 823         testInvokeOnPool(mainPool(), a);
 824     }
 825 
 826     /**
 827      * invokeAll(t1, t2) invokes all task arguments
 828      */
 829     public void testInvokeAll2() {
 830         RecursiveAction a = new CheckedRecursiveAction() {
 831             protected void realCompute() {
 832                 AsyncFib f = new AsyncFib(8);
 833                 AsyncFib g = new AsyncFib(9);
 834                 invokeAll(f, g);
 835                 assertEquals(21, f.number);
 836                 assertEquals(34, g.number);
 837                 checkCompletedNormally(f);
 838                 checkCompletedNormally(g);
 839             }};
 840         testInvokeOnPool(mainPool(), a);
 841     }
 842 
 843     /**
 844      * invokeAll(tasks) with 1 argument invokes task
 845      */
 846     public void testInvokeAll1() {
 847         RecursiveAction a = new CheckedRecursiveAction() {
 848             protected void realCompute() {
 849                 AsyncFib f = new AsyncFib(8);
 850                 invokeAll(f);
 851                 checkCompletedNormally(f);
 852                 assertEquals(21, f.number);
 853             }};
 854         testInvokeOnPool(mainPool(), a);
 855     }
 856 
 857     /**
 858      * invokeAll(tasks) with > 2 argument invokes tasks
 859      */
 860     public void testInvokeAll3() {
 861         RecursiveAction a = new CheckedRecursiveAction() {
 862             protected void realCompute() {
 863                 AsyncFib f = new AsyncFib(8);
 864                 AsyncFib g = new AsyncFib(9);
 865                 AsyncFib h = new AsyncFib(7);
 866                 invokeAll(f, g, h);
 867                 assertEquals(21, f.number);
 868                 assertEquals(34, g.number);
 869                 assertEquals(13, h.number);
 870                 checkCompletedNormally(f);
 871                 checkCompletedNormally(g);
 872                 checkCompletedNormally(h);
 873             }};
 874         testInvokeOnPool(mainPool(), a);
 875     }
 876 
 877     /**
 878      * invokeAll(collection) invokes all tasks in the collection
 879      */
 880     public void testInvokeAllCollection() {
 881         RecursiveAction a = new CheckedRecursiveAction() {
 882             protected void realCompute() {
 883                 AsyncFib f = new AsyncFib(8);
 884                 AsyncFib g = new AsyncFib(9);
 885                 AsyncFib h = new AsyncFib(7);
 886                 HashSet set = new HashSet();
 887                 set.add(f);
 888                 set.add(g);
 889                 set.add(h);
 890                 invokeAll(set);
 891                 assertEquals(21, f.number);
 892                 assertEquals(34, g.number);
 893                 assertEquals(13, h.number);
 894                 checkCompletedNormally(f);
 895                 checkCompletedNormally(g);
 896                 checkCompletedNormally(h);
 897             }};
 898         testInvokeOnPool(mainPool(), a);
 899     }
 900 
 901     /**
 902      * invokeAll(tasks) with any null task throws NPE
 903      */
 904     public void testInvokeAllNPE() {
 905         RecursiveAction a = new CheckedRecursiveAction() {
 906             protected void realCompute() {
 907                 AsyncFib f = new AsyncFib(8);
 908                 AsyncFib g = new AsyncFib(9);
 909                 AsyncFib h = null;
 910                 try {
 911                     invokeAll(f, g, h);
 912                     shouldThrow();
 913                 } catch (NullPointerException success) {}
 914             }};
 915         testInvokeOnPool(mainPool(), a);
 916     }
 917 
 918     /**
 919      * invokeAll(t1, t2) throw exception if any task does
 920      */
 921     public void testAbnormalInvokeAll2() {
 922         RecursiveAction a = new CheckedRecursiveAction() {
 923             protected void realCompute() {
 924                 AsyncFib f = new AsyncFib(8);
 925                 FailingAsyncFib g = new FailingAsyncFib(9);
 926                 ForkJoinTask[] tasks = { f, g };
 927                 shuffle(tasks);
 928                 try {
 929                     invokeAll(tasks);
 930                     shouldThrow();
 931                 } catch (FJException success) {
 932                     checkCompletedAbnormally(g, success);
 933                 }
 934             }};
 935         testInvokeOnPool(mainPool(), a);
 936     }
 937 
 938     /**
 939      * invokeAll(tasks) with 1 argument throws exception if task does
 940      */
 941     public void testAbnormalInvokeAll1() {
 942         RecursiveAction a = new CheckedRecursiveAction() {
 943             protected void realCompute() {
 944                 FailingAsyncFib g = new FailingAsyncFib(9);
 945                 try {
 946                     invokeAll(g);
 947                     shouldThrow();
 948                 } catch (FJException success) {
 949                     checkCompletedAbnormally(g, success);
 950                 }
 951             }};
 952         testInvokeOnPool(mainPool(), a);
 953     }
 954 
 955     /**
 956      * invokeAll(tasks) with > 2 argument throws exception if any task does
 957      */
 958     public void testAbnormalInvokeAll3() {
 959         RecursiveAction a = new CheckedRecursiveAction() {
 960             protected void realCompute() {
 961                 AsyncFib f = new AsyncFib(8);
 962                 FailingAsyncFib g = new FailingAsyncFib(9);
 963                 AsyncFib h = new AsyncFib(7);
 964                 ForkJoinTask[] tasks = { f, g, h };
 965                 shuffle(tasks);
 966                 try {
 967                     invokeAll(tasks);
 968                     shouldThrow();
 969                 } catch (FJException success) {
 970                     checkCompletedAbnormally(g, success);
 971                 }
 972             }};
 973         testInvokeOnPool(mainPool(), a);
 974     }
 975 
 976     /**
 977      * invokeAll(collection) throws exception if any task does
 978      */
 979     public void testAbnormalInvokeAllCollection() {
 980         RecursiveAction a = new CheckedRecursiveAction() {
 981             protected void realCompute() {
 982                 FailingAsyncFib f = new FailingAsyncFib(8);
 983                 AsyncFib g = new AsyncFib(9);
 984                 AsyncFib h = new AsyncFib(7);
 985                 ForkJoinTask[] tasks = { f, g, h };
 986                 shuffle(tasks);
 987                 try {
 988                     invokeAll(Arrays.asList(tasks));
 989                     shouldThrow();
 990                 } catch (FJException success) {
 991                     checkCompletedAbnormally(f, success);
 992                 }
 993             }};
 994         testInvokeOnPool(mainPool(), a);
 995     }
 996 
 997     /**
 998      * tryUnfork returns true for most recent unexecuted task,
 999      * and suppresses execution
1000      */
1001     public void testTryUnfork() {
1002         RecursiveAction a = new CheckedRecursiveAction() {
1003             protected void realCompute() {
1004                 AsyncFib g = new AsyncFib(9);
1005                 assertSame(g, g.fork());
1006                 AsyncFib f = new AsyncFib(8);
1007                 assertSame(f, f.fork());
1008                 assertTrue(f.tryUnfork());
1009                 helpQuiesce();
1010                 checkNotDone(f);
1011                 checkCompletedNormally(g);
1012             }};
1013         testInvokeOnPool(singletonPool(), a);
1014     }
1015 
1016     /**
1017      * getSurplusQueuedTaskCount returns > 0 when
1018      * there are more tasks than threads
1019      */
1020     public void testGetSurplusQueuedTaskCount() {
1021         RecursiveAction a = new CheckedRecursiveAction() {
1022             protected void realCompute() {
1023                 AsyncFib h = new AsyncFib(7);
1024                 assertSame(h, h.fork());
1025                 AsyncFib g = new AsyncFib(9);
1026                 assertSame(g, g.fork());
1027                 AsyncFib f = new AsyncFib(8);
1028                 assertSame(f, f.fork());
1029                 assertTrue(getSurplusQueuedTaskCount() > 0);
1030                 helpQuiesce();
1031                 assertEquals(0, getSurplusQueuedTaskCount());
1032                 checkCompletedNormally(f);
1033                 checkCompletedNormally(g);
1034                 checkCompletedNormally(h);
1035             }};
1036         testInvokeOnPool(singletonPool(), a);
1037     }
1038 
1039     /**
1040      * peekNextLocalTask returns most recent unexecuted task.
1041      */
1042     public void testPeekNextLocalTask() {
1043         RecursiveAction a = new CheckedRecursiveAction() {
1044             protected void realCompute() {
1045                 AsyncFib g = new AsyncFib(9);
1046                 assertSame(g, g.fork());
1047                 AsyncFib f = new AsyncFib(8);
1048                 assertSame(f, f.fork());
1049                 assertSame(f, peekNextLocalTask());
1050                 assertNull(f.join());
1051                 checkCompletedNormally(f);
1052                 helpQuiesce();
1053                 checkCompletedNormally(g);
1054             }};
1055         testInvokeOnPool(singletonPool(), a);
1056     }
1057 
1058     /**
1059      * pollNextLocalTask returns most recent unexecuted task without
1060      * executing it
1061      */
1062     public void testPollNextLocalTask() {
1063         RecursiveAction a = new CheckedRecursiveAction() {
1064             protected void realCompute() {
1065                 AsyncFib g = new AsyncFib(9);
1066                 assertSame(g, g.fork());
1067                 AsyncFib f = new AsyncFib(8);
1068                 assertSame(f, f.fork());
1069                 assertSame(f, pollNextLocalTask());
1070                 helpQuiesce();
1071                 checkNotDone(f);
1072                 assertEquals(34, g.number);
1073                 checkCompletedNormally(g);
1074             }};
1075         testInvokeOnPool(singletonPool(), a);
1076     }
1077 
1078     /**
1079      * pollTask returns an unexecuted task without executing it
1080      */
1081     public void testPollTask() {
1082         RecursiveAction a = new CheckedRecursiveAction() {
1083             protected void realCompute() {
1084                 AsyncFib g = new AsyncFib(9);
1085                 assertSame(g, g.fork());
1086                 AsyncFib f = new AsyncFib(8);
1087                 assertSame(f, f.fork());
1088                 assertSame(f, pollTask());
1089                 helpQuiesce();
1090                 checkNotDone(f);
1091                 checkCompletedNormally(g);
1092             }};
1093         testInvokeOnPool(singletonPool(), a);
1094     }
1095 
1096     /**
1097      * peekNextLocalTask returns least recent unexecuted task in async mode
1098      */
1099     public void testPeekNextLocalTaskAsync() {
1100         RecursiveAction a = new CheckedRecursiveAction() {
1101             protected void realCompute() {
1102                 AsyncFib g = new AsyncFib(9);
1103                 assertSame(g, g.fork());
1104                 AsyncFib f = new AsyncFib(8);
1105                 assertSame(f, f.fork());
1106                 assertSame(g, peekNextLocalTask());
1107                 assertNull(f.join());
1108                 helpQuiesce();
1109                 checkCompletedNormally(f);
1110                 assertEquals(34, g.number);
1111                 checkCompletedNormally(g);
1112             }};
1113         testInvokeOnPool(asyncSingletonPool(), a);
1114     }
1115 
1116     /**
1117      * pollNextLocalTask returns least recent unexecuted task without
1118      * executing it, in async mode
1119      */
1120     public void testPollNextLocalTaskAsync() {
1121         RecursiveAction a = new CheckedRecursiveAction() {
1122             protected void realCompute() {
1123                 AsyncFib g = new AsyncFib(9);
1124                 assertSame(g, g.fork());
1125                 AsyncFib f = new AsyncFib(8);
1126                 assertSame(f, f.fork());
1127                 assertSame(g, pollNextLocalTask());
1128                 helpQuiesce();
1129                 assertEquals(21, f.number);
1130                 checkCompletedNormally(f);
1131                 checkNotDone(g);
1132             }};
1133         testInvokeOnPool(asyncSingletonPool(), a);
1134     }
1135 
1136     /**
1137      * pollTask returns an unexecuted task without executing it, in
1138      * async mode
1139      */
1140     public void testPollTaskAsync() {
1141         RecursiveAction a = new CheckedRecursiveAction() {
1142             protected void realCompute() {
1143                 AsyncFib g = new AsyncFib(9);
1144                 assertSame(g, g.fork());
1145                 AsyncFib f = new AsyncFib(8);
1146                 assertSame(f, f.fork());
1147                 assertSame(g, pollTask());
1148                 helpQuiesce();
1149                 assertEquals(21, f.number);
1150                 checkCompletedNormally(f);
1151                 checkNotDone(g);
1152             }};
1153         testInvokeOnPool(asyncSingletonPool(), a);
1154     }
1155 
1156     // versions for singleton pools
1157 
1158     /**
1159      * invoke returns when task completes normally.
1160      * isCompletedAbnormally and isCancelled return false for normally
1161      * completed tasks; getRawResult returns null.
1162      */
1163     public void testInvokeSingleton() {
1164         RecursiveAction a = new CheckedRecursiveAction() {
1165             protected void realCompute() {
1166                 AsyncFib f = new AsyncFib(8);
1167                 assertNull(f.invoke());
1168                 assertEquals(21, f.number);
1169                 checkCompletedNormally(f);
1170             }};
1171         testInvokeOnPool(singletonPool(), a);
1172     }
1173 
1174     /**
1175      * quietlyInvoke task returns when task completes normally.
1176      * isCompletedAbnormally and isCancelled return false for normally
1177      * completed tasks
1178      */
1179     public void testQuietlyInvokeSingleton() {
1180         RecursiveAction a = new CheckedRecursiveAction() {
1181             protected void realCompute() {
1182                 AsyncFib f = new AsyncFib(8);
1183                 f.quietlyInvoke();
1184                 assertEquals(21, f.number);
1185                 checkCompletedNormally(f);
1186             }};
1187         testInvokeOnPool(singletonPool(), a);
1188     }
1189 
1190     /**
1191      * join of a forked task returns when task completes
1192      */
1193     public void testForkJoinSingleton() {
1194         RecursiveAction a = new CheckedRecursiveAction() {
1195             protected void realCompute() {
1196                 AsyncFib f = new AsyncFib(8);
1197                 assertSame(f, f.fork());
1198                 assertNull(f.join());
1199                 assertEquals(21, f.number);
1200                 checkCompletedNormally(f);
1201             }};
1202         testInvokeOnPool(singletonPool(), a);
1203     }
1204 
1205     /**
1206      * get of a forked task returns when task completes
1207      */
1208     public void testForkGetSingleton() {
1209         RecursiveAction a = new CheckedRecursiveAction() {
1210             protected void realCompute() throws Exception {
1211                 AsyncFib f = new AsyncFib(8);
1212                 assertSame(f, f.fork());
1213                 assertNull(f.get());
1214                 assertEquals(21, f.number);
1215                 checkCompletedNormally(f);
1216             }};
1217         testInvokeOnPool(singletonPool(), a);
1218     }
1219 
1220     /**
1221      * timed get of a forked task returns when task completes
1222      */
1223     public void testForkTimedGetSingleton() {
1224         RecursiveAction a = new CheckedRecursiveAction() {
1225             protected void realCompute() throws Exception {
1226                 AsyncFib f = new AsyncFib(8);
1227                 assertSame(f, f.fork());
1228                 assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
1229                 assertEquals(21, f.number);
1230                 checkCompletedNormally(f);
1231             }};
1232         testInvokeOnPool(singletonPool(), a);
1233     }
1234 
1235     /**
1236      * timed get with null time unit throws NPE
1237      */
1238     public void testForkTimedGetNPESingleton() {
1239         RecursiveAction a = new CheckedRecursiveAction() {
1240             protected void realCompute() throws Exception {
1241                 AsyncFib f = new AsyncFib(8);
1242                 assertSame(f, f.fork());
1243                 try {
1244                     f.get(randomTimeout(), null);
1245                     shouldThrow();
1246                 } catch (NullPointerException success) {}
1247             }};
1248         testInvokeOnPool(singletonPool(), a);
1249     }
1250 
1251     /**
1252      * quietlyJoin of a forked task returns when task completes
1253      */
1254     public void testForkQuietlyJoinSingleton() {
1255         RecursiveAction a = new CheckedRecursiveAction() {
1256             protected void realCompute() {
1257                 AsyncFib f = new AsyncFib(8);
1258                 assertSame(f, f.fork());
1259                 f.quietlyJoin();
1260                 assertEquals(21, f.number);
1261                 checkCompletedNormally(f);
1262             }};
1263         testInvokeOnPool(singletonPool(), a);
1264     }
1265 
1266     /**
1267      * helpQuiesce returns when tasks are complete.
1268      * getQueuedTaskCount returns 0 when quiescent
1269      */
1270     public void testForkHelpQuiesceSingleton() {
1271         RecursiveAction a = new CheckedRecursiveAction() {
1272             protected void realCompute() {
1273                 AsyncFib f = new AsyncFib(8);
1274                 assertSame(f, f.fork());
1275                 helpQuiesce();
1276                 assertEquals(0, getQueuedTaskCount());
1277                 assertEquals(21, f.number);
1278                 checkCompletedNormally(f);
1279             }};
1280         testInvokeOnPool(singletonPool(), a);
1281     }
1282 
1283     /**
1284      * invoke task throws exception when task completes abnormally
1285      */
1286     public void testAbnormalInvokeSingleton() {
1287         RecursiveAction a = new CheckedRecursiveAction() {
1288             protected void realCompute() {
1289                 FailingAsyncFib f = new FailingAsyncFib(8);
1290                 try {
1291                     f.invoke();
1292                     shouldThrow();
1293                 } catch (FJException success) {
1294                     checkCompletedAbnormally(f, success);
1295                 }
1296             }};
1297         testInvokeOnPool(singletonPool(), a);
1298     }
1299 
1300     /**
1301      * quietlyInvoke task returns when task completes abnormally
1302      */
1303     public void testAbnormalQuietlyInvokeSingleton() {
1304         RecursiveAction a = new CheckedRecursiveAction() {
1305             protected void realCompute() {
1306                 FailingAsyncFib f = new FailingAsyncFib(8);
1307                 f.quietlyInvoke();
1308                 assertTrue(f.getException() instanceof FJException);
1309                 checkCompletedAbnormally(f, f.getException());
1310             }};
1311         testInvokeOnPool(singletonPool(), a);
1312     }
1313 
1314     /**
1315      * join of a forked task throws exception when task completes abnormally
1316      */
1317     public void testAbnormalForkJoinSingleton() {
1318         RecursiveAction a = new CheckedRecursiveAction() {
1319             protected void realCompute() {
1320                 FailingAsyncFib f = new FailingAsyncFib(8);
1321                 assertSame(f, f.fork());
1322                 try {
1323                     f.join();
1324                     shouldThrow();
1325                 } catch (FJException success) {
1326                     checkCompletedAbnormally(f, success);
1327                 }
1328             }};
1329         testInvokeOnPool(singletonPool(), a);
1330     }
1331 
1332     /**
1333      * get of a forked task throws exception when task completes abnormally
1334      */
1335     public void testAbnormalForkGetSingleton() {
1336         RecursiveAction a = new CheckedRecursiveAction() {
1337             protected void realCompute() throws Exception {
1338                 FailingAsyncFib f = new FailingAsyncFib(8);
1339                 assertSame(f, f.fork());
1340                 try {
1341                     f.get();
1342                     shouldThrow();
1343                 } catch (ExecutionException success) {
1344                     Throwable cause = success.getCause();
1345                     assertTrue(cause instanceof FJException);
1346                     checkCompletedAbnormally(f, cause);
1347                 }
1348             }};
1349         testInvokeOnPool(singletonPool(), a);
1350     }
1351 
1352     /**
1353      * timed get of a forked task throws exception when task completes abnormally
1354      */
1355     public void testAbnormalForkTimedGetSingleton() {
1356         RecursiveAction a = new CheckedRecursiveAction() {
1357             protected void realCompute() throws Exception {
1358                 FailingAsyncFib f = new FailingAsyncFib(8);
1359                 assertSame(f, f.fork());
1360                 try {
1361                     f.get(LONG_DELAY_MS, MILLISECONDS);
1362                     shouldThrow();
1363                 } catch (ExecutionException success) {
1364                     Throwable cause = success.getCause();
1365                     assertTrue(cause instanceof FJException);
1366                     checkCompletedAbnormally(f, cause);
1367                 }
1368             }};
1369         testInvokeOnPool(singletonPool(), a);
1370     }
1371 
1372     /**
1373      * quietlyJoin of a forked task returns when task completes abnormally
1374      */
1375     public void testAbnormalForkQuietlyJoinSingleton() {
1376         RecursiveAction a = new CheckedRecursiveAction() {
1377             protected void realCompute() {
1378                 FailingAsyncFib f = new FailingAsyncFib(8);
1379                 assertSame(f, f.fork());
1380                 f.quietlyJoin();
1381                 assertTrue(f.getException() instanceof FJException);
1382                 checkCompletedAbnormally(f, f.getException());
1383             }};
1384         testInvokeOnPool(singletonPool(), a);
1385     }
1386 
1387     /**
1388      * invoke task throws exception when task cancelled
1389      */
1390     public void testCancelledInvokeSingleton() {
1391         RecursiveAction a = new CheckedRecursiveAction() {
1392             protected void realCompute() {
1393                 AsyncFib f = new AsyncFib(8);
1394                 assertTrue(f.cancel(true));
1395                 try {
1396                     f.invoke();
1397                     shouldThrow();
1398                 } catch (CancellationException success) {
1399                     checkCancelled(f);
1400                 }
1401             }};
1402         testInvokeOnPool(singletonPool(), a);
1403     }
1404 
1405     /**
1406      * join of a forked task throws exception when task cancelled
1407      */
1408     public void testCancelledForkJoinSingleton() {
1409         RecursiveAction a = new CheckedRecursiveAction() {
1410             protected void realCompute() {
1411                 AsyncFib f = new AsyncFib(8);
1412                 assertTrue(f.cancel(true));
1413                 assertSame(f, f.fork());
1414                 try {
1415                     f.join();
1416                     shouldThrow();
1417                 } catch (CancellationException success) {
1418                     checkCancelled(f);
1419                 }
1420             }};
1421         testInvokeOnPool(singletonPool(), a);
1422     }
1423 
1424     /**
1425      * get of a forked task throws exception when task cancelled
1426      */
1427     public void testCancelledForkGetSingleton() {
1428         RecursiveAction a = new CheckedRecursiveAction() {
1429             protected void realCompute() throws Exception {
1430                 AsyncFib f = new AsyncFib(8);
1431                 assertTrue(f.cancel(true));
1432                 assertSame(f, f.fork());
1433                 try {
1434                     f.get();
1435                     shouldThrow();
1436                 } catch (CancellationException success) {
1437                     checkCancelled(f);
1438                 }
1439             }};
1440         testInvokeOnPool(singletonPool(), a);
1441     }
1442 
1443     /**
1444      * timed get of a forked task throws exception when task cancelled
1445      */
1446     public void testCancelledForkTimedGetSingleton() throws Exception {
1447         RecursiveAction a = new CheckedRecursiveAction() {
1448             protected void realCompute() throws Exception {
1449                 AsyncFib f = new AsyncFib(8);
1450                 assertTrue(f.cancel(true));
1451                 assertSame(f, f.fork());
1452                 try {
1453                     f.get(LONG_DELAY_MS, MILLISECONDS);
1454                     shouldThrow();
1455                 } catch (CancellationException success) {
1456                     checkCancelled(f);
1457                 }
1458             }};
1459         testInvokeOnPool(singletonPool(), a);
1460     }
1461 
1462     /**
1463      * quietlyJoin of a forked task returns when task cancelled
1464      */
1465     public void testCancelledForkQuietlyJoinSingleton() {
1466         RecursiveAction a = new CheckedRecursiveAction() {
1467             protected void realCompute() {
1468                 AsyncFib f = new AsyncFib(8);
1469                 assertTrue(f.cancel(true));
1470                 assertSame(f, f.fork());
1471                 f.quietlyJoin();
1472                 checkCancelled(f);
1473             }};
1474         testInvokeOnPool(singletonPool(), a);
1475     }
1476 
1477     /**
1478      * invoke task throws exception after invoking completeExceptionally
1479      */
1480     public void testCompleteExceptionallySingleton() {
1481         RecursiveAction a = new CheckedRecursiveAction() {
1482             protected void realCompute() {
1483                 AsyncFib f = new AsyncFib(8);
1484                 f.completeExceptionally(new FJException());
1485                 try {
1486                     f.invoke();
1487                     shouldThrow();
1488                 } catch (FJException success) {
1489                     checkCompletedAbnormally(f, success);
1490                 }
1491             }};
1492         testInvokeOnPool(singletonPool(), a);
1493     }
1494 
1495     /**
1496      * invokeAll(t1, t2) invokes all task arguments
1497      */
1498     public void testInvokeAll2Singleton() {
1499         RecursiveAction a = new CheckedRecursiveAction() {
1500             protected void realCompute() {
1501                 AsyncFib f = new AsyncFib(8);
1502                 AsyncFib g = new AsyncFib(9);
1503                 invokeAll(f, g);
1504                 assertEquals(21, f.number);
1505                 assertEquals(34, g.number);
1506                 checkCompletedNormally(f);
1507                 checkCompletedNormally(g);
1508             }};
1509         testInvokeOnPool(singletonPool(), a);
1510     }
1511 
1512     /**
1513      * invokeAll(tasks) with 1 argument invokes task
1514      */
1515     public void testInvokeAll1Singleton() {
1516         RecursiveAction a = new CheckedRecursiveAction() {
1517             protected void realCompute() {
1518                 AsyncFib f = new AsyncFib(8);
1519                 invokeAll(f);
1520                 checkCompletedNormally(f);
1521                 assertEquals(21, f.number);
1522             }};
1523         testInvokeOnPool(singletonPool(), a);
1524     }
1525 
1526     /**
1527      * invokeAll(tasks) with > 2 argument invokes tasks
1528      */
1529     public void testInvokeAll3Singleton() {
1530         RecursiveAction a = new CheckedRecursiveAction() {
1531             protected void realCompute() {
1532                 AsyncFib f = new AsyncFib(8);
1533                 AsyncFib g = new AsyncFib(9);
1534                 AsyncFib h = new AsyncFib(7);
1535                 invokeAll(f, g, h);
1536                 assertEquals(21, f.number);
1537                 assertEquals(34, g.number);
1538                 assertEquals(13, h.number);
1539                 checkCompletedNormally(f);
1540                 checkCompletedNormally(g);
1541                 checkCompletedNormally(h);
1542             }};
1543         testInvokeOnPool(singletonPool(), a);
1544     }
1545 
1546     /**
1547      * invokeAll(collection) invokes all tasks in the collection
1548      */
1549     public void testInvokeAllCollectionSingleton() {
1550         RecursiveAction a = new CheckedRecursiveAction() {
1551             protected void realCompute() {
1552                 AsyncFib f = new AsyncFib(8);
1553                 AsyncFib g = new AsyncFib(9);
1554                 AsyncFib h = new AsyncFib(7);
1555                 HashSet set = new HashSet();
1556                 set.add(f);
1557                 set.add(g);
1558                 set.add(h);
1559                 invokeAll(set);
1560                 assertEquals(21, f.number);
1561                 assertEquals(34, g.number);
1562                 assertEquals(13, h.number);
1563                 checkCompletedNormally(f);
1564                 checkCompletedNormally(g);
1565                 checkCompletedNormally(h);
1566             }};
1567         testInvokeOnPool(singletonPool(), a);
1568     }
1569 
1570     /**
1571      * invokeAll(tasks) with any null task throws NPE
1572      */
1573     public void testInvokeAllNPESingleton() {
1574         RecursiveAction a = new CheckedRecursiveAction() {
1575             protected void realCompute() {
1576                 AsyncFib f = new AsyncFib(8);
1577                 AsyncFib g = new AsyncFib(9);
1578                 AsyncFib h = null;
1579                 try {
1580                     invokeAll(f, g, h);
1581                     shouldThrow();
1582                 } catch (NullPointerException success) {}
1583             }};
1584         testInvokeOnPool(singletonPool(), a);
1585     }
1586 
1587     /**
1588      * invokeAll(t1, t2) throw exception if any task does
1589      */
1590     public void testAbnormalInvokeAll2Singleton() {
1591         RecursiveAction a = new CheckedRecursiveAction() {
1592             protected void realCompute() {
1593                 AsyncFib f = new AsyncFib(8);
1594                 FailingAsyncFib g = new FailingAsyncFib(9);
1595                 ForkJoinTask[] tasks = { f, g };
1596                 shuffle(tasks);
1597                 try {
1598                     invokeAll(tasks);
1599                     shouldThrow();
1600                 } catch (FJException success) {
1601                     checkCompletedAbnormally(g, success);
1602                 }
1603             }};
1604         testInvokeOnPool(singletonPool(), a);
1605     }
1606 
1607     /**
1608      * invokeAll(tasks) with 1 argument throws exception if task does
1609      */
1610     public void testAbnormalInvokeAll1Singleton() {
1611         RecursiveAction a = new CheckedRecursiveAction() {
1612             protected void realCompute() {
1613                 FailingAsyncFib g = new FailingAsyncFib(9);
1614                 try {
1615                     invokeAll(g);
1616                     shouldThrow();
1617                 } catch (FJException success) {
1618                     checkCompletedAbnormally(g, success);
1619                 }
1620             }};
1621         testInvokeOnPool(singletonPool(), a);
1622     }
1623 
1624     /**
1625      * invokeAll(tasks) with > 2 argument throws exception if any task does
1626      */
1627     public void testAbnormalInvokeAll3Singleton() {
1628         RecursiveAction a = new CheckedRecursiveAction() {
1629             protected void realCompute() {
1630                 AsyncFib f = new AsyncFib(8);
1631                 FailingAsyncFib g = new FailingAsyncFib(9);
1632                 AsyncFib h = new AsyncFib(7);
1633                 ForkJoinTask[] tasks = { f, g, h };
1634                 shuffle(tasks);
1635                 try {
1636                     invokeAll(tasks);
1637                     shouldThrow();
1638                 } catch (FJException success) {
1639                     checkCompletedAbnormally(g, success);
1640                 }
1641             }};
1642         testInvokeOnPool(singletonPool(), a);
1643     }
1644 
1645     /**
1646      * invokeAll(collection) throws exception if any task does
1647      */
1648     public void testAbnormalInvokeAllCollectionSingleton() {
1649         RecursiveAction a = new CheckedRecursiveAction() {
1650             protected void realCompute() {
1651                 FailingAsyncFib f = new FailingAsyncFib(8);
1652                 AsyncFib g = new AsyncFib(9);
1653                 AsyncFib h = new AsyncFib(7);
1654                 ForkJoinTask[] tasks = { f, g, h };
1655                 shuffle(tasks);
1656                 try {
1657                     invokeAll(Arrays.asList(tasks));
1658                     shouldThrow();
1659                 } catch (FJException success) {
1660                     checkCompletedAbnormally(f, success);
1661                 }
1662             }};
1663         testInvokeOnPool(singletonPool(), a);
1664     }
1665 
1666     /**
1667      * ForkJoinTask.quietlyComplete returns when task completes
1668      * normally without setting a value. The most recent value
1669      * established by setRawResult(V) (or null by default) is returned
1670      * from invoke.
1671      */
1672     public void testQuietlyComplete() {
1673         RecursiveAction a = new CheckedRecursiveAction() {
1674                 protected void realCompute() {
1675                     AsyncFib f = new AsyncFib(8);
1676                     f.quietlyComplete();
1677                     assertEquals(8, f.number);
1678                     checkCompletedNormally(f);
1679                 }};
1680         testInvokeOnPool(mainPool(), a);
1681     }
1682 
1683     /**
1684      * adapt(runnable).toString() contains toString of wrapped task
1685      */
1686     public void testAdapt_Runnable_toString() {
1687         if (testImplementationDetails) {
1688             Runnable r = () -> {};
1689             ForkJoinTask<?> task = ForkJoinTask.adapt(r);
1690             assertEquals(
1691                 identityString(task) + "[Wrapped task = " + r.toString() + "]",
1692                 task.toString());
1693         }
1694     }
1695 
1696     /**
1697      * adapt(runnable, x).toString() contains toString of wrapped task
1698      */
1699     public void testAdapt_Runnable_withResult_toString() {
1700         if (testImplementationDetails) {
1701             Runnable r = () -> {};
1702             ForkJoinTask<String> task = ForkJoinTask.adapt(r, "");
1703             assertEquals(
1704                 identityString(task) + "[Wrapped task = " + r.toString() + "]",
1705                 task.toString());
1706         }
1707     }
1708 
1709     /**
1710      * adapt(callable).toString() contains toString of wrapped task
1711      */
1712     public void testAdapt_Callable_toString() {
1713         if (testImplementationDetails) {
1714             Callable<String> c = () -> "";
1715             ForkJoinTask<String> task = ForkJoinTask.adapt(c);
1716             assertEquals(
1717                 identityString(task) + "[Wrapped task = " + c.toString() + "]",
1718                 task.toString());
1719         }
1720     }
1721 }