/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

package jsr166;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeoutException;

import junit.framework.Test;
import junit.framework.TestSuite;

public class ForkJoinTask8Test extends JSR166TestCase {

    /*
     * Testing notes: This differs from ForkJoinTaskTest mainly by
     * defining a version of BinaryAsyncAction that uses JDK8 task
     * tags for control state, thereby testing getForkJoinTaskTag,
     * setForkJoinTaskTag, and compareAndSetForkJoinTaskTag across
     * various contexts. Most of the test methods using it are
     * otherwise identical, but omitting retest of those dealing with
     * cancellation, which is not represented in this tag scheme.
     */

    static final short INITIAL_STATE = -1;
    static final short COMPLETE_STATE = 0;
    static final short EXCEPTION_STATE = 1;

    // android-note: Removed because the CTS runner does a bad job of
    // retrying tests that have suite() declarations.
    //
    // public static void main(String[] args) {
    //     main(suite(), args);
    // }
    // public static Test suite() {
    //     return new TestSuite(ForkJoinTask8Test.class);
    // }

    // Runs with "mainPool" use > 1 thread. singletonPool tests use 1
    static final int mainPoolSize =
        Math.max(2, Runtime.getRuntime().availableProcessors());

    private static ForkJoinPool mainPool() {
        return new ForkJoinPool(mainPoolSize);
    }

    private static ForkJoinPool singletonPool() {
        return new ForkJoinPool(1);
    }

    private static ForkJoinPool asyncSingletonPool() {
        return new ForkJoinPool(1,
                                ForkJoinPool.defaultForkJoinWorkerThreadFactory,
                                null, true);
    }

    // Compute fib naively and efficiently
    final int[] fib;
    {
        int[] fib = new int[10];
        fib[0] = 0;
        fib[1] = 1;
        for (int i = 2; i < fib.length; i++)
            fib[i] = fib[i - 1] + fib[i - 2];
        this.fib = fib;
    }

