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.concurrent.CountDownLatch;
  38 import java.util.concurrent.ExecutionException;
  39 import java.util.concurrent.ForkJoinPool;
  40 import java.util.concurrent.ForkJoinTask;
  41 import java.util.concurrent.ForkJoinWorkerThread;
  42 import java.util.concurrent.RecursiveAction;
  43 import java.util.concurrent.TimeoutException;
  44 
  45 import junit.framework.Test;
  46 import junit.framework.TestSuite;
  47 
  48 public class ForkJoinTask8Test extends JSR166TestCase {
  49 
  50     /*
  51      * Testing notes: This differs from ForkJoinTaskTest mainly by
  52      * defining a version of BinaryAsyncAction that uses JDK8 task
  53      * tags for control state, thereby testing getForkJoinTaskTag,
  54      * setForkJoinTaskTag, and compareAndSetForkJoinTaskTag across
  55      * various contexts. Most of the test methods using it are
  56      * otherwise identical, but omitting retest of those dealing with
  57      * cancellation, which is not represented in this tag scheme.
  58      */
  59 
  60     static final short INITIAL_STATE = -1;
  61     static final short COMPLETE_STATE = 0;
  62     static final short EXCEPTION_STATE = 1;
  63 
  64     public static void main(String[] args) {
  65         main(suite(), args);
  66     }
  67 
  68     public static Test suite() {
  69         return new TestSuite(ForkJoinTask8Test.class);
  70     }
  71 
  72     // Runs with "mainPool" use > 1 thread. singletonPool tests use 1
  73     static final int mainPoolSize =
  74         Math.max(2, Runtime.getRuntime().availableProcessors());
  75 
  76     private static ForkJoinPool mainPool() {
  77         return new ForkJoinPool(mainPoolSize);
  78     }
  79 
  80     private static ForkJoinPool singletonPool() {
  81         return new ForkJoinPool(1);
  82     }
  83 
  84     private static ForkJoinPool asyncSingletonPool() {
  85         return new ForkJoinPool(1,
  86                                 ForkJoinPool.defaultForkJoinWorkerThreadFactory,
  87                                 null, true);
  88     }
  89 
  90     // Compute fib naively and efficiently
  91     final int[] fib;
  92     {
  93         int[] fib = new int[10];
  94         fib[0] = 0;
  95         fib[1] = 1;
  96         for (int i = 2; i < fib.length; i++)
  97             fib[i] = fib[i - 1] + fib[i - 2];
  98         this.fib = fib;
  99     }
 100 
 101     private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) {
 102         try (PoolCleaner cleaner = cleaner(pool)) {
 103             assertFalse(a.isDone());
 104             assertFalse(a.isCompletedNormally());
 105             assertFalse(a.isCompletedAbnormally());
 106             assertFalse(a.isCancelled());
 107             assertNull(a.getException());
 108             assertNull(a.getRawResult());
 109 
 110             assertNull(pool.invoke(a));
 111 
 112             assertTrue(a.isDone());
 113             assertTrue(a.isCompletedNormally());
 114             assertFalse(a.isCompletedAbnormally());
 115             assertFalse(a.isCancelled());
 116             assertNull(a.getException());
 117             assertNull(a.getRawResult());
 118         }
 119     }
 120 
 121     void checkNotDone(ForkJoinTask a) {
 122         assertFalse(a.isDone());
 123         assertFalse(a.isCompletedNormally());
 124         assertFalse(a.isCompletedAbnormally());
 125         assertFalse(a.isCancelled());
 126         assertNull(a.getException());
 127         assertNull(a.getRawResult());
 128         if (a instanceof BinaryAsyncAction)
 129             assertEquals(INITIAL_STATE,
 130                          ((BinaryAsyncAction)a).getForkJoinTaskTag());
 131 
 132         try {
 133             a.get(randomExpiredTimeout(), randomTimeUnit());
 134             shouldThrow();
 135         } catch (TimeoutException success) {
 136         } catch (Throwable fail) { threadUnexpectedException(fail); }
 137     }
 138 
 139     <T> void checkCompletedNormally(ForkJoinTask<T> a) {
 140         checkCompletedNormally(a, null);
 141     }
 142 
 143     <T> void checkCompletedNormally(ForkJoinTask<T> a, T expectedValue) {
 144         assertTrue(a.isDone());
 145         assertFalse(a.isCancelled());
 146         assertTrue(a.isCompletedNormally());
 147         assertFalse(a.isCompletedAbnormally());
 148         assertNull(a.getException());
 149         assertSame(expectedValue, a.getRawResult());
 150         if (a instanceof BinaryAsyncAction)
 151             assertEquals(COMPLETE_STATE,
 152                          ((BinaryAsyncAction)a).getForkJoinTaskTag());
 153 
 154         {
 155             Thread.currentThread().interrupt();
 156             long startTime = System.nanoTime();
 157             assertSame(expectedValue, a.join());
 158             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 159             Thread.interrupted();
 160         }
 161 
 162         {
 163             Thread.currentThread().interrupt();
 164             long startTime = System.nanoTime();
 165             a.quietlyJoin();        // should be no-op
 166             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 167             Thread.interrupted();
 168         }
 169 
 170         assertFalse(a.cancel(false));
 171         assertFalse(a.cancel(true));
 172 
 173         T v1 = null, v2 = null;
 174         try {
 175             v1 = a.get();
 176             v2 = a.get(randomTimeout(), randomTimeUnit());
 177         } catch (Throwable fail) { threadUnexpectedException(fail); }
 178         assertSame(expectedValue, v1);
 179         assertSame(expectedValue, v2);
 180     }
 181 
 182     void checkCompletedAbnormally(ForkJoinTask a, Throwable t) {
 183         assertTrue(a.isDone());
 184         assertFalse(a.isCancelled());
 185         assertFalse(a.isCompletedNormally());
 186         assertTrue(a.isCompletedAbnormally());
 187         assertSame(t.getClass(), a.getException().getClass());
 188         assertNull(a.getRawResult());
 189         assertFalse(a.cancel(false));
 190         assertFalse(a.cancel(true));
 191         if (a instanceof BinaryAsyncAction)
 192             assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() != INITIAL_STATE);
 193 
 194         try {
 195             Thread.currentThread().interrupt();
 196             a.join();
 197             shouldThrow();
 198         } catch (Throwable expected) {
 199             assertSame(t.getClass(), expected.getClass());
 200         }
 201         Thread.interrupted();
 202 
 203         {
 204             long startTime = System.nanoTime();
 205             a.quietlyJoin();        // should be no-op
 206             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 207         }
 208 
 209         try {
 210             a.get();
 211             shouldThrow();
 212         } catch (ExecutionException success) {
 213             assertSame(t.getClass(), success.getCause().getClass());
 214         } catch (Throwable fail) { threadUnexpectedException(fail); }
 215 
 216         try {
 217             a.get(randomTimeout(), randomTimeUnit());
 218             shouldThrow();
 219         } catch (ExecutionException success) {
 220             assertSame(t.getClass(), success.getCause().getClass());
 221         } catch (Throwable fail) { threadUnexpectedException(fail); }
 222     }
 223 
 224     public static final class FJException extends RuntimeException {
 225         FJException() { super(); }
 226     }
 227 
 228     abstract static class BinaryAsyncAction extends ForkJoinTask<Void> {
 229 
 230         private volatile BinaryAsyncAction parent;
 231 
 232         private volatile BinaryAsyncAction sibling;
 233 
 234         protected BinaryAsyncAction() {
 235             setForkJoinTaskTag(INITIAL_STATE);
 236         }
 237 
 238         public final Void getRawResult() { return null; }
 239         protected final void setRawResult(Void mustBeNull) { }
 240 
 241         public final void linkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
 242             x.parent = y.parent = this;
 243             x.sibling = y;
 244             y.sibling = x;
 245         }
 246 
 247         protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
 248             if (this.getForkJoinTaskTag() != COMPLETE_STATE ||
 249                 x.getForkJoinTaskTag() != COMPLETE_STATE ||
 250                 y.getForkJoinTaskTag() != COMPLETE_STATE) {
 251                 completeThisExceptionally(new FJException());
 252             }
 253         }
 254 
 255         protected boolean onException() {
 256             return true;
 257         }
 258 
 259         public void linkAndForkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
 260             linkSubtasks(x, y);
 261             y.fork();
 262             x.fork();
 263         }
 264 
 265         private void completeThis() {
 266             setForkJoinTaskTag(COMPLETE_STATE);
 267             super.complete(null);
 268         }
 269 
 270         private void completeThisExceptionally(Throwable ex) {
 271             setForkJoinTaskTag(EXCEPTION_STATE);
 272             super.completeExceptionally(ex);
 273         }
 274 
 275         public boolean cancel(boolean mayInterruptIfRunning) {
 276             if (super.cancel(mayInterruptIfRunning)) {
 277                 completeExceptionally(new FJException());
 278                 return true;
 279             }
 280             return false;
 281         }
 282 
 283         public final void complete() {
 284             BinaryAsyncAction a = this;
 285             for (;;) {
 286                 BinaryAsyncAction s = a.sibling;
 287                 BinaryAsyncAction p = a.parent;
 288                 a.sibling = null;
 289                 a.parent = null;
 290                 a.completeThis();
 291                 if (p == null ||
 292                     p.compareAndSetForkJoinTaskTag(INITIAL_STATE, COMPLETE_STATE))
 293                     break;
 294                 try {
 295                     p.onComplete(a, s);
 296                 } catch (Throwable rex) {
 297                     p.completeExceptionally(rex);
 298                     return;
 299                 }
 300                 a = p;
 301             }
 302         }
 303 
 304         public final void completeExceptionally(Throwable ex) {
 305             for (BinaryAsyncAction a = this;;) {
 306                 a.completeThisExceptionally(ex);
 307                 BinaryAsyncAction s = a.sibling;
 308                 if (s != null && !s.isDone())
 309                     s.completeExceptionally(ex);
 310                 if ((a = a.parent) == null)
 311                     break;
 312             }
 313         }
 314 
 315         public final BinaryAsyncAction getParent() {
 316             return parent;
 317         }
 318 
 319         public BinaryAsyncAction getSibling() {
 320             return sibling;
 321         }
 322 
 323         public void reinitialize() {
 324             parent = sibling = null;
 325             super.reinitialize();
 326         }
 327 
 328     }
 329 
 330     final class AsyncFib extends BinaryAsyncAction {
 331         int number;
 332         int expectedResult;
 333         public AsyncFib(int number) {
 334             this.number = number;
 335             this.expectedResult = fib[number];
 336         }
 337 
 338         public final boolean exec() {
 339             try {
 340                 AsyncFib f = this;
 341                 int n = f.number;
 342                 while (n > 1) {
 343                     AsyncFib p = f;
 344                     AsyncFib r = new AsyncFib(n - 2);
 345                     f = new AsyncFib(--n);
 346                     p.linkSubtasks(r, f);
 347                     r.fork();
 348                 }
 349                 f.complete();
 350             }
 351             catch (Throwable ex) {
 352                 compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE);
 353             }
 354             if (getForkJoinTaskTag() == EXCEPTION_STATE)
 355                 throw new FJException();
 356             return false;
 357         }
 358 
 359         protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
 360             number = ((AsyncFib)x).number + ((AsyncFib)y).number;
 361             super.onComplete(x, y);
 362         }
 363 
 364         public void checkCompletedNormally() {
 365             assertEquals(expectedResult, number);
 366             ForkJoinTask8Test.this.checkCompletedNormally(this);
 367         }
 368     }
 369 
 370     static final class FailingAsyncFib extends BinaryAsyncAction {
 371         int number;
 372         public FailingAsyncFib(int n) {
 373             this.number = n;
 374         }
 375 
 376         public final boolean exec() {
 377             try {
 378                 FailingAsyncFib f = this;
 379                 int n = f.number;
 380                 while (n > 1) {
 381                     FailingAsyncFib p = f;
 382                     FailingAsyncFib r = new FailingAsyncFib(n - 2);
 383                     f = new FailingAsyncFib(--n);
 384                     p.linkSubtasks(r, f);
 385                     r.fork();
 386                 }
 387                 f.complete();
 388             }
 389             catch (Throwable ex) {
 390                 compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE);
 391             }
 392             if (getForkJoinTaskTag() == EXCEPTION_STATE)
 393                 throw new FJException();
 394             return false;
 395         }
 396 
 397         protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
 398             completeExceptionally(new FJException());
 399         }
 400     }
 401 
 402     /**
 403      * invoke returns when task completes normally.
 404      * isCompletedAbnormally and isCancelled return false for normally
 405      * completed tasks; getRawResult returns null.
 406      */
 407     public void testInvoke() {
 408         testInvoke(mainPool());
 409     }
 410     public void testInvoke_Singleton() {
 411         testInvoke(singletonPool());
 412     }
 413     public void testInvoke(ForkJoinPool pool) {
 414         RecursiveAction a = new CheckedRecursiveAction() {
 415             protected void realCompute() {
 416                 AsyncFib f = new AsyncFib(8);
 417                 assertNull(f.invoke());
 418                 f.checkCompletedNormally();
 419             }};
 420         testInvokeOnPool(pool, a);
 421     }
 422 
 423     /**
 424      * quietlyInvoke task returns when task completes normally.
 425      * isCompletedAbnormally and isCancelled return false for normally
 426      * completed tasks
 427      */
 428     public void testQuietlyInvoke() {
 429         testQuietlyInvoke(mainPool());
 430     }
 431     public void testQuietlyInvoke_Singleton() {
 432         testQuietlyInvoke(singletonPool());
 433     }
 434     public void testQuietlyInvoke(ForkJoinPool pool) {
 435         RecursiveAction a = new CheckedRecursiveAction() {
 436             protected void realCompute() {
 437                 AsyncFib f = new AsyncFib(8);
 438                 f.quietlyInvoke();
 439                 f.checkCompletedNormally();
 440             }};
 441         testInvokeOnPool(pool, a);
 442     }
 443 
 444     /**
 445      * join of a forked task returns when task completes
 446      */
 447     public void testForkJoin() {
 448         testForkJoin(mainPool());
 449     }
 450     public void testForkJoin_Singleton() {
 451         testForkJoin(singletonPool());
 452     }
 453     public void testForkJoin(ForkJoinPool pool) {
 454         RecursiveAction a = new CheckedRecursiveAction() {
 455             protected void realCompute() {
 456                 AsyncFib f = new AsyncFib(8);
 457                 assertSame(f, f.fork());
 458                 assertNull(f.join());
 459                 f.checkCompletedNormally();
 460             }};
 461         testInvokeOnPool(pool, a);
 462     }
 463 
 464     /**
 465      * get of a forked task returns when task completes
 466      */
 467     public void testForkGet() {
 468         testForkGet(mainPool());
 469     }
 470     public void testForkGet_Singleton() {
 471         testForkGet(singletonPool());
 472     }
 473     public void testForkGet(ForkJoinPool pool) {
 474         RecursiveAction a = new CheckedRecursiveAction() {
 475             protected void realCompute() throws Exception {
 476                 AsyncFib f = new AsyncFib(8);
 477                 assertSame(f, f.fork());
 478                 assertNull(f.get());
 479                 f.checkCompletedNormally();
 480             }};
 481         testInvokeOnPool(pool, a);
 482     }
 483 
 484     /**
 485      * timed get of a forked task returns when task completes
 486      */
 487     public void testForkTimedGet() {
 488         testForkTimedGet(mainPool());
 489     }
 490     public void testForkTimedGet_Singleton() {
 491         testForkTimedGet(singletonPool());
 492     }
 493     public void testForkTimedGet(ForkJoinPool pool) {
 494         RecursiveAction a = new CheckedRecursiveAction() {
 495             protected void realCompute() throws Exception {
 496                 AsyncFib f = new AsyncFib(8);
 497                 assertSame(f, f.fork());
 498                 assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
 499                 f.checkCompletedNormally();
 500             }};
 501         testInvokeOnPool(pool, a);
 502     }
 503 
 504     /**
 505      * timed get with null time unit throws NullPointerException
 506      */
 507     public void testForkTimedGetNullTimeUnit() {
 508         testForkTimedGetNullTimeUnit(mainPool());
 509     }
 510     public void testForkTimedGetNullTimeUnit_Singleton() {
 511         testForkTimedGet(singletonPool());
 512     }
 513     public void testForkTimedGetNullTimeUnit(ForkJoinPool pool) {
 514         RecursiveAction a = new CheckedRecursiveAction() {
 515             protected void realCompute() throws Exception {
 516                 AsyncFib f = new AsyncFib(8);
 517                 assertSame(f, f.fork());
 518                 try {
 519                     f.get(randomTimeout(), null);
 520                     shouldThrow();
 521                 } catch (NullPointerException success) {}
 522             }};
 523         testInvokeOnPool(pool, a);
 524     }
 525 
 526     /**
 527      * quietlyJoin of a forked task returns when task completes
 528      */
 529     public void testForkQuietlyJoin() {
 530         testForkQuietlyJoin(mainPool());
 531     }
 532     public void testForkQuietlyJoin_Singleton() {
 533         testForkQuietlyJoin(singletonPool());
 534     }
 535     public void testForkQuietlyJoin(ForkJoinPool pool) {
 536         RecursiveAction a = new CheckedRecursiveAction() {
 537             protected void realCompute() {
 538                 AsyncFib f = new AsyncFib(8);
 539                 assertSame(f, f.fork());
 540                 f.quietlyJoin();
 541                 f.checkCompletedNormally();
 542             }};
 543         testInvokeOnPool(pool, a);
 544     }
 545 
 546     /**
 547      * helpQuiesce returns when tasks are complete.
 548      * getQueuedTaskCount returns 0 when quiescent
 549      */
 550     public void testForkHelpQuiesce() {
 551         testForkHelpQuiesce(mainPool());
 552     }
 553     public void testForkHelpQuiesce_Singleton() {
 554         testForkHelpQuiesce(singletonPool());
 555     }
 556     public void testForkHelpQuiesce(ForkJoinPool pool) {
 557         RecursiveAction a = new CheckedRecursiveAction() {
 558             protected void realCompute() {
 559                 AsyncFib f = new AsyncFib(8);
 560                 assertSame(f, f.fork());
 561                 helpQuiesce();
 562                 while (!f.isDone()) // wait out race
 563                     ;
 564                 assertEquals(0, getQueuedTaskCount());
 565                 f.checkCompletedNormally();
 566             }};
 567         testInvokeOnPool(pool, a);
 568     }
 569 
 570     /**
 571      * invoke task throws exception when task completes abnormally
 572      */
 573     public void testAbnormalInvoke() {
 574         testAbnormalInvoke(mainPool());
 575     }
 576     public void testAbnormalInvoke_Singleton() {
 577         testAbnormalInvoke(singletonPool());
 578     }
 579     public void testAbnormalInvoke(ForkJoinPool pool) {
 580         RecursiveAction a = new CheckedRecursiveAction() {
 581             protected void realCompute() {
 582                 FailingAsyncFib f = new FailingAsyncFib(8);
 583                 try {
 584                     f.invoke();
 585                     shouldThrow();
 586                 } catch (FJException success) {
 587                     checkCompletedAbnormally(f, success);
 588                 }
 589             }};
 590         testInvokeOnPool(pool, a);
 591     }
 592 
 593     /**
 594      * quietlyInvoke task returns when task completes abnormally
 595      */
 596     public void testAbnormalQuietlyInvoke() {
 597         testAbnormalQuietlyInvoke(mainPool());
 598     }
 599     public void testAbnormalQuietlyInvoke_Singleton() {
 600         testAbnormalQuietlyInvoke(singletonPool());
 601     }
 602     public void testAbnormalQuietlyInvoke(ForkJoinPool pool) {
 603         RecursiveAction a = new CheckedRecursiveAction() {
 604             protected void realCompute() {
 605                 FailingAsyncFib f = new FailingAsyncFib(8);
 606                 f.quietlyInvoke();
 607                 assertTrue(f.getException() instanceof FJException);
 608                 checkCompletedAbnormally(f, f.getException());
 609             }};
 610         testInvokeOnPool(pool, a);
 611     }
 612 
 613     /**
 614      * join of a forked task throws exception when task completes abnormally
 615      */
 616     public void testAbnormalForkJoin() {
 617         testAbnormalForkJoin(mainPool());
 618     }
 619     public void testAbnormalForkJoin_Singleton() {
 620         testAbnormalForkJoin(singletonPool());
 621     }
 622     public void testAbnormalForkJoin(ForkJoinPool pool) {
 623         RecursiveAction a = new CheckedRecursiveAction() {
 624             protected void realCompute() {
 625                 FailingAsyncFib f = new FailingAsyncFib(8);
 626                 assertSame(f, f.fork());
 627                 try {
 628                     f.join();
 629                     shouldThrow();
 630                 } catch (FJException success) {
 631                     checkCompletedAbnormally(f, success);
 632                 }
 633             }};
 634         testInvokeOnPool(pool, a);
 635     }
 636 
 637     /**
 638      * get of a forked task throws exception when task completes abnormally
 639      */
 640     public void testAbnormalForkGet() {
 641         testAbnormalForkGet(mainPool());
 642     }
 643     public void testAbnormalForkGet_Singleton() {
 644         testAbnormalForkJoin(singletonPool());
 645     }
 646     public void testAbnormalForkGet(ForkJoinPool pool) {
 647         RecursiveAction a = new CheckedRecursiveAction() {
 648             protected void realCompute() throws Exception {
 649                 FailingAsyncFib f = new FailingAsyncFib(8);
 650                 assertSame(f, f.fork());
 651                 try {
 652                     f.get();
 653                     shouldThrow();
 654                 } catch (ExecutionException success) {
 655                     Throwable cause = success.getCause();
 656                     assertTrue(cause instanceof FJException);
 657                     checkCompletedAbnormally(f, cause);
 658                 }
 659             }};
 660         testInvokeOnPool(pool, a);
 661     }
 662 
 663     /**
 664      * timed get of a forked task throws exception when task completes abnormally
 665      */
 666     public void testAbnormalForkTimedGet() {
 667         testAbnormalForkTimedGet(mainPool());
 668     }
 669     public void testAbnormalForkTimedGet_Singleton() {
 670         testAbnormalForkTimedGet(singletonPool());
 671     }
 672     public void testAbnormalForkTimedGet(ForkJoinPool pool) {
 673         RecursiveAction a = new CheckedRecursiveAction() {
 674             protected void realCompute() throws Exception {
 675                 FailingAsyncFib f = new FailingAsyncFib(8);
 676                 assertSame(f, f.fork());
 677                 try {
 678                     f.get(LONG_DELAY_MS, MILLISECONDS);
 679                     shouldThrow();
 680                 } catch (ExecutionException success) {
 681                     Throwable cause = success.getCause();
 682                     assertTrue(cause instanceof FJException);
 683                     checkCompletedAbnormally(f, cause);
 684                 }
 685             }};
 686         testInvokeOnPool(pool, a);
 687     }
 688 
 689     /**
 690      * quietlyJoin of a forked task returns when task completes abnormally
 691      */
 692     public void testAbnormalForkQuietlyJoin() {
 693         testAbnormalForkQuietlyJoin(mainPool());
 694     }
 695     public void testAbnormalForkQuietlyJoin_Singleton() {
 696         testAbnormalForkQuietlyJoin(singletonPool());
 697     }
 698     public void testAbnormalForkQuietlyJoin(ForkJoinPool pool) {
 699         RecursiveAction a = new CheckedRecursiveAction() {
 700             protected void realCompute() {
 701                 FailingAsyncFib f = new FailingAsyncFib(8);
 702                 assertSame(f, f.fork());
 703                 f.quietlyJoin();
 704                 assertTrue(f.getException() instanceof FJException);
 705                 checkCompletedAbnormally(f, f.getException());
 706             }};
 707         testInvokeOnPool(pool, a);
 708     }
 709 
 710     /**
 711      * getPool of executing task returns its pool
 712      */
 713     public void testGetPool() {
 714         testGetPool(mainPool());
 715     }
 716     public void testGetPool_Singleton() {
 717         testGetPool(singletonPool());
 718     }
 719     public void testGetPool(ForkJoinPool pool) {
 720         RecursiveAction a = new CheckedRecursiveAction() {
 721             protected void realCompute() {
 722                 assertSame(pool, getPool());
 723             }};
 724         testInvokeOnPool(pool, a);
 725     }
 726 
 727     /**
 728      * getPool of non-FJ task returns null
 729      */
 730     public void testGetPool2() {
 731         RecursiveAction a = new CheckedRecursiveAction() {
 732             protected void realCompute() {
 733                 assertNull(getPool());
 734             }};
 735         assertNull(a.invoke());
 736     }
 737 
 738     /**
 739      * inForkJoinPool of executing task returns true
 740      */
 741     public void testInForkJoinPool() {
 742         testInForkJoinPool(mainPool());
 743     }
 744     public void testInForkJoinPool_Singleton() {
 745         testInForkJoinPool(singletonPool());
 746     }
 747     public void testInForkJoinPool(ForkJoinPool pool) {
 748         RecursiveAction a = new CheckedRecursiveAction() {
 749             protected void realCompute() {
 750                 assertTrue(inForkJoinPool());
 751             }};
 752         testInvokeOnPool(pool, a);
 753     }
 754 
 755     /**
 756      * inForkJoinPool of non-FJ task returns false
 757      */
 758     public void testInForkJoinPool2() {
 759         RecursiveAction a = new CheckedRecursiveAction() {
 760             protected void realCompute() {
 761                 assertFalse(inForkJoinPool());
 762             }};
 763         assertNull(a.invoke());
 764     }
 765 
 766     /**
 767      * setRawResult(null) succeeds
 768      */
 769     public void testSetRawResult() {
 770         RecursiveAction a = new CheckedRecursiveAction() {
 771             protected void realCompute() {
 772                 setRawResult(null);
 773                 assertNull(getRawResult());
 774             }};
 775         assertNull(a.invoke());
 776     }
 777 
 778     /**
 779      * invoke task throws exception after invoking completeExceptionally
 780      */
 781     public void testCompleteExceptionally() {
 782         testCompleteExceptionally(mainPool());
 783     }
 784     public void testCompleteExceptionally_Singleton() {
 785         testCompleteExceptionally(singletonPool());
 786     }
 787     public void testCompleteExceptionally(ForkJoinPool pool) {
 788         RecursiveAction a = new CheckedRecursiveAction() {
 789             protected void realCompute() {
 790                 AsyncFib f = new AsyncFib(8);
 791                 f.completeExceptionally(new FJException());
 792                 try {
 793                     f.invoke();
 794                     shouldThrow();
 795                 } catch (FJException success) {
 796                     checkCompletedAbnormally(f, success);
 797                 }
 798             }};
 799         testInvokeOnPool(pool, a);
 800     }
 801 
 802     /**
 803      * invokeAll(tasks) with 1 argument invokes task
 804      */
 805     public void testInvokeAll1() {
 806         testInvokeAll1(mainPool());
 807     }
 808     public void testInvokeAll1_Singleton() {
 809         testInvokeAll1(singletonPool());
 810     }
 811     public void testInvokeAll1(ForkJoinPool pool) {
 812         RecursiveAction a = new CheckedRecursiveAction() {
 813             protected void realCompute() {
 814                 AsyncFib f = new AsyncFib(8);
 815                 invokeAll(f);
 816                 f.checkCompletedNormally();
 817             }};
 818         testInvokeOnPool(pool, a);
 819     }
 820 
 821     /**
 822      * invokeAll(t1, t2) invokes all task arguments
 823      */
 824     public void testInvokeAll2() {
 825         testInvokeAll2(mainPool());
 826     }
 827     public void testInvokeAll2_Singleton() {
 828         testInvokeAll2(singletonPool());
 829     }
 830     public void testInvokeAll2(ForkJoinPool pool) {
 831         RecursiveAction a = new CheckedRecursiveAction() {
 832             protected void realCompute() {
 833                 AsyncFib[] tasks = {
 834                     new AsyncFib(8),
 835                     new AsyncFib(9),
 836                 };
 837                 invokeAll(tasks[0], tasks[1]);
 838                 for (AsyncFib task : tasks) assertTrue(task.isDone());
 839                 for (AsyncFib task : tasks) task.checkCompletedNormally();
 840             }};
 841         testInvokeOnPool(pool, a);
 842     }
 843 
 844     /**
 845      * invokeAll(tasks) with > 2 argument invokes tasks
 846      */
 847     public void testInvokeAll3() {
 848         testInvokeAll3(mainPool());
 849     }
 850     public void testInvokeAll3_Singleton() {
 851         testInvokeAll3(singletonPool());
 852     }
 853     public void testInvokeAll3(ForkJoinPool pool) {
 854         RecursiveAction a = new CheckedRecursiveAction() {
 855             protected void realCompute() {
 856                 AsyncFib[] tasks = {
 857                     new AsyncFib(8),
 858                     new AsyncFib(9),
 859                     new AsyncFib(7),
 860                 };
 861                 invokeAll(tasks[0], tasks[1], tasks[2]);
 862                 for (AsyncFib task : tasks) assertTrue(task.isDone());
 863                 for (AsyncFib task : tasks) task.checkCompletedNormally();
 864             }};
 865         testInvokeOnPool(pool, a);
 866     }
 867 
 868     /**
 869      * invokeAll(collection) invokes all tasks in the collection
 870      */
 871     public void testInvokeAllCollection() {
 872         testInvokeAllCollection(mainPool());
 873     }
 874     public void testInvokeAllCollection_Singleton() {
 875         testInvokeAllCollection(singletonPool());
 876     }
 877     public void testInvokeAllCollection(ForkJoinPool pool) {
 878         RecursiveAction a = new CheckedRecursiveAction() {
 879             protected void realCompute() {
 880                 AsyncFib[] tasks = {
 881                     new AsyncFib(8),
 882                     new AsyncFib(9),
 883                     new AsyncFib(7),
 884                 };
 885                 invokeAll(Arrays.asList(tasks));
 886                 for (AsyncFib task : tasks) assertTrue(task.isDone());
 887                 for (AsyncFib task : tasks) task.checkCompletedNormally();
 888             }};
 889         testInvokeOnPool(pool, a);
 890     }
 891 
 892     /**
 893      * invokeAll(tasks) with any null task throws NullPointerException
 894      */
 895     public void testInvokeAllNullTask() {
 896         testInvokeAllNullTask(mainPool());
 897     }
 898     public void testInvokeAllNullTask_Singleton() {
 899         testInvokeAllNullTask(singletonPool());
 900     }
 901     public void testInvokeAllNullTask(ForkJoinPool pool) {
 902         RecursiveAction a = new CheckedRecursiveAction() {
 903             protected void realCompute() {
 904                 AsyncFib nul = null;
 905                 assertThrows(
 906                     NullPointerException.class,
 907                     () -> invokeAll(nul),
 908                     () -> invokeAll(nul, nul),
 909                     () -> invokeAll(new AsyncFib(8), new AsyncFib(9), nul),
 910                     () -> invokeAll(new AsyncFib(8), nul, new AsyncFib(9)),
 911                     () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)));
 912             }};
 913         testInvokeOnPool(pool, a);
 914     }
 915 
 916     /**
 917      * invokeAll(tasks) with 1 argument throws exception if task does
 918      */
 919     public void testAbnormalInvokeAll1() {
 920         testAbnormalInvokeAll1(mainPool());
 921     }
 922     public void testAbnormalInvokeAll1_Singleton() {
 923         testAbnormalInvokeAll1(singletonPool());
 924     }
 925     public void testAbnormalInvokeAll1(ForkJoinPool pool) {
 926         RecursiveAction a = new CheckedRecursiveAction() {
 927             protected void realCompute() {
 928                 FailingAsyncFib g = new FailingAsyncFib(9);
 929                 try {
 930                     invokeAll(g);
 931                     shouldThrow();
 932                 } catch (FJException success) {
 933                     checkCompletedAbnormally(g, success);
 934                 }
 935             }};
 936         testInvokeOnPool(pool, a);
 937     }
 938 
 939     /**
 940      * invokeAll(t1, t2) throw exception if any task does
 941      */
 942     public void testAbnormalInvokeAll2() {
 943         testAbnormalInvokeAll2(mainPool());
 944     }
 945     public void testAbnormalInvokeAll2_Singleton() {
 946         testAbnormalInvokeAll2(singletonPool());
 947     }
 948     public void testAbnormalInvokeAll2(ForkJoinPool pool) {
 949         RecursiveAction a = new CheckedRecursiveAction() {
 950             protected void realCompute() {
 951                 AsyncFib f = new AsyncFib(8);
 952                 FailingAsyncFib g = new FailingAsyncFib(9);
 953                 ForkJoinTask[] tasks = { f, g };
 954                 shuffle(tasks);
 955                 try {
 956                     invokeAll(tasks[0], tasks[1]);
 957                     shouldThrow();
 958                 } catch (FJException success) {
 959                     checkCompletedAbnormally(g, success);
 960                 }
 961             }};
 962         testInvokeOnPool(pool, a);
 963     }
 964 
 965     /**
 966      * invokeAll(tasks) with > 2 argument throws exception if any task does
 967      */
 968     public void testAbnormalInvokeAll3() {
 969         testAbnormalInvokeAll3(mainPool());
 970     }
 971     public void testAbnormalInvokeAll3_Singleton() {
 972         testAbnormalInvokeAll3(singletonPool());
 973     }
 974     public void testAbnormalInvokeAll3(ForkJoinPool pool) {
 975         RecursiveAction a = new CheckedRecursiveAction() {
 976             protected void realCompute() {
 977                 AsyncFib f = new AsyncFib(8);
 978                 FailingAsyncFib g = new FailingAsyncFib(9);
 979                 AsyncFib h = new AsyncFib(7);
 980                 ForkJoinTask[] tasks = { f, g, h };
 981                 shuffle(tasks);
 982                 try {
 983                     invokeAll(tasks[0], tasks[1], tasks[2]);
 984                     shouldThrow();
 985                 } catch (FJException success) {
 986                     checkCompletedAbnormally(g, success);
 987                 }
 988             }};
 989         testInvokeOnPool(pool, a);
 990     }
 991 
 992     /**
 993      * invokeAll(collection) throws exception if any task does
 994      */
 995     public void testAbnormalInvokeAllCollection() {
 996         testAbnormalInvokeAllCollection(mainPool());
 997     }
 998     public void testAbnormalInvokeAllCollection_Singleton() {
 999         testAbnormalInvokeAllCollection(singletonPool());
1000     }
1001     public void testAbnormalInvokeAllCollection(ForkJoinPool pool) {
1002         RecursiveAction a = new CheckedRecursiveAction() {
1003             protected void realCompute() {
1004                 FailingAsyncFib f = new FailingAsyncFib(8);
1005                 AsyncFib g = new AsyncFib(9);
1006                 AsyncFib h = new AsyncFib(7);
1007                 ForkJoinTask[] tasks = { f, g, h };
1008                 shuffle(tasks);
1009                 try {
1010                     invokeAll(Arrays.asList(tasks));
1011                     shouldThrow();
1012                 } catch (FJException success) {
1013                     checkCompletedAbnormally(f, success);
1014                 }
1015             }};
1016         testInvokeOnPool(pool, a);
1017     }
1018 
1019     /**
1020      * tryUnfork returns true for most recent unexecuted task,
1021      * and suppresses execution
1022      */
1023     public void testTryUnfork() {
1024         RecursiveAction a = new CheckedRecursiveAction() {
1025             protected void realCompute() {
1026                 AsyncFib g = new AsyncFib(9);
1027                 assertSame(g, g.fork());
1028                 AsyncFib f = new AsyncFib(8);
1029                 assertSame(f, f.fork());
1030                 assertTrue(f.tryUnfork());
1031                 helpQuiesce();
1032                 checkNotDone(f);
1033                 g.checkCompletedNormally();
1034             }};
1035         testInvokeOnPool(singletonPool(), a);
1036     }
1037 
1038     /**
1039      * getSurplusQueuedTaskCount returns > 0 when
1040      * there are more tasks than threads
1041      */
1042     public void testGetSurplusQueuedTaskCount() {
1043         RecursiveAction a = new CheckedRecursiveAction() {
1044             protected void realCompute() {
1045                 AsyncFib h = new AsyncFib(7);
1046                 assertSame(h, h.fork());
1047                 AsyncFib g = new AsyncFib(9);
1048                 assertSame(g, g.fork());
1049                 AsyncFib f = new AsyncFib(8);
1050                 assertSame(f, f.fork());
1051                 assertTrue(getSurplusQueuedTaskCount() > 0);
1052                 helpQuiesce();
1053                 assertEquals(0, getSurplusQueuedTaskCount());
1054                 f.checkCompletedNormally();
1055                 g.checkCompletedNormally();
1056                 h.checkCompletedNormally();
1057             }};
1058         testInvokeOnPool(singletonPool(), a);
1059     }
1060 
1061     /**
1062      * peekNextLocalTask returns most recent unexecuted task.
1063      */
1064     public void testPeekNextLocalTask() {
1065         RecursiveAction a = new CheckedRecursiveAction() {
1066             protected void realCompute() {
1067                 AsyncFib g = new AsyncFib(9);
1068                 assertSame(g, g.fork());
1069                 AsyncFib f = new AsyncFib(8);
1070                 assertSame(f, f.fork());
1071                 assertSame(f, peekNextLocalTask());
1072                 assertNull(f.join());
1073                 f.checkCompletedNormally();
1074                 helpQuiesce();
1075                 g.checkCompletedNormally();
1076             }};
1077         testInvokeOnPool(singletonPool(), a);
1078     }
1079 
1080     /**
1081      * pollNextLocalTask returns most recent unexecuted task without
1082      * executing it
1083      */
1084     public void testPollNextLocalTask() {
1085         RecursiveAction a = new CheckedRecursiveAction() {
1086             protected void realCompute() {
1087                 AsyncFib g = new AsyncFib(9);
1088                 assertSame(g, g.fork());
1089                 AsyncFib f = new AsyncFib(8);
1090                 assertSame(f, f.fork());
1091                 assertSame(f, pollNextLocalTask());
1092                 helpQuiesce();
1093                 checkNotDone(f);
1094                 g.checkCompletedNormally();
1095             }};
1096         testInvokeOnPool(singletonPool(), a);
1097     }
1098 
1099     /**
1100      * pollTask returns an unexecuted task without executing it
1101      */
1102     public void testPollTask() {
1103         RecursiveAction a = new CheckedRecursiveAction() {
1104             protected void realCompute() {
1105                 AsyncFib g = new AsyncFib(9);
1106                 assertSame(g, g.fork());
1107                 AsyncFib f = new AsyncFib(8);
1108                 assertSame(f, f.fork());
1109                 assertSame(f, pollTask());
1110                 helpQuiesce();
1111                 checkNotDone(f);
1112                 g.checkCompletedNormally();
1113             }};
1114         testInvokeOnPool(singletonPool(), a);
1115     }
1116 
1117     /**
1118      * peekNextLocalTask returns least recent unexecuted task in async mode
1119      */
1120     public void testPeekNextLocalTaskAsync() {
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, peekNextLocalTask());
1128                 assertNull(f.join());
1129                 helpQuiesce();
1130                 f.checkCompletedNormally();
1131                 g.checkCompletedNormally();
1132             }};
1133         testInvokeOnPool(asyncSingletonPool(), a);
1134     }
1135 
1136     /**
1137      * pollNextLocalTask returns least recent unexecuted task without
1138      * executing it, in async mode
1139      */
1140     public void testPollNextLocalTaskAsync() {
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, pollNextLocalTask());
1148                 helpQuiesce();
1149                 f.checkCompletedNormally();
1150                 checkNotDone(g);
1151             }};
1152         testInvokeOnPool(asyncSingletonPool(), a);
1153     }
1154 
1155     /**
1156      * pollTask returns an unexecuted task without executing it, in
1157      * async mode
1158      */
1159     public void testPollTaskAsync() {
1160         RecursiveAction a = new CheckedRecursiveAction() {
1161             protected void realCompute() {
1162                 AsyncFib g = new AsyncFib(9);
1163                 assertSame(g, g.fork());
1164                 AsyncFib f = new AsyncFib(8);
1165                 assertSame(f, f.fork());
1166                 assertSame(g, pollTask());
1167                 helpQuiesce();
1168                 f.checkCompletedNormally();
1169                 checkNotDone(g);
1170             }};
1171         testInvokeOnPool(asyncSingletonPool(), a);
1172     }
1173 
1174     /**
1175      * ForkJoinTask.quietlyComplete returns when task completes
1176      * normally without setting a value. The most recent value
1177      * established by setRawResult(V) (or null by default) is returned
1178      * from invoke.
1179      */
1180     public void testQuietlyComplete() {
1181         RecursiveAction a = new CheckedRecursiveAction() {
1182                 protected void realCompute() {
1183                     AsyncFib f = new AsyncFib(8);
1184                     f.quietlyComplete();
1185                     assertEquals(8, f.number);
1186                     assertTrue(f.isDone());
1187                     assertFalse(f.isCancelled());
1188                     assertTrue(f.isCompletedNormally());
1189                     assertFalse(f.isCompletedAbnormally());
1190                     assertNull(f.getException());
1191                 }};
1192         testInvokeOnPool(mainPool(), a);
1193     }
1194 
1195     // jdk9
1196 
1197     /**
1198      * pollSubmission returns unexecuted submitted task, if present
1199      */
1200     public void testPollSubmission() {
1201         final CountDownLatch done = new CountDownLatch(1);
1202         final ForkJoinTask a = ForkJoinTask.adapt(awaiter(done));
1203         final ForkJoinTask b = ForkJoinTask.adapt(awaiter(done));
1204         final ForkJoinTask c = ForkJoinTask.adapt(awaiter(done));
1205         final ForkJoinPool p = singletonPool();
1206         try (PoolCleaner cleaner = cleaner(p, done)) {
1207             Thread external = new Thread(new CheckedRunnable() {
1208                 public void realRun() {
1209                     p.execute(a);
1210                     p.execute(b);
1211                     p.execute(c);
1212                 }});
1213             RecursiveAction s = new CheckedRecursiveAction() {
1214                 protected void realCompute() {
1215                     external.start();
1216                     try {
1217                         external.join();
1218                     } catch (Exception ex) {
1219                         threadUnexpectedException(ex);
1220                     }
1221                     assertTrue(p.hasQueuedSubmissions());
1222                     assertTrue(Thread.currentThread() instanceof ForkJoinWorkerThread);
1223                     ForkJoinTask r = ForkJoinTask.pollSubmission();
1224                     assertTrue(r == a || r == b || r == c);
1225                     assertFalse(r.isDone());
1226                 }};
1227             p.invoke(s);
1228         }
1229     }
1230 
1231 }