/*
 * Written by Doug Lea and Martin Buchholz 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 static java.util.concurrent.CompletableFuture.completedFuture;
import static java.util.concurrent.CompletableFuture.failedFuture;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import java.util.stream.Collectors;
import java.util.stream.Stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

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

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

    static class CFException extends RuntimeException {}

    void checkIncomplete(CompletableFuture<?> f) {
        assertFalse(f.isDone());
        assertFalse(f.isCancelled());
        assertTrue(f.toString().contains("Not completed"));
        try {
            assertNull(f.getNow(null));
        } catch (Throwable fail) { threadUnexpectedException(fail); }
        try {
            f.get(0L, SECONDS);
            shouldThrow();
        }
        catch (TimeoutException success) {}
        catch (Throwable fail) { threadUnexpectedException(fail); }
    }

    <T> void checkCompletedNormally(CompletableFuture<T> f, T value) {
        checkTimedGet(f, value);

        try {
            assertEquals(value, f.join());
        } catch (Throwable fail) { threadUnexpectedException(fail); }
        try {
            assertEquals(value, f.getNow(null));
        } catch (Throwable fail) { threadUnexpectedException(fail); }
        try {
            assertEquals(value, f.get());
        } catch (Throwable fail) { threadUnexpectedException(fail); }
        assertTrue(f.isDone());
        assertFalse(f.isCancelled());
        assertFalse(f.isCompletedExceptionally());
        assertTrue(f.toString().contains("[Completed normally]"));
    }

    /**
     * Returns the "raw" internal exceptional completion of f,
     * without any additional wrapping with CompletionException.
     */
    <U> Throwable exceptionalCompletion(CompletableFuture<U> f) {
        // handle (and whenComplete) can distinguish between "direct"
        // and "wrapped" exceptional completion
        return f.handle((U u, Throwable t) -> t).join();
    }

    void checkCompletedExceptionally(CompletableFuture<?> f,
                                     boolean wrapped,
                                     Consumer<Throwable> checker) {
        Throwable cause = exceptionalCompletion(f);
        if (wrapped) {
            assertTrue(cause instanceof CompletionException);
            cause = cause.getCause();
        }
        checker.accept(cause);

        long startTime = System.nanoTime();
        try {
            f.get(LONG_DELAY_MS, MILLISECONDS);
            shouldThrow();
        } catch (ExecutionException success) {
            assertSame(cause, success.getCause());
        } catch (Throwable fail) { threadUnexpectedException(fail); }
        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);

        try {
            f.join();
            shouldThrow();
        } catch (CompletionException success) {
            assertSame(cause, success.getCause());
        } catch (Throwable fail) { threadUnexpectedException(fail); }

        try {
            f.getNow(null);
            shouldThrow();
        } catch (CompletionException success) {
            assertSame(cause, success.getCause());
        } catch (Throwable fail) { threadUnexpectedException(fail); }

        try {
            f.get();
            shouldThrow();
        } catch (ExecutionException success) {
            assertSame(cause, success.getCause());
        } catch (Throwable fail) { threadUnexpectedException(fail); }

        assertFalse(f.isCancelled());
        assertTrue(f.isDone());
        assertTrue(f.isCompletedExceptionally());
        assertTrue(f.toString().contains("[Completed exceptionally]"));
    }

    void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
        checkCompletedExceptionally(f, true,
            (t) -> assertTrue(t instanceof CFException));
    }

    void checkCompletedWithWrappedCancellationException(CompletableFuture<?> f) {
        checkCompletedExceptionally(f, true,
            (t) -> assertTrue(t instanceof CancellationException));
    }

    void checkCompletedWithTimeoutException(CompletableFuture<?> f) {
        checkCompletedExceptionally(f, false,
            (t) -> assertTrue(t instanceof TimeoutException));
    }

    void checkCompletedWithWrappedException(CompletableFuture<?> f,
                                            Throwable ex) {
        checkCompletedExceptionally(f, true, (t) -> assertSame(t, ex));
    }

    void checkCompletedExceptionally(CompletableFuture<?> f, Throwable ex) {
        checkCompletedExceptionally(f, false, (t) -> assertSame(t, ex));
    }

    void checkCancelled(CompletableFuture<?> f) {
        long startTime = System.nanoTime();
        try {
            f.get(LONG_DELAY_MS, MILLISECONDS);
            shouldThrow();
        } catch (CancellationException success) {
        } catch (Throwable fail) { threadUnexpectedException(fail); }
        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);

        try {
            f.join();
            shouldThrow();
        } catch (CancellationException success) {}
        try {
            f.getNow(null);
            shouldThrow();
        } catch (CancellationException success) {}
        try {
            f.get();
            shouldThrow();
        } catch (CancellationException success) {
        } catch (Throwable fail) { threadUnexpectedException(fail); }

        assertTrue(exceptionalCompletion(f) instanceof CancellationException);

        assertTrue(f.isDone());
        assertTrue(f.isCompletedExceptionally());
        assertTrue(f.isCancelled());
        assertTrue(f.toString().contains("[Completed exceptionally]"));
    }

    /**
     * A newly constructed CompletableFuture is incomplete, as indicated
     * by methods isDone, isCancelled, and getNow
     */
    public void testConstructor() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        checkIncomplete(f);
    }

    /**
     * complete completes normally, as indicated by methods isDone,
     * isCancelled, join, get, and getNow
     */
    public void testComplete() {
        for (Integer v1 : new Integer[] { 1, null })
    {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        checkIncomplete(f);
        assertTrue(f.complete(v1));
        assertFalse(f.complete(v1));
        checkCompletedNormally(f, v1);
    }}

    /**
     * completeExceptionally completes exceptionally, as indicated by
     * methods isDone, isCancelled, join, get, and getNow
     */
    public void testCompleteExceptionally() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CFException ex = new CFException();
        checkIncomplete(f);
        f.completeExceptionally(ex);
        checkCompletedExceptionally(f, ex);
    }

    /**
     * cancel completes exceptionally and reports cancelled, as indicated by
     * methods isDone, isCancelled, join, get, and getNow
     */
    public void testCancel() {
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
    {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        checkIncomplete(f);
        assertTrue(f.cancel(mayInterruptIfRunning));
        assertTrue(f.cancel(mayInterruptIfRunning));
        assertTrue(f.cancel(!mayInterruptIfRunning));
        checkCancelled(f);
    }}

    /**
     * obtrudeValue forces completion with given value
     */
    public void testObtrudeValue() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        checkIncomplete(f);
        assertTrue(f.complete(one));
        checkCompletedNormally(f, one);
        f.obtrudeValue(three);
        checkCompletedNormally(f, three);
        f.obtrudeValue(two);
        checkCompletedNormally(f, two);
        f = new CompletableFuture<>();
        f.obtrudeValue(three);
        checkCompletedNormally(f, three);
        f.obtrudeValue(null);
        checkCompletedNormally(f, null);
        f = new CompletableFuture<>();
        f.completeExceptionally(new CFException());
        f.obtrudeValue(four);
        checkCompletedNormally(f, four);
    }

    /**
     * obtrudeException forces completion with given exception
     */
    public void testObtrudeException() {
        for (Integer v1 : new Integer[] { 1, null })
    {
        CFException ex;
        CompletableFuture<Integer> f;

        f = new CompletableFuture<>();
        assertTrue(f.complete(v1));
        for (int i = 0; i < 2; i++) {
            f.obtrudeException(ex = new CFException());
            checkCompletedExceptionally(f, ex);
        }

        f = new CompletableFuture<>();
        for (int i = 0; i < 2; i++) {
            f.obtrudeException(ex = new CFException());
            checkCompletedExceptionally(f, ex);
        }

        f = new CompletableFuture<>();
        f.completeExceptionally(ex = new CFException());
        f.obtrudeValue(v1);
        checkCompletedNormally(f, v1);
        f.obtrudeException(ex = new CFException());
        checkCompletedExceptionally(f, ex);
        f.completeExceptionally(new CFException());
        checkCompletedExceptionally(f, ex);
        assertFalse(f.complete(v1));
        checkCompletedExceptionally(f, ex);
    }}

    /**
     * getNumberOfDependents returns number of dependent tasks
     */
    public void testGetNumberOfDependents() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        assertEquals(0, f.getNumberOfDependents());
        final CompletableFuture<Void> g = m.thenRun(f, new Noop(m));
        assertEquals(1, f.getNumberOfDependents());
        assertEquals(0, g.getNumberOfDependents());
        final CompletableFuture<Void> h = m.thenRun(f, new Noop(m));
        assertEquals(2, f.getNumberOfDependents());
        assertEquals(0, h.getNumberOfDependents());
        assertTrue(f.complete(v1));
        checkCompletedNormally(g, null);
        checkCompletedNormally(h, null);
        assertEquals(0, f.getNumberOfDependents());
        assertEquals(0, g.getNumberOfDependents());
        assertEquals(0, h.getNumberOfDependents());
    }}

    /**
     * toString indicates current completion state
     */
    public void testToString() {
        CompletableFuture<String> f;

        f = new CompletableFuture<String>();
        assertTrue(f.toString().contains("[Not completed]"));

        assertTrue(f.complete("foo"));
        assertTrue(f.toString().contains("[Completed normally]"));

        f = new CompletableFuture<String>();
        assertTrue(f.completeExceptionally(new IndexOutOfBoundsException()));
        assertTrue(f.toString().contains("[Completed exceptionally]"));

        for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
            f = new CompletableFuture<String>();
            assertTrue(f.cancel(mayInterruptIfRunning));
            assertTrue(f.toString().contains("[Completed exceptionally]"));
        }
    }

    /**
     * completedFuture returns a completed CompletableFuture with given value
     */
    public void testCompletedFuture() {
        CompletableFuture<String> f = CompletableFuture.completedFuture("test");
        checkCompletedNormally(f, "test");
    }

    abstract class CheckedAction {
        int invocationCount = 0;
        final ExecutionMode m;
        CheckedAction(ExecutionMode m) { this.m = m; }
        void invoked() {
            m.checkExecutionMode();
            assertEquals(0, invocationCount++);
        }
        void assertNotInvoked() { assertEquals(0, invocationCount); }
        void assertInvoked() { assertEquals(1, invocationCount); }
    }

    abstract class CheckedIntegerAction extends CheckedAction {
        Integer value;
        CheckedIntegerAction(ExecutionMode m) { super(m); }
        void assertValue(Integer expected) {
            assertInvoked();
            assertEquals(expected, value);
        }
    }

    class IntegerSupplier extends CheckedAction
        implements Supplier<Integer>
    {
        final Integer value;
        IntegerSupplier(ExecutionMode m, Integer value) {
            super(m);
            this.value = value;
        }
        public Integer get() {
            invoked();
            return value;
        }
    }

    // A function that handles and produces null values as well.
    static Integer inc(Integer x) {
        return (x == null) ? null : x + 1;
    }

    class NoopConsumer extends CheckedIntegerAction
        implements Consumer<Integer>
    {
        NoopConsumer(ExecutionMode m) { super(m); }
        public void accept(Integer x) {
            invoked();
            value = x;
        }
    }

    class IncFunction extends CheckedIntegerAction
        implements Function<Integer,Integer>
    {
        IncFunction(ExecutionMode m) { super(m); }
        public Integer apply(Integer x) {
            invoked();
            return value = inc(x);
        }
    }

    // Choose non-commutative actions for better coverage
    // A non-commutative function that handles and produces null values as well.
    static Integer subtract(Integer x, Integer y) {
        return (x == null && y == null) ? null :
            ((x == null) ? 42 : x.intValue())
            - ((y == null) ? 99 : y.intValue());
    }

    class SubtractAction extends CheckedIntegerAction
        implements BiConsumer<Integer, Integer>
    {
        SubtractAction(ExecutionMode m) { super(m); }
        public void accept(Integer x, Integer y) {
            invoked();
            value = subtract(x, y);
        }
    }

    class SubtractFunction extends CheckedIntegerAction
        implements BiFunction<Integer, Integer, Integer>
    {
        SubtractFunction(ExecutionMode m) { super(m); }
        public Integer apply(Integer x, Integer y) {
            invoked();
            return value = subtract(x, y);
        }
    }

    class Noop extends CheckedAction implements Runnable {
        Noop(ExecutionMode m) { super(m); }
        public void run() {
            invoked();
        }
    }

    class FailingSupplier extends CheckedAction
        implements Supplier<Integer>
    {
        FailingSupplier(ExecutionMode m) { super(m); }
        public Integer get() {
            invoked();
            throw new CFException();
        }
    }

    class FailingConsumer extends CheckedIntegerAction
        implements Consumer<Integer>
    {
        FailingConsumer(ExecutionMode m) { super(m); }
        public void accept(Integer x) {
            invoked();
            value = x;
            throw new CFException();
        }
    }

    class FailingBiConsumer extends CheckedIntegerAction
        implements BiConsumer<Integer, Integer>
    {
        FailingBiConsumer(ExecutionMode m) { super(m); }
        public void accept(Integer x, Integer y) {
            invoked();
            value = subtract(x, y);
            throw new CFException();
        }
    }

    class FailingFunction extends CheckedIntegerAction
        implements Function<Integer, Integer>
    {
        FailingFunction(ExecutionMode m) { super(m); }
        public Integer apply(Integer x) {
            invoked();
            value = x;
            throw new CFException();
        }
    }

    class FailingBiFunction extends CheckedIntegerAction
        implements BiFunction<Integer, Integer, Integer>
    {
        FailingBiFunction(ExecutionMode m) { super(m); }
        public Integer apply(Integer x, Integer y) {
            invoked();
            value = subtract(x, y);
            throw new CFException();
        }
    }

    class FailingRunnable extends CheckedAction implements Runnable {
        FailingRunnable(ExecutionMode m) { super(m); }
        public void run() {
            invoked();
            throw new CFException();
        }
    }

    class CompletableFutureInc extends CheckedIntegerAction
        implements Function<Integer, CompletableFuture<Integer>>
    {
        CompletableFutureInc(ExecutionMode m) { super(m); }
        public CompletableFuture<Integer> apply(Integer x) {
            invoked();
            value = x;
            CompletableFuture<Integer> f = new CompletableFuture<>();
            assertTrue(f.complete(inc(x)));
            return f;
        }
    }

    class FailingCompletableFutureFunction extends CheckedIntegerAction
        implements Function<Integer, CompletableFuture<Integer>>
    {
        FailingCompletableFutureFunction(ExecutionMode m) { super(m); }
        public CompletableFuture<Integer> apply(Integer x) {
            invoked();
            value = x;
            throw new CFException();
        }
    }

    // Used for explicit executor tests
    static final class ThreadExecutor implements Executor {
        final AtomicInteger count = new AtomicInteger(0);
        static final ThreadGroup tg = new ThreadGroup("ThreadExecutor");
        static boolean startedCurrentThread() {
            return Thread.currentThread().getThreadGroup() == tg;
        }

        public void execute(Runnable r) {
            count.getAndIncrement();
            new Thread(tg, r).start();
        }
    }

    static final boolean defaultExecutorIsCommonPool
        = ForkJoinPool.getCommonPoolParallelism() > 1;

    /**
     * Permits the testing of parallel code for the 3 different
     * execution modes without copy/pasting all the test methods.
     */
    enum ExecutionMode {
        SYNC {
            public void checkExecutionMode() {
                assertFalse(ThreadExecutor.startedCurrentThread());
                assertNull(ForkJoinTask.getPool());
            }
            public CompletableFuture<Void> runAsync(Runnable a) {
                throw new UnsupportedOperationException();
            }
            public <U> CompletableFuture<U> supplyAsync(Supplier<U> a) {
                throw new UnsupportedOperationException();
            }
            public <T> CompletableFuture<Void> thenRun
                (CompletableFuture<T> f, Runnable a) {
                return f.thenRun(a);
            }
            public <T> CompletableFuture<Void> thenAccept
                (CompletableFuture<T> f, Consumer<? super T> a) {
                return f.thenAccept(a);
            }
            public <T,U> CompletableFuture<U> thenApply
                (CompletableFuture<T> f, Function<? super T,U> a) {
                return f.thenApply(a);
            }
            public <T,U> CompletableFuture<U> thenCompose
                (CompletableFuture<T> f,
                 Function<? super T,? extends CompletionStage<U>> a) {
                return f.thenCompose(a);
            }
            public <T,U> CompletableFuture<U> handle
                (CompletableFuture<T> f,
                 BiFunction<? super T,Throwable,? extends U> a) {
                return f.handle(a);
            }
            public <T> CompletableFuture<T> whenComplete
                (CompletableFuture<T> f,
                 BiConsumer<? super T,? super Throwable> a) {
                return f.whenComplete(a);
            }
            public <T,U> CompletableFuture<Void> runAfterBoth
                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
                return f.runAfterBoth(g, a);
            }
            public <T,U> CompletableFuture<Void> thenAcceptBoth
                (CompletableFuture<T> f,
                 CompletionStage<? extends U> g,
                 BiConsumer<? super T,? super U> a) {
                return f.thenAcceptBoth(g, a);
            }
            public <T,U,V> CompletableFuture<V> thenCombine
                (CompletableFuture<T> f,
                 CompletionStage<? extends U> g,
                 BiFunction<? super T,? super U,? extends V> a) {
                return f.thenCombine(g, a);
            }
            public <T> CompletableFuture<Void> runAfterEither
                (CompletableFuture<T> f,
                 CompletionStage<?> g,
                 java.lang.Runnable a) {
                return f.runAfterEither(g, a);
            }
            public <T> CompletableFuture<Void> acceptEither
                (CompletableFuture<T> f,
                 CompletionStage<? extends T> g,
                 Consumer<? super T> a) {
                return f.acceptEither(g, a);
            }
            public <T,U> CompletableFuture<U> applyToEither
                (CompletableFuture<T> f,
                 CompletionStage<? extends T> g,
                 Function<? super T,U> a) {
                return f.applyToEither(g, a);
            }
        },

        ASYNC {
            public void checkExecutionMode() {
                assertEquals(defaultExecutorIsCommonPool,
                             (ForkJoinPool.commonPool() == ForkJoinTask.getPool()));
            }
            public CompletableFuture<Void> runAsync(Runnable a) {
                return CompletableFuture.runAsync(a);
            }
            public <U> CompletableFuture<U> supplyAsync(Supplier<U> a) {
                return CompletableFuture.supplyAsync(a);
            }
            public <T> CompletableFuture<Void> thenRun
                (CompletableFuture<T> f, Runnable a) {
                return f.thenRunAsync(a);
            }
            public <T> CompletableFuture<Void> thenAccept
                (CompletableFuture<T> f, Consumer<? super T> a) {
                return f.thenAcceptAsync(a);
            }
            public <T,U> CompletableFuture<U> thenApply
                (CompletableFuture<T> f, Function<? super T,U> a) {
                return f.thenApplyAsync(a);
            }
            public <T,U> CompletableFuture<U> thenCompose
                (CompletableFuture<T> f,
                 Function<? super T,? extends CompletionStage<U>> a) {
                return f.thenComposeAsync(a);
            }
            public <T,U> CompletableFuture<U> handle
                (CompletableFuture<T> f,
                 BiFunction<? super T,Throwable,? extends U> a) {
                return f.handleAsync(a);
            }
            public <T> CompletableFuture<T> whenComplete
                (CompletableFuture<T> f,
                 BiConsumer<? super T,? super Throwable> a) {
                return f.whenCompleteAsync(a);
            }
            public <T,U> CompletableFuture<Void> runAfterBoth
                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
                return f.runAfterBothAsync(g, a);
            }
            public <T,U> CompletableFuture<Void> thenAcceptBoth
                (CompletableFuture<T> f,
                 CompletionStage<? extends U> g,
                 BiConsumer<? super T,? super U> a) {
                return f.thenAcceptBothAsync(g, a);
            }
            public <T,U,V> CompletableFuture<V> thenCombine
                (CompletableFuture<T> f,
                 CompletionStage<? extends U> g,
                 BiFunction<? super T,? super U,? extends V> a) {
                return f.thenCombineAsync(g, a);
            }
            public <T> CompletableFuture<Void> runAfterEither
                (CompletableFuture<T> f,
                 CompletionStage<?> g,
                 java.lang.Runnable a) {
                return f.runAfterEitherAsync(g, a);
            }
            public <T> CompletableFuture<Void> acceptEither
                (CompletableFuture<T> f,
                 CompletionStage<? extends T> g,
                 Consumer<? super T> a) {
                return f.acceptEitherAsync(g, a);
            }
            public <T,U> CompletableFuture<U> applyToEither
                (CompletableFuture<T> f,
                 CompletionStage<? extends T> g,
                 Function<? super T,U> a) {
                return f.applyToEitherAsync(g, a);
            }
        },

        EXECUTOR {
            public void checkExecutionMode() {
                assertTrue(ThreadExecutor.startedCurrentThread());
            }
            public CompletableFuture<Void> runAsync(Runnable a) {
                return CompletableFuture.runAsync(a, new ThreadExecutor());
            }
            public <U> CompletableFuture<U> supplyAsync(Supplier<U> a) {
                return CompletableFuture.supplyAsync(a, new ThreadExecutor());
            }
            public <T> CompletableFuture<Void> thenRun
                (CompletableFuture<T> f, Runnable a) {
                return f.thenRunAsync(a, new ThreadExecutor());
            }
            public <T> CompletableFuture<Void> thenAccept
                (CompletableFuture<T> f, Consumer<? super T> a) {
                return f.thenAcceptAsync(a, new ThreadExecutor());
            }
            public <T,U> CompletableFuture<U> thenApply
                (CompletableFuture<T> f, Function<? super T,U> a) {
                return f.thenApplyAsync(a, new ThreadExecutor());
            }
            public <T,U> CompletableFuture<U> thenCompose
                (CompletableFuture<T> f,
                 Function<? super T,? extends CompletionStage<U>> a) {
                return f.thenComposeAsync(a, new ThreadExecutor());
            }
            public <T,U> CompletableFuture<U> handle
                (CompletableFuture<T> f,
                 BiFunction<? super T,Throwable,? extends U> a) {
                return f.handleAsync(a, new ThreadExecutor());
            }
            public <T> CompletableFuture<T> whenComplete
                (CompletableFuture<T> f,
                 BiConsumer<? super T,? super Throwable> a) {
                return f.whenCompleteAsync(a, new ThreadExecutor());
            }
            public <T,U> CompletableFuture<Void> runAfterBoth
                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
                return f.runAfterBothAsync(g, a, new ThreadExecutor());
            }
            public <T,U> CompletableFuture<Void> thenAcceptBoth
                (CompletableFuture<T> f,
                 CompletionStage<? extends U> g,
                 BiConsumer<? super T,? super U> a) {
                return f.thenAcceptBothAsync(g, a, new ThreadExecutor());
            }
            public <T,U,V> CompletableFuture<V> thenCombine
                (CompletableFuture<T> f,
                 CompletionStage<? extends U> g,
                 BiFunction<? super T,? super U,? extends V> a) {
                return f.thenCombineAsync(g, a, new ThreadExecutor());
            }
            public <T> CompletableFuture<Void> runAfterEither
                (CompletableFuture<T> f,
                 CompletionStage<?> g,
                 java.lang.Runnable a) {
                return f.runAfterEitherAsync(g, a, new ThreadExecutor());
            }
            public <T> CompletableFuture<Void> acceptEither
                (CompletableFuture<T> f,
                 CompletionStage<? extends T> g,
                 Consumer<? super T> a) {
                return f.acceptEitherAsync(g, a, new ThreadExecutor());
            }
            public <T,U> CompletableFuture<U> applyToEither
                (CompletableFuture<T> f,
                 CompletionStage<? extends T> g,
                 Function<? super T,U> a) {
                return f.applyToEitherAsync(g, a, new ThreadExecutor());
            }
        };

        public abstract void checkExecutionMode();
        public abstract CompletableFuture<Void> runAsync(Runnable a);
        public abstract <U> CompletableFuture<U> supplyAsync(Supplier<U> a);
        public abstract <T> CompletableFuture<Void> thenRun
            (CompletableFuture<T> f, Runnable a);
        public abstract <T> CompletableFuture<Void> thenAccept
            (CompletableFuture<T> f, Consumer<? super T> a);
        public abstract <T,U> CompletableFuture<U> thenApply
            (CompletableFuture<T> f, Function<? super T,U> a);
        public abstract <T,U> CompletableFuture<U> thenCompose
            (CompletableFuture<T> f,
             Function<? super T,? extends CompletionStage<U>> a);
        public abstract <T,U> CompletableFuture<U> handle
            (CompletableFuture<T> f,
             BiFunction<? super T,Throwable,? extends U> a);
        public abstract <T> CompletableFuture<T> whenComplete
            (CompletableFuture<T> f,
             BiConsumer<? super T,? super Throwable> a);
        public abstract <T,U> CompletableFuture<Void> runAfterBoth
            (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a);
        public abstract <T,U> CompletableFuture<Void> thenAcceptBoth
            (CompletableFuture<T> f,
             CompletionStage<? extends U> g,
             BiConsumer<? super T,? super U> a);
        public abstract <T,U,V> CompletableFuture<V> thenCombine
            (CompletableFuture<T> f,
             CompletionStage<? extends U> g,
             BiFunction<? super T,? super U,? extends V> a);
        public abstract <T> CompletableFuture<Void> runAfterEither
            (CompletableFuture<T> f,
             CompletionStage<?> g,
             java.lang.Runnable a);
        public abstract <T> CompletableFuture<Void> acceptEither
            (CompletableFuture<T> f,
             CompletionStage<? extends T> g,
             Consumer<? super T> a);
        public abstract <T,U> CompletableFuture<U> applyToEither
            (CompletableFuture<T> f,
             CompletionStage<? extends T> g,
             Function<? super T,U> a);
    }

    /**
     * exceptionally action is not invoked when source completes
     * normally, and source result is propagated
     */
    public void testExceptionally_normalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final AtomicInteger a = new AtomicInteger(0);
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Integer> g = f.exceptionally
            ((Throwable t) -> {
                a.getAndIncrement();
                threadFail("should not be called");
                return null;            // unreached
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(g, v1);
        checkCompletedNormally(f, v1);
        assertEquals(0, a.get());
    }}

    /**
     * exceptionally action completes with function value on source
     * exception
     */
    public void testExceptionally_exceptionalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final AtomicInteger a = new AtomicInteger(0);
        final CFException ex = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletableFuture<Integer> g = f.exceptionally
            ((Throwable t) -> {
                ExecutionMode.SYNC.checkExecutionMode();
                threadAssertSame(t, ex);
                a.getAndIncrement();
                return v1;
            });
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedNormally(g, v1);
        assertEquals(1, a.get());
    }}

    /**
     * If an "exceptionally action" throws an exception, it completes
     * exceptionally with that exception
     */
    public void testExceptionally_exceptionalCompletionActionFailed() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final AtomicInteger a = new AtomicInteger(0);
        final CFException ex1 = new CFException();
        final CFException ex2 = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        if (!createIncomplete) f.completeExceptionally(ex1);
        final CompletableFuture<Integer> g = f.exceptionally
            ((Throwable t) -> {
                ExecutionMode.SYNC.checkExecutionMode();
                threadAssertSame(t, ex1);
                a.getAndIncrement();
                throw ex2;
            });
        if (createIncomplete) f.completeExceptionally(ex1);

        checkCompletedWithWrappedException(g, ex2);
        checkCompletedExceptionally(f, ex1);
        assertEquals(1, a.get());
    }}

    /**
     * whenComplete action executes on normal completion, propagating
     * source result.
     */
    public void testWhenComplete_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final AtomicInteger a = new AtomicInteger(0);
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Integer> g = m.whenComplete
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertSame(result, v1);
                threadAssertNull(t);
                a.getAndIncrement();
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(g, v1);
        checkCompletedNormally(f, v1);
        assertEquals(1, a.get());
    }}

    /**
     * whenComplete action executes on exceptional completion, propagating
     * source result.
     */
    public void testWhenComplete_exceptionalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final AtomicInteger a = new AtomicInteger(0);
        final CFException ex = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletableFuture<Integer> g = m.whenComplete
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertNull(result);
                threadAssertSame(t, ex);
                a.getAndIncrement();
            });
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedWithWrappedException(g, ex);
        checkCompletedExceptionally(f, ex);
        assertEquals(1, a.get());
    }}

    /**
     * whenComplete action executes on cancelled source, propagating
     * CancellationException.
     */
    public void testWhenComplete_sourceCancelled() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final AtomicInteger a = new AtomicInteger(0);
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Integer> g = m.whenComplete
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertNull(result);
                threadAssertTrue(t instanceof CancellationException);
                a.getAndIncrement();
            });
        if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));

        checkCompletedWithWrappedCancellationException(g);
        checkCancelled(f);
        assertEquals(1, a.get());
    }}

    /**
     * If a whenComplete action throws an exception when triggered by
     * a normal completion, it completes exceptionally
     */
    public void testWhenComplete_sourceCompletedNormallyActionFailed() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final AtomicInteger a = new AtomicInteger(0);
        final CFException ex = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Integer> g = m.whenComplete
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertSame(result, v1);
                threadAssertNull(t);
                a.getAndIncrement();
                throw ex;
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedWithWrappedException(g, ex);
        checkCompletedNormally(f, v1);
        assertEquals(1, a.get());
    }}

    /**
     * If a whenComplete action throws an exception when triggered by
     * a source completion that also throws an exception, the source
     * exception takes precedence (unlike handle)
     */
    public void testWhenComplete_sourceFailedActionFailed() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (ExecutionMode m : ExecutionMode.values())
    {
        final AtomicInteger a = new AtomicInteger(0);
        final CFException ex1 = new CFException();
        final CFException ex2 = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();

        if (!createIncomplete) f.completeExceptionally(ex1);
        final CompletableFuture<Integer> g = m.whenComplete
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertSame(t, ex1);
                threadAssertNull(result);
                a.getAndIncrement();
                throw ex2;
            });
        if (createIncomplete) f.completeExceptionally(ex1);

        checkCompletedWithWrappedException(g, ex1);
        checkCompletedExceptionally(f, ex1);
        if (testImplementationDetails) {
            assertEquals(1, ex1.getSuppressed().length);
            assertSame(ex2, ex1.getSuppressed()[0]);
        }
        assertEquals(1, a.get());
    }}

    /**
     * handle action completes normally with function value on normal
     * completion of source
     */
    public void testHandle_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final AtomicInteger a = new AtomicInteger(0);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Integer> g = m.handle
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertSame(result, v1);
                threadAssertNull(t);
                a.getAndIncrement();
                return inc(v1);
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(g, inc(v1));
        checkCompletedNormally(f, v1);
        assertEquals(1, a.get());
    }}

    /**
     * handle action completes normally with function value on
     * exceptional completion of source
     */
    public void testHandle_exceptionalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final AtomicInteger a = new AtomicInteger(0);
        final CFException ex = new CFException();
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletableFuture<Integer> g = m.handle
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertNull(result);
                threadAssertSame(t, ex);
                a.getAndIncrement();
                return v1;
            });
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedNormally(g, v1);
        checkCompletedExceptionally(f, ex);
        assertEquals(1, a.get());
    }}

    /**
     * handle action completes normally with function value on
     * cancelled source
     */
    public void testHandle_sourceCancelled() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final AtomicInteger a = new AtomicInteger(0);
        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Integer> g = m.handle
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertNull(result);
                threadAssertTrue(t instanceof CancellationException);
                a.getAndIncrement();
                return v1;
            });
        if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));

        checkCompletedNormally(g, v1);
        checkCancelled(f);
        assertEquals(1, a.get());
    }}

    /**
     * If a "handle action" throws an exception when triggered by
     * a normal completion, it completes exceptionally
     */
    public void testHandle_sourceCompletedNormallyActionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final AtomicInteger a = new AtomicInteger(0);
        final CFException ex = new CFException();
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Integer> g = m.handle
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertSame(result, v1);
                threadAssertNull(t);
                a.getAndIncrement();
                throw ex;
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedWithWrappedException(g, ex);
        checkCompletedNormally(f, v1);
        assertEquals(1, a.get());
    }}

    /**
     * If a "handle action" throws an exception when triggered by
     * a source completion that also throws an exception, the action
     * exception takes precedence (unlike whenComplete)
     */
    public void testHandle_sourceFailedActionFailed() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (ExecutionMode m : ExecutionMode.values())
    {
        final AtomicInteger a = new AtomicInteger(0);
        final CFException ex1 = new CFException();
        final CFException ex2 = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();

        if (!createIncomplete) f.completeExceptionally(ex1);
        final CompletableFuture<Integer> g = m.handle
            (f,
             (Integer result, Throwable t) -> {
                m.checkExecutionMode();
                threadAssertNull(result);
                threadAssertSame(ex1, t);
                a.getAndIncrement();
                throw ex2;
            });
        if (createIncomplete) f.completeExceptionally(ex1);

        checkCompletedWithWrappedException(g, ex2);
        checkCompletedExceptionally(f, ex1);
        assertEquals(1, a.get());
    }}

    /**
     * runAsync completes after running Runnable
     */
    public void testRunAsync_normalCompletion() {
        ExecutionMode[] executionModes = {
            ExecutionMode.ASYNC,
            ExecutionMode.EXECUTOR,
        };
        for (ExecutionMode m : executionModes)
    {
        final Noop r = new Noop(m);
        final CompletableFuture<Void> f = m.runAsync(r);
        assertNull(f.join());
        checkCompletedNormally(f, null);
        r.assertInvoked();
    }}

    /**
     * failing runAsync completes exceptionally after running Runnable
     */
    public void testRunAsync_exceptionalCompletion() {
        ExecutionMode[] executionModes = {
            ExecutionMode.ASYNC,
            ExecutionMode.EXECUTOR,
        };
        for (ExecutionMode m : executionModes)
    {
        final FailingRunnable r = new FailingRunnable(m);
        final CompletableFuture<Void> f = m.runAsync(r);
        checkCompletedWithWrappedCFException(f);
        r.assertInvoked();
    }}

    /**
     * supplyAsync completes with result of supplier
     */
    public void testSupplyAsync_normalCompletion() {
        ExecutionMode[] executionModes = {
            ExecutionMode.ASYNC,
            ExecutionMode.EXECUTOR,
        };
        for (ExecutionMode m : executionModes)
        for (Integer v1 : new Integer[] { 1, null })
    {
        final IntegerSupplier r = new IntegerSupplier(m, v1);
        final CompletableFuture<Integer> f = m.supplyAsync(r);
        assertSame(v1, f.join());
        checkCompletedNormally(f, v1);
        r.assertInvoked();
    }}

    /**
     * Failing supplyAsync completes exceptionally
     */
    public void testSupplyAsync_exceptionalCompletion() {
        ExecutionMode[] executionModes = {
            ExecutionMode.ASYNC,
            ExecutionMode.EXECUTOR,
        };
        for (ExecutionMode m : executionModes)
    {
        FailingSupplier r = new FailingSupplier(m);
        CompletableFuture<Integer> f = m.supplyAsync(r);
        checkCompletedWithWrappedCFException(f);
        r.assertInvoked();
    }}

    // seq completion methods

    /**
     * thenRun result completes normally after normal completion of source
     */
    public void testThenRun_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final Noop[] rs = new Noop[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);

        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(f.complete(v1));
        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);

        checkCompletedNormally(h0, null);
        checkCompletedNormally(h1, null);
        checkCompletedNormally(h2, null);
        checkCompletedNormally(h3, null);
        checkCompletedNormally(h4, null);
        checkCompletedNormally(h5, null);
        checkCompletedNormally(f, v1);
        for (Noop r : rs) r.assertInvoked();
    }}

    /**
     * thenRun result completes exceptionally after exceptional
     * completion of source
     */
    public void testThenRun_exceptionalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
    {
        final CFException ex = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final Noop[] rs = new Noop[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);

        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(f.completeExceptionally(ex));
        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);

        checkCompletedWithWrappedException(h0, ex);
        checkCompletedWithWrappedException(h1, ex);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        checkCompletedWithWrappedException(h4, ex);
        checkCompletedWithWrappedException(h5, ex);
        checkCompletedExceptionally(f, ex);
        for (Noop r : rs) r.assertNotInvoked();
    }}

    /**
     * thenRun result completes exceptionally if source cancelled
     */
    public void testThenRun_sourceCancelled() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final Noop[] rs = new Noop[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);

        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);

        checkCompletedWithWrappedCancellationException(h0);
        checkCompletedWithWrappedCancellationException(h1);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        checkCompletedWithWrappedCancellationException(h4);
        checkCompletedWithWrappedCancellationException(h5);
        checkCancelled(f);
        for (Noop r : rs) r.assertNotInvoked();
    }}

    /**
     * thenRun result completes exceptionally if action does
     */
    public void testThenRun_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final FailingRunnable[] rs = new FailingRunnable[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new FailingRunnable(m);

        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
        assertTrue(f.complete(v1));
        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);

        checkCompletedWithWrappedCFException(h0);
        checkCompletedWithWrappedCFException(h1);
        checkCompletedWithWrappedCFException(h2);
        checkCompletedWithWrappedCFException(h3);
        checkCompletedWithWrappedCFException(h4);
        checkCompletedWithWrappedCFException(h5);
        checkCompletedNormally(f, v1);
    }}

    /**
     * thenApply result completes normally after normal completion of source
     */
    public void testThenApply_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        assertTrue(f.complete(v1));
        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);

        checkCompletedNormally(h0, inc(v1));
        checkCompletedNormally(h1, inc(v1));
        checkCompletedNormally(h2, inc(v1));
        checkCompletedNormally(h3, inc(v1));
        checkCompletedNormally(f, v1);
        for (IncFunction r : rs) r.assertValue(inc(v1));
    }}

    /**
     * thenApply result completes exceptionally after exceptional
     * completion of source
     */
    public void testThenApply_exceptionalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
    {
        final CFException ex = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
        assertTrue(f.completeExceptionally(ex));
        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);

        checkCompletedWithWrappedException(h0, ex);
        checkCompletedWithWrappedException(h1, ex);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        checkCompletedExceptionally(f, ex);
        for (IncFunction r : rs) r.assertNotInvoked();
    }}

    /**
     * thenApply result completes exceptionally if source cancelled
     */
    public void testThenApply_sourceCancelled() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
        assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);

        checkCompletedWithWrappedCancellationException(h0);
        checkCompletedWithWrappedCancellationException(h1);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        checkCancelled(f);
        for (IncFunction r : rs) r.assertNotInvoked();
    }}

    /**
     * thenApply result completes exceptionally if action does
     */
    public void testThenApply_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final FailingFunction[] rs = new FailingFunction[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m);

        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
        assertTrue(f.complete(v1));
        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);

        checkCompletedWithWrappedCFException(h0);
        checkCompletedWithWrappedCFException(h1);
        checkCompletedWithWrappedCFException(h2);
        checkCompletedWithWrappedCFException(h3);
        checkCompletedNormally(f, v1);
    }}

    /**
     * thenAccept result completes normally after normal completion of source
     */
    public void testThenAccept_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final NoopConsumer[] rs = new NoopConsumer[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);

        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        assertTrue(f.complete(v1));
        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);

        checkCompletedNormally(h0, null);
        checkCompletedNormally(h1, null);
        checkCompletedNormally(h2, null);
        checkCompletedNormally(h3, null);
        checkCompletedNormally(f, v1);
        for (NoopConsumer r : rs) r.assertValue(v1);
    }}

    /**
     * thenAccept result completes exceptionally after exceptional
     * completion of source
     */
    public void testThenAccept_exceptionalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
    {
        final CFException ex = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final NoopConsumer[] rs = new NoopConsumer[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);

        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
        assertTrue(f.completeExceptionally(ex));
        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);

        checkCompletedWithWrappedException(h0, ex);
        checkCompletedWithWrappedException(h1, ex);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        checkCompletedExceptionally(f, ex);
        for (NoopConsumer r : rs) r.assertNotInvoked();
    }}

    /**
     * thenAccept result completes exceptionally if source cancelled
     */
    public void testThenAccept_sourceCancelled() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final NoopConsumer[] rs = new NoopConsumer[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);

        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
        assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);

        checkCompletedWithWrappedCancellationException(h0);
        checkCompletedWithWrappedCancellationException(h1);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        checkCancelled(f);
        for (NoopConsumer r : rs) r.assertNotInvoked();
    }}

    /**
     * thenAccept result completes exceptionally if action does
     */
    public void testThenAccept_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final FailingConsumer[] rs = new FailingConsumer[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new FailingConsumer(m);

        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
        assertTrue(f.complete(v1));
        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);

        checkCompletedWithWrappedCFException(h0);
        checkCompletedWithWrappedCFException(h1);
        checkCompletedWithWrappedCFException(h2);
        checkCompletedWithWrappedCFException(h3);
        checkCompletedNormally(f, v1);
    }}

    /**
     * thenCombine result completes normally after normal completion
     * of sources
     */
    public void testThenCombine_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final SubtractFunction[] rs = new SubtractFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new SubtractFunction(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Integer w1 =  fFirst ? v1 : v2;
        final Integer w2 = !fFirst ? v1 : v2;

        final CompletableFuture<Integer> h0 = m.thenCombine(f, g, rs[0]);
        final CompletableFuture<Integer> h1 = m.thenCombine(fst, fst, rs[1]);
        assertTrue(fst.complete(w1));
        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, rs[2]);
        final CompletableFuture<Integer> h3 = m.thenCombine(fst, fst, rs[3]);
        checkIncomplete(h0); rs[0].assertNotInvoked();
        checkIncomplete(h2); rs[2].assertNotInvoked();
        checkCompletedNormally(h1, subtract(w1, w1));
        checkCompletedNormally(h3, subtract(w1, w1));
        rs[1].assertValue(subtract(w1, w1));
        rs[3].assertValue(subtract(w1, w1));
        assertTrue(snd.complete(w2));
        final CompletableFuture<Integer> h4 = m.thenCombine(f, g, rs[4]);

        checkCompletedNormally(h0, subtract(v1, v2));
        checkCompletedNormally(h2, subtract(v1, v2));
        checkCompletedNormally(h4, subtract(v1, v2));
        rs[0].assertValue(subtract(v1, v2));
        rs[2].assertValue(subtract(v1, v2));
        rs[4].assertValue(subtract(v1, v2));

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
    }}

    /**
     * thenCombine result completes exceptionally after exceptional
     * completion of either source
     */
    public void testThenCombine_exceptionalCompletion() throws Throwable {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (boolean failFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CFException ex = new CFException();
        final SubtractFunction r1 = new SubtractFunction(m);
        final SubtractFunction r2 = new SubtractFunction(m);
        final SubtractFunction r3 = new SubtractFunction(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Callable<Boolean> complete1 = failFirst ?
            () -> fst.completeExceptionally(ex) :
            () -> fst.complete(v1);
        final Callable<Boolean> complete2 = failFirst ?
            () -> snd.complete(v1) :
            () -> snd.completeExceptionally(ex);

        final CompletableFuture<Integer> h1 = m.thenCombine(f, g, r1);
        assertTrue(complete1.call());
        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(complete2.call());
        final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);

        checkCompletedWithWrappedException(h1, ex);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        r1.assertNotInvoked();
        r2.assertNotInvoked();
        r3.assertNotInvoked();
        checkCompletedNormally(failFirst ? snd : fst, v1);
        checkCompletedExceptionally(failFirst ? fst : snd, ex);
    }}

    /**
     * thenCombine result completes exceptionally if either source cancelled
     */
    public void testThenCombine_sourceCancelled() throws Throwable {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (boolean fFirst : new boolean[] { true, false })
        for (boolean failFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final SubtractFunction r1 = new SubtractFunction(m);
        final SubtractFunction r2 = new SubtractFunction(m);
        final SubtractFunction r3 = new SubtractFunction(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Callable<Boolean> complete1 = failFirst ?
            () -> fst.cancel(mayInterruptIfRunning) :
            () -> fst.complete(v1);
        final Callable<Boolean> complete2 = failFirst ?
            () -> snd.complete(v1) :
            () -> snd.cancel(mayInterruptIfRunning);

        final CompletableFuture<Integer> h1 = m.thenCombine(f, g, r1);
        assertTrue(complete1.call());
        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(complete2.call());
        final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);

        checkCompletedWithWrappedCancellationException(h1);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        r1.assertNotInvoked();
        r2.assertNotInvoked();
        r3.assertNotInvoked();
        checkCompletedNormally(failFirst ? snd : fst, v1);
        checkCancelled(failFirst ? fst : snd);
    }}

    /**
     * thenCombine result completes exceptionally if action does
     */
    public void testThenCombine_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final FailingBiFunction r1 = new FailingBiFunction(m);
        final FailingBiFunction r2 = new FailingBiFunction(m);
        final FailingBiFunction r3 = new FailingBiFunction(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Integer w1 =  fFirst ? v1 : v2;
        final Integer w2 = !fFirst ? v1 : v2;

        final CompletableFuture<Integer> h1 = m.thenCombine(f, g, r1);
        assertTrue(fst.complete(w1));
        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, r2);
        assertTrue(snd.complete(w2));
        final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);

        checkCompletedWithWrappedCFException(h1);
        checkCompletedWithWrappedCFException(h2);
        checkCompletedWithWrappedCFException(h3);
        r1.assertInvoked();
        r2.assertInvoked();
        r3.assertInvoked();
        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
    }}

    /**
     * thenAcceptBoth result completes normally after normal
     * completion of sources
     */
    public void testThenAcceptBoth_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final SubtractAction r1 = new SubtractAction(m);
        final SubtractAction r2 = new SubtractAction(m);
        final SubtractAction r3 = new SubtractAction(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Integer w1 =  fFirst ? v1 : v2;
        final Integer w2 = !fFirst ? v1 : v2;

        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
        assertTrue(fst.complete(w1));
        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        r1.assertNotInvoked();
        r2.assertNotInvoked();
        assertTrue(snd.complete(w2));
        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);

        checkCompletedNormally(h1, null);
        checkCompletedNormally(h2, null);
        checkCompletedNormally(h3, null);
        r1.assertValue(subtract(v1, v2));
        r2.assertValue(subtract(v1, v2));
        r3.assertValue(subtract(v1, v2));
        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
    }}

    /**
     * thenAcceptBoth result completes exceptionally after exceptional
     * completion of either source
     */
    public void testThenAcceptBoth_exceptionalCompletion() throws Throwable {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (boolean failFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CFException ex = new CFException();
        final SubtractAction r1 = new SubtractAction(m);
        final SubtractAction r2 = new SubtractAction(m);
        final SubtractAction r3 = new SubtractAction(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Callable<Boolean> complete1 = failFirst ?
            () -> fst.completeExceptionally(ex) :
            () -> fst.complete(v1);
        final Callable<Boolean> complete2 = failFirst ?
            () -> snd.complete(v1) :
            () -> snd.completeExceptionally(ex);

        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
        assertTrue(complete1.call());
        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(complete2.call());
        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);

        checkCompletedWithWrappedException(h1, ex);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        r1.assertNotInvoked();
        r2.assertNotInvoked();
        r3.assertNotInvoked();
        checkCompletedNormally(failFirst ? snd : fst, v1);
        checkCompletedExceptionally(failFirst ? fst : snd, ex);
    }}

    /**
     * thenAcceptBoth result completes exceptionally if either source cancelled
     */
    public void testThenAcceptBoth_sourceCancelled() throws Throwable {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (boolean fFirst : new boolean[] { true, false })
        for (boolean failFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final SubtractAction r1 = new SubtractAction(m);
        final SubtractAction r2 = new SubtractAction(m);
        final SubtractAction r3 = new SubtractAction(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Callable<Boolean> complete1 = failFirst ?
            () -> fst.cancel(mayInterruptIfRunning) :
            () -> fst.complete(v1);
        final Callable<Boolean> complete2 = failFirst ?
            () -> snd.complete(v1) :
            () -> snd.cancel(mayInterruptIfRunning);

        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
        assertTrue(complete1.call());
        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(complete2.call());
        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);

        checkCompletedWithWrappedCancellationException(h1);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        r1.assertNotInvoked();
        r2.assertNotInvoked();
        r3.assertNotInvoked();
        checkCompletedNormally(failFirst ? snd : fst, v1);
        checkCancelled(failFirst ? fst : snd);
    }}

    /**
     * thenAcceptBoth result completes exceptionally if action does
     */
    public void testThenAcceptBoth_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final FailingBiConsumer r1 = new FailingBiConsumer(m);
        final FailingBiConsumer r2 = new FailingBiConsumer(m);
        final FailingBiConsumer r3 = new FailingBiConsumer(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Integer w1 =  fFirst ? v1 : v2;
        final Integer w2 = !fFirst ? v1 : v2;

        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
        assertTrue(fst.complete(w1));
        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
        assertTrue(snd.complete(w2));
        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);

        checkCompletedWithWrappedCFException(h1);
        checkCompletedWithWrappedCFException(h2);
        checkCompletedWithWrappedCFException(h3);
        r1.assertInvoked();
        r2.assertInvoked();
        r3.assertInvoked();
        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
    }}

    /**
     * runAfterBoth result completes normally after normal
     * completion of sources
     */
    public void testRunAfterBoth_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final Noop r1 = new Noop(m);
        final Noop r2 = new Noop(m);
        final Noop r3 = new Noop(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Integer w1 =  fFirst ? v1 : v2;
        final Integer w2 = !fFirst ? v1 : v2;

        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
        assertTrue(fst.complete(w1));
        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        r1.assertNotInvoked();
        r2.assertNotInvoked();
        assertTrue(snd.complete(w2));
        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);

        checkCompletedNormally(h1, null);
        checkCompletedNormally(h2, null);
        checkCompletedNormally(h3, null);
        r1.assertInvoked();
        r2.assertInvoked();
        r3.assertInvoked();
        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
    }}

    /**
     * runAfterBoth result completes exceptionally after exceptional
     * completion of either source
     */
    public void testRunAfterBoth_exceptionalCompletion() throws Throwable {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (boolean failFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CFException ex = new CFException();
        final Noop r1 = new Noop(m);
        final Noop r2 = new Noop(m);
        final Noop r3 = new Noop(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Callable<Boolean> complete1 = failFirst ?
            () -> fst.completeExceptionally(ex) :
            () -> fst.complete(v1);
        final Callable<Boolean> complete2 = failFirst ?
            () -> snd.complete(v1) :
            () -> snd.completeExceptionally(ex);

        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
        assertTrue(complete1.call());
        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(complete2.call());
        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);

        checkCompletedWithWrappedException(h1, ex);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        r1.assertNotInvoked();
        r2.assertNotInvoked();
        r3.assertNotInvoked();
        checkCompletedNormally(failFirst ? snd : fst, v1);
        checkCompletedExceptionally(failFirst ? fst : snd, ex);
    }}

    /**
     * runAfterBoth result completes exceptionally if either source cancelled
     */
    public void testRunAfterBoth_sourceCancelled() throws Throwable {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (boolean fFirst : new boolean[] { true, false })
        for (boolean failFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final Noop r1 = new Noop(m);
        final Noop r2 = new Noop(m);
        final Noop r3 = new Noop(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Callable<Boolean> complete1 = failFirst ?
            () -> fst.cancel(mayInterruptIfRunning) :
            () -> fst.complete(v1);
        final Callable<Boolean> complete2 = failFirst ?
            () -> snd.complete(v1) :
            () -> snd.cancel(mayInterruptIfRunning);

        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
        assertTrue(complete1.call());
        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(complete2.call());
        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);

        checkCompletedWithWrappedCancellationException(h1);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        r1.assertNotInvoked();
        r2.assertNotInvoked();
        r3.assertNotInvoked();
        checkCompletedNormally(failFirst ? snd : fst, v1);
        checkCancelled(failFirst ? fst : snd);
    }}

    /**
     * runAfterBoth result completes exceptionally if action does
     */
    public void testRunAfterBoth_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final FailingRunnable r1 = new FailingRunnable(m);
        final FailingRunnable r2 = new FailingRunnable(m);
        final FailingRunnable r3 = new FailingRunnable(m);

        final CompletableFuture<Integer> fst =  fFirst ? f : g;
        final CompletableFuture<Integer> snd = !fFirst ? f : g;
        final Integer w1 =  fFirst ? v1 : v2;
        final Integer w2 = !fFirst ? v1 : v2;

        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
        assertTrue(fst.complete(w1));
        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
        assertTrue(snd.complete(w2));
        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);

        checkCompletedWithWrappedCFException(h1);
        checkCompletedWithWrappedCFException(h2);
        checkCompletedWithWrappedCFException(h3);
        r1.assertInvoked();
        r2.assertInvoked();
        r3.assertInvoked();
        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
    }}

    /**
     * applyToEither result completes normally after normal completion
     * of either source
     */
    public void testApplyToEither_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        rs[0].assertNotInvoked();
        rs[1].assertNotInvoked();
        f.complete(v1);
        checkCompletedNormally(h0, inc(v1));
        checkCompletedNormally(h1, inc(v1));
        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
        checkCompletedNormally(h2, inc(v1));
        checkCompletedNormally(h3, inc(v1));
        g.complete(v2);

        // unspecified behavior - both source completions available
        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
        rs[4].assertValue(h4.join());
        rs[5].assertValue(h5.join());
        assertTrue(Objects.equals(inc(v1), h4.join()) ||
                   Objects.equals(inc(v2), h4.join()));
        assertTrue(Objects.equals(inc(v1), h5.join()) ||
                   Objects.equals(inc(v2), h5.join()));

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
        checkCompletedNormally(h0, inc(v1));
        checkCompletedNormally(h1, inc(v1));
        checkCompletedNormally(h2, inc(v1));
        checkCompletedNormally(h3, inc(v1));
        for (int i = 0; i < 4; i++) rs[i].assertValue(inc(v1));
    }}

    /**
     * applyToEither result completes exceptionally after exceptional
     * completion of either source
     */
    public void testApplyToEither_exceptionalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CFException ex = new CFException();
        final IncFunction[] rs = new IncFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        rs[0].assertNotInvoked();
        rs[1].assertNotInvoked();
        f.completeExceptionally(ex);
        checkCompletedWithWrappedException(h0, ex);
        checkCompletedWithWrappedException(h1, ex);
        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        g.complete(v1);

        // unspecified behavior - both source completions available
        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
        try {
            assertEquals(inc(v1), h4.join());
            rs[4].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h4, ex);
            rs[4].assertNotInvoked();
        }
        try {
            assertEquals(inc(v1), h5.join());
            rs[5].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h5, ex);
            rs[5].assertNotInvoked();
        }

        checkCompletedExceptionally(f, ex);
        checkCompletedNormally(g, v1);
        checkCompletedWithWrappedException(h0, ex);
        checkCompletedWithWrappedException(h1, ex);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        checkCompletedWithWrappedException(h4, ex);
        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
    }}

    public void testApplyToEither_exceptionalCompletion2() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CFException ex = new CFException();
        final IncFunction[] rs = new IncFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
        assertTrue(fFirst ? f.complete(v1) : g.completeExceptionally(ex));
        assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex));
        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);

        // unspecified behavior - both source completions available
        try {
            assertEquals(inc(v1), h0.join());
            rs[0].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h0, ex);
            rs[0].assertNotInvoked();
        }
        try {
            assertEquals(inc(v1), h1.join());
            rs[1].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h1, ex);
            rs[1].assertNotInvoked();
        }
        try {
            assertEquals(inc(v1), h2.join());
            rs[2].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h2, ex);
            rs[2].assertNotInvoked();
        }
        try {
            assertEquals(inc(v1), h3.join());
            rs[3].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h3, ex);
            rs[3].assertNotInvoked();
        }

        checkCompletedNormally(f, v1);
        checkCompletedExceptionally(g, ex);
    }}

    /**
     * applyToEither result completes exceptionally if either source cancelled
     */
    public void testApplyToEither_sourceCancelled() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        rs[0].assertNotInvoked();
        rs[1].assertNotInvoked();
        f.cancel(mayInterruptIfRunning);
        checkCompletedWithWrappedCancellationException(h0);
        checkCompletedWithWrappedCancellationException(h1);
        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        g.complete(v1);

        // unspecified behavior - both source completions available
        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
        try {
            assertEquals(inc(v1), h4.join());
            rs[4].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h4);
            rs[4].assertNotInvoked();
        }
        try {
            assertEquals(inc(v1), h5.join());
            rs[5].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h5);
            rs[5].assertNotInvoked();
        }

        checkCancelled(f);
        checkCompletedNormally(g, v1);
        checkCompletedWithWrappedCancellationException(h0);
        checkCompletedWithWrappedCancellationException(h1);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
    }}

    public void testApplyToEither_sourceCancelled2() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
        assertTrue(fFirst ? f.complete(v1) : g.cancel(mayInterruptIfRunning));
        assertTrue(!fFirst ? f.complete(v1) : g.cancel(mayInterruptIfRunning));
        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);

        // unspecified behavior - both source completions available
        try {
            assertEquals(inc(v1), h0.join());
            rs[0].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h0);
            rs[0].assertNotInvoked();
        }
        try {
            assertEquals(inc(v1), h1.join());
            rs[1].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h1);
            rs[1].assertNotInvoked();
        }
        try {
            assertEquals(inc(v1), h2.join());
            rs[2].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h2);
            rs[2].assertNotInvoked();
        }
        try {
            assertEquals(inc(v1), h3.join());
            rs[3].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h3);
            rs[3].assertNotInvoked();
        }

        checkCompletedNormally(f, v1);
        checkCancelled(g);
    }}

    /**
     * applyToEither result completes exceptionally if action does
     */
    public void testApplyToEither_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final FailingFunction[] rs = new FailingFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m);

        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
        f.complete(v1);
        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
        checkCompletedWithWrappedCFException(h0);
        checkCompletedWithWrappedCFException(h1);
        checkCompletedWithWrappedCFException(h2);
        checkCompletedWithWrappedCFException(h3);
        for (int i = 0; i < 4; i++) rs[i].assertValue(v1);

        g.complete(v2);

        // unspecified behavior - both source completions available
        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);

        checkCompletedWithWrappedCFException(h4);
        assertTrue(Objects.equals(v1, rs[4].value) ||
                   Objects.equals(v2, rs[4].value));
        checkCompletedWithWrappedCFException(h5);
        assertTrue(Objects.equals(v1, rs[5].value) ||
                   Objects.equals(v2, rs[5].value));

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
    }}

    /**
     * acceptEither result completes normally after normal completion
     * of either source
     */
    public void testAcceptEither_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final NoopConsumer[] rs = new NoopConsumer[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);

        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        rs[0].assertNotInvoked();
        rs[1].assertNotInvoked();
        f.complete(v1);
        checkCompletedNormally(h0, null);
        checkCompletedNormally(h1, null);
        rs[0].assertValue(v1);
        rs[1].assertValue(v1);
        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
        checkCompletedNormally(h2, null);
        checkCompletedNormally(h3, null);
        rs[2].assertValue(v1);
        rs[3].assertValue(v1);
        g.complete(v2);

        // unspecified behavior - both source completions available
        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
        checkCompletedNormally(h4, null);
        checkCompletedNormally(h5, null);
        assertTrue(Objects.equals(v1, rs[4].value) ||
                   Objects.equals(v2, rs[4].value));
        assertTrue(Objects.equals(v1, rs[5].value) ||
                   Objects.equals(v2, rs[5].value));

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
        checkCompletedNormally(h0, null);
        checkCompletedNormally(h1, null);
        checkCompletedNormally(h2, null);
        checkCompletedNormally(h3, null);
        for (int i = 0; i < 4; i++) rs[i].assertValue(v1);
    }}

    /**
     * acceptEither result completes exceptionally after exceptional
     * completion of either source
     */
    public void testAcceptEither_exceptionalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CFException ex = new CFException();
        final NoopConsumer[] rs = new NoopConsumer[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);

        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        rs[0].assertNotInvoked();
        rs[1].assertNotInvoked();
        f.completeExceptionally(ex);
        checkCompletedWithWrappedException(h0, ex);
        checkCompletedWithWrappedException(h1, ex);
        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);

        g.complete(v1);

        // unspecified behavior - both source completions available
        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
        try {
            assertNull(h4.join());
            rs[4].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h4, ex);
            rs[4].assertNotInvoked();
        }
        try {
            assertNull(h5.join());
            rs[5].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h5, ex);
            rs[5].assertNotInvoked();
        }

        checkCompletedExceptionally(f, ex);
        checkCompletedNormally(g, v1);
        checkCompletedWithWrappedException(h0, ex);
        checkCompletedWithWrappedException(h1, ex);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        checkCompletedWithWrappedException(h4, ex);
        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
    }}

    public void testAcceptEither_exceptionalCompletion2() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CFException ex = new CFException();
        final NoopConsumer[] rs = new NoopConsumer[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);

        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
        assertTrue(fFirst ? f.complete(v1) : g.completeExceptionally(ex));
        assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex));
        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);

        // unspecified behavior - both source completions available
        try {
            assertEquals(null, h0.join());
            rs[0].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h0, ex);
            rs[0].assertNotInvoked();
        }
        try {
            assertEquals(null, h1.join());
            rs[1].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h1, ex);
            rs[1].assertNotInvoked();
        }
        try {
            assertEquals(null, h2.join());
            rs[2].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h2, ex);
            rs[2].assertNotInvoked();
        }
        try {
            assertEquals(null, h3.join());
            rs[3].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h3, ex);
            rs[3].assertNotInvoked();
        }

        checkCompletedNormally(f, v1);
        checkCompletedExceptionally(g, ex);
    }}

    /**
     * acceptEither result completes exceptionally if either source cancelled
     */
    public void testAcceptEither_sourceCancelled() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final NoopConsumer[] rs = new NoopConsumer[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);

        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        rs[0].assertNotInvoked();
        rs[1].assertNotInvoked();
        f.cancel(mayInterruptIfRunning);
        checkCompletedWithWrappedCancellationException(h0);
        checkCompletedWithWrappedCancellationException(h1);
        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);

        g.complete(v1);

        // unspecified behavior - both source completions available
        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
        try {
            assertNull(h4.join());
            rs[4].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h4);
            rs[4].assertNotInvoked();
        }
        try {
            assertNull(h5.join());
            rs[5].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h5);
            rs[5].assertNotInvoked();
        }

        checkCancelled(f);
        checkCompletedNormally(g, v1);
        checkCompletedWithWrappedCancellationException(h0);
        checkCompletedWithWrappedCancellationException(h1);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
    }}

    /**
     * acceptEither result completes exceptionally if action does
     */
    public void testAcceptEither_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final FailingConsumer[] rs = new FailingConsumer[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new FailingConsumer(m);

        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
        f.complete(v1);
        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
        checkCompletedWithWrappedCFException(h0);
        checkCompletedWithWrappedCFException(h1);
        checkCompletedWithWrappedCFException(h2);
        checkCompletedWithWrappedCFException(h3);
        for (int i = 0; i < 4; i++) rs[i].assertValue(v1);

        g.complete(v2);

        // unspecified behavior - both source completions available
        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);

        checkCompletedWithWrappedCFException(h4);
        assertTrue(Objects.equals(v1, rs[4].value) ||
                   Objects.equals(v2, rs[4].value));
        checkCompletedWithWrappedCFException(h5);
        assertTrue(Objects.equals(v1, rs[5].value) ||
                   Objects.equals(v2, rs[5].value));

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
    }}

    /**
     * runAfterEither result completes normally after normal completion
     * of either source
     */
    public void testRunAfterEither_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final Noop[] rs = new Noop[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);

        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        rs[0].assertNotInvoked();
        rs[1].assertNotInvoked();
        f.complete(v1);
        checkCompletedNormally(h0, null);
        checkCompletedNormally(h1, null);
        rs[0].assertInvoked();
        rs[1].assertInvoked();
        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
        checkCompletedNormally(h2, null);
        checkCompletedNormally(h3, null);
        rs[2].assertInvoked();
        rs[3].assertInvoked();

        g.complete(v2);

        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
        checkCompletedNormally(h0, null);
        checkCompletedNormally(h1, null);
        checkCompletedNormally(h2, null);
        checkCompletedNormally(h3, null);
        checkCompletedNormally(h4, null);
        checkCompletedNormally(h5, null);
        for (int i = 0; i < 6; i++) rs[i].assertInvoked();
    }}

    /**
     * runAfterEither result completes exceptionally after exceptional
     * completion of either source
     */
    public void testRunAfterEither_exceptionalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CFException ex = new CFException();
        final Noop[] rs = new Noop[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);

        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        rs[0].assertNotInvoked();
        rs[1].assertNotInvoked();
        assertTrue(f.completeExceptionally(ex));
        checkCompletedWithWrappedException(h0, ex);
        checkCompletedWithWrappedException(h1, ex);
        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);

        assertTrue(g.complete(v1));

        // unspecified behavior - both source completions available
        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
        try {
            assertNull(h4.join());
            rs[4].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h4, ex);
            rs[4].assertNotInvoked();
        }
        try {
            assertNull(h5.join());
            rs[5].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h5, ex);
            rs[5].assertNotInvoked();
        }

        checkCompletedExceptionally(f, ex);
        checkCompletedNormally(g, v1);
        checkCompletedWithWrappedException(h0, ex);
        checkCompletedWithWrappedException(h1, ex);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        checkCompletedWithWrappedException(h4, ex);
        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
    }}

    public void testRunAfterEither_exceptionalCompletion2() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean fFirst : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CFException ex = new CFException();
        final Noop[] rs = new Noop[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);

        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
        assertTrue( fFirst ? f.complete(v1) : g.completeExceptionally(ex));
        assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex));
        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);

        // unspecified behavior - both source completions available
        try {
            assertEquals(null, h0.join());
            rs[0].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h0, ex);
            rs[0].assertNotInvoked();
        }
        try {
            assertEquals(null, h1.join());
            rs[1].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h1, ex);
            rs[1].assertNotInvoked();
        }
        try {
            assertEquals(null, h2.join());
            rs[2].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h2, ex);
            rs[2].assertNotInvoked();
        }
        try {
            assertEquals(null, h3.join());
            rs[3].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h3, ex);
            rs[3].assertNotInvoked();
        }

        checkCompletedNormally(f, v1);
        checkCompletedExceptionally(g, ex);
    }}

    /**
     * runAfterEither result completes exceptionally if either source cancelled
     */
    public void testRunAfterEither_sourceCancelled() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final Noop[] rs = new Noop[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);

        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        rs[0].assertNotInvoked();
        rs[1].assertNotInvoked();
        f.cancel(mayInterruptIfRunning);
        checkCompletedWithWrappedCancellationException(h0);
        checkCompletedWithWrappedCancellationException(h1);
        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);

        assertTrue(g.complete(v1));

        // unspecified behavior - both source completions available
        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
        try {
            assertNull(h4.join());
            rs[4].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h4);
            rs[4].assertNotInvoked();
        }
        try {
            assertNull(h5.join());
            rs[5].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h5);
            rs[5].assertNotInvoked();
        }

        checkCancelled(f);
        checkCompletedNormally(g, v1);
        checkCompletedWithWrappedCancellationException(h0);
        checkCompletedWithWrappedCancellationException(h1);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
    }}

    /**
     * runAfterEither result completes exceptionally if action does
     */
    public void testRunAfterEither_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Integer v1 : new Integer[] { 1, null })
        for (Integer v2 : new Integer[] { 2, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final FailingRunnable[] rs = new FailingRunnable[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new FailingRunnable(m);

        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
        assertTrue(f.complete(v1));
        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
        checkCompletedWithWrappedCFException(h0);
        checkCompletedWithWrappedCFException(h1);
        checkCompletedWithWrappedCFException(h2);
        checkCompletedWithWrappedCFException(h3);
        for (int i = 0; i < 4; i++) rs[i].assertInvoked();
        assertTrue(g.complete(v2));
        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
        checkCompletedWithWrappedCFException(h4);
        checkCompletedWithWrappedCFException(h5);

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v2);
        for (int i = 0; i < 6; i++) rs[i].assertInvoked();
    }}

    /**
     * thenCompose result completes normally after normal completion of source
     */
    public void testThenCompose_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFutureInc r = new CompletableFutureInc(m);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Integer> g = m.thenCompose(f, r);
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(g, inc(v1));
        checkCompletedNormally(f, v1);
        r.assertValue(v1);
    }}

    /**
     * thenCompose result completes exceptionally after exceptional
     * completion of source
     */
    public void testThenCompose_exceptionalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final CFException ex = new CFException();
        final CompletableFutureInc r = new CompletableFutureInc(m);
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletableFuture<Integer> g = m.thenCompose(f, r);
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedWithWrappedException(g, ex);
        checkCompletedExceptionally(f, ex);
        r.assertNotInvoked();
    }}

    /**
     * thenCompose result completes exceptionally if action does
     */
    public void testThenCompose_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final FailingCompletableFutureFunction r
            = new FailingCompletableFutureFunction(m);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Integer> g = m.thenCompose(f, r);
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedWithWrappedCFException(g);
        checkCompletedNormally(f, v1);
    }}

    /**
     * thenCompose result completes exceptionally if source cancelled
     */
    public void testThenCompose_sourceCancelled() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
    {
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFutureInc r = new CompletableFutureInc(m);
        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Integer> g = m.thenCompose(f, r);
        if (createIncomplete) {
            checkIncomplete(g);
            assertTrue(f.cancel(mayInterruptIfRunning));
        }

        checkCompletedWithWrappedCancellationException(g);
        checkCancelled(f);
    }}

    /**
     * thenCompose result completes exceptionally if the result of the action does
     */
    public void testThenCompose_actionReturnsFailingFuture() {
        for (ExecutionMode m : ExecutionMode.values())
        for (int order = 0; order < 6; order++)
        for (Integer v1 : new Integer[] { 1, null })
    {
        final CFException ex = new CFException();
        final CompletableFuture<Integer> f = new CompletableFuture<>();
        final CompletableFuture<Integer> g = new CompletableFuture<>();
        final CompletableFuture<Integer> h;
        // Test all permutations of orders
        switch (order) {
        case 0:
            assertTrue(f.complete(v1));
            assertTrue(g.completeExceptionally(ex));
            h = m.thenCompose(f, (x -> g));
            break;
        case 1:
            assertTrue(f.complete(v1));
            h = m.thenCompose(f, (x -> g));
            assertTrue(g.completeExceptionally(ex));
            break;
        case 2:
            assertTrue(g.completeExceptionally(ex));
            assertTrue(f.complete(v1));
            h = m.thenCompose(f, (x -> g));
            break;
        case 3:
            assertTrue(g.completeExceptionally(ex));
            h = m.thenCompose(f, (x -> g));
            assertTrue(f.complete(v1));
            break;
        case 4:
            h = m.thenCompose(f, (x -> g));
            assertTrue(f.complete(v1));
            assertTrue(g.completeExceptionally(ex));
            break;
        case 5:
            h = m.thenCompose(f, (x -> g));
            assertTrue(f.complete(v1));
            assertTrue(g.completeExceptionally(ex));
            break;
        default: throw new AssertionError();
        }

        checkCompletedExceptionally(g, ex);
        checkCompletedWithWrappedException(h, ex);
        checkCompletedNormally(f, v1);
    }}

    // other static methods

    /**
     * allOf(no component futures) returns a future completed normally
     * with the value null
     */
    public void testAllOf_empty() throws Exception {
        CompletableFuture<Void> f = CompletableFuture.allOf();
        checkCompletedNormally(f, null);
    }

    /**
     * allOf returns a future completed normally with the value null
     * when all components complete normally
     */
    public void testAllOf_normal() throws Exception {
        for (int k = 1; k < 10; k++) {
            CompletableFuture<Integer>[] fs
                = (CompletableFuture<Integer>[]) new CompletableFuture[k];
            for (int i = 0; i < k; i++)
                fs[i] = new CompletableFuture<>();
            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
            for (int i = 0; i < k; i++) {
                checkIncomplete(f);
                checkIncomplete(CompletableFuture.allOf(fs));
                fs[i].complete(one);
            }
            checkCompletedNormally(f, null);
            checkCompletedNormally(CompletableFuture.allOf(fs), null);
        }
    }

    public void testAllOf_backwards() throws Exception {
        for (int k = 1; k < 10; k++) {
            CompletableFuture<Integer>[] fs
                = (CompletableFuture<Integer>[]) new CompletableFuture[k];
            for (int i = 0; i < k; i++)
                fs[i] = new CompletableFuture<>();
            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
            for (int i = k - 1; i >= 0; i--) {
                checkIncomplete(f);
                checkIncomplete(CompletableFuture.allOf(fs));
                fs[i].complete(one);
            }
            checkCompletedNormally(f, null);
            checkCompletedNormally(CompletableFuture.allOf(fs), null);
        }
    }

    public void testAllOf_exceptional() throws Exception {
        for (int k = 1; k < 10; k++) {
            CompletableFuture<Integer>[] fs
                = (CompletableFuture<Integer>[]) new CompletableFuture[k];
            CFException ex = new CFException();
            for (int i = 0; i < k; i++)
                fs[i] = new CompletableFuture<>();
            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
            for (int i = 0; i < k; i++) {
                checkIncomplete(f);
                checkIncomplete(CompletableFuture.allOf(fs));
                if (i != k / 2) {
                    fs[i].complete(i);
                    checkCompletedNormally(fs[i], i);
                } else {
                    fs[i].completeExceptionally(ex);
                    checkCompletedExceptionally(fs[i], ex);
                }
            }
            checkCompletedWithWrappedException(f, ex);
            checkCompletedWithWrappedException(CompletableFuture.allOf(fs), ex);
        }
    }

    /**
     * anyOf(no component futures) returns an incomplete future
     */
    public void testAnyOf_empty() throws Exception {
        for (Integer v1 : new Integer[] { 1, null })
    {
        CompletableFuture<Object> f = CompletableFuture.anyOf();
        checkIncomplete(f);

        f.complete(v1);
        checkCompletedNormally(f, v1);
    }}

    /**
     * anyOf returns a future completed normally with a value when
     * a component future does
     */
    public void testAnyOf_normal() throws Exception {
        for (int k = 0; k < 10; k++) {
            CompletableFuture[] fs = new CompletableFuture[k];
            for (int i = 0; i < k; i++)
                fs[i] = new CompletableFuture<>();
            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
            checkIncomplete(f);
            for (int i = 0; i < k; i++) {
                fs[i].complete(i);
                checkCompletedNormally(f, 0);
                int x = (int) CompletableFuture.anyOf(fs).join();
                assertTrue(0 <= x && x <= i);
            }
        }
    }
    public void testAnyOf_normal_backwards() throws Exception {
        for (int k = 0; k < 10; k++) {
            CompletableFuture[] fs = new CompletableFuture[k];
            for (int i = 0; i < k; i++)
                fs[i] = new CompletableFuture<>();
            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
            checkIncomplete(f);
            for (int i = k - 1; i >= 0; i--) {
                fs[i].complete(i);
                checkCompletedNormally(f, k - 1);
                int x = (int) CompletableFuture.anyOf(fs).join();
                assertTrue(i <= x && x <= k - 1);
            }
        }
    }

    /**
     * anyOf result completes exceptionally when any component does.
     */
    public void testAnyOf_exceptional() throws Exception {
        for (int k = 0; k < 10; k++) {
            CompletableFuture[] fs = new CompletableFuture[k];
            CFException[] exs = new CFException[k];
            for (int i = 0; i < k; i++) {
                fs[i] = new CompletableFuture<>();
                exs[i] = new CFException();
            }
            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
            checkIncomplete(f);
            for (int i = 0; i < k; i++) {
                fs[i].completeExceptionally(exs[i]);
                checkCompletedWithWrappedException(f, exs[0]);
                checkCompletedWithWrappedCFException(CompletableFuture.anyOf(fs));
            }
        }
    }

    public void testAnyOf_exceptional_backwards() throws Exception {
        for (int k = 0; k < 10; k++) {
            CompletableFuture[] fs = new CompletableFuture[k];
            CFException[] exs = new CFException[k];
            for (int i = 0; i < k; i++) {
                fs[i] = new CompletableFuture<>();
                exs[i] = new CFException();
            }
            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
            checkIncomplete(f);
            for (int i = k - 1; i >= 0; i--) {
                fs[i].completeExceptionally(exs[i]);
                checkCompletedWithWrappedException(f, exs[k - 1]);
                checkCompletedWithWrappedCFException(CompletableFuture.anyOf(fs));
            }
        }
    }

    /**
     * Completion methods throw NullPointerException with null arguments
     */
    public void testNPE() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CompletableFuture<Integer> g = new CompletableFuture<>();
        CompletableFuture<Integer> nullFuture = (CompletableFuture<Integer>)null;
        ThreadExecutor exec = new ThreadExecutor();

        Runnable[] throwingActions = {
            () -> CompletableFuture.supplyAsync(null),
            () -> CompletableFuture.supplyAsync(null, exec),
            () -> CompletableFuture.supplyAsync(new IntegerSupplier(ExecutionMode.SYNC, 42), null),

            () -> CompletableFuture.runAsync(null),
            () -> CompletableFuture.runAsync(null, exec),
            () -> CompletableFuture.runAsync(() -> {}, null),

            () -> f.completeExceptionally(null),

            () -> f.thenApply(null),
            () -> f.thenApplyAsync(null),
            () -> f.thenApplyAsync((x) -> x, null),
            () -> f.thenApplyAsync(null, exec),

            () -> f.thenAccept(null),
            () -> f.thenAcceptAsync(null),
            () -> f.thenAcceptAsync((x) -> {} , null),
            () -> f.thenAcceptAsync(null, exec),

            () -> f.thenRun(null),
            () -> f.thenRunAsync(null),
            () -> f.thenRunAsync(() -> {} , null),
            () -> f.thenRunAsync(null, exec),

            () -> f.thenCombine(g, null),
            () -> f.thenCombineAsync(g, null),
            () -> f.thenCombineAsync(g, null, exec),
            () -> f.thenCombine(nullFuture, (x, y) -> x),
            () -> f.thenCombineAsync(nullFuture, (x, y) -> x),
            () -> f.thenCombineAsync(nullFuture, (x, y) -> x, exec),
            () -> f.thenCombineAsync(g, (x, y) -> x, null),

            () -> f.thenAcceptBoth(g, null),
            () -> f.thenAcceptBothAsync(g, null),
            () -> f.thenAcceptBothAsync(g, null, exec),
            () -> f.thenAcceptBoth(nullFuture, (x, y) -> {}),
            () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}),
            () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}, exec),
            () -> f.thenAcceptBothAsync(g, (x, y) -> {}, null),

            () -> f.runAfterBoth(g, null),
            () -> f.runAfterBothAsync(g, null),
            () -> f.runAfterBothAsync(g, null, exec),
            () -> f.runAfterBoth(nullFuture, () -> {}),
            () -> f.runAfterBothAsync(nullFuture, () -> {}),
            () -> f.runAfterBothAsync(nullFuture, () -> {}, exec),
            () -> f.runAfterBothAsync(g, () -> {}, null),

            () -> f.applyToEither(g, null),
            () -> f.applyToEitherAsync(g, null),
            () -> f.applyToEitherAsync(g, null, exec),
            () -> f.applyToEither(nullFuture, (x) -> x),
            () -> f.applyToEitherAsync(nullFuture, (x) -> x),
            () -> f.applyToEitherAsync(nullFuture, (x) -> x, exec),
            () -> f.applyToEitherAsync(g, (x) -> x, null),

            () -> f.acceptEither(g, null),
            () -> f.acceptEitherAsync(g, null),
            () -> f.acceptEitherAsync(g, null, exec),
            () -> f.acceptEither(nullFuture, (x) -> {}),
            () -> f.acceptEitherAsync(nullFuture, (x) -> {}),
            () -> f.acceptEitherAsync(nullFuture, (x) -> {}, exec),
            () -> f.acceptEitherAsync(g, (x) -> {}, null),

            () -> f.runAfterEither(g, null),
            () -> f.runAfterEitherAsync(g, null),
            () -> f.runAfterEitherAsync(g, null, exec),
            () -> f.runAfterEither(nullFuture, () -> {}),
            () -> f.runAfterEitherAsync(nullFuture, () -> {}),
            () -> f.runAfterEitherAsync(nullFuture, () -> {}, exec),
            () -> f.runAfterEitherAsync(g, () -> {}, null),

            () -> f.thenCompose(null),
            () -> f.thenComposeAsync(null),
            () -> f.thenComposeAsync(new CompletableFutureInc(ExecutionMode.EXECUTOR), null),
            () -> f.thenComposeAsync(null, exec),

            () -> f.exceptionally(null),

            () -> f.handle(null),

            () -> CompletableFuture.allOf((CompletableFuture<?>)null),
            () -> CompletableFuture.allOf((CompletableFuture<?>[])null),
            () -> CompletableFuture.allOf(f, null),
            () -> CompletableFuture.allOf(null, f),

            () -> CompletableFuture.anyOf((CompletableFuture<?>)null),
            () -> CompletableFuture.anyOf((CompletableFuture<?>[])null),
            () -> CompletableFuture.anyOf(f, null),
            () -> CompletableFuture.anyOf(null, f),

            () -> f.obtrudeException(null),

            () -> CompletableFuture.delayedExecutor(1L, SECONDS, null),
            () -> CompletableFuture.delayedExecutor(1L, null, new ThreadExecutor()),
            () -> CompletableFuture.delayedExecutor(1L, null),

            () -> f.orTimeout(1L, null),
            () -> f.completeOnTimeout(42, 1L, null),

            () -> CompletableFuture.failedFuture(null),
            () -> CompletableFuture.failedStage(null),
        };

        assertThrows(NullPointerException.class, throwingActions);
        assertEquals(0, exec.count.get());
    }

    /**
     * toCompletableFuture returns this CompletableFuture.
     */
    public void testToCompletableFuture() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        assertSame(f, f.toCompletableFuture());
    }

    // jdk9

    /**
     * newIncompleteFuture returns an incomplete CompletableFuture
     */
    public void testNewIncompleteFuture() {
        for (Integer v1 : new Integer[] { 1, null })
    {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CompletableFuture<Integer> g = f.newIncompleteFuture();
        checkIncomplete(f);
        checkIncomplete(g);
        f.complete(v1);
        checkCompletedNormally(f, v1);
        checkIncomplete(g);
        g.complete(v1);
        checkCompletedNormally(g, v1);
        assertSame(g.getClass(), CompletableFuture.class);
    }}

    /**
     * completedStage returns a completed CompletionStage
     */
    public void testCompletedStage() {
        AtomicInteger x = new AtomicInteger(0);
        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
        CompletionStage<Integer> f = CompletableFuture.completedStage(1);
        f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
        assertEquals(x.get(), 1);
        assertNull(r.get());
    }

    /**
     * defaultExecutor by default returns the commonPool if
     * it supports more than one thread.
     */
    public void testDefaultExecutor() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        Executor e = f.defaultExecutor();
        Executor c = ForkJoinPool.commonPool();
        if (ForkJoinPool.getCommonPoolParallelism() > 1)
            assertSame(e, c);
        else
            assertNotSame(e, c);
    }

    /**
     * failedFuture returns a CompletableFuture completed
     * exceptionally with the given Exception
     */
    public void testFailedFuture() {
        CFException ex = new CFException();
        CompletableFuture<Integer> f = CompletableFuture.failedFuture(ex);
        checkCompletedExceptionally(f, ex);
    }

    /**
     * failedFuture(null) throws NPE
     */
    public void testFailedFuture_null() {
        try {
            CompletableFuture<Integer> f = CompletableFuture.failedFuture(null);
            shouldThrow();
        } catch (NullPointerException success) {}
    }

    /**
     * copy returns a CompletableFuture that is completed normally,
     * with the same value, when source is.
     */
    public void testCopy() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CompletableFuture<Integer> g = f.copy();
        checkIncomplete(f);
        checkIncomplete(g);
        f.complete(1);
        checkCompletedNormally(f, 1);
        checkCompletedNormally(g, 1);
    }

    /**
     * copy returns a CompletableFuture that is completed exceptionally
     * when source is.
     */
    public void testCopy2() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CompletableFuture<Integer> g = f.copy();
        checkIncomplete(f);
        checkIncomplete(g);
        CFException ex = new CFException();
        f.completeExceptionally(ex);
        checkCompletedExceptionally(f, ex);
        checkCompletedWithWrappedException(g, ex);
    }

    /**
     * minimalCompletionStage returns a CompletableFuture that is
     * completed normally, with the same value, when source is.
     */
    public void testMinimalCompletionStage() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CompletionStage<Integer> g = f.minimalCompletionStage();
        AtomicInteger x = new AtomicInteger(0);
        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
        checkIncomplete(f);
        g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
        f.complete(1);
        checkCompletedNormally(f, 1);
        assertEquals(x.get(), 1);
        assertNull(r.get());
    }

    /**
     * minimalCompletionStage returns a CompletableFuture that is
     * completed exceptionally when source is.
     */
    public void testMinimalCompletionStage2() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CompletionStage<Integer> g = f.minimalCompletionStage();
        AtomicInteger x = new AtomicInteger(0);
        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
        g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
        checkIncomplete(f);
        CFException ex = new CFException();
        f.completeExceptionally(ex);
        checkCompletedExceptionally(f, ex);
        assertEquals(x.get(), 0);
        assertEquals(r.get().getCause(), ex);
    }

    /**
     * failedStage returns a CompletionStage completed
     * exceptionally with the given Exception
     */
    public void testFailedStage() {
        CFException ex = new CFException();
        CompletionStage<Integer> f = CompletableFuture.failedStage(ex);
        AtomicInteger x = new AtomicInteger(0);
        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
        f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
        assertEquals(x.get(), 0);
        assertEquals(r.get(), ex);
    }

    /**
     * completeAsync completes with value of given supplier
     */
    public void testCompleteAsync() {
        for (Integer v1 : new Integer[] { 1, null })
    {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        f.completeAsync(() -> v1);
        f.join();
        checkCompletedNormally(f, v1);
    }}

    /**
     * completeAsync completes exceptionally if given supplier throws
     */
    public void testCompleteAsync2() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CFException ex = new CFException();
        f.completeAsync(() -> {if (true) throw ex; return 1;});
        try {
            f.join();
            shouldThrow();
        } catch (CompletionException success) {}
        checkCompletedWithWrappedException(f, ex);
    }

    /**
     * completeAsync with given executor completes with value of given supplier
     */
    public void testCompleteAsync3() {
        for (Integer v1 : new Integer[] { 1, null })
    {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        ThreadExecutor executor = new ThreadExecutor();
        f.completeAsync(() -> v1, executor);
        assertSame(v1, f.join());
        checkCompletedNormally(f, v1);
        assertEquals(1, executor.count.get());
    }}

    /**
     * completeAsync with given executor completes exceptionally if
     * given supplier throws
     */
    public void testCompleteAsync4() {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CFException ex = new CFException();
        ThreadExecutor executor = new ThreadExecutor();
        f.completeAsync(() -> {if (true) throw ex; return 1;}, executor);
        try {
            f.join();
            shouldThrow();
        } catch (CompletionException success) {}
        checkCompletedWithWrappedException(f, ex);
        assertEquals(1, executor.count.get());
    }

    /**
     * orTimeout completes with TimeoutException if not complete
     */
    public void testOrTimeout_timesOut() {
        long timeoutMillis = timeoutMillis();
        CompletableFuture<Integer> f = new CompletableFuture<>();
        long startTime = System.nanoTime();
        f.orTimeout(timeoutMillis, MILLISECONDS);
        checkCompletedWithTimeoutException(f);
        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
    }

    /**
     * orTimeout completes normally if completed before timeout
     */
    public void testOrTimeout_completed() {
        for (Integer v1 : new Integer[] { 1, null })
    {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CompletableFuture<Integer> g = new CompletableFuture<>();
        long startTime = System.nanoTime();
        f.complete(v1);
        f.orTimeout(LONG_DELAY_MS, MILLISECONDS);
        g.orTimeout(LONG_DELAY_MS, MILLISECONDS);
        g.complete(v1);
        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v1);
        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
    }}

    /**
     * completeOnTimeout completes with given value if not complete
     */
    public void testCompleteOnTimeout_timesOut() {
        testInParallel(() -> testCompleteOnTimeout_timesOut(42),
                       () -> testCompleteOnTimeout_timesOut(null));
    }

    public void testCompleteOnTimeout_timesOut(Integer v) {
        long timeoutMillis = timeoutMillis();
        CompletableFuture<Integer> f = new CompletableFuture<>();
        long startTime = System.nanoTime();
        f.completeOnTimeout(v, timeoutMillis, MILLISECONDS);
        assertSame(v, f.join());
        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
        f.complete(99);         // should have no effect
        checkCompletedNormally(f, v);
    }

    /**
     * completeOnTimeout has no effect if completed within timeout
     */
    public void testCompleteOnTimeout_completed() {
        for (Integer v1 : new Integer[] { 1, null })
    {
        CompletableFuture<Integer> f = new CompletableFuture<>();
        CompletableFuture<Integer> g = new CompletableFuture<>();
        long startTime = System.nanoTime();
        f.complete(v1);
        f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS);
        g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS);
        g.complete(v1);
        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v1);
        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
    }}

    /**
     * delayedExecutor returns an executor that delays submission
     */
    public void testDelayedExecutor() {
        testInParallel(() -> testDelayedExecutor(null, null),
                       () -> testDelayedExecutor(null, 1),
                       () -> testDelayedExecutor(new ThreadExecutor(), 1),
                       () -> testDelayedExecutor(new ThreadExecutor(), 1));
    }

    public void testDelayedExecutor(Executor executor, Integer v) throws Exception {
        long timeoutMillis = timeoutMillis();
        // Use an "unreasonably long" long timeout to catch lingering threads
        long longTimeoutMillis = 1000 * 60 * 60 * 24;
        final Executor delayer, longDelayer;
        if (executor == null) {
            delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS);
            longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS);
        } else {
            delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS, executor);
            longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS, executor);
        }
        long startTime = System.nanoTime();
        CompletableFuture<Integer> f =
            CompletableFuture.supplyAsync(() -> v, delayer);
        CompletableFuture<Integer> g =
            CompletableFuture.supplyAsync(() -> v, longDelayer);

        assertNull(g.getNow(null));

        assertSame(v, f.get(LONG_DELAY_MS, MILLISECONDS));
        long millisElapsed = millisElapsedSince(startTime);
        assertTrue(millisElapsed >= timeoutMillis);
        assertTrue(millisElapsed < LONG_DELAY_MS / 2);

        checkCompletedNormally(f, v);

        checkIncomplete(g);
        assertTrue(g.cancel(true));
    }

    //--- tests of implementation details; not part of official tck ---

    Object resultOf(CompletableFuture<?> f) {
        try {
            java.lang.reflect.Field resultField
                = CompletableFuture.class.getDeclaredField("result");
            resultField.setAccessible(true);
            return resultField.get(f);
        } catch (Throwable t) { throw new AssertionError(t); }
    }

    public void testExceptionPropagationReusesResultObject() {
        if (!testImplementationDetails) return;
        for (ExecutionMode m : ExecutionMode.values())
    {
        final CFException ex = new CFException();
        final CompletableFuture<Integer> v42 = CompletableFuture.completedFuture(42);
        final CompletableFuture<Integer> incomplete = new CompletableFuture<>();

        List<Function<CompletableFuture<Integer>, CompletableFuture<?>>> funs
            = new ArrayList<>();

        funs.add((y) -> m.thenRun(y, new Noop(m)));
        funs.add((y) -> m.thenAccept(y, new NoopConsumer(m)));
        funs.add((y) -> m.thenApply(y, new IncFunction(m)));

        funs.add((y) -> m.runAfterEither(y, incomplete, new Noop(m)));
        funs.add((y) -> m.acceptEither(y, incomplete, new NoopConsumer(m)));
        funs.add((y) -> m.applyToEither(y, incomplete, new IncFunction(m)));

        funs.add((y) -> m.runAfterBoth(y, v42, new Noop(m)));
        funs.add((y) -> m.thenAcceptBoth(y, v42, new SubtractAction(m)));
        funs.add((y) -> m.thenCombine(y, v42, new SubtractFunction(m)));

        funs.add((y) -> m.whenComplete(y, (Integer r, Throwable t) -> {}));

        funs.add((y) -> m.thenCompose(y, new CompletableFutureInc(m)));

        funs.add((y) -> CompletableFuture.allOf(new CompletableFuture<?>[] {y, v42}));
        funs.add((y) -> CompletableFuture.anyOf(new CompletableFuture<?>[] {y, incomplete}));

        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
                 fun : funs) {
            CompletableFuture<Integer> f = new CompletableFuture<>();
            f.completeExceptionally(ex);
            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
            checkCompletedWithWrappedException(src, ex);
            CompletableFuture<?> dep = fun.apply(src);
            checkCompletedWithWrappedException(dep, ex);
            assertSame(resultOf(src), resultOf(dep));
        }

        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
                 fun : funs) {
            CompletableFuture<Integer> f = new CompletableFuture<>();
            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
            CompletableFuture<?> dep = fun.apply(src);
            f.completeExceptionally(ex);
            checkCompletedWithWrappedException(src, ex);
            checkCompletedWithWrappedException(dep, ex);
            assertSame(resultOf(src), resultOf(dep));
        }

        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
                 fun : funs) {
            CompletableFuture<Integer> f = new CompletableFuture<>();
            f.cancel(mayInterruptIfRunning);
            checkCancelled(f);
            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
            checkCompletedWithWrappedCancellationException(src);
            CompletableFuture<?> dep = fun.apply(src);
            checkCompletedWithWrappedCancellationException(dep);
            assertSame(resultOf(src), resultOf(dep));
        }

        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
                 fun : funs) {
            CompletableFuture<Integer> f = new CompletableFuture<>();
            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
            CompletableFuture<?> dep = fun.apply(src);
            f.cancel(mayInterruptIfRunning);
            checkCancelled(f);
            checkCompletedWithWrappedCancellationException(src);
            checkCompletedWithWrappedCancellationException(dep);
            assertSame(resultOf(src), resultOf(dep));
        }
    }}

    /**
     * Minimal completion stages throw UOE for all non-CompletionStage methods
     */
    public void testMinimalCompletionStage_minimality() {
        if (!testImplementationDetails) return;
        Function<Method, String> toSignature =
            (method) -> method.getName() + Arrays.toString(method.getParameterTypes());
        Predicate<Method> isNotStatic =
            (method) -> (method.getModifiers() & Modifier.STATIC) == 0;
        List<Method> minimalMethods =
            Stream.of(Object.class, CompletionStage.class)
            .flatMap((klazz) -> Stream.of(klazz.getMethods()))
            .filter(isNotStatic)
            .collect(Collectors.toList());
        // Methods from CompletableFuture permitted NOT to throw UOE
        String[] signatureWhitelist = {
            "newIncompleteFuture[]",
            "defaultExecutor[]",
            "minimalCompletionStage[]",
            "copy[]",
        };
        Set<String> permittedMethodSignatures =
            Stream.concat(minimalMethods.stream().map(toSignature),
                          Stream.of(signatureWhitelist))
            .collect(Collectors.toSet());
        List<Method> allMethods = Stream.of(CompletableFuture.class.getMethods())
            .filter(isNotStatic)
            .filter((method) -> !permittedMethodSignatures.contains(toSignature.apply(method)))
            .collect(Collectors.toList());

        CompletionStage<Integer> minimalStage =
            new CompletableFuture<Integer>().minimalCompletionStage();

        List<Method> bugs = new ArrayList<>();
        for (Method method : allMethods) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            Object[] args = new Object[parameterTypes.length];
            // Manufacture boxed primitives for primitive params
            for (int i = 0; i < args.length; i++) {
                Class<?> type = parameterTypes[i];
                if (parameterTypes[i] == boolean.class)
                    args[i] = false;
                else if (parameterTypes[i] == int.class)
                    args[i] = 0;
                else if (parameterTypes[i] == long.class)
                    args[i] = 0L;
            }
            try {
                method.invoke(minimalStage, args);
                bugs.add(method);
            }
            catch (java.lang.reflect.InvocationTargetException expected) {
                if (! (expected.getCause() instanceof UnsupportedOperationException)) {
                    bugs.add(method);
                    // expected.getCause().printStackTrace();
                }
            }
            catch (ReflectiveOperationException bad) { throw new Error(bad); }
        }
        if (!bugs.isEmpty())
            throw new Error("Methods did not throw UOE: " + bugs.toString());
    }

    static class Monad {
        static class ZeroException extends RuntimeException {
            public ZeroException() { super("monadic zero"); }
        }
        // "return", "unit"
        static <T> CompletableFuture<T> unit(T value) {
            return completedFuture(value);
        }
        // monadic zero ?
        static <T> CompletableFuture<T> zero() {
            return failedFuture(new ZeroException());
        }
        // >=>
        static <T,U,V> Function<T, CompletableFuture<V>> compose
            (Function<T, CompletableFuture<U>> f,
             Function<U, CompletableFuture<V>> g) {
            return (x) -> f.apply(x).thenCompose(g);
        }

        static void assertZero(CompletableFuture<?> f) {
            try {
                f.getNow(null);
                throw new AssertionFailedError("should throw");
            } catch (CompletionException success) {
                assertTrue(success.getCause() instanceof ZeroException);
            }
        }

        static <T> void assertFutureEquals(CompletableFuture<T> f,
                                           CompletableFuture<T> g) {
            T fval = null, gval = null;
            Throwable fex = null, gex = null;

            try { fval = f.get(); }
            catch (ExecutionException ex) { fex = ex.getCause(); }
            catch (Throwable ex) { fex = ex; }

            try { gval = g.get(); }
            catch (ExecutionException ex) { gex = ex.getCause(); }
            catch (Throwable ex) { gex = ex; }

            if (fex != null || gex != null)
                assertSame(fex.getClass(), gex.getClass());
            else
                assertEquals(fval, gval);
        }

        static class PlusFuture<T> extends CompletableFuture<T> {
            AtomicReference<Throwable> firstFailure = new AtomicReference<>(null);
        }

        /** Implements "monadic plus". */
        static <T> CompletableFuture<T> plus(CompletableFuture<? extends T> f,
                                             CompletableFuture<? extends T> g) {
            PlusFuture<T> plus = new PlusFuture<T>();
            BiConsumer<T, Throwable> action = (T result, Throwable ex) -> {
                try {
                    if (ex == null) {
                        if (plus.complete(result))
                            if (plus.firstFailure.get() != null)
                                plus.firstFailure.set(null);
                    }
                    else if (plus.firstFailure.compareAndSet(null, ex)) {
                        if (plus.isDone())
                            plus.firstFailure.set(null);
                    }
                    else {
                        // first failure has precedence
                        Throwable first = plus.firstFailure.getAndSet(null);

                        // may fail with "Self-suppression not permitted"
                        try { first.addSuppressed(ex); }
                        catch (Exception ignored) {}

                        plus.completeExceptionally(first);
                    }
                } catch (Throwable unexpected) {
                    plus.completeExceptionally(unexpected);
                }
            };
            f.whenComplete(action);
            g.whenComplete(action);
            return plus;
        }
    }

    /**
     * CompletableFuture is an additive monad - sort of.
     * https://en.wikipedia.org/wiki/Monad_(functional_programming)#Additive_monads
     */
    public void testAdditiveMonad() throws Throwable {
        Function<Long, CompletableFuture<Long>> unit = Monad::unit;
        CompletableFuture<Long> zero = Monad.zero();

        // Some mutually non-commutative functions
        Function<Long, CompletableFuture<Long>> triple
            = (x) -> Monad.unit(3 * x);
        Function<Long, CompletableFuture<Long>> inc
            = (x) -> Monad.unit(x + 1);

        // unit is a right identity: m >>= unit === m
        Monad.assertFutureEquals(inc.apply(5L).thenCompose(unit),
                                 inc.apply(5L));
        // unit is a left identity: (unit x) >>= f === f x
        Monad.assertFutureEquals(unit.apply(5L).thenCompose(inc),
                                 inc.apply(5L));

        // associativity: (m >>= f) >>= g === m >>= ( \x -> (f x >>= g) )
        Monad.assertFutureEquals(
            unit.apply(5L).thenCompose(inc).thenCompose(triple),
            unit.apply(5L).thenCompose((x) -> inc.apply(x).thenCompose(triple)));

        // The case for CompletableFuture as an additive monad is weaker...

        // zero is a monadic zero
        Monad.assertZero(zero);

        // left zero: zero >>= f === zero
        Monad.assertZero(zero.thenCompose(inc));
        // right zero: f >>= (\x -> zero) === zero
        Monad.assertZero(inc.apply(5L).thenCompose((x) -> zero));

        // f plus zero === f
        Monad.assertFutureEquals(Monad.unit(5L),
                                 Monad.plus(Monad.unit(5L), zero));
        // zero plus f === f
        Monad.assertFutureEquals(Monad.unit(5L),
                                 Monad.plus(zero, Monad.unit(5L)));
        // zero plus zero === zero
        Monad.assertZero(Monad.plus(zero, zero));
        {
            CompletableFuture<Long> f = Monad.plus(Monad.unit(5L),
                                                   Monad.unit(8L));
            // non-determinism
            assertTrue(f.get() == 5L || f.get() == 8L);
        }

        CompletableFuture<Long> godot = new CompletableFuture<>();
        // f plus godot === f (doesn't wait for godot)
        Monad.assertFutureEquals(Monad.unit(5L),
                                 Monad.plus(Monad.unit(5L), godot));
        // godot plus f === f (doesn't wait for godot)
        Monad.assertFutureEquals(Monad.unit(5L),
                                 Monad.plus(godot, Monad.unit(5L)));
    }

//     static <U> U join(CompletionStage<U> stage) {
//         CompletableFuture<U> f = new CompletableFuture<>();
//         stage.whenComplete((v, ex) -> {
//             if (ex != null) f.completeExceptionally(ex); else f.complete(v);
//         });
//         return f.join();
//     }

//     static <U> boolean isDone(CompletionStage<U> stage) {
//         CompletableFuture<U> f = new CompletableFuture<>();
//         stage.whenComplete((v, ex) -> {
//             if (ex != null) f.completeExceptionally(ex); else f.complete(v);
//         });
//         return f.isDone();
//     }

//     static <U> U join2(CompletionStage<U> stage) {
//         return stage.toCompletableFuture().copy().join();
//     }

//     static <U> boolean isDone2(CompletionStage<U> stage) {
//         return stage.toCompletableFuture().copy().isDone();
//     }

}
