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