/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file:
 *
 * 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/
 */

import static java.util.concurrent.TimeUnit.NANOSECONDS;
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.ForkJoinWorkerThread;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeoutException;
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.Test;
import junit.framework.TestSuite;

public class CompletableFutureTest extends JSR166TestCase {

    public static void main(String[] args) {
        main(suite(), args);
    }
    public static Test suite() {
        return new TestSuite(CompletableFutureTest.class);
    }

    static class CFException extends RuntimeException {
        // This makes sure that CompletableFuture still behaves appropriately
        // even if thrown exceptions end up throwing exceptions from their String
        // representations.
        @Override public String getMessage() {
            throw new IllegalStateException("malformed");
        }
    }

    void checkIncomplete(CompletableFuture<?> f) {
        assertFalse(f.isDone());
        assertFalse(f.isCancelled());
        assertTrue(f.toString().matches(".*\\[.*Not completed.*\\]"));

        Object result = null;
        try {
            result = f.getNow(null);
        } catch (Throwable fail) { threadUnexpectedException(fail); }
        assertNull(result);

        try {
            f.get(1, NANOSECONDS);
            shouldThrow();
        }
        catch (TimeoutException success) {}
        catch (Throwable fail) { threadUnexpectedException(fail); }
    }

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

        mustEqual(expectedValue, f.join());
        mustEqual(expectedValue, f.getNow(null));

        T result = null;
        try {
            result = f.get();
        } catch (Throwable fail) { threadUnexpectedException(fail); }
        mustEqual(expectedValue, result);

