/*
 * 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.SECONDS;

import java.util.HashSet;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeoutException;

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

public class RecursiveTaskTest extends JSR166TestCase {

    // 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(...);
    // }

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

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

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

    private <T> T testInvokeOnPool(ForkJoinPool pool, RecursiveTask<T> a) {
        try {
            checkNotDone(a);

            T result = pool.invoke(a);

            checkCompletedNormally(a, result);
            return result;
        } finally {
            joinPool(pool);
        }
    }

    void checkNotDone(RecursiveTask a) {
        assertFalse(a.isDone());
        assertFalse(a.isCompletedNormally());
        assertFalse(a.isCompletedAbnormally());
        assertFalse(a.isCancelled());
        assertNull(a.getException());
        assertNull(a.getRawResult());

        if (! ForkJoinTask.inForkJoinPool()) {
            Thread.currentThread().interrupt();
            try {
                a.get();
                shouldThrow();
            } catch (InterruptedException success) {
            } catch (Throwable fail) { threadUnexpectedException(fail); }

            Thread.currentThread().interrupt();
            try {
                a.get(5L, SECONDS);
                shouldThrow();
            } catch (InterruptedException success) {
            } catch (Throwable fail) { threadUnexpectedException(fail); }
        }

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

    <T> void checkCompletedNormally(RecursiveTask<T> a, T expected) {
        assertTrue(a.isDone());
        assertFalse(a.isCancelled());
        assertTrue(a.isCompletedNormally());
        assertFalse(a.isCompletedAbnormally());
        assertNull(a.getException());
        assertSame(expected, a.getRawResult());
        assertSame(expected, a.join());
        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); }
    }

    /**
     * Waits for the task to complete, and checks that when it does,
     * it will have an Integer result equals to the given int.
     */
    void checkCompletesNormally(RecursiveTask<Integer> a, int expected) {
        Integer r = a.join();
        assertEquals(expected, (int) r);
        checkCompletedNormally(a, r);
    }

    /**
     * Like checkCompletesNormally, but verifies that the task has
     * already completed.
     */
    void checkCompletedNormally(RecursiveTask<Integer> a, int expected) {
        Integer r = a.getRawResult();
        assertEquals(expected, (int) r);
        checkCompletedNormally(a, r);
    }

    void checkCancelled(RecursiveTask a) {
        assertTrue(a.isDone());
        assertTrue(a.isCancelled());
        assertFalse(a.isCompletedNormally());
        assertTrue(a.isCompletedAbnormally());
        assertTrue(a.getException() instanceof CancellationException);
        assertNull(a.getRawResult());

        try {
            a.join();
            shouldThrow();
        } catch (CancellationException success) {
        } catch (Throwable fail) { threadUnexpectedException(fail); }

        try {
            a.get();
            shouldThrow();
        } catch (CancellationException success) {
        } catch (Throwable fail) { threadUnexpectedException(fail); }

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

    void checkCompletedAbnormally(RecursiveTask 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));

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

        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 {
        public FJException() { super(); }
    }

    // An invalid return value for Fib
    static final Integer NoResult = Integer.valueOf(-17);

    // A simple recursive task for testing
    final class FibTask extends CheckedRecursiveTask<Integer> {
        final int number;
        FibTask(int n) { number = n; }
        public Integer realCompute() {
            int n = number;
            if (n <= 1)
                return n;
            FibTask f1 = new FibTask(n - 1);
            f1.fork();
            return (new FibTask(n - 2)).compute() + f1.join();
        }

        public void publicSetRawResult(Integer result) {
            setRawResult(result);
        }
    }

    // A recursive action failing in base case
    final class FailingFibTask extends RecursiveTask<Integer> {
        final int number;
        int result;
        FailingFibTask(int n) { number = n; }
        public Integer compute() {
            int n = number;
            if (n <= 1)
                throw new FJException();
            FailingFibTask f1 = new FailingFibTask(n - 1);
            f1.fork();
            return (new FibTask(n - 2)).compute() + f1.join();
        }
    }

    /**
     * invoke returns value when task completes normally.
     * isCompletedAbnormally and isCancelled return false for normally
     * completed tasks. getRawResult of a completed non-null task
     * returns value;
     */
    public void testInvoke() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                Integer r = f.invoke();
                assertEquals(21, (int) r);
                checkCompletedNormally(f, r);
                return r;
            }};
        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
    }

    /**
     * quietlyInvoke task returns when task completes normally.
     * isCompletedAbnormally and isCancelled return false for normally
     * completed tasks
     */
    public void testQuietlyInvoke() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                f.quietlyInvoke();
                checkCompletedNormally(f, 21);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * join of a forked task returns when task completes
     */
    public void testForkJoin() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                Integer r = f.join();
                assertEquals(21, (int) r);
                checkCompletedNormally(f, r);
                return r;
            }};
        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
    }

    /**
     * get of a forked task returns when task completes
     */
    public void testForkGet() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() throws Exception {
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                Integer r = f.get();
                assertEquals(21, (int) r);
                checkCompletedNormally(f, r);
                return r;
            }};
        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
    }

    /**
     * timed get of a forked task returns when task completes
     */
    public void testForkTimedGet() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() throws Exception {
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                Integer r = f.get(5L, SECONDS);
                assertEquals(21, (int) r);
                checkCompletedNormally(f, r);
                return r;
            }};
        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
    }

    /**
     * quietlyJoin of a forked task returns when task completes
     */
    public void testForkQuietlyJoin() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                f.quietlyJoin();
                Integer r = f.getRawResult();
                assertEquals(21, (int) r);
                checkCompletedNormally(f, r);
                return r;
            }};
        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
    }

    /**
     * helpQuiesce returns when tasks are complete.
     * getQueuedTaskCount returns 0 when quiescent
     */
    public void testForkHelpQuiesce() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                helpQuiesce();
                assertEquals(0, getQueuedTaskCount());
                checkCompletedNormally(f, 21);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invoke task throws exception when task completes abnormally
     */
    public void testAbnormalInvoke() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FailingFibTask f = new FailingFibTask(8);
                try {
                    f.invoke();
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(f, success);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * quietlyInvoke task returns when task completes abnormally
     */
    public void testAbnormalQuietlyInvoke() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FailingFibTask f = new FailingFibTask(8);
                f.quietlyInvoke();
                assertTrue(f.getException() instanceof FJException);
                checkCompletedAbnormally(f, f.getException());
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * join of a forked task throws exception when task completes abnormally
     */
    public void testAbnormalForkJoin() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FailingFibTask f = new FailingFibTask(8);
                assertSame(f, f.fork());
                try {
                    Integer r = f.join();
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(f, success);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * get of a forked task throws exception when task completes abnormally
     */
    public void testAbnormalForkGet() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() throws Exception {
                FailingFibTask f = new FailingFibTask(8);
                assertSame(f, f.fork());
                try {
                    Integer r = f.get();
                    shouldThrow();
                } catch (ExecutionException success) {
                    Throwable cause = success.getCause();
                    assertTrue(cause instanceof FJException);
                    checkCompletedAbnormally(f, cause);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * timed get of a forked task throws exception when task completes abnormally
     */
    public void testAbnormalForkTimedGet() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() throws Exception {
                FailingFibTask f = new FailingFibTask(8);
                assertSame(f, f.fork());
                try {
                    Integer r = f.get(5L, SECONDS);
                    shouldThrow();
                } catch (ExecutionException success) {
                    Throwable cause = success.getCause();
                    assertTrue(cause instanceof FJException);
                    checkCompletedAbnormally(f, cause);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * quietlyJoin of a forked task returns when task completes abnormally
     */
    public void testAbnormalForkQuietlyJoin() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FailingFibTask f = new FailingFibTask(8);
                assertSame(f, f.fork());
                f.quietlyJoin();
                assertTrue(f.getException() instanceof FJException);
                checkCompletedAbnormally(f, f.getException());
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invoke task throws exception when task cancelled
     */
    public void testCancelledInvoke() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                assertTrue(f.cancel(true));
                try {
                    Integer r = f.invoke();
                    shouldThrow();
                } catch (CancellationException success) {
                    checkCancelled(f);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * join of a forked task throws exception when task cancelled
     */
    public void testCancelledForkJoin() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                assertTrue(f.cancel(true));
                assertSame(f, f.fork());
                try {
                    Integer r = f.join();
                    shouldThrow();
                } catch (CancellationException success) {
                    checkCancelled(f);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * get of a forked task throws exception when task cancelled
     */
    public void testCancelledForkGet() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() throws Exception {
                FibTask f = new FibTask(8);
                assertTrue(f.cancel(true));
                assertSame(f, f.fork());
                try {
                    Integer r = f.get();
                    shouldThrow();
                } catch (CancellationException success) {
                    checkCancelled(f);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * timed get of a forked task throws exception when task cancelled
     */
    public void testCancelledForkTimedGet() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() throws Exception {
                FibTask f = new FibTask(8);
                assertTrue(f.cancel(true));
                assertSame(f, f.fork());
                try {
                    Integer r = f.get(5L, SECONDS);
                    shouldThrow();
                } catch (CancellationException success) {
                    checkCancelled(f);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * quietlyJoin of a forked task returns when task cancelled
     */
    public void testCancelledForkQuietlyJoin() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                assertTrue(f.cancel(true));
                assertSame(f, f.fork());
                f.quietlyJoin();
                checkCancelled(f);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * getPool of executing task returns its pool
     */
    public void testGetPool() {
        final ForkJoinPool mainPool = mainPool();
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                assertSame(mainPool, getPool());
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool, a));
    }

    /**
     * getPool of non-FJ task returns null
     */
    public void testGetPool2() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                assertNull(getPool());
                return NoResult;
            }};
        assertSame(NoResult, a.invoke());
    }

    /**
     * inForkJoinPool of executing task returns true
     */
    public void testInForkJoinPool() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                assertTrue(inForkJoinPool());
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * inForkJoinPool of non-FJ task returns false
     */
    public void testInForkJoinPool2() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                assertFalse(inForkJoinPool());
                return NoResult;
            }};
        assertSame(NoResult, a.invoke());
    }

    /**
     * The value set by setRawResult is returned by getRawResult
     */
    public void testSetRawResult() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                setRawResult(NoResult);
                assertSame(NoResult, getRawResult());
                return NoResult;
            }
        };
        assertSame(NoResult, a.invoke());
    }

    /**
     * A reinitialized normally completed task may be re-invoked
     */
    public void testReinitialize() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                checkNotDone(f);

                for (int i = 0; i < 3; i++) {
                    Integer r = f.invoke();
                    assertEquals(21, (int) r);
                    checkCompletedNormally(f, r);
                    f.reinitialize();
                    f.publicSetRawResult(null);
                    checkNotDone(f);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * A reinitialized abnormally completed task may be re-invoked
     */
    public void testReinitializeAbnormal() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FailingFibTask f = new FailingFibTask(8);
                checkNotDone(f);

                for (int i = 0; i < 3; i++) {
                    try {
                        f.invoke();
                        shouldThrow();
                    } catch (FJException success) {
                        checkCompletedAbnormally(f, success);
                    }
                    f.reinitialize();
                    checkNotDone(f);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invoke task throws exception after invoking completeExceptionally
     */
    public void testCompleteExceptionally() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                f.completeExceptionally(new FJException());
                try {
                    Integer r = f.invoke();
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(f, success);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invoke task suppresses execution invoking complete
     */
    public void testComplete() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                f.complete(NoResult);
                Integer r = f.invoke();
                assertSame(NoResult, r);
                checkCompletedNormally(f, NoResult);
                return r;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invokeAll(t1, t2) invokes all task arguments
     */
    public void testInvokeAll2() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                FibTask g = new FibTask(9);
                invokeAll(f, g);
                checkCompletedNormally(f, 21);
                checkCompletedNormally(g, 34);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invokeAll(tasks) with 1 argument invokes task
     */
    public void testInvokeAll1() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                invokeAll(f);
                checkCompletedNormally(f, 21);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invokeAll(tasks) with > 2 argument invokes tasks
     */
    public void testInvokeAll3() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                FibTask g = new FibTask(9);
                FibTask h = new FibTask(7);
                invokeAll(f, g, h);
                assertTrue(f.isDone());
                assertTrue(g.isDone());
                assertTrue(h.isDone());
                checkCompletedNormally(f, 21);
                checkCompletedNormally(g, 34);
                checkCompletedNormally(h, 13);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invokeAll(collection) invokes all tasks in the collection
     */
    public void testInvokeAllCollection() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                FibTask g = new FibTask(9);
                FibTask h = new FibTask(7);
                HashSet set = new HashSet();
                set.add(f);
                set.add(g);
                set.add(h);
                invokeAll(set);
                assertTrue(f.isDone());
                assertTrue(g.isDone());
                assertTrue(h.isDone());
                checkCompletedNormally(f, 21);
                checkCompletedNormally(g, 34);
                checkCompletedNormally(h, 13);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invokeAll(tasks) with any null task throws NPE
     */
    public void testInvokeAllNPE() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                FibTask g = new FibTask(9);
                FibTask h = null;
                try {
                    invokeAll(f, g, h);
                    shouldThrow();
                } catch (NullPointerException success) {}
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invokeAll(t1, t2) throw exception if any task does
     */
    public void testAbnormalInvokeAll2() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                FailingFibTask g = new FailingFibTask(9);
                try {
                    invokeAll(f, g);
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(g, success);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invokeAll(tasks) with 1 argument throws exception if task does
     */
    public void testAbnormalInvokeAll1() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FailingFibTask g = new FailingFibTask(9);
                try {
                    invokeAll(g);
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(g, success);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invokeAll(tasks) with > 2 argument throws exception if any task does
     */
    public void testAbnormalInvokeAll3() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask f = new FibTask(8);
                FailingFibTask g = new FailingFibTask(9);
                FibTask h = new FibTask(7);
                try {
                    invokeAll(f, g, h);
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(g, success);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * invokeAll(collection) throws exception if any task does
     */
    public void testAbnormalInvokeAllCollection() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FailingFibTask f = new FailingFibTask(8);
                FibTask g = new FibTask(9);
                FibTask h = new FibTask(7);
                HashSet set = new HashSet();
                set.add(f);
                set.add(g);
                set.add(h);
                try {
                    invokeAll(set);
                    shouldThrow();
                } catch (FJException success) {
                    checkCompletedAbnormally(f, success);
                }
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
    }

    /**
     * tryUnfork returns true for most recent unexecuted task,
     * and suppresses execution
     */
    public void testTryUnfork() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask g = new FibTask(9);
                assertSame(g, g.fork());
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                assertTrue(f.tryUnfork());
                helpQuiesce();
                checkNotDone(f);
                checkCompletedNormally(g, 34);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
    }

    /**
     * getSurplusQueuedTaskCount returns > 0 when
     * there are more tasks than threads
     */
    public void testGetSurplusQueuedTaskCount() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask h = new FibTask(7);
                assertSame(h, h.fork());
                FibTask g = new FibTask(9);
                assertSame(g, g.fork());
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                assertTrue(getSurplusQueuedTaskCount() > 0);
                helpQuiesce();
                assertEquals(0, getSurplusQueuedTaskCount());
                checkCompletedNormally(f, 21);
                checkCompletedNormally(g, 34);
                checkCompletedNormally(h, 13);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
    }

    /**
     * peekNextLocalTask returns most recent unexecuted task.
     */
    public void testPeekNextLocalTask() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask g = new FibTask(9);
                assertSame(g, g.fork());
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                assertSame(f, peekNextLocalTask());
                checkCompletesNormally(f, 21);
                helpQuiesce();
                checkCompletedNormally(g, 34);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
    }

    /**
     * pollNextLocalTask returns most recent unexecuted task
     * without executing it
     */
    public void testPollNextLocalTask() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask g = new FibTask(9);
                assertSame(g, g.fork());
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                assertSame(f, pollNextLocalTask());
                helpQuiesce();
                checkNotDone(f);
                checkCompletedNormally(g, 34);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
    }

    /**
     * pollTask returns an unexecuted task without executing it
     */
    public void testPollTask() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask g = new FibTask(9);
                assertSame(g, g.fork());
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                assertSame(f, pollTask());
                helpQuiesce();
                checkNotDone(f);
                checkCompletedNormally(g, 34);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
    }

    /**
     * peekNextLocalTask returns least recent unexecuted task in async mode
     */
    public void testPeekNextLocalTaskAsync() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask g = new FibTask(9);
                assertSame(g, g.fork());
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                assertSame(g, peekNextLocalTask());
                assertEquals(21, (int) f.join());
                helpQuiesce();
                checkCompletedNormally(f, 21);
                checkCompletedNormally(g, 34);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
    }

    /**
     * pollNextLocalTask returns least recent unexecuted task without
     * executing it, in async mode
     */
    public void testPollNextLocalTaskAsync() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask g = new FibTask(9);
                assertSame(g, g.fork());
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                assertSame(g, pollNextLocalTask());
                helpQuiesce();
                checkCompletedNormally(f, 21);
                checkNotDone(g);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
    }

    /**
     * pollTask returns an unexecuted task without executing it, in
     * async mode
     */
    public void testPollTaskAsync() {
        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
            public Integer realCompute() {
                FibTask g = new FibTask(9);
                assertSame(g, g.fork());
                FibTask f = new FibTask(8);
                assertSame(f, f.fork());
                assertSame(g, pollTask());
                helpQuiesce();
                checkCompletedNormally(f, 21);
                checkNotDone(g);
                return NoResult;
            }};
        assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
    }

}
