/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * 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.
 */
package org.openjdk.testlib.java.util.stream;

import org.testng.annotations.Test;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Spliterator;
import java.util.function.*;

import static org.testng.Assert.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;

/**
 * Assertion methods for spliterators, to be called from other tests
 */
public class SpliteratorTestHelper {

    public interface ContentAsserter<T> {
        void assertContents(Collection<T> actual, Collection<T> expected, boolean isOrdered);
    }

    private static ContentAsserter<Object> DEFAULT_CONTENT_ASSERTER
            = SpliteratorTestHelper::assertContents;

    @SuppressWarnings("unchecked")
    private static <T> ContentAsserter<T> defaultContentAsserter() {
        return (ContentAsserter<T>) DEFAULT_CONTENT_ASSERTER;
    }

    public static void testSpliterator(Supplier<Spliterator<Integer>> supplier) {
        testSpliterator(supplier, defaultContentAsserter());
    }

    public static void testSpliterator(Supplier<Spliterator<Integer>> supplier,
                                       ContentAsserter<Integer> asserter) {
        testSpliterator(supplier, (Consumer<Integer> b) -> b, asserter);
    }

    public static void testIntSpliterator(Supplier<Spliterator.OfInt> supplier) {
        testIntSpliterator(supplier, defaultContentAsserter());
    }

    public static void testIntSpliterator(Supplier<Spliterator.OfInt> supplier,
                                          ContentAsserter<Integer> asserter) {
        class BoxingAdapter implements Consumer<Integer>, IntConsumer {
            private final Consumer<Integer> b;

            BoxingAdapter(Consumer<Integer> b) {
                this.b = b;
            }

            @Override
            public void accept(Integer value) {
                throw new IllegalStateException();
            }

            @Override
            public void accept(int value) {
                b.accept(value);
            }
        }

        testSpliterator(supplier, BoxingAdapter::new, asserter);
    }