        assertTrue(f.isDone());
        assertFalse(f.isCancelled());
        assertFalse(f.isCompletedExceptionally());
        assertTrue(f.toString().matches(".*\\[.*Completed normally.*\\]"));
    }

    /**
     * Returns the "raw" internal exceptional completion of f,
     * without any additional wrapping with CompletionException.
     */
    Throwable exceptionalCompletion(CompletableFuture<?> f) {
        // handle (and whenComplete and exceptionally) can distinguish
        // between "direct" and "wrapped" exceptional completion
        return f.handle((u, 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().matches(".*\\[.*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 checkCancellationException(CancellationException thrown, String message) {
        assertTrue(message.equals(thrown.getMessage()));

        assertTrue(thrown.getCause() instanceof CancellationException);
        assertTrue(thrown.getCause().getCause() == null);
    }

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

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

        assertTrue(exceptionalCompletion(f) instanceof CancellationException);

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

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

    /**
     * complete completes normally, as indicated by methods isDone,
     * isCancelled, join, get, and getNow
     */
    public void testComplete() {
        for (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> 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<Item> f = new CompletableFuture<>();
        checkIncomplete(f);
        CFException ex = new CFException();
        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<Item> 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<Item> 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 (Item v1 : new Item[] { one, null })
    {
        CFException ex;
        CompletableFuture<Item> 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(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 (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> f = new CompletableFuture<>();
        mustEqual(0, f.getNumberOfDependents());
        final CompletableFuture<Void> g = m.thenRun(f, new Noop(m));
        mustEqual(1, f.getNumberOfDependents());
        mustEqual(0, g.getNumberOfDependents());
        final CompletableFuture<Void> h = m.thenRun(f, new Noop(m));
        mustEqual(2, f.getNumberOfDependents());
        mustEqual(0, h.getNumberOfDependents());
        assertTrue(f.complete(v1));
        checkCompletedNormally(g, null);
        checkCompletedNormally(h, null);
        mustEqual(0, f.getNumberOfDependents());
        mustEqual(0, g.getNumberOfDependents());
        mustEqual(0, h.getNumberOfDependents());
    }}

    /**
     * toString indicates current completion state
     */
    public void testToString_incomplete() {
        CompletableFuture<String> f = new CompletableFuture<>();
        assertTrue(f.toString().matches(".*\\[.*Not completed.*\\]"));
        if (testImplementationDetails)
            mustEqual(identityString(f) + "[Not completed]",
                         f.toString());
    }

    public void testToString_normal() {
        CompletableFuture<String> f = new CompletableFuture<>();
        assertTrue(f.complete("foo"));
        assertTrue(f.toString().matches(".*\\[.*Completed normally.*\\]"));
        if (testImplementationDetails)
            mustEqual(identityString(f) + "[Completed normally]",
                         f.toString());
    }

    public void testToString_exception() {
        CompletableFuture<String> f = new CompletableFuture<>();
        assertTrue(f.completeExceptionally(new IndexOutOfBoundsException()));
        assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]"));
        if (testImplementationDetails)
            assertTrue(f.toString().startsWith(
                               identityString(f) + "[Completed exceptionally: "));
    }

    public void testToString_cancelled() {
        for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
            CompletableFuture<String> f = new CompletableFuture<>();
            assertTrue(f.cancel(mayInterruptIfRunning));
            assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]"));
            if (testImplementationDetails)
                assertTrue(f.toString().startsWith(
                                   identityString(f) + "[Completed exceptionally: "));
        }
    }

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

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

    abstract static class CheckedItemAction extends CheckedAction {
        Item value;
        CheckedItemAction(ExecutionMode m) { super(m); }
        void assertValue(Item expected) {
            assertInvoked();
            mustEqual(expected, value);
        }
    }

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

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

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

    static class IncFunction extends CheckedItemAction
        implements Function<Item,Item>
    {
        IncFunction(ExecutionMode m) { super(m); }
        public Item apply(Item 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 Item subtract(Item x, Item y) {
        return (x == null && y == null) ? null :
            new Item(((x == null) ? 42 : x.value)
                    - ((y == null) ? 99 : y.value));
    }

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

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

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

    static class FailingSupplier extends CheckedAction
        implements Supplier<Item>
    {
        final CFException ex;
        FailingSupplier(ExecutionMode m) { super(m); ex = new CFException(); }
        public Item get() {
            invoked();
            throw ex;
        }
    }

    static class FailingConsumer extends CheckedItemAction
        implements Consumer<Item>
    {
        final CFException ex;
        FailingConsumer(ExecutionMode m) { super(m); ex = new CFException(); }
        public void accept(Item x) {
            invoked();
            value = x;
            throw ex;
        }
    }

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

    static class FailingFunction extends CheckedItemAction
        implements Function<Item, Item>
    {
        final CFException ex;
        FailingFunction(ExecutionMode m) { super(m); ex = new CFException(); }
        public Item apply(Item x) {
            invoked();
            value = x;
            throw ex;
        }
    }

    static class FailingBiFunction extends CheckedItemAction
        implements BiFunction<Item, Item, Item>
    {
        final CFException ex;
        FailingBiFunction(ExecutionMode m) { super(m); ex = new CFException(); }
        public Item apply(Item x, Item y) {
            invoked();
            value = subtract(x, y);
            throw ex;
        }
    }

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

    static class CompletableFutureInc extends CheckedItemAction
        implements Function<Item, CompletableFuture<Item>>
    {
        CompletableFutureInc(ExecutionMode m) { super(m); }
        public CompletableFuture<Item> apply(Item x) {
            invoked();
            value = x;
            return CompletableFuture.completedFuture(inc(x));
        }
    }

    static class FailingExceptionalCompletableFutureFunction extends CheckedAction
        implements Function<Throwable, CompletableFuture<Item>>
    {
        final CFException ex;
        FailingExceptionalCompletableFutureFunction(ExecutionMode m) { super(m); ex = new CFException(); }
        public CompletableFuture<Item> apply(Throwable x) {
            invoked();
            throw ex;
        }
    }

    static class ExceptionalCompletableFutureFunction extends CheckedAction
        implements Function<Throwable, CompletionStage<Item>> {
        final Item value = three;
        ExceptionalCompletableFutureFunction(ExecutionMode m) { super(m); }
        public CompletionStage<Item> apply(Throwable x) {
            invoked();
            return CompletableFuture.completedFuture(value);
        }
    }

    static class FailingCompletableFutureFunction extends CheckedItemAction
        implements Function<Item, CompletableFuture<Item>>
    {
        final CFException ex;
        FailingCompletableFutureFunction(ExecutionMode m) { super(m); ex = new CFException(); }
        public CompletableFuture<Item> apply(Item x) {
            invoked();
            value = x;
            throw ex;
        }
    }

    static class CountingRejectingExecutor implements Executor {
        final RejectedExecutionException ex = new RejectedExecutionException();
        final AtomicInteger count = new AtomicInteger(0);
        public void execute(Runnable r) {
            count.getAndIncrement();
            throw ex;
        }
    }

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


    /**
     * 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);
            }
            public <T> CompletableFuture<T> exceptionally
                (CompletableFuture<T> f,
                 Function<Throwable, ? extends T> fn) {
                return f.exceptionally(fn);
            }
            public <T> CompletableFuture<T> exceptionallyCompose
                (CompletableFuture<T> f, Function<Throwable, ? extends CompletionStage<T>> fn) {
                return f.exceptionallyCompose(fn);
            }
        },
        ASYNC {
            public void checkExecutionMode() {
                mustEqual(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);
            }
            public <T> CompletableFuture<T> exceptionally
                (CompletableFuture<T> f,
                 Function<Throwable, ? extends T> fn) {
                return f.exceptionallyAsync(fn);
            }

            public <T> CompletableFuture<T> exceptionallyCompose
                (CompletableFuture<T> f, Function<Throwable, ? extends CompletionStage<T>> fn) {
                return f.exceptionallyComposeAsync(fn);
            }

        },

        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 <T> CompletableFuture<T> exceptionally
                (CompletableFuture<T> f,
                 Function<Throwable, ? extends T> fn) {
                return f.exceptionallyAsync(fn, new ThreadExecutor());
            }
            public <T> CompletableFuture<T> exceptionallyCompose
                (CompletableFuture<T> f, Function<Throwable, ? extends CompletionStage<T>> fn) {
                return f.exceptionallyComposeAsync(fn, 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);
        public abstract <T> CompletableFuture<T> exceptionally
            (CompletableFuture<T> f,
             Function<Throwable, ? extends T> fn);
        public abstract <T> CompletableFuture<T> exceptionallyCompose
            (CompletableFuture<T> f,
             Function<Throwable, ? extends CompletionStage<T>> fn);
    }

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

        checkCompletedNormally(g, v1);
        checkCompletedNormally(f, v1);
        mustEqual(0, ran.get());
    }}

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

        checkCompletedNormally(g, v1);
        mustEqual(1, ran.get());
    }}

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

        checkCompletedWithWrappedException(g, ex2);
        checkCompletedExceptionally(f, ex1);
        mustEqual(1, ran.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 (Item v1 : new Item[] { one, null })
    {
        final AtomicInteger ran = new AtomicInteger(0);
        final CompletableFuture<Item> f = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Item> g = m.whenComplete
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertSame(result, v1);
                assertNull(t);
                ran.getAndIncrement();
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(g, v1);
        checkCompletedNormally(f, v1);
        mustEqual(1, ran.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 ran = new AtomicInteger(0);
        final CFException ex = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletableFuture<Item> g = m.whenComplete
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertNull(result);
                assertSame(t, ex);
                ran.getAndIncrement();
            });
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedWithWrappedException(g, ex);
        checkCompletedExceptionally(f, ex);
        mustEqual(1, ran.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 ran = new AtomicInteger(0);
        final CompletableFuture<Item> f = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Item> g = m.whenComplete
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertNull(result);
                assertTrue(t instanceof CancellationException);
                ran.getAndIncrement();
            });
        if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));

        checkCompletedWithWrappedCancellationException(g);
        checkCancelled(f);
        mustEqual(1, ran.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 (Item v1 : new Item[] { one, null })
    {
        final AtomicInteger ran = new AtomicInteger(0);
        final CFException ex = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Item> g = m.whenComplete
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertSame(result, v1);
                assertNull(t);
                ran.getAndIncrement();
                throw ex;
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedWithWrappedException(g, ex);
        checkCompletedNormally(f, v1);
        mustEqual(1, ran.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 ran = new AtomicInteger(0);
        final CFException ex1 = new CFException();
        final CFException ex2 = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();

        if (!createIncomplete) f.completeExceptionally(ex1);
        final CompletableFuture<Item> g = m.whenComplete
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertSame(t, ex1);
                assertNull(result);
                ran.getAndIncrement();
                throw ex2;
            });
        if (createIncomplete) f.completeExceptionally(ex1);

        checkCompletedWithWrappedException(g, ex1);
        checkCompletedExceptionally(f, ex1);
        if (testImplementationDetails) {
            mustEqual(1, ex1.getSuppressed().length);
            assertSame(ex2, ex1.getSuppressed()[0]);
        }
        mustEqual(1, ran.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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final AtomicInteger ran = new AtomicInteger(0);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Item> g = m.handle
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertSame(result, v1);
                assertNull(t);
                ran.getAndIncrement();
                return inc(v1);
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(g, inc(v1));
        checkCompletedNormally(f, v1);
        mustEqual(1, ran.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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final AtomicInteger ran = new AtomicInteger(0);
        final CFException ex = new CFException();
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletableFuture<Item> g = m.handle
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertNull(result);
                assertSame(t, ex);
                ran.getAndIncrement();
                return v1;
            });
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedNormally(g, v1);
        checkCompletedExceptionally(f, ex);
        mustEqual(1, ran.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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final AtomicInteger ran = new AtomicInteger(0);
        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Item> g = m.handle
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertNull(result);
                assertTrue(t instanceof CancellationException);
                ran.getAndIncrement();
                return v1;
            });
        if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));

        checkCompletedNormally(g, v1);
        checkCancelled(f);
        mustEqual(1, ran.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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final AtomicInteger ran = new AtomicInteger(0);
        final CFException ex = new CFException();
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Item> g = m.handle
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertSame(result, v1);
                assertNull(t);
                ran.getAndIncrement();
                throw ex;
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedWithWrappedException(g, ex);
        checkCompletedNormally(f, v1);
        mustEqual(1, ran.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 ran = new AtomicInteger(0);
        final CFException ex1 = new CFException();
        final CFException ex2 = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();

        if (!createIncomplete) f.completeExceptionally(ex1);
        final CompletableFuture<Item> g = m.handle
            (f,
             (Item result, Throwable t) -> {
                m.checkExecutionMode();
                assertNull(result);
                assertSame(ex1, t);
                ran.getAndIncrement();
                throw ex2;
            });
        if (createIncomplete) f.completeExceptionally(ex1);

        checkCompletedWithWrappedException(g, ex2);
        checkCompletedExceptionally(f, ex1);
        mustEqual(1, ran.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);
        checkCompletedWithWrappedException(f, r.ex);
        r.assertInvoked();
    }}

    @SuppressWarnings("FutureReturnValueIgnored")
    public void testRunAsync_rejectingExecutor() {
        CountingRejectingExecutor e = new CountingRejectingExecutor();
        try {
            CompletableFuture.runAsync(() -> {}, e);
            shouldThrow();
        } catch (Throwable t) {
            assertSame(e.ex, t);
        }

        mustEqual(1, e.count.get());
    }

    /**
     * supplyAsync completes with result of supplier
     */
    public void testSupplyAsync_normalCompletion() {
        ExecutionMode[] executionModes = {
            ExecutionMode.ASYNC,
            ExecutionMode.EXECUTOR,
        };
        for (ExecutionMode m : executionModes)
        for (Item v1 : new Item[] { one, null })
    {
        final ItemSupplier r = new ItemSupplier(m, v1);
        final CompletableFuture<Item> 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<Item> f = m.supplyAsync(r);
        checkCompletedWithWrappedException(f, r.ex);
        r.assertInvoked();
    }}

    @SuppressWarnings("FutureReturnValueIgnored")
    public void testSupplyAsync_rejectingExecutor() {
        CountingRejectingExecutor e = new CountingRejectingExecutor();
        try {
            CompletableFuture.supplyAsync(() -> null, e);
            shouldThrow();
        } catch (Throwable t) {
            assertSame(e.ex, t);
        }

        mustEqual(1, e.count.get());
    }

    // seq completion methods

    /**
     * thenRun result completes normally after normal completion of source
     */
    public void testThenRun_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> 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<Item> 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<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> 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]);

        checkCompletedWithWrappedException(h0, rs[0].ex);
        checkCompletedWithWrappedException(h1, rs[1].ex);
        checkCompletedWithWrappedException(h2, rs[2].ex);
        checkCompletedWithWrappedException(h3, rs[3].ex);
        checkCompletedWithWrappedException(h4, rs[4].ex);
        checkCompletedWithWrappedException(h5, rs[5].ex);
        checkCompletedNormally(f, v1);
    }}

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

        final CompletableFuture<Item> h0 = m.thenApply(f, rs[0]);
        final CompletableFuture<Item> h1 = m.applyToEither(f, f, rs[1]);
        checkIncomplete(h0);
        checkIncomplete(h1);
        assertTrue(f.complete(v1));
        final CompletableFuture<Item> h2 = m.thenApply(f, rs[2]);
        final CompletableFuture<Item> 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<Item> f = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Item> h0 = m.thenApply(f, rs[0]);
        final CompletableFuture<Item> h1 = m.applyToEither(f, f, rs[1]);
        assertTrue(f.completeExceptionally(ex));
        final CompletableFuture<Item> h2 = m.thenApply(f, rs[2]);
        final CompletableFuture<Item> 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<Item> f = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Item> h0 = m.thenApply(f, rs[0]);
        final CompletableFuture<Item> h1 = m.applyToEither(f, f, rs[1]);
        assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Item> h2 = m.thenApply(f, rs[2]);
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final FailingFunction[] rs = new FailingFunction[4];
        for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m);

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

        checkCompletedWithWrappedException(h0, rs[0].ex);
        checkCompletedWithWrappedException(h1, rs[1].ex);
        checkCompletedWithWrappedException(h2, rs[2].ex);
        checkCompletedWithWrappedException(h3, rs[3].ex);
        checkCompletedNormally(f, v1);
    }}

    /**
     * thenAccept result completes normally after normal completion of source
     */
    public void testThenAccept_normalCompletion() {
        for (ExecutionMode m : ExecutionMode.values())
        for (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> 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<Item> 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<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> 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]);

        checkCompletedWithWrappedException(h0, rs[0].ex);
        checkCompletedWithWrappedException(h1, rs[1].ex);
        checkCompletedWithWrappedException(h2, rs[2].ex);
        checkCompletedWithWrappedException(h3, rs[3].ex);
        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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final SubtractFunction[] rs = new SubtractFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new SubtractFunction(m);

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

        final CompletableFuture<Item> h0 = m.thenCombine(f, g, rs[0]);
        final CompletableFuture<Item> h1 = m.thenCombine(fst, fst, rs[1]);
        assertTrue(fst.complete(w1));
        final CompletableFuture<Item> h2 = m.thenCombine(f, g, rs[2]);
        final CompletableFuture<Item> 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<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> 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<Item> h1 = m.thenCombine(f, g, r1);
        assertTrue(complete1.call());
        final CompletableFuture<Item> h2 = m.thenCombine(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(complete2.call());
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final SubtractFunction r1 = new SubtractFunction(m);
        final SubtractFunction r2 = new SubtractFunction(m);
        final SubtractFunction r3 = new SubtractFunction(m);

        final CompletableFuture<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> 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<Item> h1 = m.thenCombine(f, g, r1);
        assertTrue(complete1.call());
        final CompletableFuture<Item> h2 = m.thenCombine(f, g, r2);
        checkIncomplete(h1);
        checkIncomplete(h2);
        assertTrue(complete2.call());
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final FailingBiFunction r1 = new FailingBiFunction(m);
        final FailingBiFunction r2 = new FailingBiFunction(m);
        final FailingBiFunction r3 = new FailingBiFunction(m);

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

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

        checkCompletedWithWrappedException(h1, r1.ex);
        checkCompletedWithWrappedException(h2, r2.ex);
        checkCompletedWithWrappedException(h3, r3.ex);
        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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final SubtractAction r1 = new SubtractAction(m);
        final SubtractAction r2 = new SubtractAction(m);
        final SubtractAction r3 = new SubtractAction(m);

        final CompletableFuture<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> snd = !fFirst ? f : g;
        final Item w1 =  fFirst ? v1 : v2;
        final Item 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final SubtractAction r1 = new SubtractAction(m);
        final SubtractAction r2 = new SubtractAction(m);
        final SubtractAction r3 = new SubtractAction(m);

        final CompletableFuture<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final FailingBiConsumer r1 = new FailingBiConsumer(m);
        final FailingBiConsumer r2 = new FailingBiConsumer(m);
        final FailingBiConsumer r3 = new FailingBiConsumer(m);

        final CompletableFuture<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> snd = !fFirst ? f : g;
        final Item w1 =  fFirst ? v1 : v2;
        final Item 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);

        checkCompletedWithWrappedException(h1, r1.ex);
        checkCompletedWithWrappedException(h2, r2.ex);
        checkCompletedWithWrappedException(h3, r3.ex);
        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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final Noop r1 = new Noop(m);
        final Noop r2 = new Noop(m);
        final Noop r3 = new Noop(m);

        final CompletableFuture<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> snd = !fFirst ? f : g;
        final Item w1 =  fFirst ? v1 : v2;
        final Item 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final Noop r1 = new Noop(m);
        final Noop r2 = new Noop(m);
        final Noop r3 = new Noop(m);

        final CompletableFuture<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final FailingRunnable r1 = new FailingRunnable(m);
        final FailingRunnable r2 = new FailingRunnable(m);
        final FailingRunnable r3 = new FailingRunnable(m);

        final CompletableFuture<Item> fst =  fFirst ? f : g;
        final CompletableFuture<Item> snd = !fFirst ? f : g;
        final Item w1 =  fFirst ? v1 : v2;
        final Item 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);

        checkCompletedWithWrappedException(h1, r1.ex);
        checkCompletedWithWrappedException(h2, r2.ex);
        checkCompletedWithWrappedException(h3, r3.ex);
        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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Item> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Item> 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<Item> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Item> 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<Item> h4 = m.applyToEither(f, g, rs[4]);
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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<Item> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Item> 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<Item> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Item> h3 = m.applyToEither(g, f, rs[3]);
        checkCompletedWithWrappedException(h2, ex);
        checkCompletedWithWrappedException(h3, ex);
        g.complete(v1);

        // unspecified behavior - both source completions available
        final CompletableFuture<Item> h4 = m.applyToEither(f, g, rs[4]);
        final CompletableFuture<Item> h5 = m.applyToEither(g, f, rs[5]);
        try {
            mustEqual(inc(v1), h4.join());
            rs[4].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h4, ex);
            rs[4].assertNotInvoked();
        }
        try {
            mustEqual(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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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<Item> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Item> 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<Item> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Item> h3 = m.applyToEither(g, f, rs[3]);

        // unspecified behavior - both source completions available
        try {
            mustEqual(inc(v1), h0.join());
            rs[0].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h0, ex);
            rs[0].assertNotInvoked();
        }
        try {
            mustEqual(inc(v1), h1.join());
            rs[1].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h1, ex);
            rs[1].assertNotInvoked();
        }
        try {
            mustEqual(inc(v1), h2.join());
            rs[2].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h2, ex);
            rs[2].assertNotInvoked();
        }
        try {
            mustEqual(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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Item> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Item> 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<Item> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Item> h3 = m.applyToEither(g, f, rs[3]);
        checkCompletedWithWrappedCancellationException(h2);
        checkCompletedWithWrappedCancellationException(h3);
        g.complete(v1);

        // unspecified behavior - both source completions available
        final CompletableFuture<Item> h4 = m.applyToEither(f, g, rs[4]);
        final CompletableFuture<Item> h5 = m.applyToEither(g, f, rs[5]);
        try {
            mustEqual(inc(v1), h4.join());
            rs[4].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h4);
            rs[4].assertNotInvoked();
        }
        try {
            mustEqual(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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final IncFunction[] rs = new IncFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);

        final CompletableFuture<Item> h0 = m.applyToEither(f, g, rs[0]);
        final CompletableFuture<Item> 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<Item> h2 = m.applyToEither(f, g, rs[2]);
        final CompletableFuture<Item> h3 = m.applyToEither(g, f, rs[3]);

        // unspecified behavior - both source completions available
        try {
            mustEqual(inc(v1), h0.join());
            rs[0].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h0);
            rs[0].assertNotInvoked();
        }
        try {
            mustEqual(inc(v1), h1.join());
            rs[1].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h1);
            rs[1].assertNotInvoked();
        }
        try {
            mustEqual(inc(v1), h2.join());
            rs[2].assertValue(inc(v1));
        } catch (CompletionException ok) {
            checkCompletedWithWrappedCancellationException(h2);
            rs[2].assertNotInvoked();
        }
        try {
            mustEqual(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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final FailingFunction[] rs = new FailingFunction[6];
        for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m);

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

        g.complete(v2);

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

        checkCompletedWithWrappedException(h4, rs[4].ex);
        assertTrue(Objects.equals(v1, rs[4].value) ||
                   Objects.equals(v2, rs[4].value));
        checkCompletedWithWrappedException(h5, rs[5].ex);
        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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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 {
            assertNull(h0.join());
            rs[0].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h0, ex);
            rs[0].assertNotInvoked();
        }
        try {
            assertNull(h1.join());
            rs[1].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h1, ex);
            rs[1].assertNotInvoked();
        }
        try {
            assertNull(h2.join());
            rs[2].assertValue(v1);
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h2, ex);
            rs[2].assertNotInvoked();
        }
        try {
            assertNull(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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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]);
        checkCompletedWithWrappedException(h0, rs[0].ex);
        checkCompletedWithWrappedException(h1, rs[1].ex);
        checkCompletedWithWrappedException(h2, rs[2].ex);
        checkCompletedWithWrappedException(h3, rs[3].ex);
        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]);

        checkCompletedWithWrappedException(h4, rs[4].ex);
        assertTrue(Objects.equals(v1, rs[4].value) ||
                   Objects.equals(v2, rs[4].value));
        checkCompletedWithWrappedException(h5, rs[5].ex);
        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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
        for (boolean pushNop : new boolean[] { true, false })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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();
        if (pushNop) {          // ad hoc test of intra-completion interference
            m.thenRun(f, () -> {});
            m.thenRun(g, () -> {});
        }
        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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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 {
            assertNull(h0.join());
            rs[0].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h0, ex);
            rs[0].assertNotInvoked();
        }
        try {
            assertNull(h1.join());
            rs[1].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h1, ex);
            rs[1].assertNotInvoked();
        }
        try {
            assertNull(h2.join());
            rs[2].assertInvoked();
        } catch (CompletionException ok) {
            checkCompletedWithWrappedException(h2, ex);
            rs[2].assertNotInvoked();
        }
        try {
            assertNull(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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
        for (Item v2 : new Item[] { two, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> 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]);
        checkCompletedWithWrappedException(h0, rs[0].ex);
        checkCompletedWithWrappedException(h1, rs[1].ex);
        checkCompletedWithWrappedException(h2, rs[2].ex);
        checkCompletedWithWrappedException(h3, rs[3].ex);
        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]);
        checkCompletedWithWrappedException(h4, rs[4].ex);
        checkCompletedWithWrappedException(h5, rs[5].ex);

        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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFutureInc r = new CompletableFutureInc(m);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Item> 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<Item> f = new CompletableFuture<>();
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final FailingCompletableFutureFunction r
            = new FailingCompletableFutureFunction(m);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletableFuture<Item> g = m.thenCompose(f, r);
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedWithWrappedException(g, r.ex);
        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<Item> f = new CompletableFuture<>();
        final CompletableFutureInc r = new CompletableFutureInc(m);
        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
        final CompletableFuture<Item> 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 (Item v1 : new Item[] { one, null })
    {
        final CFException ex = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final CompletableFuture<Item> g = new CompletableFuture<>();
        final CompletableFuture<Item> 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);
    }}

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

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v1);
        r.assertNotInvoked();
    }}

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

        checkCompletedExceptionally(f, ex);
        checkCompletedNormally(g, r.value);
        r.assertInvoked();
    }}

    /**
     * exceptionallyCompose completes exceptionally on exception if action does
     */
    public void testExceptionallyCompose_actionFailed() {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final CFException ex = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final FailingExceptionalCompletableFutureFunction r
            = new FailingExceptionalCompletableFutureFunction(m);
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletableFuture<Item> g = m.exceptionallyCompose(f, r);
        if (createIncomplete) f.completeExceptionally(ex);

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

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

        checkCompletedExceptionally(g, ex);
        checkCompletedWithWrappedException(h, ex);
        checkCompletedExceptionally(f, ex0);
    }}

    // 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++) {
            @SuppressWarnings("unchecked")
            CompletableFuture<Item>[] fs
                = (CompletableFuture<Item>[]) 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_normal_backwards() throws Exception {
        for (int k = 1; k < 10; k++) {
            @SuppressWarnings("unchecked")
            CompletableFuture<Item>[] fs
                = (CompletableFuture<Item>[]) 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++) {
            @SuppressWarnings("unchecked")
            CompletableFuture<Item>[] fs
                = (CompletableFuture<Item>[]) 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++) {
                Item I = itemFor(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 (Item v1 : new Item[] { one, 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++) {
            @SuppressWarnings("unchecked")
            CompletableFuture<Item>[] fs =
                (CompletableFuture<Item>[])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(itemFor(i));
                checkCompletedNormally(f, zero);
                Item x = (Item)CompletableFuture.anyOf(fs).join();
                assertTrue(0 <= x.value && x.value <= i);
            }
        }
    }
    public void testAnyOf_normal_backwards() throws Exception {
        for (int k = 0; k < 10; k++) {
            @SuppressWarnings("unchecked")
            CompletableFuture<Item>[] fs =
                (CompletableFuture<Item>[])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(itemFor(i));
                checkCompletedNormally(f, itemFor(k - 1));
                Item x = (Item)CompletableFuture.anyOf(fs).join();
                assertTrue(i <= x.value && x.value <= k - 1);
            }
        }
    }

    /**
     * anyOf result completes exceptionally when any component does.
     */
    public void testAnyOf_exceptional() throws Exception {
        for (int k = 0; k < 10; k++) {
            @SuppressWarnings("unchecked")
            CompletableFuture<Item>[] fs =
                (CompletableFuture<Item>[])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++) {
            @SuppressWarnings("unchecked")
            CompletableFuture<Object>[] fs =
                (CompletableFuture<Object>[])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
     */
    @SuppressWarnings("FutureReturnValueIgnored")
    public void testNPE() {
        CompletableFuture<Item> f = new CompletableFuture<>();
        CompletableFuture<Item> g = new CompletableFuture<>();
        CompletableFuture<Item> nullFuture = (CompletableFuture<Item>)null;
        ThreadExecutor exec = new ThreadExecutor();

        assertThrows(
            NullPointerException.class,

            () -> CompletableFuture.supplyAsync(null),
            () -> CompletableFuture.supplyAsync(null, exec),
            () -> CompletableFuture.supplyAsync(new ItemSupplier(ExecutionMode.SYNC, fortytwo), 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, exec),
            () -> CompletableFuture.delayedExecutor(1L, null),

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

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

        mustEqual(0, exec.count.get());
    }

    /**
     * Test submissions to an executor that rejects all tasks.
     */
    public void testRejectingExecutor() {
        for (Item v : new Item[] { one, null })
    {
        final CountingRejectingExecutor e = new CountingRejectingExecutor();

        final CompletableFuture<Item> complete = CompletableFuture.completedFuture(v);
        final CompletableFuture<Item> incomplete = new CompletableFuture<>();

        List<CompletableFuture<?>> futures = new ArrayList<>();

        List<CompletableFuture<Item>> srcs = new ArrayList<>();
        srcs.add(complete);
        srcs.add(incomplete);

        for (CompletableFuture<Item> src : srcs) {
            List<CompletableFuture<?>> fs = new ArrayList<>();
            fs.add(src.thenRunAsync(() -> {}, e));
            fs.add(src.thenAcceptAsync(z -> {}, e));
            fs.add(src.thenApplyAsync(z -> z, e));

            fs.add(src.thenCombineAsync(src, (x, y) -> x, e));
            fs.add(src.thenAcceptBothAsync(src, (x, y) -> {}, e));
            fs.add(src.runAfterBothAsync(src, () -> {}, e));

            fs.add(src.applyToEitherAsync(src, z -> z, e));
            fs.add(src.acceptEitherAsync(src, z -> {}, e));
            fs.add(src.runAfterEitherAsync(src, () -> {}, e));

            fs.add(src.thenComposeAsync(z -> null, e));
            fs.add(src.whenCompleteAsync((z, t) -> {}, e));
            fs.add(src.handleAsync((z, t) -> null, e));

            for (CompletableFuture<?> future : fs) {
                if (src.isDone())
                    checkCompletedWithWrappedException(future, e.ex);
                else
                    checkIncomplete(future);
            }
            futures.addAll(fs);
        }

        {
            List<CompletableFuture<?>> fs = new ArrayList<>();

            fs.add(complete.thenCombineAsync(incomplete, (x, y) -> x, e));
            fs.add(incomplete.thenCombineAsync(complete, (x, y) -> x, e));

            fs.add(complete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
            fs.add(incomplete.thenAcceptBothAsync(complete, (x, y) -> {}, e));

            fs.add(complete.runAfterBothAsync(incomplete, () -> {}, e));
            fs.add(incomplete.runAfterBothAsync(complete, () -> {}, e));

            for (CompletableFuture<?> future : fs)
                checkIncomplete(future);
            futures.addAll(fs);
        }

        {
            List<CompletableFuture<?>> fs = new ArrayList<>();

            fs.add(complete.applyToEitherAsync(incomplete, z -> z, e));
            fs.add(incomplete.applyToEitherAsync(complete, z -> z, e));

            fs.add(complete.acceptEitherAsync(incomplete, z -> {}, e));
            fs.add(incomplete.acceptEitherAsync(complete, z -> {}, e));

            fs.add(complete.runAfterEitherAsync(incomplete, () -> {}, e));
            fs.add(incomplete.runAfterEitherAsync(complete, () -> {}, e));

            for (CompletableFuture<?> future : fs)
                checkCompletedWithWrappedException(future, e.ex);
            futures.addAll(fs);
        }

        incomplete.complete(v);

        for (CompletableFuture<?> future : futures)
            checkCompletedWithWrappedException(future, e.ex);

        mustEqual(futures.size(), e.count.get());
    }}

    /**
     * Test submissions to an executor that rejects all tasks, but
     * should never be invoked because the dependent future is
     * explicitly completed.
     */
    public void testRejectingExecutorNeverInvoked() {
        for (Item v : new Item[] { one, null })
    {
        final CountingRejectingExecutor e = new CountingRejectingExecutor();

        final CompletableFuture<Item> complete = CompletableFuture.completedFuture(v);
        final CompletableFuture<Item> incomplete = new CompletableFuture<>();

        List<CompletableFuture<?>> fs = new ArrayList<>();
        fs.add(incomplete.thenRunAsync(() -> {}, e));
        fs.add(incomplete.thenAcceptAsync(z -> {}, e));
        fs.add(incomplete.thenApplyAsync(z -> z, e));

        fs.add(incomplete.thenCombineAsync(incomplete, (x, y) -> x, e));
        fs.add(incomplete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
        fs.add(incomplete.runAfterBothAsync(incomplete, () -> {}, e));

        fs.add(incomplete.applyToEitherAsync(incomplete, z -> z, e));
        fs.add(incomplete.acceptEitherAsync(incomplete, z -> {}, e));
        fs.add(incomplete.runAfterEitherAsync(incomplete, () -> {}, e));

        fs.add(incomplete.thenComposeAsync(z -> null, e));
        fs.add(incomplete.whenCompleteAsync((z, t) -> {}, e));
        fs.add(incomplete.handleAsync((z, t) -> null, e));

        fs.add(complete.thenCombineAsync(incomplete, (x, y) -> x, e));
        fs.add(incomplete.thenCombineAsync(complete, (x, y) -> x, e));

        fs.add(complete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
        fs.add(incomplete.thenAcceptBothAsync(complete, (x, y) -> {}, e));

        fs.add(complete.runAfterBothAsync(incomplete, () -> {}, e));
        fs.add(incomplete.runAfterBothAsync(complete, () -> {}, e));

        for (CompletableFuture<?> future : fs)
            checkIncomplete(future);

        for (CompletableFuture<?> future : fs)
            future.complete(null);

        incomplete.complete(v);

        for (CompletableFuture<?> future : fs)
            checkCompletedNormally(future, null);

        mustEqual(0, e.count.get());
    }}

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

    // jdk9

    /**
     * newIncompleteFuture returns an incomplete CompletableFuture
     */
    public void testNewIncompleteFuture() {
        for (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> f = new CompletableFuture<>();
        CompletableFuture<Item> 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<>();
        CompletionStage<Item> f = CompletableFuture.completedStage(one);
        f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v.value);});
        mustEqual(x.get(), 1);
        assertNull(r.get());
    }

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

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

    /**
     * copy returns a CompletableFuture that is completed normally,
     * with the same value, when source is.
     */
    public void testCopy_normalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> f = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.complete(v1));
        CompletableFuture<Item> g = f.copy();
        if (createIncomplete) {
            checkIncomplete(f);
            checkIncomplete(g);
            assertTrue(f.complete(v1));
        }
        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v1);
    }}

    /**
     * copy returns a CompletableFuture that is completed exceptionally
     * when source is.
     */
    public void testCopy_exceptionalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        CFException ex = new CFException();
        CompletableFuture<Item> f = new CompletableFuture<>();
        if (!createIncomplete) f.completeExceptionally(ex);
        CompletableFuture<Item> g = f.copy();
        if (createIncomplete) {
            checkIncomplete(f);
            checkIncomplete(g);
            f.completeExceptionally(ex);
        }
        checkCompletedExceptionally(f, ex);
        checkCompletedWithWrappedException(g, ex);
    }}

    /**
     * Completion of a copy does not complete its source.
     */
    public void testCopy_oneWayPropagation() {
        CompletableFuture<Item> f = new CompletableFuture<>();
        assertTrue(f.copy().complete(one));
        assertTrue(f.copy().complete(null));
        assertTrue(f.copy().cancel(true));
        assertTrue(f.copy().cancel(false));
        assertTrue(f.copy().completeExceptionally(new CFException()));
        checkIncomplete(f);
    }

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

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

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

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

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

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

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

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

    /**
     * orTimeout completes normally if completed before timeout
     */
    public void testOrTimeout_completed() {
        for (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> f = new CompletableFuture<>();
        CompletableFuture<Item> g = new CompletableFuture<>();
        long startTime = System.nanoTime();
        f.complete(v1);
        assertSame(f, f.orTimeout(LONG_DELAY_MS, MILLISECONDS));
        assertSame(g, 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(fortytwo),
                       () -> testCompleteOnTimeout_timesOut(null));
    }

    /**
     * completeOnTimeout completes with given value if not complete
     */
    public void testCompleteOnTimeout_timesOut(Item v) {
        long timeoutMillis = timeoutMillis();
        CompletableFuture<Item> f = new CompletableFuture<>();
        long startTime = System.nanoTime();
        assertSame(f, f.completeOnTimeout(v, timeoutMillis, MILLISECONDS));
        assertSame(v, f.join());
        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
        f.complete(ninetynine);         // should have no effect
        checkCompletedNormally(f, v);
    }

    /**
     * completeOnTimeout has no effect if completed within timeout
     */
    public void testCompleteOnTimeout_completed() {
        for (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> f = new CompletableFuture<>();
        CompletableFuture<Item> g = new CompletableFuture<>();
        long startTime = System.nanoTime();
        f.complete(v1);
        mustEqual(f, f.completeOnTimeout(minusOne, LONG_DELAY_MS, MILLISECONDS));
        mustEqual(g, g.completeOnTimeout(minusOne, 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, one),
                       () -> testDelayedExecutor(new ThreadExecutor(), one),
                       () -> testDelayedExecutor(new ThreadExecutor(), one));
    }

    public void testDelayedExecutor(Executor executor, Item 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<Item> f =
            CompletableFuture.supplyAsync(() -> v, delayer);
        CompletableFuture<Item> 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<Item> v42 = CompletableFuture.completedFuture(fortytwo);
        final CompletableFuture<Item> incomplete = new CompletableFuture<>();

        final Runnable noopRunnable = new Noop(m);
        final Consumer<Item> noopConsumer = new NoopConsumer(m);
        final Function<Item, Item> incFunction = new IncFunction(m);

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

        funs.add(y -> m.thenRun(y, noopRunnable));
        funs.add(y -> m.thenAccept(y, noopConsumer));
        funs.add(y -> m.thenApply(y, incFunction));

        funs.add(y -> m.runAfterEither(y, incomplete, noopRunnable));
        funs.add(y -> m.acceptEither(y, incomplete, noopConsumer));
        funs.add(y -> m.applyToEither(y, incomplete, incFunction));

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

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

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

        funs.add(y -> CompletableFuture.allOf(y));
        funs.add(y -> CompletableFuture.allOf(y, v42));
        funs.add(y -> CompletableFuture.allOf(v42, y));
        funs.add(y -> CompletableFuture.anyOf(y));
        funs.add(y -> CompletableFuture.anyOf(y, incomplete));
        funs.add(y -> CompletableFuture.anyOf(incomplete, y));

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

        for (Function<CompletableFuture<Item>, CompletableFuture<?>>
                 fun : funs) {
            CompletableFuture<Item> f = new CompletableFuture<>();
            CompletableFuture<Item> src = m.thenApply(f, incFunction);
            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<Item>, CompletableFuture<?>>
                 fun : funs) {
            CompletableFuture<Item> f = new CompletableFuture<>();
            f.cancel(mayInterruptIfRunning);
            checkCancelled(f);
            CompletableFuture<Item> src = m.thenApply(f, incFunction);
            checkCompletedWithWrappedCancellationException(src);
            CompletableFuture<?> dep = fun.apply(src);
            checkCompletedWithWrappedCancellationException(dep);
            assertSame(resultOf(src), resultOf(dep));
        }

        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
        for (Function<CompletableFuture<Item>, CompletableFuture<?>>
                 fun : funs) {
            CompletableFuture<Item> f = new CompletableFuture<>();
            CompletableFuture<Item> src = m.thenApply(f, incFunction);
            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 most 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());

        List<CompletionStage<Item>> stages = new ArrayList<>();
        CompletionStage<Item> min =
            new CompletableFuture<Item>().minimalCompletionStage();
        stages.add(min);
        stages.add(min.thenApply(x -> x));
        stages.add(CompletableFuture.completedStage(one));
        stages.add(CompletableFuture.failedStage(new CFException()));

        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      (type == boolean.class) args[i] = false;
                else if (type == int.class)     args[i] = 0;
                else if (type == long.class)    args[i] = 0L;
            }
            for (CompletionStage<Item> stage : stages) {
                try {
                    method.invoke(stage, 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);
    }

    /**
     * minimalStage.toCompletableFuture() returns a CompletableFuture that
     * is completed normally, with the same value, when source is.
     */
    public void testMinimalCompletionStage_toCompletableFuture_normalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> f = new CompletableFuture<>();
        CompletionStage<Item> minimal = f.minimalCompletionStage();
        if (!createIncomplete) assertTrue(f.complete(v1));
        CompletableFuture<Item> g = minimal.toCompletableFuture();
        if (createIncomplete) {
            checkIncomplete(f);
            checkIncomplete(g);
            assertTrue(f.complete(v1));
        }
        checkCompletedNormally(f, v1);
        checkCompletedNormally(g, v1);
    }}

    /**
     * minimalStage.toCompletableFuture() returns a CompletableFuture that
     * is completed exceptionally when source is.
     */
    public void testMinimalCompletionStage_toCompletableFuture_exceptionalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        CFException ex = new CFException();
        CompletableFuture<Item> f = new CompletableFuture<>();
        CompletionStage<Item> minimal = f.minimalCompletionStage();
        if (!createIncomplete) f.completeExceptionally(ex);
        CompletableFuture<Item> g = minimal.toCompletableFuture();
        if (createIncomplete) {
            checkIncomplete(f);
            checkIncomplete(g);
            f.completeExceptionally(ex);
        }
        checkCompletedExceptionally(f, ex);
        checkCompletedWithWrappedException(g, ex);
    }}

    /**
     * minimalStage.toCompletableFuture() gives mutable CompletableFuture
     */
    public void testMinimalCompletionStage_toCompletableFuture_mutable() {
        for (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> f = new CompletableFuture<>();
        CompletionStage<Item> minimal = f.minimalCompletionStage();
        CompletableFuture<Item> g = minimal.toCompletableFuture();
        assertTrue(g.complete(v1));
        checkCompletedNormally(g, v1);
        checkIncomplete(f);
        checkIncomplete(minimal.toCompletableFuture());
    }}

    /**
     * minimalStage.toCompletableFuture().join() awaits completion
     */
    public void testMinimalCompletionStage_toCompletableFuture_join() throws Exception {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> f = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.complete(v1));
        CompletionStage<Item> minimal = f.minimalCompletionStage();
        if (createIncomplete) assertTrue(f.complete(v1));
        mustEqual(v1, minimal.toCompletableFuture().join());
        mustEqual(v1, minimal.toCompletableFuture().get());
        checkCompletedNormally(minimal.toCompletableFuture(), v1);
    }}

    /**
     * Completion of a toCompletableFuture copy of a minimal stage
     * does not complete its source.
     */
    public void testMinimalCompletionStage_toCompletableFuture_oneWayPropagation() {
        CompletableFuture<Item> f = new CompletableFuture<>();
        CompletionStage<Item> g = f.minimalCompletionStage();
        assertTrue(g.toCompletableFuture().complete(one));
        assertTrue(g.toCompletableFuture().complete(null));
        assertTrue(g.toCompletableFuture().cancel(true));
        assertTrue(g.toCompletableFuture().cancel(false));
        assertTrue(g.toCompletableFuture().completeExceptionally(new CFException()));
        checkIncomplete(g.toCompletableFuture());
        f.complete(one);
        checkCompletedNormally(g.toCompletableFuture(), one);
    }

    /** Demo utility method for external reliable toCompletableFuture */
    static <T> CompletableFuture<T> toCompletableFuture(CompletionStage<T> stage) {
        CompletableFuture<T> f = new CompletableFuture<>();
        stage.handle((T t, Throwable ex) -> {
                         if (ex != null) f.completeExceptionally(ex);
                         else f.complete(t);
                         return null;
                     });
        return f;
    }

    /** Demo utility method to join a CompletionStage */
    static <T> T join(CompletionStage<T> stage) {
        return toCompletableFuture(stage).join();
    }

    /**
     * Joining a minimal stage "by hand" works
     */
    public void testMinimalCompletionStage_join_by_hand() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Item v1 : new Item[] { one, null })
    {
        CompletableFuture<Item> f = new CompletableFuture<>();
        CompletionStage<Item> minimal = f.minimalCompletionStage();
        CompletableFuture<Item> g = new CompletableFuture<>();
        if (!createIncomplete) assertTrue(f.complete(v1));
        minimal.thenAccept(x -> g.complete(x));
        if (createIncomplete) assertTrue(f.complete(v1));
        g.join();
        checkCompletedNormally(g, v1);
        checkCompletedNormally(f, v1);
        mustEqual(v1, join(minimal));
    }}

    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 AssertionError("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
                mustEqual(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)));
    }

    /** Test long recursive chains of CompletableFutures with cascading completions */
    @SuppressWarnings("FutureReturnValueIgnored")
    public void testRecursiveChains() throws Throwable {
        for (ExecutionMode m : ExecutionMode.values())
        for (boolean addDeadEnds : new boolean[] { true, false })
    {
        final int val = 42;
        final int n = expensiveTests ? 1_000 : 2;
        CompletableFuture<Item> head = new CompletableFuture<>();
        CompletableFuture<Item> tail = head;
        for (int i = 0; i < n; i++) {
            if (addDeadEnds) m.thenApply(tail, v -> new Item(v.value + 1));
            tail = m.thenApply(tail, v -> new Item(v.value + 1));
            if (addDeadEnds) m.applyToEither(tail, tail, v -> new Item(v.value + 1));
            tail = m.applyToEither(tail, tail, v -> new Item(v.value + 1));
            if (addDeadEnds) m.thenCombine(tail, tail, (v, w) -> new Item(v.value + 1));
            tail = m.thenCombine(tail, tail, (v, w) -> new Item(v.value + 1));
        }
        head.complete(itemFor(val));
        mustEqual(val + 3 * n, tail.join());
    }}

    /**
     * A single CompletableFuture with many dependents.
     * A demo of scalability - runtime is O(n).
     */
    @SuppressWarnings("FutureReturnValueIgnored")
    public void testManyDependents() throws Throwable {
        final int n = expensiveTests ? 1_000_000 : 10;
        final CompletableFuture<Void> head = new CompletableFuture<>();
        final CompletableFuture<Void> complete = CompletableFuture.completedFuture((Void)null);
        final AtomicInteger count = new AtomicInteger(0);
        for (int i = 0; i < n; i++) {
            head.thenRun(() -> count.getAndIncrement());
            head.thenAccept(x -> count.getAndIncrement());
            head.thenApply(x -> count.getAndIncrement());

            head.runAfterBoth(complete, () -> count.getAndIncrement());
            head.thenAcceptBoth(complete, (x, y) -> count.getAndIncrement());
            head.thenCombine(complete, (x, y) -> count.getAndIncrement());
            complete.runAfterBoth(head, () -> count.getAndIncrement());
            complete.thenAcceptBoth(head, (x, y) -> count.getAndIncrement());
            complete.thenCombine(head, (x, y) -> count.getAndIncrement());

            head.runAfterEither(new CompletableFuture<Void>(), () -> count.getAndIncrement());
            head.acceptEither(new CompletableFuture<Void>(), x -> count.getAndIncrement());
            head.applyToEither(new CompletableFuture<Void>(), x -> count.getAndIncrement());
            new CompletableFuture<Void>().runAfterEither(head, () -> count.getAndIncrement());
            new CompletableFuture<Void>().acceptEither(head, x -> count.getAndIncrement());
            new CompletableFuture<Void>().applyToEither(head, x -> count.getAndIncrement());
        }
        head.complete(null);
        mustEqual(5 * 3 * n, count.get());
    }

    /** ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest tck */
    @SuppressWarnings("FutureReturnValueIgnored")
    public void testCoCompletionGarbageRetention() throws Throwable {
        final int n = expensiveTests ? 1_000_000 : 10;
        final CompletableFuture<Item> incomplete = new CompletableFuture<>();
        CompletableFuture<Item> f;
        for (int i = 0; i < n; i++) {
            f = new CompletableFuture<>();
            f.runAfterEither(incomplete, () -> {});
            f.complete(null);

            f = new CompletableFuture<>();
            f.acceptEither(incomplete, x -> {});
            f.complete(null);

            f = new CompletableFuture<>();
            f.applyToEither(incomplete, x -> x);
            f.complete(null);

            f = new CompletableFuture<>();
            CompletableFuture.anyOf(f, incomplete);
            f.complete(null);
        }

        for (int i = 0; i < n; i++) {
            f = new CompletableFuture<>();
            incomplete.runAfterEither(f, () -> {});
            f.complete(null);

            f = new CompletableFuture<>();
            incomplete.acceptEither(f, x -> {});
            f.complete(null);

            f = new CompletableFuture<>();
            incomplete.applyToEither(f, x -> x);
            f.complete(null);

            f = new CompletableFuture<>();
            CompletableFuture.anyOf(incomplete, f);
            f.complete(null);
        }
    }

    /**
     * Reproduction recipe for:
     * 8160402: Garbage retention with CompletableFuture.anyOf
     * cvs update -D '2016-05-01' ./src/main/java/util/concurrent/CompletableFuture.java && ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest -Djsr166.methodFilter=testAnyOfGarbageRetention tck; cvs update -A
     */
    public void testAnyOfGarbageRetention() throws Throwable {
        for (Item v : new Item[] { one, null })
    {
        final int n = expensiveTests ? 100_000 : 10;
        @SuppressWarnings("unchecked")
        CompletableFuture<Item>[] fs =
            (CompletableFuture<Item>[])new CompletableFuture[100];
        for (int i = 0; i < fs.length; i++)
            fs[i] = new CompletableFuture<>();
        fs[fs.length - 1].complete(v);
        for (int i = 0; i < n; i++)
            checkCompletedNormally(CompletableFuture.anyOf(fs), v);
    }}

    /**
     * Checks for garbage retention with allOf.
     *
     * As of 2016-07, fails with OOME:
     * ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest -Djsr166.methodFilter=testCancelledAllOfGarbageRetention tck
     */
    public void testCancelledAllOfGarbageRetention() throws Throwable {
        final int n = expensiveTests ? 100_000 : 10;
        @SuppressWarnings("unchecked")
        CompletableFuture<Item>[] fs
            = (CompletableFuture<Item>[]) new CompletableFuture<?>[100];
        for (int i = 0; i < fs.length; i++)
            fs[i] = new CompletableFuture<>();
        for (int i = 0; i < n; i++)
            assertTrue(CompletableFuture.allOf(fs).cancel(false));
    }

    /**
     * Checks for garbage retention when a dependent future is
     * cancelled and garbage-collected.
     * 8161600: Garbage retention when source CompletableFutures are never completed
     *
     * As of 2016-07, fails with OOME:
     * ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest -Djsr166.methodFilter=testCancelledGarbageRetention tck
     */
    public void testCancelledGarbageRetention() throws Throwable {
        final int n = expensiveTests ? 100_000 : 10;
        CompletableFuture<Item> neverCompleted = new CompletableFuture<>();
        for (int i = 0; i < n; i++)
            assertTrue(neverCompleted.thenRun(() -> {}).cancel(true));
    }

    /**
     * Checks for garbage retention when MinimalStage.toCompletableFuture()
     * is invoked many times.
     * 8161600: Garbage retention when source CompletableFutures are never completed
     *
     * As of 2016-07, fails with OOME:
     * ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest -Djsr166.methodFilter=testToCompletableFutureGarbageRetention tck
     */
    public void testToCompletableFutureGarbageRetention() throws Throwable {
        final int n = expensiveTests ? 900_000 : 10;
        CompletableFuture<Item> neverCompleted = new CompletableFuture<>();
        CompletionStage<Item> minimal = neverCompleted.minimalCompletionStage();
        for (int i = 0; i < n; i++)
            assertTrue(minimal.toCompletableFuture().cancel(true));
    }

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

    // For testing default implementations
    // Only non-default interface methods defined.
    static final class DelegatedCompletionStage<T> implements CompletionStage<T> {
        final CompletableFuture<T> cf;
        DelegatedCompletionStage(CompletableFuture<T> cf) { this.cf = cf; }
        public CompletableFuture<T> toCompletableFuture() {
            return cf; }
        public CompletionStage<Void> thenRun
            (Runnable action) {
            return cf.thenRun(action); }
        public CompletionStage<Void> thenRunAsync
            (Runnable action) {
            return cf.thenRunAsync(action); }
        public CompletionStage<Void> thenRunAsync
            (Runnable action,
             Executor executor) {
            return cf.thenRunAsync(action, executor); }
        public CompletionStage<Void> thenAccept
            (Consumer<? super T> action) {
            return cf.thenAccept(action); }
        public CompletionStage<Void> thenAcceptAsync
            (Consumer<? super T> action) {
            return cf.thenAcceptAsync(action); }
        public CompletionStage<Void> thenAcceptAsync
            (Consumer<? super T> action,
             Executor executor) {
            return cf.thenAcceptAsync(action, executor); }
        public <U> CompletionStage<U> thenApply
            (Function<? super T,? extends U> a) {
            return cf.thenApply(a); }
        public <U> CompletionStage<U> thenApplyAsync
            (Function<? super T,? extends U> fn) {
            return cf.thenApplyAsync(fn); }
        public <U> CompletionStage<U> thenApplyAsync
            (Function<? super T,? extends U> fn,
             Executor executor) {
            return cf.thenApplyAsync(fn, executor); }
        public <U,V> CompletionStage<V> thenCombine
            (CompletionStage<? extends U> other,
             BiFunction<? super T,? super U,? extends V> fn) {
            return cf.thenCombine(other, fn); }
        public <U,V> CompletionStage<V> thenCombineAsync
            (CompletionStage<? extends U> other,
             BiFunction<? super T,? super U,? extends V> fn) {
            return cf.thenCombineAsync(other, fn); }
        public <U,V> CompletionStage<V> thenCombineAsync
            (CompletionStage<? extends U> other,
             BiFunction<? super T,? super U,? extends V> fn,
             Executor executor) {
            return cf.thenCombineAsync(other, fn, executor); }
        public <U> CompletionStage<Void> thenAcceptBoth
            (CompletionStage<? extends U> other,
             BiConsumer<? super T, ? super U> action) {
            return cf.thenAcceptBoth(other, action); }
        public <U> CompletionStage<Void> thenAcceptBothAsync
            (CompletionStage<? extends U> other,
             BiConsumer<? super T, ? super U> action) {
            return cf.thenAcceptBothAsync(other, action); }
        public <U> CompletionStage<Void> thenAcceptBothAsync
            (CompletionStage<? extends U> other,
             BiConsumer<? super T, ? super U> action,
             Executor executor) {
            return cf.thenAcceptBothAsync(other, action, executor); }
        public CompletionStage<Void> runAfterBoth
            (CompletionStage<?> other,
             Runnable action) {
            return cf.runAfterBoth(other, action); }
        public CompletionStage<Void> runAfterBothAsync
            (CompletionStage<?> other,
             Runnable action) {
            return cf.runAfterBothAsync(other, action); }
        public CompletionStage<Void> runAfterBothAsync
            (CompletionStage<?> other,
             Runnable action,
             Executor executor) {
            return cf.runAfterBothAsync(other, action, executor); }
        public <U> CompletionStage<U> applyToEither
            (CompletionStage<? extends T> other,
             Function<? super T, U> fn) {
            return cf.applyToEither(other, fn); }
        public <U> CompletionStage<U> applyToEitherAsync
            (CompletionStage<? extends T> other,
             Function<? super T, U> fn) {
            return cf.applyToEitherAsync(other, fn); }
        public <U> CompletionStage<U> applyToEitherAsync
            (CompletionStage<? extends T> other,
             Function<? super T, U> fn,
             Executor executor) {
            return cf.applyToEitherAsync(other, fn, executor); }
        public CompletionStage<Void> acceptEither
            (CompletionStage<? extends T> other,
             Consumer<? super T> action) {
            return cf.acceptEither(other, action); }
        public CompletionStage<Void> acceptEitherAsync
            (CompletionStage<? extends T> other,
             Consumer<? super T> action) {
            return cf.acceptEitherAsync(other, action); }
        public CompletionStage<Void> acceptEitherAsync
            (CompletionStage<? extends T> other,
             Consumer<? super T> action,
             Executor executor) {
            return cf.acceptEitherAsync(other, action, executor); }
        public CompletionStage<Void> runAfterEither
            (CompletionStage<?> other,
             Runnable action) {
            return cf.runAfterEither(other, action); }
        public CompletionStage<Void> runAfterEitherAsync
            (CompletionStage<?> other,
             Runnable action) {
            return cf.runAfterEitherAsync(other, action); }
        public CompletionStage<Void> runAfterEitherAsync
            (CompletionStage<?> other,
             Runnable action,
             Executor executor) {
            return cf.runAfterEitherAsync(other, action, executor); }
        public <U> CompletionStage<U> thenCompose
            (Function<? super T, ? extends CompletionStage<U>> fn) {
            return cf.thenCompose(fn); }
        public <U> CompletionStage<U> thenComposeAsync
            (Function<? super T, ? extends CompletionStage<U>> fn) {
            return cf.thenComposeAsync(fn); }
        public <U> CompletionStage<U> thenComposeAsync
            (Function<? super T, ? extends CompletionStage<U>> fn,
             Executor executor) {
            return cf.thenComposeAsync(fn, executor); }
        public <U> CompletionStage<U> handle
            (BiFunction<? super T, Throwable, ? extends U> fn) {
            return cf.handle(fn); }
        public <U> CompletionStage<U> handleAsync
            (BiFunction<? super T, Throwable, ? extends U> fn) {
            return cf.handleAsync(fn); }
        public <U> CompletionStage<U> handleAsync
            (BiFunction<? super T, Throwable, ? extends U> fn,
             Executor executor) {
            return cf.handleAsync(fn, executor); }
        public CompletionStage<T> whenComplete
            (BiConsumer<? super T, ? super Throwable> action) {
            return cf.whenComplete(action); }
        public CompletionStage<T> whenCompleteAsync
            (BiConsumer<? super T, ? super Throwable> action) {
            return cf.whenCompleteAsync(action); }
        public CompletionStage<T> whenCompleteAsync
            (BiConsumer<? super T, ? super Throwable> action,
             Executor executor) {
            return cf.whenCompleteAsync(action, executor); }
        public CompletionStage<T> exceptionally
            (Function<Throwable, ? extends T> fn) {
            return cf.exceptionally(fn); }
    }

    /**
     * default-implemented exceptionallyAsync action is not invoked when
     * source completes normally, and source result is propagated
     */
    public void testDefaultExceptionallyAsync_normalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Item v1 : new Item[] { one, null })
    {
        final AtomicInteger ran = new AtomicInteger(0);
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletionStage<Item> g = d.exceptionallyAsync
            ((Throwable t) -> {
                ran.getAndIncrement();
                throw new AssertionError("should not be called");
            });
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(g.toCompletableFuture(), v1);
        checkCompletedNormally(f, v1);
        mustEqual(0, ran.get());
    }}

    /**
     * default-implemented exceptionallyAsync action completes with
     * function value on source exception
     */
    public void testDefaultExceptionallyAsync_exceptionalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Item v1 : new Item[] { one, null })
    {
        final AtomicInteger ran = new AtomicInteger(0);
        final CFException ex = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletionStage<Item> g = d.exceptionallyAsync
            ((Throwable t) -> {
                assertSame(t, ex);
                ran.getAndIncrement();
                return v1;
            });
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedNormally(g.toCompletableFuture(), v1);
        checkCompletedExceptionally(f, ex);
        mustEqual(1, ran.get());
    }}

    /**
     * Under default implementation, if an "exceptionally action"
     * throws an exception, it completes exceptionally with that
     * exception
     */
    public void testDefaultExceptionallyAsync_exceptionalCompletionActionFailed() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final AtomicInteger ran = new AtomicInteger(0);
        final CFException ex1 = new CFException();
        final CFException ex2 = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) f.completeExceptionally(ex1);
        final CompletionStage<Item> g = d.exceptionallyAsync
            ((Throwable t) -> {
                assertSame(t, ex1);
                ran.getAndIncrement();
                throw ex2;
            });
        if (createIncomplete) f.completeExceptionally(ex1);

        checkCompletedWithWrappedException(g.toCompletableFuture(), ex2);
        checkCompletedExceptionally(f, ex1);
        checkCompletedExceptionally(d.toCompletableFuture(), ex1);
        mustEqual(1, ran.get());
    }}

    /**
     * default-implemented exceptionallyCompose result completes
     * normally after normal completion of source
     */
    public void testDefaultExceptionallyCompose_normalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final ExceptionalCompletableFutureFunction r =
            new ExceptionalCompletableFutureFunction(ExecutionMode.SYNC);
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletionStage<Item> g = d.exceptionallyCompose(r);
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g.toCompletableFuture(), v1);
        r.assertNotInvoked();
    }}

    /**
     * default-implemented exceptionallyCompose result completes
     * normally after exceptional completion of source
     */
    public void testDefaultExceptionallyCompose_exceptionalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final CFException ex = new CFException();
        final ExceptionalCompletableFutureFunction r =
            new ExceptionalCompletableFutureFunction(ExecutionMode.SYNC);
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletionStage<Item> g = d.exceptionallyCompose(r);
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedExceptionally(f, ex);
        checkCompletedNormally(g.toCompletableFuture(), r.value);
        r.assertInvoked();
    }}

    /**
     * default-implemented exceptionallyCompose completes
     * exceptionally on exception if action does
     */
    public void testDefaultExceptionallyCompose_actionFailed() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final CFException ex = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final FailingExceptionalCompletableFutureFunction r
            = new FailingExceptionalCompletableFutureFunction(ExecutionMode.SYNC);
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletionStage<Item> g = d.exceptionallyCompose(r);
        if (createIncomplete) f.completeExceptionally(ex);

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

    /**
     * default-implemented exceptionallyComposeAsync result completes
     * normally after normal completion of source
     */
    public void testDefaultExceptionallyComposeAsync_normalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final ExceptionalCompletableFutureFunction r =
            new ExceptionalCompletableFutureFunction(ExecutionMode.ASYNC);
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletionStage<Item> g = d.exceptionallyComposeAsync(r);
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g.toCompletableFuture(), v1);
        r.assertNotInvoked();
    }}

    /**
     * default-implemented exceptionallyComposeAsync result completes
     * normally after exceptional completion of source
     */
    public void testDefaultExceptionallyComposeAsync_exceptionalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final CFException ex = new CFException();
        final ExceptionalCompletableFutureFunction r =
            new ExceptionalCompletableFutureFunction(ExecutionMode.ASYNC);
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletionStage<Item> g = d.exceptionallyComposeAsync(r);
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedExceptionally(f, ex);
        checkCompletedNormally(g.toCompletableFuture(), r.value);
        r.assertInvoked();
    }}

    /**
     * default-implemented exceptionallyComposeAsync completes
     * exceptionally on exception if action does
     */
    public void testDefaultExceptionallyComposeAsync_actionFailed() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final CFException ex = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final FailingExceptionalCompletableFutureFunction r
            = new FailingExceptionalCompletableFutureFunction(ExecutionMode.ASYNC);
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletionStage<Item> g = d.exceptionallyComposeAsync(r);
        if (createIncomplete) f.completeExceptionally(ex);

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

    /**
     * default-implemented exceptionallyComposeAsync result completes
     * normally after normal completion of source
     */
    public void testDefaultExceptionallyComposeAsyncExecutor_normalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
        for (Item v1 : new Item[] { one, null })
    {
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final ExceptionalCompletableFutureFunction r =
            new ExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR);
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) assertTrue(f.complete(v1));
        final CompletionStage<Item> g = d.exceptionallyComposeAsync(r, new ThreadExecutor());
        if (createIncomplete) assertTrue(f.complete(v1));

        checkCompletedNormally(f, v1);
        checkCompletedNormally(g.toCompletableFuture(), v1);
        r.assertNotInvoked();
    }}

    /**
     * default-implemented exceptionallyComposeAsync result completes
     * normally after exceptional completion of source
     */
    public void testDefaultExceptionallyComposeAsyncExecutor_exceptionalCompletion() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final CFException ex = new CFException();
        final ExceptionalCompletableFutureFunction r =
            new ExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR);
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletionStage<Item> g = d.exceptionallyComposeAsync(r, new ThreadExecutor());
        if (createIncomplete) f.completeExceptionally(ex);

        checkCompletedExceptionally(f, ex);
        checkCompletedNormally(g.toCompletableFuture(), r.value);
        r.assertInvoked();
    }}

    /**
     * default-implemented exceptionallyComposeAsync completes
     * exceptionally on exception if action does
     */
    public void testDefaultExceptionallyComposeAsyncExecutor_actionFailed() {
        for (boolean createIncomplete : new boolean[] { true, false })
    {
        final CFException ex = new CFException();
        final CompletableFuture<Item> f = new CompletableFuture<>();
        final FailingExceptionalCompletableFutureFunction r
            = new FailingExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR);
        final DelegatedCompletionStage<Item> d =
            new DelegatedCompletionStage<>(f);
        if (!createIncomplete) f.completeExceptionally(ex);
        final CompletionStage<Item> g = d.exceptionallyComposeAsync(r, new ThreadExecutor());
        if (createIncomplete) f.completeExceptionally(ex);

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

    public void testOnlyHelpsIfInTheSamePool() throws Exception {
        class Logic {
            interface Extractor { ForkJoinPool pool(CompletableFuture<ForkJoinPool> cf) throws Exception; }
            static final List<ForkJoinPool> executeInnerOuter(
                ForkJoinPool outer, ForkJoinPool inner, Logic.Extractor extractor
            ) throws Exception {
                return CompletableFuture.supplyAsync(() ->
                    Stream.iterate(1, i -> i + 1)
                        .limit(64)
                        .map(i -> CompletableFuture.supplyAsync(
                            () -> Thread.currentThread() instanceof ForkJoinWorkerThread wt ? wt.getPool() : null, inner)
                        )
                        .map(cf -> {
                            try {
                                return extractor.pool(cf);
                            } catch (Exception ex) {
                                throw new AssertionError("Unexpected", ex);
                            }
                        })
                        .toList()
                , outer).join();
            }
        }

        List<Logic.Extractor> extractors =
            List.of(
                c -> c.get(60, SECONDS),
                CompletableFuture::get,
                CompletableFuture::join
            );

        try (var pool = new ForkJoinPool(2)) {
            for (var extractor : extractors) {
                for (var p : Logic.executeInnerOuter(pool, ForkJoinPool.commonPool(), extractor))
                    assertTrue(p != pool); // The inners should have all been executed by commonPool

                for (var p : Logic.executeInnerOuter(pool, pool, extractor))
                    assertTrue(p == pool); // The inners could have been helped by the outer
            }
        }
    }
}
