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                 assertEquals(0, getQueuedTaskCount());
 563                 f.checkCompletedNormally();
 564             }};
 565         testInvokeOnPool(pool, a);
 566     }
 567 
 568     /**
 569      * invoke task throws exception when task completes abnormally
 570      */
 571     public void testAbnormalInvoke() {
 572         testAbnormalInvoke(mainPool());
 573     }
 574     public void testAbnormalInvoke_Singleton() {
 575         testAbnormalInvoke(singletonPool());
 576     }
 577     public void testAbnormalInvoke(ForkJoinPool pool) {
 578         RecursiveAction a = new CheckedRecursiveAction() {
 579             protected void realCompute() {
 580                 FailingAsyncFib f = new FailingAsyncFib(8);
 581                 try {
 582                     f.invoke();
 583                     shouldThrow();
 584                 } catch (FJException success) {
 585                     checkCompletedAbnormally(f, success);
 586                 }
 587             }};
 588         testInvokeOnPool(pool, a);
 589     }
 590 
 591     /**
 592      * quietlyInvoke task returns when task completes abnormally
 593      */
 594     public void testAbnormalQuietlyInvoke() {
 595         testAbnormalQuietlyInvoke(mainPool());
 596     }
 597     public void testAbnormalQuietlyInvoke_Singleton() {
 598         testAbnormalQuietlyInvoke(singletonPool());
 599     }
 600     public void testAbnormalQuietlyInvoke(ForkJoinPool pool) {
 601         RecursiveAction a = new CheckedRecursiveAction() {
 602             protected void realCompute() {
 603                 FailingAsyncFib f = new FailingAsyncFib(8);
 604                 f.quietlyInvoke();
 605                 assertTrue(f.getException() instanceof FJException);
 606                 checkCompletedAbnormally(f, f.getException());
 607             }};
 608         testInvokeOnPool(pool, a);
 609     }
 610 
 611     /**
 612      * join of a forked task throws exception when task completes abnormally
 613      */
 614     public void testAbnormalForkJoin() {
 615         testAbnormalForkJoin(mainPool());
 616     }
 617     public void testAbnormalForkJoin_Singleton() {
 618         testAbnormalForkJoin(singletonPool());
 619     }
 620     public void testAbnormalForkJoin(ForkJoinPool pool) {
 621         RecursiveAction a = new CheckedRecursiveAction() {
 622             protected void realCompute() {
 623                 FailingAsyncFib f = new FailingAsyncFib(8);
 624                 assertSame(f, f.fork());
 625                 try {
 626                     f.join();
 627                     shouldThrow();
 628                 } catch (FJException success) {
 629                     checkCompletedAbnormally(f, success);
 630                 }
 631             }};
 632         testInvokeOnPool(pool, a);
 633     }
 634 
 635     /**
 636      * get of a forked task throws exception when task completes abnormally
 637      */
 638     public void testAbnormalForkGet() {
 639         testAbnormalForkGet(mainPool());
 640     }
 641     public void testAbnormalForkGet_Singleton() {
 642         testAbnormalForkJoin(singletonPool());
 643     }
 644     public void testAbnormalForkGet(ForkJoinPool pool) {
 645         RecursiveAction a = new CheckedRecursiveAction() {
 646             protected void realCompute() throws Exception {
 647                 FailingAsyncFib f = new FailingAsyncFib(8);
 648                 assertSame(f, f.fork());
 649                 try {
 650                     f.get();
 651                     shouldThrow();
 652                 } catch (ExecutionException success) {
 653                     Throwable cause = success.getCause();
 654                     assertTrue(cause instanceof FJException);
 655                     checkCompletedAbnormally(f, cause);
 656                 }
 657             }};
 658         testInvokeOnPool(pool, a);
 659     }
 660 
 661     /**
 662      * timed get of a forked task throws exception when task completes abnormally
 663      */
 664     public void testAbnormalForkTimedGet() {
 665         testAbnormalForkTimedGet(mainPool());
 666     }
 667     public void testAbnormalForkTimedGet_Singleton() {
 668         testAbnormalForkTimedGet(singletonPool());
 669     }
 670     public void testAbnormalForkTimedGet(ForkJoinPool pool) {
 671         RecursiveAction a = new CheckedRecursiveAction() {
 672             protected void realCompute() throws Exception {
 673                 FailingAsyncFib f = new FailingAsyncFib(8);
 674                 assertSame(f, f.fork());
 675                 try {
 676                     f.get(LONG_DELAY_MS, MILLISECONDS);
 677                     shouldThrow();
 678                 } catch (ExecutionException success) {
 679                     Throwable cause = success.getCause();
 680                     assertTrue(cause instanceof FJException);
 681                     checkCompletedAbnormally(f, cause);
 682                 }
 683             }};
 684         testInvokeOnPool(pool, a);
 685     }
 686 
 687     /**
 688      * quietlyJoin of a forked task returns when task completes abnormally
 689      */
 690     public void testAbnormalForkQuietlyJoin() {
 691         testAbnormalForkQuietlyJoin(mainPool());
 692     }
 693     public void testAbnormalForkQuietlyJoin_Singleton() {
 694         testAbnormalForkQuietlyJoin(singletonPool());
 695     }
 696     public void testAbnormalForkQuietlyJoin(ForkJoinPool pool) {
 697         RecursiveAction a = new CheckedRecursiveAction() {
 698             protected void realCompute() {
 699                 FailingAsyncFib f = new FailingAsyncFib(8);
 700                 assertSame(f, f.fork());
 701                 f.quietlyJoin();
 702                 assertTrue(f.getException() instanceof FJException);
 703                 checkCompletedAbnormally(f, f.getException());
 704             }};
 705         testInvokeOnPool(pool, a);
 706     }
 707 
 708     /**
 709      * getPool of executing task returns its pool
 710      */
 711     public void testGetPool() {
 712         testGetPool(mainPool());
 713     }
 714     public void testGetPool_Singleton() {
 715         testGetPool(singletonPool());
 716     }
 717     public void testGetPool(ForkJoinPool pool) {
 718         RecursiveAction a = new CheckedRecursiveAction() {
 719             protected void realCompute() {
 720                 assertSame(pool, getPool());
 721             }};
 722         testInvokeOnPool(pool, a);
 723     }
 724 
 725     /**
 726      * getPool of non-FJ task returns null
 727      */
 728     public void testGetPool2() {
 729         RecursiveAction a = new CheckedRecursiveAction() {
 730             protected void realCompute() {
 731                 assertNull(getPool());
 732             }};
 733         assertNull(a.invoke());
 734     }
 735 
 736     /**
 737      * inForkJoinPool of executing task returns true
 738      */
 739     public void testInForkJoinPool() {
 740         testInForkJoinPool(mainPool());
 741     }
 742     public void testInForkJoinPool_Singleton() {
 743         testInForkJoinPool(singletonPool());
 744     }
 745     public void testInForkJoinPool(ForkJoinPool pool) {
 746         RecursiveAction a = new CheckedRecursiveAction() {
 747             protected void realCompute() {
 748                 assertTrue(inForkJoinPool());
 749             }};
 750         testInvokeOnPool(pool, a);
 751     }
 752 
 753     /**
 754      * inForkJoinPool of non-FJ task returns false
 755      */
 756     public void testInForkJoinPool2() {
 757         RecursiveAction a = new CheckedRecursiveAction() {
 758             protected void realCompute() {
 759                 assertFalse(inForkJoinPool());
 760             }};
 761         assertNull(a.invoke());
 762     }
 763 
 764     /**
 765      * setRawResult(null) succeeds
 766      */
 767     public void testSetRawResult() {
 768         RecursiveAction a = new CheckedRecursiveAction() {
 769             protected void realCompute() {
 770                 setRawResult(null);
 771                 assertNull(getRawResult());
 772             }};
 773         assertNull(a.invoke());
 774     }
 775 
 776     /**
 777      * invoke task throws exception after invoking completeExceptionally
 778      */
 779     public void testCompleteExceptionally() {
 780         testCompleteExceptionally(mainPool());
 781     }
 782     public void testCompleteExceptionally_Singleton() {
 783         testCompleteExceptionally(singletonPool());
 784     }
 785     public void testCompleteExceptionally(ForkJoinPool pool) {
 786         RecursiveAction a = new CheckedRecursiveAction() {
 787             protected void realCompute() {
 788                 AsyncFib f = new AsyncFib(8);
 789                 f.completeExceptionally(new FJException());
 790                 try {
 791                     f.invoke();
 792                     shouldThrow();
 793                 } catch (FJException success) {
 794                     checkCompletedAbnormally(f, success);
 795                 }
 796             }};
 797         testInvokeOnPool(pool, a);
 798     }
 799 
 800     /**
 801      * invokeAll(tasks) with 1 argument invokes task
 802      */
 803     public void testInvokeAll1() {
 804         testInvokeAll1(mainPool());
 805     }
 806     public void testInvokeAll1_Singleton() {
 807         testInvokeAll1(singletonPool());
 808     }
 809     public void testInvokeAll1(ForkJoinPool pool) {
 810         RecursiveAction a = new CheckedRecursiveAction() {
 811             protected void realCompute() {
 812                 AsyncFib f = new AsyncFib(8);
 813                 invokeAll(f);
 814                 f.checkCompletedNormally();
 815             }};
 816         testInvokeOnPool(pool, a);
 817     }
 818 
 819     /**
 820      * invokeAll(t1, t2) invokes all task arguments
 821      */
 822     public void testInvokeAll2() {
 823         testInvokeAll2(mainPool());
 824     }
 825     public void testInvokeAll2_Singleton() {
 826         testInvokeAll2(singletonPool());
 827     }
 828     public void testInvokeAll2(ForkJoinPool pool) {
 829         RecursiveAction a = new CheckedRecursiveAction() {
 830             protected void realCompute() {
 831                 AsyncFib[] tasks = {
 832                     new AsyncFib(8),
 833                     new AsyncFib(9),
 834                 };
 835                 invokeAll(tasks[0], tasks[1]);
 836                 for (AsyncFib task : tasks) assertTrue(task.isDone());
 837                 for (AsyncFib task : tasks) task.checkCompletedNormally();
 838             }};
 839         testInvokeOnPool(pool, a);
 840     }
 841 
 842     /**
 843      * invokeAll(tasks) with > 2 argument invokes tasks
 844      */
 845     public void testInvokeAll3() {
 846         testInvokeAll3(mainPool());
 847     }
 848     public void testInvokeAll3_Singleton() {
 849         testInvokeAll3(singletonPool());
 850     }
 851     public void testInvokeAll3(ForkJoinPool pool) {
 852         RecursiveAction a = new CheckedRecursiveAction() {
 853             protected void realCompute() {
 854                 AsyncFib[] tasks = {
 855                     new AsyncFib(8),
 856                     new AsyncFib(9),
 857                     new AsyncFib(7),
 858                 };
 859                 invokeAll(tasks[0], tasks[1], tasks[2]);
 860                 for (AsyncFib task : tasks) assertTrue(task.isDone());
 861                 for (AsyncFib task : tasks) task.checkCompletedNormally();
 862             }};
 863         testInvokeOnPool(pool, a);
 864     }
 865 
 866     /**
 867      * invokeAll(collection) invokes all tasks in the collection
 868      */
 869     public void testInvokeAllCollection() {
 870         testInvokeAllCollection(mainPool());
 871     }
 872     public void testInvokeAllCollection_Singleton() {
 873         testInvokeAllCollection(singletonPool());
 874     }
 875     public void testInvokeAllCollection(ForkJoinPool pool) {
 876         RecursiveAction a = new CheckedRecursiveAction() {
 877             protected void realCompute() {
 878                 AsyncFib[] tasks = {
 879                     new AsyncFib(8),
 880                     new AsyncFib(9),
 881                     new AsyncFib(7),
 882                 };
 883                 invokeAll(Arrays.asList(tasks));
 884                 for (AsyncFib task : tasks) assertTrue(task.isDone());
 885                 for (AsyncFib task : tasks) task.checkCompletedNormally();
 886             }};
 887         testInvokeOnPool(pool, a);
 888     }
 889 
 890     /**
 891      * invokeAll(tasks) with any null task throws NullPointerException
 892      */
 893     public void testInvokeAllNullTask() {
 894         testInvokeAllNullTask(mainPool());
 895     }
 896     public void testInvokeAllNullTask_Singleton() {
 897         testInvokeAllNullTask(singletonPool());
 898     }
 899     public void testInvokeAllNullTask(ForkJoinPool pool) {
 900         RecursiveAction a = new CheckedRecursiveAction() {
 901             protected void realCompute() {
 902                 AsyncFib nul = null;
 903                 assertThrows(
 904                     NullPointerException.class,
 905                     () -> invokeAll(nul),
 906                     () -> invokeAll(nul, nul),
 907                     () -> invokeAll(new AsyncFib(8), new AsyncFib(9), nul),
 908                     () -> invokeAll(new AsyncFib(8), nul, new AsyncFib(9)),
 909                     () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)));
 910             }};
 911         testInvokeOnPool(pool, a);
 912     }
 913 
 914     /**
 915      * invokeAll(tasks) with 1 argument throws exception if task does
 916      */
 917     public void testAbnormalInvokeAll1() {
 918         testAbnormalInvokeAll1(mainPool());
 919     }
 920     public void testAbnormalInvokeAll1_Singleton() {
 921         testAbnormalInvokeAll1(singletonPool());
 922     }
 923     public void testAbnormalInvokeAll1(ForkJoinPool pool) {
 924         RecursiveAction a = new CheckedRecursiveAction() {
 925             protected void realCompute() {
 926                 FailingAsyncFib g = new FailingAsyncFib(9);
 927                 try {
 928                     invokeAll(g);
 929                     shouldThrow();
 930                 } catch (FJException success) {
 931                     checkCompletedAbnormally(g, success);
 932                 }
 933             }};
 934         testInvokeOnPool(pool, a);
 935     }
 936 
 937     /**
 938      * invokeAll(t1, t2) throw exception if any task does
 939      */
 940     public void testAbnormalInvokeAll2() {
 941         testAbnormalInvokeAll2(mainPool());
 942     }
 943     public void testAbnormalInvokeAll2_Singleton() {
 944         testAbnormalInvokeAll2(singletonPool());
 945     }
 946     public void testAbnormalInvokeAll2(ForkJoinPool pool) {
 947         RecursiveAction a = new CheckedRecursiveAction() {
 948             protected void realCompute() {
 949                 AsyncFib f = new AsyncFib(8);
 950                 FailingAsyncFib g = new FailingAsyncFib(9);
 951                 ForkJoinTask[] tasks = { f, g };
 952                 shuffle(tasks);
 953                 try {
 954                     invokeAll(tasks[0], tasks[1]);
 955                     shouldThrow();
 956                 } catch (FJException success) {
 957                     checkCompletedAbnormally(g, success);
 958                 }
 959             }};
 960         testInvokeOnPool(pool, a);
 961     }
 962 
 963     /**
 964      * invokeAll(tasks) with > 2 argument throws exception if any task does
 965      */
 966     public void testAbnormalInvokeAll3() {
 967         testAbnormalInvokeAll3(mainPool());
 968     }
 969     public void testAbnormalInvokeAll3_Singleton() {
 970         testAbnormalInvokeAll3(singletonPool());
 971     }
 972     public void testAbnormalInvokeAll3(ForkJoinPool pool) {
 973         RecursiveAction a = new CheckedRecursiveAction() {
 974             protected void realCompute() {
 975                 AsyncFib f = new AsyncFib(8);
 976                 FailingAsyncFib g = new FailingAsyncFib(9);
 977                 AsyncFib h = new AsyncFib(7);
 978                 ForkJoinTask[] tasks = { f, g, h };
 979                 shuffle(tasks);
 980                 try {
 981                     invokeAll(tasks[0], tasks[1], tasks[2]);
 982                     shouldThrow();
 983                 } catch (FJException success) {
 984                     checkCompletedAbnormally(g, success);
 985                 }
 986             }};
 987         testInvokeOnPool(pool, a);
 988     }
 989 
 990     /**
 991      * invokeAll(collection) throws exception if any task does
 992      */
 993     public void testAbnormalInvokeAllCollection() {
 994         testAbnormalInvokeAllCollection(mainPool());
 995     }
 996     public void testAbnormalInvokeAllCollection_Singleton() {
 997         testAbnormalInvokeAllCollection(singletonPool());
 998     }
 999     public void testAbnormalInvokeAllCollection(ForkJoinPool pool) {
1000         RecursiveAction a = new CheckedRecursiveAction() {
1001             protected void realCompute() {
1002                 FailingAsyncFib f = new FailingAsyncFib(8);
1003                 AsyncFib g = new AsyncFib(9);
1004                 AsyncFib h = new AsyncFib(7);
1005                 ForkJoinTask[] tasks = { f, g, h };
1006                 shuffle(tasks);
1007                 try {
1008                     invokeAll(Arrays.asList(tasks));
1009                     shouldThrow();
1010                 } catch (FJException success) {
1011                     checkCompletedAbnormally(f, success);
1012                 }
1013             }};
1014         testInvokeOnPool(pool, a);
1015     }
1016 
1017     /**
1018      * tryUnfork returns true for most recent unexecuted task,
1019      * and suppresses execution
1020      */
1021     public void testTryUnfork() {
1022         RecursiveAction a = new CheckedRecursiveAction() {
1023             protected void realCompute() {
1024                 AsyncFib g = new AsyncFib(9);
1025                 assertSame(g, g.fork());
1026                 AsyncFib f = new AsyncFib(8);
1027                 assertSame(f, f.fork());
1028                 assertTrue(f.tryUnfork());
1029                 helpQuiesce();
1030                 checkNotDone(f);
1031                 g.checkCompletedNormally();
1032             }};
1033         testInvokeOnPool(singletonPool(), a);
1034     }
1035 
1036     /**
1037      * getSurplusQueuedTaskCount returns > 0 when
1038      * there are more tasks than threads
1039      */
1040     public void testGetSurplusQueuedTaskCount() {
1041         RecursiveAction a = new CheckedRecursiveAction() {
1042             protected void realCompute() {
1043                 AsyncFib h = new AsyncFib(7);
1044                 assertSame(h, h.fork());
1045                 AsyncFib g = new AsyncFib(9);
1046                 assertSame(g, g.fork());
1047                 AsyncFib f = new AsyncFib(8);
1048                 assertSame(f, f.fork());
1049                 assertTrue(getSurplusQueuedTaskCount() > 0);
1050                 helpQuiesce();
1051                 assertEquals(0, getSurplusQueuedTaskCount());
1052                 f.checkCompletedNormally();
1053                 g.checkCompletedNormally();
1054                 h.checkCompletedNormally();
1055             }};
1056         testInvokeOnPool(singletonPool(), a);
1057     }
1058 
1059     /**
1060      * peekNextLocalTask returns most recent unexecuted task.
1061      */
1062     public void testPeekNextLocalTask() {
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, peekNextLocalTask());
1070                 assertNull(f.join());
1071                 f.checkCompletedNormally();
1072                 helpQuiesce();
1073                 g.checkCompletedNormally();
1074             }};
1075         testInvokeOnPool(singletonPool(), a);
1076     }
1077 
1078     /**
1079      * pollNextLocalTask returns most recent unexecuted task without
1080      * executing it
1081      */
1082     public void testPollNextLocalTask() {
1083         RecursiveAction a = new CheckedRecursiveAction() {
1084             protected void realCompute() {
1085                 AsyncFib g = new AsyncFib(9);
1086                 assertSame(g, g.fork());
1087                 AsyncFib f = new AsyncFib(8);
1088                 assertSame(f, f.fork());
1089                 assertSame(f, pollNextLocalTask());
1090                 helpQuiesce();
1091                 checkNotDone(f);
1092                 g.checkCompletedNormally();
1093             }};
1094         testInvokeOnPool(singletonPool(), a);
1095     }
1096 
1097     /**
1098      * pollTask returns an unexecuted task without executing it
1099      */
1100     public void testPollTask() {
1101         RecursiveAction a = new CheckedRecursiveAction() {
1102             protected void realCompute() {
1103                 AsyncFib g = new AsyncFib(9);
1104                 assertSame(g, g.fork());
1105                 AsyncFib f = new AsyncFib(8);
1106                 assertSame(f, f.fork());
1107                 assertSame(f, pollTask());
1108                 helpQuiesce();
1109                 checkNotDone(f);
1110                 g.checkCompletedNormally();
1111             }};
1112         testInvokeOnPool(singletonPool(), a);
1113     }
1114 
1115     /**
1116      * peekNextLocalTask returns least recent unexecuted task in async mode
1117      */
1118     public void testPeekNextLocalTaskAsync() {
1119         RecursiveAction a = new CheckedRecursiveAction() {
1120             protected void realCompute() {
1121                 AsyncFib g = new AsyncFib(9);
1122                 assertSame(g, g.fork());
1123                 AsyncFib f = new AsyncFib(8);
1124                 assertSame(f, f.fork());
1125                 assertSame(g, peekNextLocalTask());
1126                 assertNull(f.join());
1127                 helpQuiesce();
1128                 f.checkCompletedNormally();
1129                 g.checkCompletedNormally();
1130             }};
1131         testInvokeOnPool(asyncSingletonPool(), a);
1132     }
1133 
1134     /**
1135      * pollNextLocalTask returns least recent unexecuted task without
1136      * executing it, in async mode
1137      */
1138     public void testPollNextLocalTaskAsync() {
1139         RecursiveAction a = new CheckedRecursiveAction() {
1140             protected void realCompute() {
1141                 AsyncFib g = new AsyncFib(9);
1142                 assertSame(g, g.fork());
1143                 AsyncFib f = new AsyncFib(8);
1144                 assertSame(f, f.fork());
1145                 assertSame(g, pollNextLocalTask());
1146                 helpQuiesce();
1147                 f.checkCompletedNormally();
1148                 checkNotDone(g);
1149             }};
1150         testInvokeOnPool(asyncSingletonPool(), a);
1151     }
1152 
1153     /**
1154      * pollTask returns an unexecuted task without executing it, in
1155      * async mode
1156      */
1157     public void testPollTaskAsync() {
1158         RecursiveAction a = new CheckedRecursiveAction() {
1159             protected void realCompute() {
1160                 AsyncFib g = new AsyncFib(9);
1161                 assertSame(g, g.fork());
1162                 AsyncFib f = new AsyncFib(8);
1163                 assertSame(f, f.fork());
1164                 assertSame(g, pollTask());
1165                 helpQuiesce();
1166                 f.checkCompletedNormally();
1167                 checkNotDone(g);
1168             }};
1169         testInvokeOnPool(asyncSingletonPool(), a);
1170     }
1171 
1172     /**
1173      * ForkJoinTask.quietlyComplete returns when task completes
1174      * normally without setting a value. The most recent value
1175      * established by setRawResult(V) (or null by default) is returned
1176      * from invoke.
1177      */
1178     public void testQuietlyComplete() {
1179         RecursiveAction a = new CheckedRecursiveAction() {
1180                 protected void realCompute() {
1181                     AsyncFib f = new AsyncFib(8);
1182                     f.quietlyComplete();
1183                     assertEquals(8, f.number);
1184                     assertTrue(f.isDone());
1185                     assertFalse(f.isCancelled());
1186                     assertTrue(f.isCompletedNormally());
1187                     assertFalse(f.isCompletedAbnormally());
1188                     assertNull(f.getException());
1189                 }};
1190         testInvokeOnPool(mainPool(), a);
1191     }
1192 
1193     // jdk9
1194 
1195     /**
1196      * pollSubmission returns unexecuted submitted task, if present
1197      */
1198     public void testPollSubmission() {
1199         final CountDownLatch done = new CountDownLatch(1);
1200         final ForkJoinTask a = ForkJoinTask.adapt(awaiter(done));
1201         final ForkJoinTask b = ForkJoinTask.adapt(awaiter(done));
1202         final ForkJoinTask c = ForkJoinTask.adapt(awaiter(done));
1203         final ForkJoinPool p = singletonPool();
1204         try (PoolCleaner cleaner = cleaner(p, done)) {
1205             Thread external = new Thread(new CheckedRunnable() {
1206                 public void realRun() {
1207                     p.execute(a);
1208                     p.execute(b);
1209                     p.execute(c);
1210                 }});
1211             RecursiveAction s = new CheckedRecursiveAction() {
1212                 protected void realCompute() {
1213                     external.start();
1214                     try {
1215                         external.join();
1216                     } catch (Exception ex) {
1217                         threadUnexpectedException(ex);
1218                     }
1219                     assertTrue(p.hasQueuedSubmissions());
1220                     assertTrue(Thread.currentThread() instanceof ForkJoinWorkerThread);
1221                     ForkJoinTask r = ForkJoinTask.pollSubmission();
1222                     assertTrue(r == a || r == b || r == c);
1223                     assertFalse(r.isDone());
1224                 }};
1225             p.invoke(s);
1226         }
1227     }
1228 
1229 }