    public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier) {
        testLongSpliterator(supplier, defaultContentAsserter());
    }

    public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier,
                                           ContentAsserter<Long> asserter) {
        class BoxingAdapter implements Consumer<Long>, LongConsumer {
            private final Consumer<Long> b;

            BoxingAdapter(Consumer<Long> b) {
                this.b = b;
            }

            @Override
            public void accept(Long value) {
                throw new IllegalStateException();
            }

            @Override
            public void accept(long value) {
                b.accept(value);
            }
        }

        testSpliterator(supplier, BoxingAdapter::new, asserter);
    }

    public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier) {
        testDoubleSpliterator(supplier, defaultContentAsserter());
    }

    public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier,
                                             ContentAsserter<Double> asserter) {
        class BoxingAdapter implements Consumer<Double>, DoubleConsumer {
            private final Consumer<Double> b;

            BoxingAdapter(Consumer<Double> b) {
                this.b = b;
            }

            @Override
            public void accept(Double value) {
                throw new IllegalStateException();
            }

            @Override
            public void accept(double value) {
                b.accept(value);
            }
        }

        testSpliterator(supplier, BoxingAdapter::new, asserter);
    }

    static <T, S extends Spliterator<T>> void testSpliterator(Supplier<S> supplier,
                                                              UnaryOperator<Consumer<T>> boxingAdapter,
                                                              ContentAsserter<T> asserter) {
        ArrayList<T> fromForEach = new ArrayList<>();
        Spliterator<T> spliterator = supplier.get();
        Consumer<T> addToFromForEach = boxingAdapter.apply(fromForEach::add);
        spliterator.forEachRemaining(addToFromForEach);

        Collection<T> exp = Collections.unmodifiableList(fromForEach);

        testNullPointerException(supplier);
        testForEach(exp, supplier, boxingAdapter, asserter);
        testTryAdvance(exp, supplier, boxingAdapter, asserter);
        testMixedTryAdvanceForEach(exp, supplier, boxingAdapter, asserter);
        testMixedTraverseAndSplit(exp, supplier, boxingAdapter, asserter);
        testSplitAfterFullTraversal(supplier, boxingAdapter);
        testSplitOnce(exp, supplier, boxingAdapter, asserter);
        testSplitSixDeep(exp, supplier, boxingAdapter, asserter);
        testSplitUntilNull(exp, supplier, boxingAdapter, asserter);
    }

    //

    private static <T, S extends Spliterator<T>> void testNullPointerException(Supplier<S> s) {
        S sp = s.get();
        // Have to check instances and use casts to avoid tripwire messages and
        // directly test the primitive methods
        if (sp instanceof Spliterator.OfInt) {
            Spliterator.OfInt psp = (Spliterator.OfInt) sp;
            executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((IntConsumer) null));
            executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((IntConsumer) null));
        }
        else if (sp instanceof Spliterator.OfLong) {
            Spliterator.OfLong psp = (Spliterator.OfLong) sp;
            executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((LongConsumer) null));
            executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((LongConsumer) null));
        }
        else if (sp instanceof Spliterator.OfDouble) {
            Spliterator.OfDouble psp = (Spliterator.OfDouble) sp;
            executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((DoubleConsumer) null));
            executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((DoubleConsumer) null));
        }
        else {
            executeAndCatch(NullPointerException.class, () -> sp.forEachRemaining(null));
            executeAndCatch(NullPointerException.class, () -> sp.tryAdvance(null));
        }
    }

    private static <T, S extends Spliterator<T>> void testForEach(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        ArrayList<T> fromForEach = new ArrayList<>();
        spliterator = supplier.get();
        Consumer<T> addToFromForEach = boxingAdapter.apply(fromForEach::add);
        spliterator.forEachRemaining(addToFromForEach);

        // Assert that forEach now produces no elements
        spliterator.forEachRemaining(boxingAdapter.apply(
                e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e)));
        // Assert that tryAdvance now produce no elements
        spliterator.tryAdvance(boxingAdapter.apply(
                e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e)));

        // assert that size, tryAdvance, and forEach are consistent
        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, exp.size());
        }
        assertEquals(fromForEach.size(), exp.size());

        asserter.assertContents(fromForEach, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testTryAdvance(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        spliterator = supplier.get();
        ArrayList<T> fromTryAdvance = new ArrayList<>();
        Consumer<T> addToFromTryAdvance = boxingAdapter.apply(fromTryAdvance::add);
        while (spliterator.tryAdvance(addToFromTryAdvance)) { }

        // Assert that forEach now produces no elements
        spliterator.forEachRemaining(boxingAdapter.apply(
                e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e)));
        // Assert that tryAdvance now produce no elements
        spliterator.tryAdvance(boxingAdapter.apply(
                e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e)));

        // assert that size, tryAdvance, and forEach are consistent
        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, exp.size());
        }
        assertEquals(fromTryAdvance.size(), exp.size());

        asserter.assertContents(fromTryAdvance, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testMixedTryAdvanceForEach(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        // tryAdvance first few elements, then forEach rest
        ArrayList<T> dest = new ArrayList<>();
        spliterator = supplier.get();
        Consumer<T> addToDest = boxingAdapter.apply(dest::add);
        for (int i = 0; i < 10 && spliterator.tryAdvance(addToDest); i++) { }
        spliterator.forEachRemaining(addToDest);

        // Assert that forEach now produces no elements
        spliterator.forEachRemaining(boxingAdapter.apply(
                e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e)));
        // Assert that tryAdvance now produce no elements
        spliterator.tryAdvance(boxingAdapter.apply(
                e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e)));

        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, dest.size());
        }
        assertEquals(dest.size(), exp.size());

        asserter.assertContents(dest, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testMixedTraverseAndSplit(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        // tryAdvance first few elements, then forEach rest
        ArrayList<T> dest = new ArrayList<>();
        spliterator = supplier.get();
        Consumer<T> b = boxingAdapter.apply(dest::add);

        Spliterator<T> spl1, spl2, spl3;
        spliterator.tryAdvance(b);
        spl2 = spliterator.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        spliterator.tryAdvance(b);
        spl3 = spliterator.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        spliterator.tryAdvance(b);
        spliterator.forEachRemaining(b);

        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, dest.size());
        }
        assertEquals(dest.size(), exp.size());

        asserter.assertContents(dest, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testSplitAfterFullTraversal(
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter) {
        // Full traversal using tryAdvance
        Spliterator<T> spliterator = supplier.get();
        while (spliterator.tryAdvance(boxingAdapter.apply(e -> { }))) { }
        Spliterator<T> split = spliterator.trySplit();
        assertNull(split);

        // Full traversal using forEach
        spliterator = supplier.get();
        spliterator.forEachRemaining(boxingAdapter.apply(e -> { }));
        split = spliterator.trySplit();
        assertNull(split);

        // Full traversal using tryAdvance then forEach
        spliterator = supplier.get();
        spliterator.tryAdvance(boxingAdapter.apply(e -> { }));
        spliterator.forEachRemaining(boxingAdapter.apply(e -> { }));
        split = spliterator.trySplit();
        assertNull(split);
    }

    private static <T, S extends Spliterator<T>> void testSplitOnce(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        ArrayList<T> fromSplit = new ArrayList<>();
        Spliterator<T> s1 = supplier.get();
        Spliterator<T> s2 = s1.trySplit();
        long s1Size = s1.getExactSizeIfKnown();
        long s2Size = (s2 != null) ? s2.getExactSizeIfKnown() : 0;
        Consumer<T> addToFromSplit = boxingAdapter.apply(fromSplit::add);
        if (s2 != null)
            s2.forEachRemaining(addToFromSplit);
        s1.forEachRemaining(addToFromSplit);

        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, fromSplit.size());
            if (s1Size >= 0 && s2Size >= 0)
                assertEquals(sizeIfKnown, s1Size + s2Size);
        }

        asserter.assertContents(fromSplit, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testSplitSixDeep(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        for (int depth=0; depth < 6; depth++) {
            List<T> dest = new ArrayList<>();
            spliterator = supplier.get();

            assertSpliterator(spliterator);

            // verify splitting with forEach
            splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false);
            asserter.assertContents(dest, exp, isOrdered);

            // verify splitting with tryAdvance
            dest.clear();
            spliterator = supplier.get();
            splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), true);
            asserter.assertContents(dest, exp, isOrdered);
        }
    }

    static void splitSixDeepVisitorUnsafe(int depth, int curLevel, List dest,
        Spliterator spliterator, UnaryOperator boxingAdapter,
        int rootCharacteristics, boolean useTryAdvance) {
      splitSixDeepVisitor(depth, curLevel, dest, spliterator, boxingAdapter, rootCharacteristics, useTryAdvance);
    }

    // Android-changed: Workaround for jack type inference bug
     private static <T>
    // private static <T, S extends Spliterator<T>>
    // Android-changed: Workaround for jack type inference bug
    void splitSixDeepVisitor(int depth, int curLevel,
                             List<T> dest, Spliterator<T> spliterator, UnaryOperator<Consumer<T>> boxingAdapter,
    //                         List<T> dest, S spliterator, UnaryOperator<Consumer<T>> boxingAdapter,
                             int rootCharacteristics, boolean useTryAdvance) {
        if (curLevel < depth) {
            long beforeSize = spliterator.getExactSizeIfKnown();
            Spliterator<T> split = spliterator.trySplit();
            if (split != null) {
                assertSpliterator(split, rootCharacteristics);
                assertSpliterator(spliterator, rootCharacteristics);

                if ((rootCharacteristics & Spliterator.SUBSIZED) != 0 &&
                    (rootCharacteristics & Spliterator.SIZED) != 0) {
                    assertEquals(beforeSize, split.estimateSize() + spliterator.estimateSize());
                }
                // Android-changed: Workaround for jack type inference bug
                splitSixDeepVisitorUnsafe(depth, curLevel + 1, dest, split, boxingAdapter, rootCharacteristics, useTryAdvance);
                // splitSixDeepVisitor(depth, curLevel + 1, dest, split, boxingAdapter, rootCharacteristics, useTryAdvance);
            }
            splitSixDeepVisitor(depth, curLevel + 1, dest, spliterator, boxingAdapter, rootCharacteristics, useTryAdvance);
        }
        else {
            long sizeIfKnown = spliterator.getExactSizeIfKnown();
            if (useTryAdvance) {
                Consumer<T> addToDest = boxingAdapter.apply(dest::add);
                int count = 0;
                while (spliterator.tryAdvance(addToDest)) {
                    ++count;
                }

                if (sizeIfKnown >= 0)
                    assertEquals(sizeIfKnown, count);

                // Assert that forEach now produces no elements
                spliterator.forEachRemaining(boxingAdapter.apply(
                        e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e)));

                Spliterator<T> split = spliterator.trySplit();
                assertNull(split);
            }
            else {
                List<T> leafDest = new ArrayList<>();
                Consumer<T> addToLeafDest = boxingAdapter.apply(leafDest::add);
                spliterator.forEachRemaining(addToLeafDest);

                if (sizeIfKnown >= 0)
                    assertEquals(sizeIfKnown, leafDest.size());

                // Assert that forEach now produces no elements
                spliterator.tryAdvance(boxingAdapter.apply(
                        e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e)));

                Spliterator<T> split = spliterator.trySplit();
                assertNull(split);

                dest.addAll(leafDest);
            }
        }
    }

    private static <T, S extends Spliterator<T>> void testSplitUntilNull(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        Spliterator<T> s = supplier.get();
        boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED);
        assertSpliterator(s);

        List<T> splits = new ArrayList<>();
        Consumer<T> c = boxingAdapter.apply(splits::add);

        testSplitUntilNull(new SplitNode<T>(c, s));
        asserter.assertContents(splits, exp, isOrdered);
    }

    private static class SplitNode<T> {
        // Constant for every node
        final Consumer<T> c;
        final int rootCharacteristics;

        final Spliterator<T> s;

        SplitNode(Consumer<T> c, Spliterator<T> s) {
            this(c, s.characteristics(), s);
        }

        private SplitNode(Consumer<T> c, int rootCharacteristics, Spliterator<T> s) {
            this.c = c;
            this.rootCharacteristics = rootCharacteristics;
            this.s = s;
        }

        SplitNode<T> fromSplit(Spliterator<T> split) {
            return new SplitNode<>(c, rootCharacteristics, split);
        }
    }

    /**
     * Set the maximum stack capacity to 0.25MB. This should be more than enough to detect a bad spliterator
     * while not unduly disrupting test infrastructure given the test data sizes that are used are small.
     * Note that j.u.c.ForkJoinPool sets the max queue size to 64M (1 << 26).
     */
    private static final int MAXIMUM_STACK_CAPACITY = 1 << 18; // 0.25MB

    private static <T> void testSplitUntilNull(SplitNode<T> e) {
        // Use an explicit stack to avoid a StackOverflowException when testing a Spliterator
        // that when repeatedly split produces a right-balanced (and maybe degenerate) tree, or
        // for a spliterator that is badly behaved.
        Deque<SplitNode<T>> stack = new ArrayDeque<>();
        stack.push(e);

        int iteration = 0;
        while (!stack.isEmpty()) {
            assertTrue(iteration++ < MAXIMUM_STACK_CAPACITY, "Exceeded maximum stack modification count of 1 << 18");

            e = stack.pop();
            Spliterator<T> parentAndRightSplit = e.s;

            long parentEstimateSize = parentAndRightSplit.estimateSize();
            assertTrue(parentEstimateSize >= 0,
                       String.format("Split size estimate %d < 0", parentEstimateSize));

            long parentSize = parentAndRightSplit.getExactSizeIfKnown();
            Spliterator<T> leftSplit = parentAndRightSplit.trySplit();
            if (leftSplit == null) {
                parentAndRightSplit.forEachRemaining(e.c);
                continue;
            }

            assertSpliterator(leftSplit, e.rootCharacteristics);
            assertSpliterator(parentAndRightSplit, e.rootCharacteristics);

            if (parentEstimateSize != Long.MAX_VALUE && leftSplit.estimateSize() > 0
                && parentAndRightSplit.estimateSize() > 0) {
                assertTrue(leftSplit.estimateSize() < parentEstimateSize,
                           String.format("Left split size estimate %d >= parent split size estimate %d",
                                         leftSplit.estimateSize(), parentEstimateSize));
                assertTrue(parentAndRightSplit.estimateSize() < parentEstimateSize,
                           String.format("Right split size estimate %d >= parent split size estimate %d",
                                         leftSplit.estimateSize(), parentEstimateSize));
            }
            else {
                assertTrue(leftSplit.estimateSize() <= parentEstimateSize,
                           String.format("Left split size estimate %d > parent split size estimate %d",
                                         leftSplit.estimateSize(), parentEstimateSize));
                assertTrue(parentAndRightSplit.estimateSize() <= parentEstimateSize,
                           String.format("Right split size estimate %d > parent split size estimate %d",
                                         leftSplit.estimateSize(), parentEstimateSize));
            }

            long leftSize = leftSplit.getExactSizeIfKnown();
            long rightSize = parentAndRightSplit.getExactSizeIfKnown();
            if (parentSize >= 0 && leftSize >= 0 && rightSize >= 0)
                assertEquals(parentSize, leftSize + rightSize,
                             String.format("exact left split size %d + exact right split size %d != parent exact split size %d",
                                           leftSize, rightSize, parentSize));

            // Add right side to stack first so left side is popped off first
            stack.push(e.fromSplit(parentAndRightSplit));
            stack.push(e.fromSplit(leftSplit));
        }
    }

    private static void assertSpliterator(Spliterator<?> s, int rootCharacteristics) {
        if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) {
            assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED),
                       "Child split is not SUBSIZED when root split is SUBSIZED");
        }
        assertSpliterator(s);
    }

    private static void assertSpliterator(Spliterator<?> s) {
        if (s.hasCharacteristics(Spliterator.SUBSIZED)) {
            assertTrue(s.hasCharacteristics(Spliterator.SIZED));
        }
        if (s.hasCharacteristics(Spliterator.SIZED)) {
            assertTrue(s.estimateSize() != Long.MAX_VALUE);
            assertTrue(s.getExactSizeIfKnown() >= 0);
        }
        try {
            s.getComparator();
            assertTrue(s.hasCharacteristics(Spliterator.SORTED));
        } catch (IllegalStateException e) {
            assertFalse(s.hasCharacteristics(Spliterator.SORTED));
        }
    }

    private static<T> void assertContents(Collection<T> actual, Collection<T> expected, boolean isOrdered) {
        if (isOrdered) {
            assertEquals(actual, expected);
        }
        else {
            LambdaTestHelpers.assertContentsUnordered(actual, expected);
        }
    }

    private static void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
        Exception caught = null;
        try {
            r.run();
        }
        catch (Exception e) {
            caught = e;
        }

        assertNotNull(caught,
                      String.format("No Exception was thrown, expected an Exception of %s to be thrown",
                                    expected.getName()));
        assertTrue(expected.isInstance(caught),
                   String.format("Exception thrown %s not an instance of %s",
                                 caught.getClass().getName(), expected.getName()));
    }

    static<U> void mixedTraverseAndSplit(Consumer<U> b, Spliterator<U> splTop) {
        Spliterator<U> spl1, spl2, spl3;
        splTop.tryAdvance(b);
        spl2 = splTop.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        spl3 = splTop.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        splTop.forEachRemaining(b);
    }

    static void mixedTraverseAndSplit(IntConsumer b, Spliterator.OfInt splTop) {
        Spliterator.OfInt spl1, spl2, spl3;
        splTop.tryAdvance(b);
        spl2 = splTop.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        spl3 = splTop.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        splTop.forEachRemaining(b);
    }
    static void mixedTraverseAndSplit(LongConsumer b, Spliterator.OfLong splTop) {
        Spliterator.OfLong spl1, spl2, spl3;
        splTop.tryAdvance(b);
        spl2 = splTop.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        spl3 = splTop.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        splTop.forEachRemaining(b);
    }

    static void mixedTraverseAndSplit(DoubleConsumer b, Spliterator.OfDouble splTop) {
        Spliterator.OfDouble spl1, spl2, spl3;
        splTop.tryAdvance(b);
        spl2 = splTop.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        spl3 = splTop.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        splTop.forEachRemaining(b);
    }
}
