diff --git a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorLateBindingFailFastTest.java b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorLateBindingFailFastTest.java deleted file mode 100644 index af7ddbf066bfe34b4ad1f2a33384adb3bce16699..0000000000000000000000000000000000000000 --- a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorLateBindingFailFastTest.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 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.tests.java.util.stream; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.ConcurrentModificationException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.Set; -import java.util.Spliterator; -import java.util.Stack; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.Vector; -import java.util.WeakHashMap; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import static org.testng.Assert.*; - -/** - * @test - * @summary Spliterator last-binding and fail-fast tests - * @run testng SpliteratorLateBindingFailFastTest - */ - -@Test(groups = { "serialization-hostile" }) -public class SpliteratorLateBindingFailFastTest { - - private interface Source { - Collection asCollection(); - void update(); - } - - private static class SpliteratorDataBuilder { - final List data; - - final T newValue; - - final List exp; - - final Map mExp; - - SpliteratorDataBuilder(List data, T newValue, List exp) { - this.data = data; - this.newValue = newValue; - this.exp = exp; - this.mExp = createMap(exp); - } - - Map createMap(List l) { - Map m = new LinkedHashMap<>(); - for (T t : l) { - m.put(t, t); - } - return m; - } - - void add(String description, Supplier> s) { - description = joiner(description).toString(); - data.add(new Object[]{description, s}); - } - - void addCollection(Function, ? extends Collection> f) { - class CollectionSource implements Source { - final Collection c = f.apply(exp); - - final Consumer> updater; - - CollectionSource(Consumer> updater) { - this.updater = updater; - } - - @Override - public Collection asCollection() { - return c; - } - - @Override - public void update() { - updater.accept(c); - } - } - - String description = "new " + f.apply(Collections.emptyList()).getClass().getName() + ".spliterator() "; - add(description + "ADD", () -> new CollectionSource(c -> c.add(newValue))); - add(description + "REMOVE", () -> new CollectionSource(c -> c.remove(c.iterator().next()))); - } - - void addList(Function, ? extends List> l) { - // @@@ If collection is instance of List then add sub-list tests - addCollection(l); - } - - void addMap(Function, ? extends Map> mapConstructor) { - class MapSource implements Source { - final Map m = mapConstructor.apply(mExp); - - final Collection c; - - final Consumer> updater; - - MapSource(Function, Collection> f, Consumer> updater) { - this.c = f.apply(m); - this.updater = updater; - } - - @Override - public Collection asCollection() { - return c; - } - - @Override - public void update() { - updater.accept(m); - } - } - - Map>> actions = new HashMap<>(); - actions.put("ADD", m -> m.put(newValue, newValue)); - actions.put("REMOVE", m -> m.remove(m.keySet().iterator().next())); - - String description = "new " + mapConstructor.apply(Collections.emptyMap()).getClass().getName(); - for (Map.Entry>> e : actions.entrySet()) { - add(description + ".keySet().spliterator() " + e.getKey(), - () -> new MapSource(m -> m.keySet(), e.getValue())); - add(description + ".values().spliterator() " + e.getKey(), - () -> new MapSource(m -> m.values(), e.getValue())); - add(description + ".entrySet().spliterator() " + e.getKey(), - () -> new MapSource>(m -> m.entrySet(), e.getValue())); - } - } - - StringBuilder joiner(String description) { - return new StringBuilder(description). - append(" {"). - append("size=").append(exp.size()). - append("}"); - } - } - - static Object[][] spliteratorDataProvider; - - @DataProvider(name = "Source") - public static Object[][] spliteratorDataProvider() { - if (spliteratorDataProvider != null) { - return spliteratorDataProvider; - } - - List data = new ArrayList<>(); - SpliteratorDataBuilder db = new SpliteratorDataBuilder<>(data, 5, Arrays.asList(1, 2, 3, 4)); - - // Collections - - db.addList(ArrayList::new); - - db.addList(LinkedList::new); - - db.addList(Vector::new); - - - db.addCollection(HashSet::new); - - db.addCollection(LinkedHashSet::new); - - db.addCollection(TreeSet::new); - - - db.addCollection(c -> { Stack s = new Stack<>(); s.addAll(c); return s;}); - - db.addCollection(PriorityQueue::new); - - // ArrayDeque fails some tests since it's fail-fast support is weaker - // than other collections and limited to detecting most, but not all, - // removals. It probably requires it's own test since it is difficult - // to abstract out the conditions under which it fails-fast. -// db.addCollection(ArrayDeque::new); - - // Maps - - db.addMap(HashMap::new); - - db.addMap(LinkedHashMap::new); - - // This fails when run through jrteg but passes when run though - // ant -// db.addMap(IdentityHashMap::new); - - db.addMap(WeakHashMap::new); - - // @@@ Descending maps etc - db.addMap(TreeMap::new); - - return spliteratorDataProvider = data.toArray(new Object[0][]); - } - - @Test(dataProvider = "Source") - public void lateBindingTestWithForEach(String description, Supplier> ss) { - Source source = ss.get(); - Collection c = source.asCollection(); - Spliterator s = c.spliterator(); - - source.update(); - - Set r = new HashSet<>(); - s.forEachRemaining(r::add); - - assertEquals(r, new HashSet<>(c)); - } - - @Test(dataProvider = "Source") - public void lateBindingTestWithTryAdvance(String description, Supplier> ss) { - Source source = ss.get(); - Collection c = source.asCollection(); - Spliterator s = c.spliterator(); - - source.update(); - - Set r = new HashSet<>(); - while (s.tryAdvance(r::add)) { } - - assertEquals(r, new HashSet<>(c)); - } - - @Test(dataProvider = "Source") - public void lateBindingTestWithCharacteritics(String description, Supplier> ss) { - Source source = ss.get(); - Collection c = source.asCollection(); - Spliterator s = c.spliterator(); - s.characteristics(); - - Set r = new HashSet<>(); - s.forEachRemaining(r::add); - - assertEquals(r, new HashSet<>(c)); - } - - - @Test(dataProvider = "Source") - public void testFailFastTestWithTryAdvance(String description, Supplier> ss) { - { - Source source = ss.get(); - Collection c = source.asCollection(); - Spliterator s = c.spliterator(); - - s.tryAdvance(e -> { - }); - source.update(); - - executeAndCatch(() -> s.tryAdvance(e -> { })); - } - - { - Source source = ss.get(); - Collection c = source.asCollection(); - Spliterator s = c.spliterator(); - - s.tryAdvance(e -> { - }); - source.update(); - - executeAndCatch(() -> s.forEachRemaining(e -> { - })); - } - } - - @Test(dataProvider = "Source") - public void testFailFastTestWithForEach(String description, Supplier> ss) { - Source source = ss.get(); - Collection c = source.asCollection(); - Spliterator s = c.spliterator(); - - executeAndCatch(() -> s.forEachRemaining(e -> { - source.update(); - })); - } - - @Test(dataProvider = "Source") - public void testFailFastTestWithEstimateSize(String description, Supplier> ss) { - { - Source source = ss.get(); - Collection c = source.asCollection(); - Spliterator s = c.spliterator(); - - s.estimateSize(); - source.update(); - - executeAndCatch(() -> s.tryAdvance(e -> { })); - } - - { - Source source = ss.get(); - Collection c = source.asCollection(); - Spliterator s = c.spliterator(); - - s.estimateSize(); - source.update(); - - executeAndCatch(() -> s.forEachRemaining(e -> { - })); - } - } - - private void executeAndCatch(Runnable r) { - executeAndCatch(ConcurrentModificationException.class, r); - } - - private void executeAndCatch(Class 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())); - } - -} diff --git a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTraversingAndSplittingTest.java b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTraversingAndSplittingTest.java deleted file mode 100644 index de9d51cf0d999b823884295dc5dec365f5b0298c..0000000000000000000000000000000000000000 --- a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTraversingAndSplittingTest.java +++ /dev/null @@ -1,1411 +0,0 @@ -/* - * Copyright (c) 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.tests.java.util.stream; - -/** - * @test - * @summary Spliterator traversing and splitting tests - * @run testng SpliteratorTraversingAndSplittingTest - */ - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.util.AbstractCollection; -import java.util.AbstractList; -import java.util.AbstractSet; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Deque; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.Set; -import java.util.SortedSet; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.Stack; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.Vector; -import java.util.WeakHashMap; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ConcurrentSkipListMap; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.LinkedTransferQueue; -import java.util.concurrent.PriorityBlockingQueue; -import java.util.function.Consumer; -import java.util.function.DoubleConsumer; -import java.util.function.Function; -import java.util.function.IntConsumer; -import java.util.function.LongConsumer; -import java.util.function.Supplier; -import java.util.function.UnaryOperator; - -import static org.testng.Assert.*; -import static org.testng.Assert.assertEquals; - -@Test(groups = { "serialization-hostile" }) -public class SpliteratorTraversingAndSplittingTest { - - private static List SIZES = Arrays.asList(0, 1, 10, 100, 1000); - - private static class SpliteratorDataBuilder { - List data; - - List exp; - - Map mExp; - - SpliteratorDataBuilder(List data, List exp) { - this.data = data; - this.exp = exp; - this.mExp = createMap(exp); - } - - Map createMap(List l) { - Map m = new LinkedHashMap<>(); - for (T t : l) { - m.put(t, t); - } - return m; - } - - void add(String description, Collection expected, Supplier> s) { - description = joiner(description).toString(); - data.add(new Object[]{description, expected, s}); - } - - void add(String description, Supplier> s) { - add(description, exp, s); - } - - void addCollection(Function, ? extends Collection> c) { - add("new " + c.apply(Collections.emptyList()).getClass().getName() + ".spliterator()", - () -> c.apply(exp).spliterator()); - } - - void addList(Function, ? extends List> l) { - // @@@ If collection is instance of List then add sub-list tests - addCollection(l); - } - - void addMap(Function, ? extends Map> m) { - String description = "new " + m.apply(Collections.emptyMap()).getClass().getName(); - add(description + ".keySet().spliterator()", () -> m.apply(mExp).keySet().spliterator()); - add(description + ".values().spliterator()", () -> m.apply(mExp).values().spliterator()); - add(description + ".entrySet().spliterator()", mExp.entrySet(), () -> m.apply(mExp).entrySet().spliterator()); - } - - StringBuilder joiner(String description) { - return new StringBuilder(description). - append(" {"). - append("size=").append(exp.size()). - append("}"); - } - } - - static Object[][] spliteratorDataProvider; - - @DataProvider(name = "Spliterator") - public static Object[][] spliteratorDataProvider() { - if (spliteratorDataProvider != null) { - return spliteratorDataProvider; - } - - List data = new ArrayList<>(); - for (int size : SIZES) { - List exp = listIntRange(size); - SpliteratorDataBuilder db = new SpliteratorDataBuilder<>(data, exp); - - // Direct spliterator methods - - db.add("Spliterators.spliterator(Collection, ...)", - () -> Spliterators.spliterator(exp, 0)); - - db.add("Spliterators.spliterator(Iterator, ...)", - () -> Spliterators.spliterator(exp.iterator(), exp.size(), 0)); - - db.add("Spliterators.spliteratorUnknownSize(Iterator, ...)", - () -> Spliterators.spliteratorUnknownSize(exp.iterator(), 0)); - - db.add("Spliterators.spliterator(Spliterators.iteratorFromSpliterator(Spliterator ), ...)", - () -> Spliterators.spliterator(Spliterators.iteratorFromSpliterator(exp.spliterator()), exp.size(), 0)); - - db.add("Spliterators.spliterator(T[], ...)", - () -> Spliterators.spliterator(exp.toArray(new Integer[0]), 0)); - - db.add("Arrays.spliterator(T[], ...)", - () -> Arrays.spliterator(exp.toArray(new Integer[0]))); - - class SpliteratorFromIterator extends Spliterators.AbstractSpliterator { - Iterator it; - - SpliteratorFromIterator(Iterator it, long est) { - super(est, Spliterator.SIZED); - this.it = it; - } - - @Override - public boolean tryAdvance(Consumer action) { - if (action == null) - throw new NullPointerException(); - if (it.hasNext()) { - action.accept(it.next()); - return true; - } - else { - return false; - } - } - } - db.add("new Spliterators.AbstractSpliterator()", - () -> new SpliteratorFromIterator(exp.iterator(), exp.size())); - - // Collections - - // default method implementations - - class AbstractCollectionImpl extends AbstractCollection { - Collection c; - - AbstractCollectionImpl(Collection c) { - this.c = c; - } - - @Override - public Iterator iterator() { - return c.iterator(); - } - - @Override - public int size() { - return c.size(); - } - } - db.addCollection( - c -> new AbstractCollectionImpl(c)); - - class AbstractListImpl extends AbstractList { - List l; - - AbstractListImpl(Collection c) { - this.l = new ArrayList<>(c); - } - - @Override - public Integer get(int index) { - return l.get(index); - } - - @Override - public int size() { - return l.size(); - } - } - db.addCollection( - c -> new AbstractListImpl(c)); - - class AbstractSetImpl extends AbstractSet { - Set s; - - AbstractSetImpl(Collection c) { - this.s = new HashSet<>(c); - } - - @Override - public Iterator iterator() { - return s.iterator(); - } - - @Override - public int size() { - return s.size(); - } - } - db.addCollection( - c -> new AbstractSetImpl(c)); - - class AbstractSortedSetImpl extends AbstractSet implements SortedSet { - SortedSet s; - - AbstractSortedSetImpl(Collection c) { - this.s = new TreeSet<>(c); - } - - @Override - public Iterator iterator() { - return s.iterator(); - } - - @Override - public int size() { - return s.size(); - } - - @Override - public Comparator comparator() { - return s.comparator(); - } - - @Override - public SortedSet subSet(Integer fromElement, Integer toElement) { - return s.subSet(fromElement, toElement); - } - - @Override - public SortedSet headSet(Integer toElement) { - return s.headSet(toElement); - } - - @Override - public SortedSet tailSet(Integer fromElement) { - return s.tailSet(fromElement); - } - - @Override - public Integer first() { - return s.first(); - } - - @Override - public Integer last() { - return s.last(); - } - - @Override - public Spliterator spliterator() { - return SortedSet.super.spliterator(); - } - } - db.addCollection( - c -> new AbstractSortedSetImpl(c)); - - // - - db.add("Arrays.asList().spliterator()", - () -> Spliterators.spliterator(Arrays.asList(exp.toArray(new Integer[0])), 0)); - - db.addList(ArrayList::new); - - db.addList(LinkedList::new); - - db.addList(Vector::new); - - - db.addCollection(HashSet::new); - - db.addCollection(LinkedHashSet::new); - - db.addCollection(TreeSet::new); - - - db.addCollection(c -> { Stack s = new Stack<>(); s.addAll(c); return s;}); - - db.addCollection(PriorityQueue::new); - - db.addCollection(ArrayDeque::new); - - - db.addCollection(ConcurrentSkipListSet::new); - - if (size > 0) { - db.addCollection(c -> { - ArrayBlockingQueue abq = new ArrayBlockingQueue<>(size); - abq.addAll(c); - return abq; - }); - } - - db.addCollection(PriorityBlockingQueue::new); - - db.addCollection(LinkedBlockingQueue::new); - - db.addCollection(LinkedTransferQueue::new); - - db.addCollection(ConcurrentLinkedQueue::new); - - db.addCollection(LinkedBlockingDeque::new); - - db.addCollection(CopyOnWriteArrayList::new); - - db.addCollection(CopyOnWriteArraySet::new); - - if (size == 1) { - db.addCollection(c -> Collections.singleton(exp.get(0))); - db.addCollection(c -> Collections.singletonList(exp.get(0))); - } - - // Collections.synchronized/unmodifiable/checked wrappers - db.addCollection(Collections::unmodifiableCollection); - db.addCollection(c -> Collections.unmodifiableSet(new HashSet<>(c))); - db.addCollection(c -> Collections.unmodifiableSortedSet(new TreeSet<>(c))); - db.addList(c -> Collections.unmodifiableList(new ArrayList<>(c))); - db.addMap(Collections::unmodifiableMap); - db.addMap(m -> Collections.unmodifiableSortedMap(new TreeMap<>(m))); - - db.addCollection(Collections::synchronizedCollection); - db.addCollection(c -> Collections.synchronizedSet(new HashSet<>(c))); - db.addCollection(c -> Collections.synchronizedSortedSet(new TreeSet<>(c))); - db.addList(c -> Collections.synchronizedList(new ArrayList<>(c))); - db.addMap(Collections::synchronizedMap); - db.addMap(m -> Collections.synchronizedSortedMap(new TreeMap<>(m))); - - db.addCollection(c -> Collections.checkedCollection(c, Integer.class)); - db.addCollection(c -> Collections.checkedQueue(new ArrayDeque<>(c), Integer.class)); - db.addCollection(c -> Collections.checkedSet(new HashSet<>(c), Integer.class)); - db.addCollection(c -> Collections.checkedSortedSet(new TreeSet<>(c), Integer.class)); - db.addList(c -> Collections.checkedList(new ArrayList<>(c), Integer.class)); - db.addMap(c -> Collections.checkedMap(c, Integer.class, Integer.class)); - db.addMap(m -> Collections.checkedSortedMap(new TreeMap<>(m), Integer.class, Integer.class)); - - // Maps - - db.addMap(HashMap::new); - - db.addMap(LinkedHashMap::new); - - db.addMap(IdentityHashMap::new); - - db.addMap(WeakHashMap::new); - - // @@@ Descending maps etc - db.addMap(TreeMap::new); - - db.addMap(ConcurrentHashMap::new); - - db.addMap(ConcurrentSkipListMap::new); - } - - return spliteratorDataProvider = data.toArray(new Object[0][]); - } - - private static List listIntRange(int upTo) { - List exp = new ArrayList<>(); - for (int i = 0; i < upTo; i++) - exp.add(i); - return Collections.unmodifiableList(exp); - } - - @Test(dataProvider = "Spliterator") - @SuppressWarnings({"unchecked", "rawtypes"}) - public void testNullPointerException(String description, Collection exp, Supplier s) { - executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining(null)); - executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance(null)); - } - - @Test(dataProvider = "Spliterator") - @SuppressWarnings({"unchecked", "rawtypes"}) - public void testForEach(String description, Collection exp, Supplier s) { - testForEach(exp, s, (Consumer b) -> b); - } - - @Test(dataProvider = "Spliterator") - @SuppressWarnings({"unchecked", "rawtypes"}) - public void testTryAdvance(String description, Collection exp, Supplier s) { - testTryAdvance(exp, s, (Consumer b) -> b); - } - - @Test(dataProvider = "Spliterator") - @SuppressWarnings({"unchecked", "rawtypes"}) - public void testMixedTryAdvanceForEach(String description, Collection exp, Supplier s) { - testMixedTryAdvanceForEach(exp, s, (Consumer b) -> b); - } - - @Test(dataProvider = "Spliterator") - @SuppressWarnings({"unchecked", "rawtypes"}) - public void testMixedTraverseAndSplit(String description, Collection exp, Supplier s) { - testMixedTraverseAndSplit(exp, s, (Consumer b) -> b); - } - - @Test(dataProvider = "Spliterator") - @SuppressWarnings({"unchecked", "rawtypes"}) - public void testSplitAfterFullTraversal(String description, Collection exp, Supplier s) { - testSplitAfterFullTraversal(s, (Consumer b) -> b); - } - - @Test(dataProvider = "Spliterator") - @SuppressWarnings({"unchecked", "rawtypes"}) - public void testSplitOnce(String description, Collection exp, Supplier s) { - testSplitOnce(exp, s, (Consumer b) -> b); - } - - @Test(dataProvider = "Spliterator") - @SuppressWarnings({"unchecked", "rawtypes"}) - public void testSplitSixDeep(String description, Collection exp, Supplier s) { - testSplitSixDeep(exp, s, (Consumer b) -> b); - } - - @Test(dataProvider = "Spliterator") - @SuppressWarnings({"unchecked", "rawtypes"}) - public void testSplitUntilNull(String description, Collection exp, Supplier s) { - testSplitUntilNull(exp, s, (Consumer b) -> b); - } - - // - - private static class SpliteratorOfIntDataBuilder { - List data; - - List exp; - - SpliteratorOfIntDataBuilder(List data, List exp) { - this.data = data; - this.exp = exp; - } - - void add(String description, List expected, Supplier s) { - description = joiner(description).toString(); - data.add(new Object[]{description, expected, s}); - } - - void add(String description, Supplier s) { - add(description, exp, s); - } - - StringBuilder joiner(String description) { - return new StringBuilder(description). - append(" {"). - append("size=").append(exp.size()). - append("}"); - } - } - - static Object[][] spliteratorOfIntDataProvider; - - @DataProvider(name = "Spliterator.OfInt") - public static Object[][] spliteratorOfIntDataProvider() { - if (spliteratorOfIntDataProvider != null) { - return spliteratorOfIntDataProvider; - } - - List data = new ArrayList<>(); - for (int size : SIZES) { - int exp[] = arrayIntRange(size); - SpliteratorOfIntDataBuilder db = new SpliteratorOfIntDataBuilder(data, listIntRange(size)); - - db.add("Spliterators.spliterator(int[], ...)", - () -> Spliterators.spliterator(exp, 0)); - - db.add("Arrays.spliterator(int[], ...)", - () -> Arrays.spliterator(exp)); - - db.add("Spliterators.spliterator(PrimitiveIterator.OfInt, ...)", - () -> Spliterators.spliterator(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), exp.length, 0)); - - db.add("Spliterators.spliteratorUnknownSize(PrimitiveIterator.OfInt, ...)", - () -> Spliterators.spliteratorUnknownSize(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), 0)); - - class IntSpliteratorFromArray extends Spliterators.AbstractIntSpliterator { - int[] a; - int index = 0; - - IntSpliteratorFromArray(int[] a) { - super(a.length, Spliterator.SIZED); - this.a = a; - } - - @Override - public boolean tryAdvance(IntConsumer action) { - if (action == null) - throw new NullPointerException(); - if (index < a.length) { - action.accept(a[index++]); - return true; - } - else { - return false; - } - } - } - db.add("new Spliterators.AbstractIntAdvancingSpliterator()", - () -> new IntSpliteratorFromArray(exp)); - } - - return spliteratorOfIntDataProvider = data.toArray(new Object[0][]); - } - - private static int[] arrayIntRange(int upTo) { - int[] exp = new int[upTo]; - for (int i = 0; i < upTo; i++) - exp[i] = i; - return exp; - } - - private static UnaryOperator> intBoxingConsumer() { - class BoxingAdapter implements Consumer, IntConsumer { - private final Consumer b; - - BoxingAdapter(Consumer b) { - this.b = b; - } - - @Override - public void accept(Integer value) { - throw new IllegalStateException(); - } - - @Override - public void accept(int value) { - b.accept(value); - } - } - - return b -> new BoxingAdapter(b); - } - - @Test(dataProvider = "Spliterator.OfInt") - public void testIntNullPointerException(String description, Collection exp, Supplier s) { - executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((IntConsumer) null)); - executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((IntConsumer) null)); - } - - @Test(dataProvider = "Spliterator.OfInt") - public void testIntForEach(String description, Collection exp, Supplier s) { - testForEach(exp, s, intBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfInt") - public void testIntTryAdvance(String description, Collection exp, Supplier s) { - testTryAdvance(exp, s, intBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfInt") - public void testIntMixedTryAdvanceForEach(String description, Collection exp, Supplier s) { - testMixedTryAdvanceForEach(exp, s, intBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfInt") - public void testIntMixedTraverseAndSplit(String description, Collection exp, Supplier s) { - testMixedTraverseAndSplit(exp, s, intBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfInt") - public void testIntSplitAfterFullTraversal(String description, Collection exp, Supplier s) { - testSplitAfterFullTraversal(s, intBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfInt") - public void testIntSplitOnce(String description, Collection exp, Supplier s) { - testSplitOnce(exp, s, intBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfInt") - public void testIntSplitSixDeep(String description, Collection exp, Supplier s) { - testSplitSixDeep(exp, s, intBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfInt") - public void testIntSplitUntilNull(String description, Collection exp, Supplier s) { - testSplitUntilNull(exp, s, intBoxingConsumer()); - } - - // - - private static class SpliteratorOfLongDataBuilder { - List data; - - List exp; - - SpliteratorOfLongDataBuilder(List data, List exp) { - this.data = data; - this.exp = exp; - } - - void add(String description, List expected, Supplier s) { - description = joiner(description).toString(); - data.add(new Object[]{description, expected, s}); - } - - void add(String description, Supplier s) { - add(description, exp, s); - } - - StringBuilder joiner(String description) { - return new StringBuilder(description). - append(" {"). - append("size=").append(exp.size()). - append("}"); - } - } - - static Object[][] spliteratorOfLongDataProvider; - - @DataProvider(name = "Spliterator.OfLong") - public static Object[][] spliteratorOfLongDataProvider() { - if (spliteratorOfLongDataProvider != null) { - return spliteratorOfLongDataProvider; - } - - List data = new ArrayList<>(); - for (int size : SIZES) { - long exp[] = arrayLongRange(size); - SpliteratorOfLongDataBuilder db = new SpliteratorOfLongDataBuilder(data, listLongRange(size)); - - db.add("Spliterators.spliterator(long[], ...)", - () -> Spliterators.spliterator(exp, 0)); - - db.add("Arrays.spliterator(long[], ...)", - () -> Arrays.spliterator(exp)); - - db.add("Spliterators.spliterator(PrimitiveIterator.OfLong, ...)", - () -> Spliterators.spliterator(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), exp.length, 0)); - - db.add("Spliterators.spliteratorUnknownSize(PrimitiveIterator.OfLong, ...)", - () -> Spliterators.spliteratorUnknownSize(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), 0)); - - class LongSpliteratorFromArray extends Spliterators.AbstractLongSpliterator { - long[] a; - int index = 0; - - LongSpliteratorFromArray(long[] a) { - super(a.length, Spliterator.SIZED); - this.a = a; - } - - @Override - public boolean tryAdvance(LongConsumer action) { - if (action == null) - throw new NullPointerException(); - if (index < a.length) { - action.accept(a[index++]); - return true; - } - else { - return false; - } - } - } - db.add("new Spliterators.AbstractLongAdvancingSpliterator()", - () -> new LongSpliteratorFromArray(exp)); - } - - return spliteratorOfLongDataProvider = data.toArray(new Object[0][]); - } - - private static List listLongRange(int upTo) { - List exp = new ArrayList<>(); - for (long i = 0; i < upTo; i++) - exp.add(i); - return Collections.unmodifiableList(exp); - } - - private static long[] arrayLongRange(int upTo) { - long[] exp = new long[upTo]; - for (int i = 0; i < upTo; i++) - exp[i] = i; - return exp; - } - - private static UnaryOperator> longBoxingConsumer() { - class BoxingAdapter implements Consumer, LongConsumer { - private final Consumer b; - - BoxingAdapter(Consumer b) { - this.b = b; - } - - @Override - public void accept(Long value) { - throw new IllegalStateException(); - } - - @Override - public void accept(long value) { - b.accept(value); - } - } - - return b -> new BoxingAdapter(b); - } - - @Test(dataProvider = "Spliterator.OfLong") - public void testLongNullPointerException(String description, Collection exp, Supplier s) { - executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((LongConsumer) null)); - executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((LongConsumer) null)); - } - - @Test(dataProvider = "Spliterator.OfLong") - public void testLongForEach(String description, Collection exp, Supplier s) { - testForEach(exp, s, longBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfLong") - public void testLongTryAdvance(String description, Collection exp, Supplier s) { - testTryAdvance(exp, s, longBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfLong") - public void testLongMixedTryAdvanceForEach(String description, Collection exp, Supplier s) { - testMixedTryAdvanceForEach(exp, s, longBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfLong") - public void testLongMixedTraverseAndSplit(String description, Collection exp, Supplier s) { - testMixedTraverseAndSplit(exp, s, longBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfLong") - public void testLongSplitAfterFullTraversal(String description, Collection exp, Supplier s) { - testSplitAfterFullTraversal(s, longBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfLong") - public void testLongSplitOnce(String description, Collection exp, Supplier s) { - testSplitOnce(exp, s, longBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfLong") - public void testLongSplitSixDeep(String description, Collection exp, Supplier s) { - testSplitSixDeep(exp, s, longBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfLong") - public void testLongSplitUntilNull(String description, Collection exp, Supplier s) { - testSplitUntilNull(exp, s, longBoxingConsumer()); - } - - // - - private static class SpliteratorOfDoubleDataBuilder { - List data; - - List exp; - - SpliteratorOfDoubleDataBuilder(List data, List exp) { - this.data = data; - this.exp = exp; - } - - void add(String description, List expected, Supplier s) { - description = joiner(description).toString(); - data.add(new Object[]{description, expected, s}); - } - - void add(String description, Supplier s) { - add(description, exp, s); - } - - StringBuilder joiner(String description) { - return new StringBuilder(description). - append(" {"). - append("size=").append(exp.size()). - append("}"); - } - } - - static Object[][] spliteratorOfDoubleDataProvider; - - @DataProvider(name = "Spliterator.OfDouble") - public static Object[][] spliteratorOfDoubleDataProvider() { - if (spliteratorOfDoubleDataProvider != null) { - return spliteratorOfDoubleDataProvider; - } - - List data = new ArrayList<>(); - for (int size : SIZES) { - double exp[] = arrayDoubleRange(size); - SpliteratorOfDoubleDataBuilder db = new SpliteratorOfDoubleDataBuilder(data, listDoubleRange(size)); - - db.add("Spliterators.spliterator(double[], ...)", - () -> Spliterators.spliterator(exp, 0)); - - db.add("Arrays.spliterator(double[], ...)", - () -> Arrays.spliterator(exp)); - - db.add("Spliterators.spliterator(PrimitiveIterator.OfDouble, ...)", - () -> Spliterators.spliterator(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), exp.length, 0)); - - db.add("Spliterators.spliteratorUnknownSize(PrimitiveIterator.OfDouble, ...)", - () -> Spliterators.spliteratorUnknownSize(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), 0)); - - class DoubleSpliteratorFromArray extends Spliterators.AbstractDoubleSpliterator { - double[] a; - int index = 0; - - DoubleSpliteratorFromArray(double[] a) { - super(a.length, Spliterator.SIZED); - this.a = a; - } - - @Override - public boolean tryAdvance(DoubleConsumer action) { - if (action == null) - throw new NullPointerException(); - if (index < a.length) { - action.accept(a[index++]); - return true; - } - else { - return false; - } - } - } - db.add("new Spliterators.AbstractDoubleAdvancingSpliterator()", - () -> new DoubleSpliteratorFromArray(exp)); - } - - return spliteratorOfDoubleDataProvider = data.toArray(new Object[0][]); - } - - private static List listDoubleRange(int upTo) { - List exp = new ArrayList<>(); - for (double i = 0; i < upTo; i++) - exp.add(i); - return Collections.unmodifiableList(exp); - } - - private static double[] arrayDoubleRange(int upTo) { - double[] exp = new double[upTo]; - for (int i = 0; i < upTo; i++) - exp[i] = i; - return exp; - } - - private static UnaryOperator> doubleBoxingConsumer() { - class BoxingAdapter implements Consumer, DoubleConsumer { - private final Consumer b; - - BoxingAdapter(Consumer b) { - this.b = b; - } - - @Override - public void accept(Double value) { - throw new IllegalStateException(); - } - - @Override - public void accept(double value) { - b.accept(value); - } - } - - return b -> new BoxingAdapter(b); - } - - @Test(dataProvider = "Spliterator.OfDouble") - public void testDoubleNullPointerException(String description, Collection exp, Supplier s) { - executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((DoubleConsumer) null)); - executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((DoubleConsumer) null)); - } - - @Test(dataProvider = "Spliterator.OfDouble") - public void testDoubleForEach(String description, Collection exp, Supplier s) { - testForEach(exp, s, doubleBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfDouble") - public void testDoubleTryAdvance(String description, Collection exp, Supplier s) { - testTryAdvance(exp, s, doubleBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfDouble") - public void testDoubleMixedTryAdvanceForEach(String description, Collection exp, Supplier s) { - testMixedTryAdvanceForEach(exp, s, doubleBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfDouble") - public void testDoubleMixedTraverseAndSplit(String description, Collection exp, Supplier s) { - testMixedTraverseAndSplit(exp, s, doubleBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfDouble") - public void testDoubleSplitAfterFullTraversal(String description, Collection exp, Supplier s) { - testSplitAfterFullTraversal(s, doubleBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfDouble") - public void testDoubleSplitOnce(String description, Collection exp, Supplier s) { - testSplitOnce(exp, s, doubleBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfDouble") - public void testDoubleSplitSixDeep(String description, Collection exp, Supplier s) { - testSplitSixDeep(exp, s, doubleBoxingConsumer()); - } - - @Test(dataProvider = "Spliterator.OfDouble") - public void testDoubleSplitUntilNull(String description, Collection exp, Supplier s) { - testSplitUntilNull(exp, s, doubleBoxingConsumer()); - } - - // - - private static > void testForEach( - Collection exp, - Supplier supplier, - UnaryOperator> boxingAdapter) { - S spliterator = supplier.get(); - long sizeIfKnown = spliterator.getExactSizeIfKnown(); - boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); - - ArrayList fromForEach = new ArrayList<>(); - spliterator = supplier.get(); - Consumer 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()); - - assertContents(fromForEach, exp, isOrdered); - } - - private static > void testTryAdvance( - Collection exp, - Supplier supplier, - UnaryOperator> boxingAdapter) { - S spliterator = supplier.get(); - long sizeIfKnown = spliterator.getExactSizeIfKnown(); - boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); - - spliterator = supplier.get(); - ArrayList fromTryAdvance = new ArrayList<>(); - Consumer 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()); - - assertContents(fromTryAdvance, exp, isOrdered); - } - - private static > void testMixedTryAdvanceForEach( - Collection exp, - Supplier supplier, - UnaryOperator> boxingAdapter) { - S spliterator = supplier.get(); - long sizeIfKnown = spliterator.getExactSizeIfKnown(); - boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); - - // tryAdvance first few elements, then forEach rest - ArrayList dest = new ArrayList<>(); - spliterator = supplier.get(); - Consumer 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()); - - if (isOrdered) { - assertEquals(dest, exp); - } - else { - assertContentsUnordered(dest, exp); - } - } - - private static > void testMixedTraverseAndSplit( - Collection exp, - Supplier supplier, - UnaryOperator> boxingAdapter) { - S spliterator = supplier.get(); - long sizeIfKnown = spliterator.getExactSizeIfKnown(); - boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); - - ArrayList dest = new ArrayList<>(); - spliterator = supplier.get(); - Consumer b = boxingAdapter.apply(dest::add); - - Spliterator 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()); - - if (isOrdered) { - assertEquals(dest, exp); - } - else { - assertContentsUnordered(dest, exp); - } - } - - private static > void testSplitAfterFullTraversal( - Supplier supplier, - UnaryOperator> boxingAdapter) { - // Full traversal using tryAdvance - Spliterator spliterator = supplier.get(); - while (spliterator.tryAdvance(boxingAdapter.apply(e -> { }))) { } - Spliterator 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 > void testSplitOnce( - Collection exp, - Supplier supplier, - UnaryOperator> boxingAdapter) { - S spliterator = supplier.get(); - long sizeIfKnown = spliterator.getExactSizeIfKnown(); - boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); - - ArrayList fromSplit = new ArrayList<>(); - Spliterator s1 = supplier.get(); - Spliterator s2 = s1.trySplit(); - long s1Size = s1.getExactSizeIfKnown(); - long s2Size = (s2 != null) ? s2.getExactSizeIfKnown() : 0; - Consumer 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); - } - assertContents(fromSplit, exp, isOrdered); - } - - private static > void testSplitSixDeep( - Collection exp, - Supplier supplier, - UnaryOperator> boxingAdapter) { - S spliterator = supplier.get(); - boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); - - for (int depth=0; depth < 6; depth++) { - List dest = new ArrayList<>(); - spliterator = supplier.get(); - - assertSpliterator(spliterator); - - // verify splitting with forEach - visit(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false); - assertContents(dest, exp, isOrdered); - - // verify splitting with tryAdvance - dest.clear(); - spliterator = supplier.get(); - visit(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), true); - assertContents(dest, exp, isOrdered); - } - } - - private static > - void visit(int depth, int curLevel, - List dest, S spliterator, UnaryOperator> boxingAdapter, - int rootCharacteristics, boolean useTryAdvance) { - if (curLevel < depth) { - long beforeSize = spliterator.getExactSizeIfKnown(); - Spliterator 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()); - } - visit(depth, curLevel + 1, dest, split, boxingAdapter, rootCharacteristics, useTryAdvance); - } - visit(depth, curLevel + 1, dest, spliterator, boxingAdapter, rootCharacteristics, useTryAdvance); - } - else { - long sizeIfKnown = spliterator.getExactSizeIfKnown(); - if (useTryAdvance) { - Consumer 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 split = spliterator.trySplit(); - assertNull(split); - } - else { - List leafDest = new ArrayList<>(); - Consumer 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 split = spliterator.trySplit(); - assertNull(split); - - dest.addAll(leafDest); - } - } - } - - private static > void testSplitUntilNull( - Collection exp, - Supplier supplier, - UnaryOperator> boxingAdapter) { - Spliterator s = supplier.get(); - boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED); - assertSpliterator(s); - - List splits = new ArrayList<>(); - Consumer c = boxingAdapter.apply(splits::add); - - testSplitUntilNull(new SplitNode(c, s)); - assertContents(splits, exp, isOrdered); - } - - private static class SplitNode { - // Constant for every node - final Consumer c; - final int rootCharacteristics; - - final Spliterator s; - - SplitNode(Consumer c, Spliterator s) { - this(c, s.characteristics(), s); - } - - private SplitNode(Consumer c, int rootCharacteristics, Spliterator s) { - this.c = c; - this.rootCharacteristics = rootCharacteristics; - this.s = s; - } - - SplitNode fromSplit(Spliterator 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 void testSplitUntilNull(SplitNode 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> 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 parentAndRightSplit = e.s; - - long parentEstimateSize = parentAndRightSplit.estimateSize(); - assertTrue(parentEstimateSize >= 0, - String.format("Split size estimate %d < 0", parentEstimateSize)); - - long parentSize = parentAndRightSplit.getExactSizeIfKnown(); - Spliterator 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 void assertContents(Collection actual, Collection expected, boolean isOrdered) { - if (isOrdered) { - assertEquals(actual, expected); - } - else { - assertContentsUnordered(actual, expected); - } - } - - private static void assertContentsUnordered(Iterable actual, Iterable expected) { - assertEquals(toBoxedMultiset(actual), toBoxedMultiset(expected)); - } - - private static Map toBoxedMultiset(Iterable c) { - Map result = new HashMap<>(); - c.forEach(e -> { - if (result.containsKey(e)) result.put(e, result.get(e) + 1); - else result.put(e, 1); - }); - return result; - } - - private void executeAndCatch(Class 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())); - } - -}