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