    private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) {
        try (PoolCleaner cleaner = cleaner(pool)) {
            assertFalse(a.isDone());
            assertFalse(a.isCompletedNormally());
            assertFalse(a.isCompletedAbnormally());
            assertFalse(a.isCancelled());
            assertNull(a.getException());
            assertNull(a.getRawResult());

            assertNull(pool.invoke(a));

            assertTrue(a.isDone());
            assertTrue(a.isCompletedNormally());
            assertFalse(a.isCompletedAbnormally());
            assertFalse(a.isCancelled());
            assertNull(a.getException());
            assertNull(a.getRawResult());
        }
    }

    void checkNotDone(ForkJoinTask a) {
        assertFalse(a.isDone());
        assertFalse(a.isCompletedNormally());
        assertFalse(a.isCompletedAbnormally());
        assertFalse(a.isCancelled());
        assertNull(a.getException());
        assertNull(a.getRawResult());
        if (a instanceof BinaryAsyncAction)
            assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == INITIAL_STATE);

        try {
            a.get(0L, SECONDS);
            shouldThrow();
        } catch (TimeoutException success) {
        } catch (Throwable fail) { threadUnexpectedException(fail); }
    }

    <T> void checkCompletedNormally(ForkJoinTask<T> a) {
        checkCompletedNormally(a, null);
    }

    <T> void checkCompletedNormally(ForkJoinTask<T> a, T expected) {
        assertTrue(a.isDone());
        assertFalse(a.isCancelled());
        assertTrue(a.isCompletedNormally());
        assertFalse(a.isCompletedAbnormally());
        assertNull(a.getException());
        assertSame(expected, a.getRawResult());
        if (a instanceof BinaryAsyncAction)
            assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == COMPLETE_STATE);

        {
            Thread.currentThread().interrupt();
            long startTime = System.nanoTime();
            assertSame(expected, a.join());
            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
            Thread.interrupted();
        }

        {
            Thread.currentThread().interrupt();
            long startTime = System.nanoTime();
            a.quietlyJoin();        // should be no-op
            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
            Thread.interrupted();
        }

        assertFalse(a.cancel(false));
        assertFalse(a.cancel(true));
        try {
            assertSame(expected, a.get());
        } catch (Throwable fail) { threadUnexpectedException(fail); }
        try {
            assertSame(expected, a.get(5L, SECONDS));
        } catch (Throwable fail) { threadUnexpectedException(fail); }
    }

    void checkCompletedAbnormally(ForkJoinTask a, Throwable t) {
        assertTrue(a.isDone());
        assertFalse(a.isCancelled());
        assertFalse(a.isCompletedNormally());
        assertTrue(a.isCompletedAbnormally());
        assertSame(t.getClass(), a.getException().getClass());
        assertNull(a.getRawResult());
        assertFalse(a.cancel(false));
        assertFalse(a.cancel(true));
        if (a instanceof BinaryAsyncAction)
            assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() != INITIAL_STATE);

        try {
            Thread.currentThread().interrupt();
            a.join();
            shouldThrow();
        } catch (Throwable expected) {
            assertSame(t.getClass(), expected.getClass());
        }
        Thread.interrupted();

        {
            long startTime = System.nanoTime();
            a.quietlyJoin();        // should be no-op
            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
        }

        try {
            a.get();
            shouldThrow();
        } catch (ExecutionException success) {
            assertSame(t.getClass(), success.getCause().getClass());
        } catch (Throwable fail) { threadUnexpectedException(fail); }

        try {
            a.get(5L, SECONDS);
            shouldThrow();
        } catch (ExecutionException success) {
            assertSame(t.getClass(), success.getCause().getClass());
        } catch (Throwable fail) { threadUnexpectedException(fail); }
    }

    public static final class FJException extends RuntimeException {
        FJException() { super(); }
    }

    abstract static class BinaryAsyncAction extends ForkJoinTask<Void> {

        private volatile BinaryAsyncAction parent;

        private volatile BinaryAsyncAction sibling;

        protected BinaryAsyncAction() {
            setForkJoinTaskTag(INITIAL_STATE);
        }

        public final Void getRawResult() { return null; }
        protected final void setRawResult(Void mustBeNull) { }

        public final void linkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
            x.parent = y.parent = this;
            x.sibling = y;
            y.sibling = x;
        }

        protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
            if (this.getForkJoinTaskTag() != COMPLETE_STATE ||
                x.getForkJoinTaskTag() != COMPLETE_STATE ||
                y.getForkJoinTaskTag() != COMPLETE_STATE) {
                completeThisExceptionally(new FJException());
            }
        }

        protected boolean onException() {
            return true;
        }

        public void linkAndForkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
            linkSubtasks(x, y);
            y.fork();
            x.fork();
        }

        private void completeThis() {
            setForkJoinTaskTag(COMPLETE_STATE);
            super.complete(null);
        }

        private void completeThisExceptionally(Throwable ex) {
            setForkJoinTaskTag(EXCEPTION_STATE);
            super.completeExceptionally(ex);
        }

        public boolean cancel(boolean mayInterruptIfRunning) {
            if (super.cancel(mayInterruptIfRunning)) {
                completeExceptionally(new FJException());
                return true;
            }
            return false;
        }

        public final void complete() {
            BinaryAsyncAction a = this;
            for (;;) {
                BinaryAsyncAction s = a.sibling;
                BinaryAsyncAction p = a.parent;
                a.sibling = null;
                a.parent = null;
                a.completeThis();
                if (p == null ||
                    p.compareAndSetForkJoinTaskTag(INITIAL_STATE, COMPLETE_STATE))
                    break;
                try {
                    p.onComplete(a, s);
                } catch (Throwable rex) {
                    p.completeExceptionally(rex);
                    return;
                }
                a = p;
            }
        }

        public final void completeExceptionally(Throwable ex) {
            for (BinaryAsyncAction a = this;;) {
                a.completeThisExceptionally(ex);
                BinaryAsyncAction s = a.sibling;
                if (s != null && !s.isDone())
                    s.completeExceptionally(ex);
                if ((a = a.parent) == null)
                    break;
            }
        }

        public final BinaryAsyncAction getParent() {
            return parent;
        }

        public BinaryAsyncAction getSibling() {
            return sibling;
        }

        public void reinitialize() {
            parent = sibling = null;
            super.reinitialize();
        }

    }

    final class AsyncFib extends BinaryAsyncAction {
        int number;
        int expectedResult;
        public AsyncFib(int number) {
            this.number = number;
            this.expectedResult = fib[number];
        }

        public final boolean exec() {
            try {
                AsyncFib f = this;
                int n = f.number;
                while (n > 1) {
                    AsyncFib p = f;
                    AsyncFib r = new AsyncFib(n - 2);
                    f = new AsyncFib(--n);
                    p.linkSubtasks(r, f);
                    r.fork();
                }
                f.complete();
            }
            catch (Throwable ex) {
                compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE);
            }
            if (getForkJoinTaskTag() == EXCEPTION_STATE)
                throw new FJException();
            return false;
        }

        protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
            number = ((AsyncFib)x).number + ((AsyncFib)y).number;
            super.onComplete(x, y);
        }

        public void checkCompletedNormally() {
            assertEquals(expectedResult, number);
            ForkJoinTask8Test.this.checkCompletedNormally(this);
        }
    }

    static final class FailingAsyncFib extends BinaryAsyncAction {
        int number;
        public FailingAsyncFib(int n) {
            this.number = n;
        }

        public final boolean exec() {
            try {
                FailingAsyncFib f = this;
                int n = f.number;
                while (n > 1) {
                    FailingAsyncFib p = f;
                    FailingAsyncFib r = new FailingAsyncFib(n - 2);
                    f = new FailingAsyncFib(--n);
                    p.linkSubtasks(r, f);
                    r.fork();
                }
                f.complete();
            }
            catch (Throwable ex) {
                compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE);
            }
            if (getForkJoinTaskTag() == EXCEPTION_STATE)
                throw new FJException();
            return false;
        }

        protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
            completeExceptionally(new FJException());
        }
    }

    /**
     * invoke returns when task completes normally.
     * isCompletedAbnormally and isCancelled return false for normally
     * completed tasks; getRawResult returns null.
     */
    public void testInvoke() {
        testInvoke(mainPool());
    }
    public void testInvoke_Singleton() {
        testInvoke(singletonPool());
    }
    public void testInvoke(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib f = new AsyncFib(8);
                assertNull(f.invoke());
                f.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * quietlyInvoke task returns when task completes normally.
     * isCompletedAbnormally and isCancelled return false for normally
     * completed tasks
     */
    public void testQuietlyInvoke() {
        testQuietlyInvoke(mainPool());
    }
    public void testQuietlyInvoke_Singleton() {
        testQuietlyInvoke(singletonPool());
    }
    public void testQuietlyInvoke(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib f = new AsyncFib(8);
                f.quietlyInvoke();
                f.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * join of a forked task returns when task completes
     */
    public void testForkJoin() {
        testForkJoin(mainPool());
    }
    public void testForkJoin_Singleton() {
        testForkJoin(singletonPool());
    }
    public void testForkJoin(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertNull(f.join());
                f.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * get of a forked task returns when task completes
     */
    public void testForkGet() {
        testForkGet(mainPool());
    }
    public void testForkGet_Singleton() {
        testForkGet(singletonPool());
    }
    public void testForkGet(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() throws Exception {
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertNull(f.get());
                f.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * timed get of a forked task returns when task completes
     */
    public void testForkTimedGet() {
        testForkTimedGet(mainPool());
    }
    public void testForkTimedGet_Singleton() {
        testForkTimedGet(singletonPool());
    }
    public void testForkTimedGet(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() throws Exception {
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
                f.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * timed get with null time unit throws NullPointerException
     */
    public void testForkTimedGetNullTimeUnit() {
        testForkTimedGetNullTimeUnit(mainPool());
    }
    public void testForkTimedGetNullTimeUnit_Singleton() {
        testForkTimedGet(singletonPool());
    }
    public void testForkTimedGetNullTimeUnit(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() throws Exception {
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                try {
                    f.get(5L, null);
                    shouldThrow();
                } catch (NullPointerException success) {}
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * quietlyJoin of a forked task returns when task completes
     */
    public void testForkQuietlyJoin() {
        testForkQuietlyJoin(mainPool());
    }
    public void testForkQuietlyJoin_Singleton() {
        testForkQuietlyJoin(singletonPool());
    }
    public void testForkQuietlyJoin(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                f.quietlyJoin();
                f.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * helpQuiesce returns when tasks are complete.
     * getQueuedTaskCount returns 0 when quiescent
     */
    public void testForkHelpQuiesce() {
        testForkHelpQuiesce(mainPool());
    }
    public void testForkHelpQuiesce_Singleton() {
        testForkHelpQuiesce(singletonPool());
    }
    public void testForkHelpQuiesce(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                helpQuiesce();
                assertEquals(0, getQueuedTaskCount());
                f.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invoke task throws exception when task completes abnormally
     */
    public void testAbnormalInvoke() {
        testAbnormalInvoke(mainPool());
    }
    public void testAbnormalInvoke_Singleton() {
        testAbnormalInvoke(singletonPool());
    }
    public void testAbnormalInvoke(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                FailingAsyncFib f = new FailingAsyncFib(8);
                try {
                    f.invoke();
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(f, success);
                }
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * quietlyInvoke task returns when task completes abnormally
     */
    public void testAbnormalQuietlyInvoke() {
        testAbnormalQuietlyInvoke(mainPool());
    }
    public void testAbnormalQuietlyInvoke_Singleton() {
        testAbnormalQuietlyInvoke(singletonPool());
    }
    public void testAbnormalQuietlyInvoke(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                FailingAsyncFib f = new FailingAsyncFib(8);
                f.quietlyInvoke();
                assertTrue(f.getException() instanceof FJException);
                checkCompletedAbnormally(f, f.getException());
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * join of a forked task throws exception when task completes abnormally
     */
    public void testAbnormalForkJoin() {
        testAbnormalForkJoin(mainPool());
    }
    public void testAbnormalForkJoin_Singleton() {
        testAbnormalForkJoin(singletonPool());
    }
    public void testAbnormalForkJoin(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                FailingAsyncFib f = new FailingAsyncFib(8);
                assertSame(f, f.fork());
                try {
                    f.join();
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(f, success);
                }
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * get of a forked task throws exception when task completes abnormally
     */
    public void testAbnormalForkGet() {
        testAbnormalForkGet(mainPool());
    }
    public void testAbnormalForkGet_Singleton() {
        testAbnormalForkJoin(singletonPool());
    }
    public void testAbnormalForkGet(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() throws Exception {
                FailingAsyncFib f = new FailingAsyncFib(8);
                assertSame(f, f.fork());
                try {
                    f.get();
                    shouldThrow();
                } catch (ExecutionException success) {
                    Throwable cause = success.getCause();
                    assertTrue(cause instanceof FJException);
                    checkCompletedAbnormally(f, cause);
                }
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * timed get of a forked task throws exception when task completes abnormally
     */
    public void testAbnormalForkTimedGet() {
        testAbnormalForkTimedGet(mainPool());
    }
    public void testAbnormalForkTimedGet_Singleton() {
        testAbnormalForkTimedGet(singletonPool());
    }
    public void testAbnormalForkTimedGet(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() throws Exception {
                FailingAsyncFib f = new FailingAsyncFib(8);
                assertSame(f, f.fork());
                try {
                    f.get(LONG_DELAY_MS, MILLISECONDS);
                    shouldThrow();
                } catch (ExecutionException success) {
                    Throwable cause = success.getCause();
                    assertTrue(cause instanceof FJException);
                    checkCompletedAbnormally(f, cause);
                }
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * quietlyJoin of a forked task returns when task completes abnormally
     */
    public void testAbnormalForkQuietlyJoin() {
        testAbnormalForkQuietlyJoin(mainPool());
    }
    public void testAbnormalForkQuietlyJoin_Singleton() {
        testAbnormalForkQuietlyJoin(singletonPool());
    }
    public void testAbnormalForkQuietlyJoin(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                FailingAsyncFib f = new FailingAsyncFib(8);
                assertSame(f, f.fork());
                f.quietlyJoin();
                assertTrue(f.getException() instanceof FJException);
                checkCompletedAbnormally(f, f.getException());
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * getPool of executing task returns its pool
     */
    public void testGetPool() {
        testGetPool(mainPool());
    }
    public void testGetPool_Singleton() {
        testGetPool(singletonPool());
    }
    public void testGetPool(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                assertSame(pool, getPool());
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * getPool of non-FJ task returns null
     */
    public void testGetPool2() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                assertNull(getPool());
            }};
        assertNull(a.invoke());
    }

    /**
     * inForkJoinPool of executing task returns true
     */
    public void testInForkJoinPool() {
        testInForkJoinPool(mainPool());
    }
    public void testInForkJoinPool_Singleton() {
        testInForkJoinPool(singletonPool());
    }
    public void testInForkJoinPool(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                assertTrue(inForkJoinPool());
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * inForkJoinPool of non-FJ task returns false
     */
    public void testInForkJoinPool2() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                assertFalse(inForkJoinPool());
            }};
        assertNull(a.invoke());
    }

    /**
     * setRawResult(null) succeeds
     */
    public void testSetRawResult() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                setRawResult(null);
                assertNull(getRawResult());
            }};
        assertNull(a.invoke());
    }

    /**
     * invoke task throws exception after invoking completeExceptionally
     */
    public void testCompleteExceptionally() {
        testCompleteExceptionally(mainPool());
    }
    public void testCompleteExceptionally_Singleton() {
        testCompleteExceptionally(singletonPool());
    }
    public void testCompleteExceptionally(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib f = new AsyncFib(8);
                f.completeExceptionally(new FJException());
                try {
                    f.invoke();
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(f, success);
                }
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invokeAll(tasks) with 1 argument invokes task
     */
    public void testInvokeAll1() {
        testInvokeAll1(mainPool());
    }
    public void testInvokeAll1_Singleton() {
        testInvokeAll1(singletonPool());
    }
    public void testInvokeAll1(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib f = new AsyncFib(8);
                invokeAll(f);
                f.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invokeAll(t1, t2) invokes all task arguments
     */
    public void testInvokeAll2() {
        testInvokeAll2(mainPool());
    }
    public void testInvokeAll2_Singleton() {
        testInvokeAll2(singletonPool());
    }
    public void testInvokeAll2(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib[] tasks = {
                    new AsyncFib(8),
                    new AsyncFib(9),
                };
                invokeAll(tasks[0], tasks[1]);
                for (AsyncFib task : tasks) assertTrue(task.isDone());
                for (AsyncFib task : tasks) task.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invokeAll(tasks) with > 2 argument invokes tasks
     */
    public void testInvokeAll3() {
        testInvokeAll3(mainPool());
    }
    public void testInvokeAll3_Singleton() {
        testInvokeAll3(singletonPool());
    }
    public void testInvokeAll3(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib[] tasks = {
                    new AsyncFib(8),
                    new AsyncFib(9),
                    new AsyncFib(7),
                };
                invokeAll(tasks[0], tasks[1], tasks[2]);
                for (AsyncFib task : tasks) assertTrue(task.isDone());
                for (AsyncFib task : tasks) task.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invokeAll(collection) invokes all tasks in the collection
     */
    public void testInvokeAllCollection() {
        testInvokeAllCollection(mainPool());
    }
    public void testInvokeAllCollection_Singleton() {
        testInvokeAllCollection(singletonPool());
    }
    public void testInvokeAllCollection(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib[] tasks = {
                    new AsyncFib(8),
                    new AsyncFib(9),
                    new AsyncFib(7),
                };
                invokeAll(Arrays.asList(tasks));
                for (AsyncFib task : tasks) assertTrue(task.isDone());
                for (AsyncFib task : tasks) task.checkCompletedNormally();
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invokeAll(tasks) with any null task throws NullPointerException
     */
    public void testInvokeAllNullTask() {
        testInvokeAllNullTask(mainPool());
    }
    public void testInvokeAllNullTask_Singleton() {
        testInvokeAllNullTask(singletonPool());
    }
    public void testInvokeAllNullTask(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib nul = null;
                Runnable[] throwingActions = {
                    () -> invokeAll(nul),
                    () -> invokeAll(nul, nul),
                    () -> invokeAll(new AsyncFib(8), new AsyncFib(9), nul),
                    () -> invokeAll(new AsyncFib(8), nul, new AsyncFib(9)),
                    () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)),
                };
                assertThrows(NullPointerException.class, throwingActions);
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invokeAll(tasks) with 1 argument throws exception if task does
     */
    public void testAbnormalInvokeAll1() {
        testAbnormalInvokeAll1(mainPool());
    }
    public void testAbnormalInvokeAll1_Singleton() {
        testAbnormalInvokeAll1(singletonPool());
    }
    public void testAbnormalInvokeAll1(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                FailingAsyncFib g = new FailingAsyncFib(9);
                try {
                    invokeAll(g);
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(g, success);
                }
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invokeAll(t1, t2) throw exception if any task does
     */
    public void testAbnormalInvokeAll2() {
        testAbnormalInvokeAll2(mainPool());
    }
    public void testAbnormalInvokeAll2_Singleton() {
        testAbnormalInvokeAll2(singletonPool());
    }
    public void testAbnormalInvokeAll2(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib f = new AsyncFib(8);
                FailingAsyncFib g = new FailingAsyncFib(9);
                ForkJoinTask[] tasks = { f, g };
                Collections.shuffle(Arrays.asList(tasks));
                try {
                    invokeAll(tasks[0], tasks[1]);
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(g, success);
                }
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invokeAll(tasks) with > 2 argument throws exception if any task does
     */
    public void testAbnormalInvokeAll3() {
        testAbnormalInvokeAll3(mainPool());
    }
    public void testAbnormalInvokeAll3_Singleton() {
        testAbnormalInvokeAll3(singletonPool());
    }
    public void testAbnormalInvokeAll3(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib f = new AsyncFib(8);
                FailingAsyncFib g = new FailingAsyncFib(9);
                AsyncFib h = new AsyncFib(7);
                ForkJoinTask[] tasks = { f, g, h };
                Collections.shuffle(Arrays.asList(tasks));
                try {
                    invokeAll(tasks[0], tasks[1], tasks[2]);
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(g, success);
                }
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * invokeAll(collection) throws exception if any task does
     */
    public void testAbnormalInvokeAllCollection() {
        testAbnormalInvokeAllCollection(mainPool());
    }
    public void testAbnormalInvokeAllCollection_Singleton() {
        testAbnormalInvokeAllCollection(singletonPool());
    }
    public void testAbnormalInvokeAllCollection(ForkJoinPool pool) {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                FailingAsyncFib f = new FailingAsyncFib(8);
                AsyncFib g = new AsyncFib(9);
                AsyncFib h = new AsyncFib(7);
                ForkJoinTask[] tasks = { f, g, h };
                Collections.shuffle(Arrays.asList(tasks));
                try {
                    invokeAll(Arrays.asList(tasks));
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(f, success);
                }
            }};
        testInvokeOnPool(pool, a);
    }

    /**
     * tryUnfork returns true for most recent unexecuted task,
     * and suppresses execution
     */
    public void testTryUnfork() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib g = new AsyncFib(9);
                assertSame(g, g.fork());
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertTrue(f.tryUnfork());
                helpQuiesce();
                checkNotDone(f);
                g.checkCompletedNormally();
            }};
        testInvokeOnPool(singletonPool(), a);
    }

    /**
     * getSurplusQueuedTaskCount returns > 0 when
     * there are more tasks than threads
     */
    public void testGetSurplusQueuedTaskCount() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib h = new AsyncFib(7);
                assertSame(h, h.fork());
                AsyncFib g = new AsyncFib(9);
                assertSame(g, g.fork());
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertTrue(getSurplusQueuedTaskCount() > 0);
                helpQuiesce();
                assertEquals(0, getSurplusQueuedTaskCount());
                f.checkCompletedNormally();
                g.checkCompletedNormally();
                h.checkCompletedNormally();
            }};
        testInvokeOnPool(singletonPool(), a);
    }

    /**
     * peekNextLocalTask returns most recent unexecuted task.
     */
    public void testPeekNextLocalTask() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib g = new AsyncFib(9);
                assertSame(g, g.fork());
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertSame(f, peekNextLocalTask());
                assertNull(f.join());
                f.checkCompletedNormally();
                helpQuiesce();
                g.checkCompletedNormally();
            }};
        testInvokeOnPool(singletonPool(), a);
    }

    /**
     * pollNextLocalTask returns most recent unexecuted task without
     * executing it
     */
    public void testPollNextLocalTask() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib g = new AsyncFib(9);
                assertSame(g, g.fork());
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertSame(f, pollNextLocalTask());
                helpQuiesce();
                checkNotDone(f);
                g.checkCompletedNormally();
            }};
        testInvokeOnPool(singletonPool(), a);
    }

    /**
     * pollTask returns an unexecuted task without executing it
     */
    public void testPollTask() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib g = new AsyncFib(9);
                assertSame(g, g.fork());
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertSame(f, pollTask());
                helpQuiesce();
                checkNotDone(f);
                g.checkCompletedNormally();
            }};
        testInvokeOnPool(singletonPool(), a);
    }

    /**
     * peekNextLocalTask returns least recent unexecuted task in async mode
     */
    public void testPeekNextLocalTaskAsync() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib g = new AsyncFib(9);
                assertSame(g, g.fork());
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertSame(g, peekNextLocalTask());
                assertNull(f.join());
                helpQuiesce();
                f.checkCompletedNormally();
                g.checkCompletedNormally();
            }};
        testInvokeOnPool(asyncSingletonPool(), a);
    }

    /**
     * pollNextLocalTask returns least recent unexecuted task without
     * executing it, in async mode
     */
    public void testPollNextLocalTaskAsync() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib g = new AsyncFib(9);
                assertSame(g, g.fork());
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertSame(g, pollNextLocalTask());
                helpQuiesce();
                f.checkCompletedNormally();
                checkNotDone(g);
            }};
        testInvokeOnPool(asyncSingletonPool(), a);
    }

    /**
     * pollTask returns an unexecuted task without executing it, in
     * async mode
     */
    public void testPollTaskAsync() {
        RecursiveAction a = new CheckedRecursiveAction() {
            protected void realCompute() {
                AsyncFib g = new AsyncFib(9);
                assertSame(g, g.fork());
                AsyncFib f = new AsyncFib(8);
                assertSame(f, f.fork());
                assertSame(g, pollTask());
                helpQuiesce();
                f.checkCompletedNormally();
                checkNotDone(g);
            }};
        testInvokeOnPool(asyncSingletonPool(), a);
    }

    /**
     * ForkJoinTask.quietlyComplete returns when task completes
     * normally without setting a value. The most recent value
     * established by setRawResult(V) (or null by default) is returned
     * from invoke.
     */
    public void testQuietlyComplete() {
        RecursiveAction a = new CheckedRecursiveAction() {
                protected void realCompute() {
                    AsyncFib f = new AsyncFib(8);
                    f.quietlyComplete();
                    assertEquals(8, f.number);
                    assertTrue(f.isDone());
                    assertFalse(f.isCancelled());
                    assertTrue(f.isCompletedNormally());
                    assertFalse(f.isCompletedAbnormally());
                    assertNull(f.getException());
                }};
        testInvokeOnPool(mainPool(), a);
    }

    // jdk9

    /**
     * pollSubmission returns unexecuted submitted task, if present
     */
    public void testPollSubmission() {
        final CountDownLatch done = new CountDownLatch(1);
        final ForkJoinTask a = ForkJoinTask.adapt(awaiter(done));
        final ForkJoinTask b = ForkJoinTask.adapt(awaiter(done));
        final ForkJoinTask c = ForkJoinTask.adapt(awaiter(done));
        final ForkJoinPool p = singletonPool();
        try (PoolCleaner cleaner = cleaner(p, done)) {
            Thread external = new Thread(new CheckedRunnable() {
                public void realRun() {
                    p.execute(a);
                    p.execute(b);
                    p.execute(c);
                }});
            RecursiveAction s = new CheckedRecursiveAction() {
                protected void realCompute() {
                    external.start();
                    try {
                        external.join();
                    } catch (Exception ex) {
                        threadUnexpectedException(ex);
                    }
                    assertTrue(p.hasQueuedSubmissions());
                    assertTrue(Thread.currentThread() instanceof ForkJoinWorkerThread);
                    ForkJoinTask r = ForkJoinTask.pollSubmission();
                    assertTrue(r == a || r == b || r == c);
                    assertFalse(r.isDone());
                }};
            p.invoke(s);
        }
    }

}
