undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2017, 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 java.util;
import java.util.function.Supplier;
public class SpliteratorOfIntDataBuilder {
List<Object[]> data;
List<Integer> exp;
public SpliteratorOfIntDataBuilder(List<Object[]> data, List<Integer> exp) {
this.data = data;
this.exp = exp;
}
public void add(String description, List<Integer> expected, Supplier<Spliterator.OfInt> s) {
description = joiner(description).toString();
data.add(new Object[]{description, expected, s});
}
public void add(String description, Supplier<Spliterator.OfInt> s) {
add(description, exp, s);
}
StringBuilder joiner(String description) {
return new StringBuilder(description).
append(" {").
append("size=").append(exp.size()).
append("}");
}
}

View file

@ -0,0 +1,754 @@
/*
* Copyright (c) 2012, 2017, 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 java.util;
import java.util.function.*;
import java.util.stream.LambdaTestHelpers;
import static org.testng.Assert.*;
/**
* 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) {
testSpliterator(supplier, intBoxingConsumer(), asserter);
}
public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier) {
testLongSpliterator(supplier, defaultContentAsserter());
}
public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier,
ContentAsserter<Long> asserter) {
testSpliterator(supplier, longBoxingConsumer(), asserter);
}
public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier) {
testDoubleSpliterator(supplier, defaultContentAsserter());
}
public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier,
ContentAsserter<Double> asserter) {
testSpliterator(supplier, doubleBoxingConsumer(), asserter);
}
public static UnaryOperator<Consumer<Integer>> intBoxingConsumer() {
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);
}
}
return b -> new BoxingAdapter(b);
}
public static UnaryOperator<Consumer<Long>> longBoxingConsumer() {
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);
}
}
return b -> new BoxingAdapter(b);
}
public static UnaryOperator<Consumer<Double>> doubleBoxingConsumer() {
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);
}
}
return b -> new BoxingAdapter(b);
}
public 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);
}
public static <T, S extends Spliterator<T>> void testForEach(
Collection<T> exp,
Supplier<S> supplier,
UnaryOperator<Consumer<T>> boxingAdapter) {
testForEach(exp, supplier, boxingAdapter, defaultContentAsserter());
}
public static <T, S extends Spliterator<T>> void testTryAdvance(
Collection<T> exp,
Supplier<S> supplier,
UnaryOperator<Consumer<T>> boxingAdapter) {
testTryAdvance(exp, supplier, boxingAdapter, defaultContentAsserter());
}
public static <T, S extends Spliterator<T>> void testMixedTryAdvanceForEach(
Collection<T> exp,
Supplier<S> supplier,
UnaryOperator<Consumer<T>> boxingAdapter) {
testMixedTryAdvanceForEach(exp, supplier, boxingAdapter, defaultContentAsserter());
}
public static <T, S extends Spliterator<T>> void testMixedTraverseAndSplit(
Collection<T> exp,
Supplier<S> supplier,
UnaryOperator<Consumer<T>> boxingAdapter) {
testMixedTraverseAndSplit(exp, supplier, boxingAdapter, defaultContentAsserter());
}
public static <T, S extends Spliterator<T>> void testSplitOnce(
Collection<T> exp,
Supplier<S> supplier,
UnaryOperator<Consumer<T>> boxingAdapter) {
testSplitOnce(exp, supplier, boxingAdapter, defaultContentAsserter());
}
public static <T, S extends Spliterator<T>> void testSplitSixDeep(
Collection<T> exp,
Supplier<S> supplier,
UnaryOperator<Consumer<T>> boxingAdapter) {
testSplitSixDeep(exp, supplier, boxingAdapter, defaultContentAsserter());
}
public static <T, S extends Spliterator<T>> void testSplitUntilNull(
Collection<T> exp,
Supplier<S> supplier,
UnaryOperator<Consumer<T>> boxingAdapter) {
testSplitUntilNull(exp, supplier, boxingAdapter, defaultContentAsserter());
}
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;
assertThrowsNPE(() -> psp.forEachRemaining((IntConsumer) null));
assertThrowsNPE(() -> psp.tryAdvance((IntConsumer) null));
}
else if (sp instanceof Spliterator.OfLong) {
Spliterator.OfLong psp = (Spliterator.OfLong) sp;
assertThrowsNPE(() -> psp.forEachRemaining((LongConsumer) null));
assertThrowsNPE(() -> psp.tryAdvance((LongConsumer) null));
}
else if (sp instanceof Spliterator.OfDouble) {
Spliterator.OfDouble psp = (Spliterator.OfDouble) sp;
assertThrowsNPE(() -> psp.forEachRemaining((DoubleConsumer) null));
assertThrowsNPE(() -> psp.tryAdvance((DoubleConsumer) null));
}
else {
assertThrowsNPE(() -> sp.forEachRemaining(null));
assertThrowsNPE(() -> 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());
}
if (exp.contains(null)) {
assertTrue(fromForEach.contains(null));
}
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);
}
public 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);
}
}
private static <T, S extends Spliterator<T>>
void splitSixDeepVisitor(int depth, int curLevel,
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());
}
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);
}
}
public static void assertThrowsNPE(ThrowingRunnable r) {
assertThrows(NullPointerException.class, r);
}
public 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);
}
public 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);
}
public 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);
}
public 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);
}
}

View file

@ -0,0 +1,113 @@
/*
* 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 java.util.stream;
import org.testng.Assert;
import java.util.Spliterator;
import java.util.function.IntFunction;
/** Test helper class for java.util.stream test framework */
public final class CollectorOps {
private CollectorOps() { }
public static <E_IN> StatefulTestOp<E_IN> collector() {
return new StatefulCollector<>(0, StreamShape.REFERENCE);
}
/* Utility classes for collecting output of intermediate pipeline stages */
public static class StatefulCollector<E_IN> implements StatefulTestOp<E_IN> {
private final int opFlags;
private final StreamShape inputShape;
public StatefulCollector(int opFlags, StreamShape inputShape) {
this.opFlags = opFlags;
this.inputShape = inputShape;
}
@Override
public StreamShape inputShape() {
return inputShape;
}
@Override
public StreamShape outputShape() {
return inputShape;
}
@Override
public int opGetFlags() {
return opFlags;
}
@Override
public Sink<E_IN> opWrapSink(int flags, boolean parallel, Sink<E_IN> sink) {
return sink;
}
@Override
public <P_IN> Node<E_IN> opEvaluateParallel(PipelineHelper<E_IN> helper,
Spliterator<P_IN> spliterator,
IntFunction<E_IN[]> generator) {
return helper.evaluate(spliterator, false, generator);
}
}
public static class TestParallelSizedOp<T> extends StatefulCollector<T> {
public TestParallelSizedOp() {
this(StreamShape.REFERENCE);
}
protected TestParallelSizedOp(StreamShape shape) {
super(0, shape);
}
@Override
public <P_IN> Node<T> opEvaluateParallel(PipelineHelper<T> helper,
Spliterator<P_IN> spliterator,
IntFunction<T[]> generator) {
int flags = helper.getStreamAndOpFlags();
Assert.assertTrue(StreamOpFlag.SIZED.isKnown(flags));
return super.opEvaluateParallel(helper, spliterator, generator);
}
public static class OfInt extends TestParallelSizedOp<Integer> {
public OfInt() {
super(StreamShape.INT_VALUE);
}
}
public static class OfLong extends TestParallelSizedOp<Long> {
public OfLong() {
super(StreamShape.LONG_VALUE);
}
}
public static class OfDouble extends TestParallelSizedOp<Double> {
public OfDouble() {
super(StreamShape.DOUBLE_VALUE);
}
}
}
}

View file

@ -0,0 +1,982 @@
/*
* Copyright (c) 2015, 2023, 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 java.util.stream;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Comparator;
import java.util.DoubleSummaryStatistics;
import java.util.IntSummaryStatistics;
import java.util.Iterator;
import java.util.LongSummaryStatistics;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.PrimitiveIterator;
import java.util.Set;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.DoubleFunction;
import java.util.function.DoublePredicate;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleToLongFunction;
import java.util.function.DoubleUnaryOperator;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongFunction;
import java.util.function.LongPredicate;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongToIntFunction;
import java.util.function.LongUnaryOperator;
import java.util.function.ObjDoubleConsumer;
import java.util.function.ObjIntConsumer;
import java.util.function.ObjLongConsumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import static java.util.stream.Collectors.*;
public final class DefaultMethodStreams {
static {
// Verify that default methods are not overridden
verify(DefaultMethodRefStream.class);
verify(DefaultMethodIntStream.class);
verify(DefaultMethodLongStream.class);
verify(DefaultMethodDoubleStream.class);
}
static void verify(Class<?> del) {
// Find the stream interface
Class<?> s = Stream.of(del.getInterfaces())
.filter(c -> BaseStream.class.isAssignableFrom(c))
.findFirst().get();
// Get all default methods on the stream class
Set<String> dms = Stream.of(s.getMethods())
.filter(m -> !Modifier.isStatic(m.getModifiers()))
.filter(m -> !m.isBridge())
.filter(Method::isDefault)
.map(Method::getName)
.collect(toSet());
// Get all methods on the delegating class
Set<String> ims = Stream.of(del.getMethods())
.filter(m -> !Modifier.isStatic(m.getModifiers()))
.filter(m -> m.getDeclaringClass() == del)
.map(Method::getName)
.collect(toSet());
if (ims.stream().anyMatch(dms::contains)) {
throw new AssertionError(String.format("%s overrides default methods of %s\n", del, s));
}
}
/**
* Creates a stream that for the next operation either delegates to
* a default method on {@link Stream}, if present for that operation,
* otherwise delegates to an underlying stream.
*
* @param s the underlying stream to be delegated to for non-default
* methods.
* @param <T> the type of the stream elements
* @return the delegating stream
*/
public static <T> Stream<T> delegateTo(Stream<T> s) {
return new DefaultMethodRefStream<>(s);
}
/**
* Creates a stream that for the next operation either delegates to
* a default method on {@link IntStream}, if present for that operation,
* otherwise delegates to an underlying stream.
*
* @param s the underlying stream to be delegated to for non-default
* methods.
* @return the delegating stream
*/
public static IntStream delegateTo(IntStream s) {
return new DefaultMethodIntStream(s);
}
/**
* Creates a stream that for the next operation either delegates to
* a default method on {@link LongStream}, if present for that operation,
* otherwise delegates to an underlying stream.
*
* @param s the underlying stream to be delegated to for non-default
* methods.
* @return the delegating stream
*/
public static LongStream delegateTo(LongStream s) {
return new DefaultMethodLongStream(s);
}
/**
* Creates a stream that for the next operation either delegates to
* a default method on {@link DoubleStream}, if present for that operation,
* otherwise delegates to an underlying stream.
*
* @param s the underlying stream to be delegated to for non-default
* methods.
* @return the delegating stream
*/
public static DoubleStream delegateTo(DoubleStream s) {
return new DefaultMethodDoubleStream(s);
}
/**
* A stream that delegates the next operation to a default method, if
* present, or to the same operation of an underlying stream.
*
* @param <T> the type of the stream elements
*/
static final class DefaultMethodRefStream<T> implements Stream<T> {
final Stream<T> s;
DefaultMethodRefStream(Stream<T> s) {
this.s = s;
}
// Delegating non-default methods
@Override
public Stream<T> filter(Predicate<? super T> predicate) {
return s.filter(predicate);
}
@Override
public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
return s.map(mapper);
}
@Override
public IntStream mapToInt(ToIntFunction<? super T> mapper) {
return s.mapToInt(mapper);
}
@Override
public LongStream mapToLong(ToLongFunction<? super T> mapper) {
return s.mapToLong(mapper);
}
@Override
public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
return s.mapToDouble(mapper);
}
@Override
public <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
return s.flatMap(mapper);
}
@Override
public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
return s.flatMapToInt(mapper);
}
@Override
public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
return s.flatMapToLong(mapper);
}
@Override
public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
return s.flatMapToDouble(mapper);
}
@Override
public Stream<T> distinct() {
return s.distinct();
}
@Override
public Stream<T> sorted() {
return s.sorted();
}
@Override
public Stream<T> sorted(Comparator<? super T> comparator) {
return s.sorted(comparator);
}
@Override
public Stream<T> peek(Consumer<? super T> action) {
return s.peek(action);
}
@Override
public Stream<T> limit(long maxSize) {
return s.limit(maxSize);
}
@Override
public Stream<T> skip(long n) {
return s.skip(n);
}
@Override
public void forEach(Consumer<? super T> action) {
s.forEach(action);
}
@Override
public void forEachOrdered(Consumer<? super T> action) {
s.forEachOrdered(action);
}
@Override
public Object[] toArray() {
return s.toArray();
}
@Override
public <A> A[] toArray(IntFunction<A[]> generator) {
return s.toArray(generator);
}
@Override
public T reduce(T identity, BinaryOperator<T> accumulator) {
return s.reduce(identity, accumulator);
}
@Override
public Optional<T> reduce(BinaryOperator<T> accumulator) {
return s.reduce(accumulator);
}
@Override
public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
return s.reduce(identity, accumulator, combiner);
}
@Override
public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
return s.collect(supplier, accumulator, combiner);
}
@Override
public <R, A> R collect(Collector<? super T, A, R> collector) {
return s.collect(collector);
}
@Override
public Optional<T> min(Comparator<? super T> comparator) {
return s.min(comparator);
}
@Override
public Optional<T> max(Comparator<? super T> comparator) {
return s.max(comparator);
}
@Override
public long count() {
return s.count();
}
@Override
public boolean anyMatch(Predicate<? super T> predicate) {
return s.anyMatch(predicate);
}
@Override
public boolean allMatch(Predicate<? super T> predicate) {
return s.allMatch(predicate);
}
@Override
public boolean noneMatch(Predicate<? super T> predicate) {
return s.noneMatch(predicate);
}
@Override
public Optional<T> findFirst() {
return s.findFirst();
}
@Override
public Optional<T> findAny() {
return s.findAny();
}
@Override
public Iterator<T> iterator() {
return s.iterator();
}
@Override
public Spliterator<T> spliterator() {
return s.spliterator();
}
@Override
public boolean isParallel() {
return s.isParallel();
}
@Override
public Stream<T> sequential() {
return s.sequential();
}
@Override
public Stream<T> parallel() {
return s.parallel();
}
@Override
public Stream<T> unordered() {
return s.unordered();
}
@Override
public Stream<T> onClose(Runnable closeHandler) {
return s.onClose(closeHandler);
}
@Override
public void close() {
s.close();
}
}
static final class DefaultMethodIntStream implements IntStream {
final IntStream s;
public DefaultMethodIntStream(IntStream s) {
this.s = s;
}
// Delegating non-default methods
@Override
public IntStream filter(IntPredicate predicate) {
return s.filter(predicate);
}
@Override
public IntStream map(IntUnaryOperator mapper) {
return s.map(mapper);
}
@Override
public <U> Stream<U> mapToObj(IntFunction<? extends U> mapper) {
return s.mapToObj(mapper);
}
@Override
public LongStream mapToLong(IntToLongFunction mapper) {
return s.mapToLong(mapper);
}
@Override
public DoubleStream mapToDouble(IntToDoubleFunction mapper) {
return s.mapToDouble(mapper);
}
@Override
public IntStream flatMap(IntFunction<? extends IntStream> mapper) {
return s.flatMap(mapper);
}
@Override
public IntStream distinct() {
return s.distinct();
}
@Override
public IntStream sorted() {
return s.sorted();
}
@Override
public IntStream peek(IntConsumer action) {
return s.peek(action);
}
@Override
public IntStream limit(long maxSize) {
return s.limit(maxSize);
}
@Override
public IntStream skip(long n) {
return s.skip(n);
}
@Override
public void forEach(IntConsumer action) {
s.forEach(action);
}
@Override
public void forEachOrdered(IntConsumer action) {
s.forEachOrdered(action);
}
@Override
public int[] toArray() {
return s.toArray();
}
@Override
public int reduce(int identity, IntBinaryOperator op) {
return s.reduce(identity, op);
}
@Override
public OptionalInt reduce(IntBinaryOperator op) {
return s.reduce(op);
}
@Override
public <R> R collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R, R> combiner) {
return s.collect(supplier, accumulator, combiner);
}
@Override
public int sum() {
return s.sum();
}
@Override
public OptionalInt min() {
return s.min();
}
@Override
public OptionalInt max() {
return s.max();
}
@Override
public long count() {
return s.count();
}
@Override
public OptionalDouble average() {
return s.average();
}
@Override
public IntSummaryStatistics summaryStatistics() {
return s.summaryStatistics();
}
@Override
public boolean anyMatch(IntPredicate predicate) {
return s.anyMatch(predicate);
}
@Override
public boolean allMatch(IntPredicate predicate) {
return s.allMatch(predicate);
}
@Override
public boolean noneMatch(IntPredicate predicate) {
return s.noneMatch(predicate);
}
@Override
public OptionalInt findFirst() {
return s.findFirst();
}
@Override
public OptionalInt findAny() {
return s.findAny();
}
@Override
public LongStream asLongStream() {
return s.asLongStream();
}
@Override
public DoubleStream asDoubleStream() {
return s.asDoubleStream();
}
@Override
public Stream<Integer> boxed() {
return s.boxed();
}
@Override
public IntStream sequential() {
return s.sequential();
}
@Override
public IntStream parallel() {
return s.parallel();
}
@Override
public PrimitiveIterator.OfInt iterator() {
return s.iterator();
}
@Override
public Spliterator.OfInt spliterator() {
return s.spliterator();
}
@Override
public boolean isParallel() {
return s.isParallel();
}
@Override
public IntStream unordered() {
return s.unordered();
}
@Override
public IntStream onClose(Runnable closeHandler) {
return s.onClose(closeHandler);
}
@Override
public void close() {
s.close();
}
}
static final class DefaultMethodLongStream implements LongStream {
final LongStream s;
public DefaultMethodLongStream(LongStream s) {
this.s = s;
}
// Delegating non-default methods
@Override
public void forEach(LongConsumer action) {
s.forEach(action);
}
@Override
public LongStream filter(LongPredicate predicate) {
return s.filter(predicate);
}
@Override
public LongStream map(LongUnaryOperator mapper) {
return s.map(mapper);
}
@Override
public <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
return s.mapToObj(mapper);
}
@Override
public IntStream mapToInt(LongToIntFunction mapper) {
return s.mapToInt(mapper);
}
@Override
public DoubleStream mapToDouble(LongToDoubleFunction mapper) {
return s.mapToDouble(mapper);
}
@Override
public LongStream flatMap(LongFunction<? extends LongStream> mapper) {
return s.flatMap(mapper);
}
@Override
public LongStream distinct() {
return s.distinct();
}
@Override
public LongStream sorted() {
return s.sorted();
}
@Override
public LongStream peek(LongConsumer action) {
return s.peek(action);
}
@Override
public LongStream limit(long maxSize) {
return s.limit(maxSize);
}
@Override
public LongStream skip(long n) {
return s.skip(n);
}
@Override
public void forEachOrdered(LongConsumer action) {
s.forEachOrdered(action);
}
@Override
public long[] toArray() {
return s.toArray();
}
@Override
public long reduce(long identity, LongBinaryOperator op) {
return s.reduce(identity, op);
}
@Override
public OptionalLong reduce(LongBinaryOperator op) {
return s.reduce(op);
}
@Override
public <R> R collect(Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R, R> combiner) {
return s.collect(supplier, accumulator, combiner);
}
@Override
public long sum() {
return s.sum();
}
@Override
public OptionalLong min() {
return s.min();
}
@Override
public OptionalLong max() {
return s.max();
}
@Override
public long count() {
return s.count();
}
@Override
public OptionalDouble average() {
return s.average();
}
@Override
public LongSummaryStatistics summaryStatistics() {
return s.summaryStatistics();
}
@Override
public boolean anyMatch(LongPredicate predicate) {
return s.anyMatch(predicate);
}
@Override
public boolean allMatch(LongPredicate predicate) {
return s.allMatch(predicate);
}
@Override
public boolean noneMatch(LongPredicate predicate) {
return s.noneMatch(predicate);
}
@Override
public OptionalLong findFirst() {
return s.findFirst();
}
@Override
public OptionalLong findAny() {
return s.findAny();
}
@Override
public DoubleStream asDoubleStream() {
return s.asDoubleStream();
}
@Override
public Stream<Long> boxed() {
return s.boxed();
}
@Override
public LongStream sequential() {
return s.sequential();
}
@Override
public LongStream parallel() {
return s.parallel();
}
@Override
public PrimitiveIterator.OfLong iterator() {
return s.iterator();
}
@Override
public Spliterator.OfLong spliterator() {
return s.spliterator();
}
@Override
public boolean isParallel() {
return s.isParallel();
}
@Override
public LongStream unordered() {
return s.unordered();
}
@Override
public LongStream onClose(Runnable closeHandler) {
return s.onClose(closeHandler);
}
@Override
public void close() {
s.close();
}
}
static final class DefaultMethodDoubleStream implements DoubleStream {
final DoubleStream s;
public DefaultMethodDoubleStream(DoubleStream s) {
this.s = s;
}
@Override
public DoubleStream filter(DoublePredicate predicate) {
return s.filter(predicate);
}
@Override
public DoubleStream map(DoubleUnaryOperator mapper) {
return s.map(mapper);
}
@Override
public <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
return s.mapToObj(mapper);
}
@Override
public IntStream mapToInt(DoubleToIntFunction mapper) {
return s.mapToInt(mapper);
}
@Override
public LongStream mapToLong(DoubleToLongFunction mapper) {
return s.mapToLong(mapper);
}
@Override
public DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper) {
return s.flatMap(mapper);
}
@Override
public DoubleStream distinct() {
return s.distinct();
}
@Override
public DoubleStream sorted() {
return s.sorted();
}
@Override
public DoubleStream peek(DoubleConsumer action) {
return s.peek(action);
}
@Override
public DoubleStream limit(long maxSize) {
return s.limit(maxSize);
}
@Override
public DoubleStream skip(long n) {
return s.skip(n);
}
@Override
public void forEach(DoubleConsumer action) {
s.forEach(action);
}
@Override
public void forEachOrdered(DoubleConsumer action) {
s.forEachOrdered(action);
}
@Override
public double[] toArray() {
return s.toArray();
}
@Override
public double reduce(double identity, DoubleBinaryOperator op) {
return s.reduce(identity, op);
}
@Override
public OptionalDouble reduce(DoubleBinaryOperator op) {
return s.reduce(op);
}
@Override
public <R> R collect(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R, R> combiner) {
return s.collect(supplier, accumulator, combiner);
}
@Override
public double sum() {
return s.sum();
}
@Override
public OptionalDouble min() {
return s.min();
}
@Override
public OptionalDouble max() {
return s.max();
}
@Override
public long count() {
return s.count();
}
@Override
public OptionalDouble average() {
return s.average();
}
@Override
public DoubleSummaryStatistics summaryStatistics() {
return s.summaryStatistics();
}
@Override
public boolean anyMatch(DoublePredicate predicate) {
return s.anyMatch(predicate);
}
@Override
public boolean allMatch(DoublePredicate predicate) {
return s.allMatch(predicate);
}
@Override
public boolean noneMatch(DoublePredicate predicate) {
return s.noneMatch(predicate);
}
@Override
public OptionalDouble findFirst() {
return s.findFirst();
}
@Override
public OptionalDouble findAny() {
return s.findAny();
}
@Override
public Stream<Double> boxed() {
return s.boxed();
}
@Override
public DoubleStream sequential() {
return s.sequential();
}
@Override
public DoubleStream parallel() {
return s.parallel();
}
@Override
public PrimitiveIterator.OfDouble iterator() {
return s.iterator();
}
@Override
public Spliterator.OfDouble spliterator() {
return s.spliterator();
}
@Override
public boolean isParallel() {
return s.isParallel();
}
@Override
public DoubleStream unordered() {
return s.unordered();
}
@Override
public DoubleStream onClose(Runnable closeHandler) {
return s.onClose(closeHandler);
}
@Override
public void close() {
s.close();
}
}
}

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2013, 2016, 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 java.util.stream;
import org.testng.annotations.DataProvider;
import java.util.*;
import java.util.Spliterators;
import java.util.function.Supplier;
/** TestNG DataProvider for double-valued streams */
public class DoubleStreamTestDataProvider {
private static final double[] to0 = new double[0];
private static final double[] to1 = new double[1];
private static final double[] to10 = new double[10];
private static final double[] to100 = new double[100];
private static final double[] to1000 = new double[1000];
private static final double[] reversed = new double[100];
private static final double[] ones = new double[100];
private static final double[] twice = new double[200];
private static final double[] pseudoRandom;
private static final Object[][] testData;
private static final Object[][] testSmallData;
private static final Object[][] spliteratorTestData;
static {
double[][] arrays = {to0, to1, to10, to100, to1000};
for (double[] arr : arrays) {
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
}
for (int i = 0; i < reversed.length; i++) {
reversed[i] = reversed.length - i;
}
for (int i = 0; i < ones.length; i++) {
ones[i] = 1;
}
System.arraycopy(to100, 0, twice, 0, to100.length);
System.arraycopy(to100, 0, twice, to100.length, to100.length);
pseudoRandom = new double[LambdaTestHelpers.LONG_STRING.length()];
for (int i = 0; i < LambdaTestHelpers.LONG_STRING.length(); i++) {
pseudoRandom[i] = (double) LambdaTestHelpers.LONG_STRING.charAt(i);
}
}
static final Object[][] arrays = {
{"empty", to0},
{"0..1", to1},
{"0..10", to10},
{"0..100", to100},
{"0..1000", to1000},
{"100x[1]", ones},
{"2x[0..100]", twice},
{"reverse 0..100", reversed},
{"pseudorandom", pseudoRandom}
};
static {
{
List<Object[]> listSmall = new ArrayList<>();
List<Object[]> list1000 = new ArrayList<>();
List<Object[]> list = null;
for (Object[] data : arrays) {
final Object name = data[0];
final double[] doubles = (double[]) data[1];
list = doubles.length >= 1000 ? list1000 : listSmall;
list.add(new Object[]{"array:" + name,
TestData.Factory.ofArray("array:" + name, doubles)});
SpinedBuffer.OfDouble isl = new SpinedBuffer.OfDouble();
for (double i : doubles) {
isl.accept(i);
}
list.add(new Object[]{"SpinedList:" + name,
TestData.Factory.ofSpinedBuffer("SpinedList:" + name, isl)});
}
testSmallData = listSmall.toArray(new Object[0][]);
list1000.addAll(listSmall);
testData = list1000.toArray(new Object[0][]);
}
{
List<Object[]> spliterators = new ArrayList<>();
for (Object[] data : arrays) {
final Object name = data[0];
final double[] doubles = (double[]) data[1];
SpinedBuffer.OfDouble isl = new SpinedBuffer.OfDouble();
for (double i : doubles) {
isl.accept(i);
}
spliterators.add(splitDescr("Arrays.s(array):" + name,
() -> Arrays.spliterator(doubles)));
spliterators.add(splitDescr("Arrays.s(array,o,l):" + name,
() -> Arrays.spliterator(doubles, 0, doubles.length / 2)));
spliterators.add(splitDescr("SpinedBuffer.s():" + name,
() -> isl.spliterator()));
spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator(), size):" + name,
() -> Spliterators.spliterator(isl.iterator(), doubles.length, 0)));
spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0)));
spliterators.add(splitDescr("DoubleStream.iterate(0,x->x<l;x->x+1):" + name,
() -> DoubleStream.iterate(0.0, x -> x < doubles.length, x -> x + 1.0)
.spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
}
}
static <T> Object[] splitDescr(String description, Supplier<Spliterator.OfDouble> s) {
return new Object[] { description, s };
}
// Return an array of ( String name, DoubleStreamTestData )
@DataProvider(name = "DoubleStreamTestData")
public static Object[][] makeDoubleStreamTestData() {
return testData;
}
@DataProvider(name = "DoubleStreamTestData.small")
public static Object[][] makeSmallDoubleStreamTestData() {
return testSmallData;
}
// returns an array of (String name, Supplier<PrimitiveSpliterator<Double>>)
@DataProvider(name = "DoubleSpliterator")
public static Object[][] spliteratorProvider() {
return spliteratorTestData;
}
}

View file

@ -0,0 +1,233 @@
/*
* Copyright (c) 2013, 2017, 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 java.util.stream;
import java.util.Collections;
import java.util.EnumSet;
import java.util.PrimitiveIterator;
import java.util.Set;
import java.util.Spliterator;
import java.util.SpliteratorTestHelper;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.Function;
/**
* Test scenarios for double streams.
*
* Each scenario is provided with a data source, a function that maps a fresh
* stream (as provided by the data source) to a new stream, and a sink to
* receive results. Each scenario describes a different way of computing the
* stream contents. The test driver will ensure that all scenarios produce
* the same output (modulo allowable differences in ordering).
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public enum DoubleStreamTestScenario implements OpTestCase.BaseStreamTestScenario {
STREAM_FOR_EACH(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
DoubleStream s = m.apply(source);
if (s.isParallel()) {
s = s.sequential();
}
s.forEach(b);
}
},
STREAM_TO_ARRAY(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
for (double t : m.apply(source).toArray()) {
b.accept(t);
}
}
},
STREAM_ITERATOR(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
for (PrimitiveIterator.OfDouble seqIter = m.apply(source).iterator(); seqIter.hasNext(); )
b.accept(seqIter.nextDouble());
}
},
// Wrap as stream, and spliterate then iterate in pull mode
STREAM_SPLITERATOR(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
for (Spliterator.OfDouble spl = m.apply(source).spliterator(); spl.tryAdvance(b); ) {
}
}
},
// Wrap as stream, spliterate, then split a few times mixing advances with forEach
STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(source).spliterator());
}
},
// Wrap as stream, and spliterate then iterate in pull mode
STREAM_SPLITERATOR_FOREACH(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
m.apply(source).spliterator().forEachRemaining(b);
}
},
PAR_STREAM_SEQUENTIAL_FOR_EACH(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
m.apply(source).sequential().forEach(b);
}
},
// Wrap as parallel stream + forEachOrdered
PAR_STREAM_FOR_EACH_ORDERED(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
// @@@ Want to explicitly select ordered equalator
m.apply(source).forEachOrdered(b);
}
},
// Wrap as stream, and spliterate then iterate sequentially
PAR_STREAM_SPLITERATOR(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
for (Spliterator.OfDouble spl = m.apply(source).spliterator(); spl.tryAdvance(b); ) {
}
}
},
// Wrap as stream, and spliterate then iterate sequentially
PAR_STREAM_SPLITERATOR_FOREACH(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
m.apply(source).spliterator().forEachRemaining(b);
}
},
PAR_STREAM_TO_ARRAY(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
for (double t : m.apply(source).toArray())
b.accept(t);
}
},
// Wrap as parallel stream, get the spliterator, wrap as a stream + toArray
PAR_STREAM_SPLITERATOR_STREAM_TO_ARRAY(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
DoubleStream s = m.apply(source);
Spliterator.OfDouble sp = s.spliterator();
DoubleStream ss = StreamSupport.doubleStream(() -> sp,
StreamOpFlag.toCharacteristics(OpTestCase.getStreamFlags(s))
| (sp.getExactSizeIfKnown() < 0 ? 0 : Spliterator.SIZED), true);
for (double t : ss.toArray())
b.accept(t);
}
},
PAR_STREAM_TO_ARRAY_CLEAR_SIZED(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
S_IN pipe1 = (S_IN) OpTestCase.chain(source,
new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape()));
DoubleStream pipe2 = m.apply(pipe1);
for (double t : pipe2.toArray())
b.accept(t);
}
},
// Wrap as parallel stream + forEach synchronizing
PAR_STREAM_FOR_EACH(true, false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
m.apply(source).forEach(e -> {
synchronized (data) {
b.accept(e);
}
});
}
},
// Wrap as parallel stream + forEach synchronizing and clear SIZED flag
PAR_STREAM_FOR_EACH_CLEAR_SIZED(true, false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
S_IN pipe1 = (S_IN) OpTestCase.chain(source,
new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape()));
m.apply(pipe1).forEach(e -> {
synchronized (data) {
b.accept(e);
}
});
}
},
;
// The set of scenarios that clean the SIZED flag
public static final Set<DoubleStreamTestScenario> CLEAR_SIZED_SCENARIOS = Collections.unmodifiableSet(
EnumSet.of(PAR_STREAM_TO_ARRAY_CLEAR_SIZED, PAR_STREAM_FOR_EACH_CLEAR_SIZED));
private boolean isParallel;
private final boolean isOrdered;
DoubleStreamTestScenario(boolean isParallel) {
this(isParallel, true);
}
DoubleStreamTestScenario(boolean isParallel, boolean isOrdered) {
this.isParallel = isParallel;
this.isOrdered = isOrdered;
}
public StreamShape getShape() {
return StreamShape.DOUBLE_VALUE;
}
public boolean isParallel() {
return isParallel;
}
public boolean isOrdered() {
return isOrdered;
}
public <T, U, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>>
void run(TestData<T, S_IN> data, Consumer<U> b, Function<S_IN, S_OUT> m) {
try (S_IN source = getStream(data)) {
run(data, source, (DoubleConsumer) b, (Function<S_IN, DoubleStream>) m);
}
}
abstract <T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, DoubleConsumer b, Function<S_IN, DoubleStream> m);
}

View file

@ -0,0 +1,61 @@
/*
* 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 java.util.stream;
/**
* An operation that injects or clears flags but otherwise performs no operation on elements.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class FlagDeclaringOp<T> implements StatelessTestOp<T, T> {
private final int flags;
private final StreamShape shape;
public FlagDeclaringOp(int flags) {
this(flags, StreamShape.REFERENCE);
}
public FlagDeclaringOp(int flags, StreamShape shape) {
this.flags = flags;
this.shape = shape;
}
@Override
public StreamShape outputShape() {
return shape;
}
@Override
public StreamShape inputShape() {
return shape;
}
@Override
public int opGetFlags() {
return flags;
}
@Override
public Sink<T> opWrapSink(int flags, boolean parallel, Sink sink) {
return sink;
}
}

View file

@ -0,0 +1,172 @@
/*
* Copyright (c) 2012, 2016, 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 java.util.stream;
import org.testng.annotations.DataProvider;
import java.util.*;
import java.util.Spliterators;
import java.util.function.Supplier;
/** TestNG DataProvider for int-valued streams */
public class IntStreamTestDataProvider {
private static final int[] to0 = new int[0];
private static final int[] to1 = new int[1];
private static final int[] to10 = new int[10];
private static final int[] to100 = new int[100];
private static final int[] to1000 = new int[1000];
private static final int[] reversed = new int[100];
private static final int[] ones = new int[100];
private static final int[] twice = new int[200];
private static final int[] pseudoRandom;
private static final Object[][] testData;
private static final Object[][] testSmallData;
private static final Object[][] spliteratorTestData;
static {
int[][] arrays = {to0, to1, to10, to100, to1000};
for (int[] arr : arrays) {
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
}
for (int i = 0; i < reversed.length; i++) {
reversed[i] = reversed.length - i;
}
for (int i = 0; i < ones.length; i++) {
ones[i] = 1;
}
System.arraycopy(to100, 0, twice, 0, to100.length);
System.arraycopy(to100, 0, twice, to100.length, to100.length);
pseudoRandom = new int[LambdaTestHelpers.LONG_STRING.length()];
for (int i = 0; i < LambdaTestHelpers.LONG_STRING.length(); i++) {
pseudoRandom[i] = (int) LambdaTestHelpers.LONG_STRING.charAt(i);
}
}
static final Object[][] arrays = {
{"empty", to0},
{"0..1", to1},
{"0..10", to10},
{"0..100", to100},
{"0..1000", to1000},
{"100x[1]", ones},
{"2x[0..100]", twice},
{"reverse 0..100", reversed},
{"pseudorandom", pseudoRandom}
};
static {
{
List<Object[]> listSmall = new ArrayList<>();
List<Object[]> list1000 = new ArrayList<>();
List<Object[]> list = null;
for (Object[] data : arrays) {
final Object name = data[0];
final int[] ints = (int[]) data[1];
list = ints.length >= 1000 ? list1000 : listSmall;
list.add(new Object[]{"array:" +
name, TestData.Factory.ofArray("array:" + name, ints)});
SpinedBuffer.OfInt isl = new SpinedBuffer.OfInt();
for (int i : ints) {
isl.accept(i);
}
list.add(new Object[]{"SpinedList:" + name,
TestData.Factory.ofSpinedBuffer("SpinedList:" + name, isl)});
list.add(streamDataDescr("IntStream.intRange(0,l): " + ints.length,
() -> IntStream.range(0, ints.length)));
list.add(streamDataDescr("IntStream.rangeClosed(0,l): " + ints.length,
() -> IntStream.rangeClosed(0, ints.length)));
}
testSmallData = listSmall.toArray(new Object[0][]);
list1000.addAll(listSmall);
testData = list1000.toArray(new Object[0][]);
}
{
List<Object[]> spliterators = new ArrayList<>();
for (Object[] data : arrays) {
final Object name = data[0];
final int[] ints = (int[]) data[1];
SpinedBuffer.OfInt isl = new SpinedBuffer.OfInt();
for (int i : ints) {
isl.accept(i);
}
spliterators.add(splitDescr("Arrays.s(array):" + name,
() -> Arrays.spliterator(ints)));
spliterators.add(splitDescr("Arrays.s(array,o,l):" + name,
() -> Arrays.spliterator(ints, 0, ints.length / 2)));
spliterators.add(splitDescr("SpinedBuffer.s():" + name,
() -> isl.spliterator()));
spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator(), size):" + name,
() -> Spliterators.spliterator(isl.iterator(), ints.length, 0)));
spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0)));
spliterators.add(splitDescr("IntStream.intRange(0,l):" + name,
() -> IntStream.range(0, ints.length).spliterator()));
spliterators.add(splitDescr("IntStream.intRangeClosed(0,l):" + name,
() -> IntStream.rangeClosed(0, ints.length).spliterator()));
spliterators.add(splitDescr("IntStream.iterate(0,x->x<l,x->x+1): " + name,
() -> IntStream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
}
}
static <T> Object[] streamDataDescr(String description, Supplier<IntStream> s) {
return new Object[] { description, TestData.Factory.ofIntSupplier(description, s) };
}
static <T> Object[] splitDescr(String description, Supplier<Spliterator.OfInt> s) {
return new Object[] { description, s };
}
// Return an array of ( String name, IntStreamTestData )
@DataProvider(name = "IntStreamTestData")
public static Object[][] makeIntStreamTestData() {
return testData;
}
@DataProvider(name = "IntStreamTestData.small")
public static Object[][] makeSmallIntStreamTestData() {
return testSmallData;
}
// returns an array of (String name, Supplier<PrimitiveSpliterator<Integer>>)
@DataProvider(name = "IntSpliterator")
public static Object[][] spliteratorProvider() {
return spliteratorTestData;
}
}

View file

@ -0,0 +1,234 @@
/*
* Copyright (c) 2012, 2017, 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 java.util.stream;
import java.util.Collections;
import java.util.EnumSet;
import java.util.PrimitiveIterator;
import java.util.Set;
import java.util.Spliterator;
import java.util.SpliteratorTestHelper;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntConsumer;
/**
* Test scenarios for int streams.
*
* Each scenario is provided with a data source, a function that maps a fresh
* stream (as provided by the data source) to a new stream, and a sink to
* receive results. Each scenario describes a different way of computing the
* stream contents. The test driver will ensure that all scenarios produce
* the same output (modulo allowable differences in ordering).
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public enum IntStreamTestScenario implements OpTestCase.BaseStreamTestScenario {
STREAM_FOR_EACH(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
IntStream s = m.apply(source);
if (s.isParallel()) {
s = s.sequential();
}
s.forEach(b);
}
},
STREAM_TO_ARRAY(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
for (int t : m.apply(source).toArray()) {
b.accept(t);
}
}
},
STREAM_ITERATOR(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
for (PrimitiveIterator.OfInt seqIter = m.apply(source).iterator(); seqIter.hasNext(); )
b.accept(seqIter.nextInt());
}
},
// Wrap as stream, and spliterate then iterate in pull mode
STREAM_SPLITERATOR(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
for (Spliterator.OfInt spl = m.apply(source).spliterator(); spl.tryAdvance(b); ) {
}
}
},
// Wrap as stream, spliterate, then split a few times mixing advances with forEach
STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(source).spliterator());
}
},
// Wrap as stream, and spliterate then iterate in pull mode
STREAM_SPLITERATOR_FOREACH(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
m.apply(source).spliterator().forEachRemaining(b);
}
},
PAR_STREAM_SEQUENTIAL_FOR_EACH(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
m.apply(source).sequential().forEach(b);
}
},
// Wrap as parallel stream + forEachOrdered
PAR_STREAM_FOR_EACH_ORDERED(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
// @@@ Want to explicitly select ordered equalator
m.apply(source).forEachOrdered(b);
}
},
// Wrap as stream, and spliterate then iterate sequentially
PAR_STREAM_SPLITERATOR(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
for (Spliterator.OfInt spl = m.apply(source).spliterator(); spl.tryAdvance(b); ) {
}
}
},
// Wrap as stream, and spliterate then iterate sequentially
PAR_STREAM_SPLITERATOR_FOREACH(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
m.apply(source).spliterator().forEachRemaining(b);
}
},
PAR_STREAM_TO_ARRAY(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
for (int t : m.apply(source).toArray())
b.accept(t);
}
},
// Wrap as parallel stream, get the spliterator, wrap as a stream + toArray
PAR_STREAM_SPLITERATOR_STREAM_TO_ARRAY(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
IntStream s = m.apply(source);
Spliterator.OfInt sp = s.spliterator();
IntStream ss = StreamSupport.intStream(() -> sp,
StreamOpFlag.toCharacteristics(OpTestCase.getStreamFlags(s))
| (sp.getExactSizeIfKnown() < 0 ? 0 : Spliterator.SIZED),
true);
for (int t : ss.toArray())
b.accept(t);
}
},
PAR_STREAM_TO_ARRAY_CLEAR_SIZED(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
S_IN pipe1 = (S_IN) OpTestCase.chain(source,
new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape()));
IntStream pipe2 = m.apply(pipe1);
for (int t : pipe2.toArray())
b.accept(t);
}
},
// Wrap as parallel stream + forEach synchronizing
PAR_STREAM_FOR_EACH(true, false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
m.apply(source).forEach(e -> {
synchronized (data) {
b.accept(e);
}
});
}
},
// Wrap as parallel stream + forEach synchronizing and clear SIZED flag
PAR_STREAM_FOR_EACH_CLEAR_SIZED(true, false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m) {
S_IN pipe1 = (S_IN) OpTestCase.chain(source,
new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape()));
m.apply(pipe1).forEach(e -> {
synchronized (data) {
b.accept(e);
}
});
}
},
;
// The set of scenarios that clean the SIZED flag
public static final Set<IntStreamTestScenario> CLEAR_SIZED_SCENARIOS = Collections.unmodifiableSet(
EnumSet.of(PAR_STREAM_TO_ARRAY_CLEAR_SIZED, PAR_STREAM_FOR_EACH_CLEAR_SIZED));
private final boolean isParallel;
private final boolean isOrdered;
IntStreamTestScenario(boolean isParallel) {
this(isParallel, true);
}
IntStreamTestScenario(boolean isParallel, boolean isOrdered) {
this.isParallel = isParallel;
this.isOrdered = isOrdered;
}
public StreamShape getShape() {
return StreamShape.INT_VALUE;
}
public boolean isParallel() {
return isParallel;
}
public boolean isOrdered() {
return isOrdered;
}
public <T, U, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>>
void run(TestData<T, S_IN> data, Consumer<U> b, Function<S_IN, S_OUT> m) {
try (S_IN source = getStream(data)) {
run(data, source, (IntConsumer) b, (Function<S_IN, IntStream>) m);
}
}
abstract <T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, IntConsumer b, Function<S_IN, IntStream> m);
}

View file

@ -0,0 +1,41 @@
/*
* 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 java.util.stream;
/**
* A base type for test operations
*/
interface IntermediateTestOp<E_IN, E_OUT> {
@SuppressWarnings({"rawtypes", "unchecked"})
public static<T> AbstractPipeline chain(AbstractPipeline upstream,
IntermediateTestOp<?, T> op) {
if (op instanceof StatelessTestOp)
return StatelessTestOp.chain(upstream, (StatelessTestOp) op);
if (op instanceof StatefulTestOp)
return StatefulTestOp.chain(upstream, (StatefulTestOp) op);
throw new IllegalStateException("Unknown test op type: " + op.getClass().getName());
}
}

View file

@ -0,0 +1,510 @@
/*
* Copyright (c) 1997, 2016, 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 java.util.stream;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.DoublePredicate;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntUnaryOperator;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;
/**
* LambdaTestHelpers -- assertion methods and useful objects for lambda test cases
*/
public class LambdaTestHelpers {
public static final String LONG_STRING = "When in the Course of human events it becomes necessary for one people to dissolve the political bands which have connected them with another and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.";
@SuppressWarnings("rawtypes")
public static final Consumer bEmpty = x -> { };
@SuppressWarnings("rawtypes")
public static final IntConsumer bIntEmpty = x -> { };
@SuppressWarnings("rawtypes")
public static final BiConsumer bBiEmpty = (x,y) -> { };
@SuppressWarnings("rawtypes")
public static final Consumer bHashCode = x -> { Objects.hashCode(x); };
@SuppressWarnings("rawtypes")
public static final BiConsumer bBiHashCode = (x,y) -> { Objects.hash(x, y); };
public static final Function<Integer, Integer> mZero = x -> 0;
public static final Function<Integer, Integer> mId = x -> x;
public static final Function<Integer, Integer> mDoubler = x -> x * 2;
public static final Function<Integer, Stream<Integer>> mfId = e -> Collections.singletonList(e).stream();
public static final Function<Integer, Stream<Integer>> mfNull = e -> Collections.<Integer>emptyList().stream();
public static final Function<Integer, Stream<Integer>> mfLt = e -> {
List<Integer> l = new ArrayList<>();
for (int i=0; i<e; i++)
l.add(i);
return l.stream();
};
public static final ToIntFunction<Integer> imDoubler = x -> x * 2;
public static final ToLongFunction<Long> lmDoubler = x -> x * 2;
public static final ToDoubleFunction<Double> dmDoubler = x -> x * 2;
public static final Predicate<Integer> pFalse = x -> false;
public static final Predicate<Integer> pTrue = x -> true;
public static final Predicate<Integer> pEven = x -> 0 == x % 2;
public static final Predicate<Integer> pOdd = x -> 1 == x % 2;
public static final IntPredicate ipFalse = x -> false;
public static final IntPredicate ipTrue = x -> true;
public static final IntPredicate ipEven = x -> 0 == x % 2;
public static final IntPredicate ipOdd = x -> 1 == x % 2;
public static final LongPredicate lpFalse = x -> false;
public static final LongPredicate lpTrue = x -> true;
public static final LongPredicate lpEven = x -> 0 == x % 2;
public static final LongPredicate lpOdd = x -> 1 == x % 2;
public static final DoublePredicate dpFalse = x -> false;
public static final DoublePredicate dpTrue = x -> true;
public static final DoublePredicate dpEven = x -> 0 == ((long) x) % 2;
public static final DoublePredicate dpOdd = x -> 1 == ((long) x) % 2;
public static final BinaryOperator<Integer> rPlus = (x, y) -> x+y;
public static final BinaryOperator<Integer> rMax = (x, y) -> Math.max(x, y);
public static final BinaryOperator<Integer> rMin = (x, y) -> Math.min(x,y);
public static final IntBinaryOperator irPlus = (x, y) -> x+y;
public static final IntBinaryOperator irMax = (x, y) -> Math.max(x, y);
public static final IntBinaryOperator irMin = (x, y) -> Math.min(x,y);
public static final IntUnaryOperator irDoubler = x -> x * 2;
public static final LongBinaryOperator lrPlus = (x, y) -> x+y;
public static final DoubleBinaryOperator drPlus = (x, y) -> x+y;
public static final Comparator<Integer> cInteger = (a, b) -> Integer.compare(a, b);
public static final BiPredicate<?, ?> bipFalse = (x, y) -> false;
public static final BiPredicate<?, ?> bipTrue = (x, y) -> true;
public static final BiPredicate<Integer, Integer> bipBothEven = (x, y) -> 0 == (x % 2 + y % 2);
public static final BiPredicate<Integer, Integer> bipBothOdd = (x, y) -> 2 == (x % 2 + y % 2);
public static final BiPredicate<?, ?> bipSameString = (x, y) -> String.valueOf(x).equals(String.valueOf(y));
public static final IntFunction<Integer[]> integerArrayGenerator = s -> new Integer[s];
public static final IntFunction<Object[]> objectArrayGenerator = s -> new Object[s];
public static final Function<String, Stream<Character>> flattenChars = string -> {
List<Character> l = new ArrayList<>();
for (int i=0; i<string.length(); i++)
l.add(string.charAt(i));
return l.stream();
};
public static final Function<String, IntStream> flattenInt
= string -> IntStream.range(0, string.length()).map(string::charAt);
public static <T, R> Function<T, R> forPredicate(Predicate<? super T> predicate, R forTrue, R forFalse) {
Objects.requireNonNull(predicate);
return t -> predicate.test(t) ? forTrue : forFalse;
}
public static <T> Function<T, T> identity() {
return t -> t;
}
public static<V, T, R> Function<V, R> compose(Function<? super T, ? extends R> after, Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> after.apply(before.apply(v));
}
public static List<Integer> empty() {
ArrayList<Integer> list = new ArrayList<>();
list.add(null);
return list;
}
public static List<Integer> countTo(int n) {
return range(1, n);
}
public static List<Integer> range(int l, int u) {
ArrayList<Integer> list = new ArrayList<>(u - l + 1);
for (int i=l; i<=u; i++) {
list.add(i);
}
return list;
}
public static List<Integer> repeat(int value, int n) {
ArrayList<Integer> list = new ArrayList<>(n);
for (int i=1; i<=n; i++) {
list.add(value);
}
return list;
}
public static List<Double> asDoubles(List<Integer> integers) {
ArrayList<Double> list = new ArrayList<>();
for (Integer i : integers) {
list.add((double) i);
}
return list;
}
public static List<Long> asLongs(List<Integer> integers) {
ArrayList<Long> list = new ArrayList<>();
for (Integer i : integers) {
list.add((long) i);
}
return list;
}
public static void assertCountSum(Stream<? super Integer> it, int count, int sum) {
assertCountSum(it.iterator(), count, sum);
}
public static void assertCountSum(Iterable<? super Integer> it, int count, int sum) {
assertCountSum(it.iterator(), count, sum);
}
public static void assertCountSum(Iterator<? super Integer> it, int count, int sum) {
int c = 0;
int s = 0;
while (it.hasNext()) {
int i = (Integer) it.next();
c++;
s += i;
}
assertEquals(c, count);
assertEquals(s, sum);
}
public static void assertConcat(Iterator<Character> it, String result) {
StringBuilder sb = new StringBuilder();
while (it.hasNext()) {
sb.append(it.next());
}
assertEquals(result, sb.toString());
}
public static<T extends Comparable<? super T>> void assertSorted(Iterator<T> i) {
i = toBoxedList(i).iterator();
if (!i.hasNext())
return;
T last = i.next();
while (i.hasNext()) {
T t = i.next();
assertTrue(last.compareTo(t) <= 0);
assertTrue(t.compareTo(last) >= 0);
last = t;
}
}
public static<T> void assertSorted(Iterator<T> i, Comparator<? super T> comp) {
if (i instanceof PrimitiveIterator.OfInt
|| i instanceof PrimitiveIterator.OfDouble
|| i instanceof PrimitiveIterator.OfLong) {
i = toBoxedList(i).iterator();
}
if (!i.hasNext())
return;
T last = i.next();
while (i.hasNext()) {
T t = i.next();
assertTrue(comp.compare(last, t) <= 0);
assertTrue(comp.compare(t, last) >= 0);
last = t;
}
}
public static<T extends Comparable<? super T>> void assertSorted(Iterable<T> iter) {
assertSorted(iter.iterator());
}
public static<T> void assertSorted(Iterable<T> iter, Comparator<? super T> comp) {
assertSorted(iter.iterator(), comp);
}
public static <T> void assertUnique(Iterable<T> iter) {
assertUnique(iter.iterator());
}
public static<T> void assertUnique(Iterator<T> iter) {
if (!iter.hasNext()) {
return;
}
if (iter instanceof PrimitiveIterator.OfInt
|| iter instanceof PrimitiveIterator.OfDouble
|| iter instanceof PrimitiveIterator.OfLong) {
iter = toBoxedList(iter).iterator();
}
Set<T> uniq = new HashSet<>();
while(iter.hasNext()) {
T each = iter.next();
assertTrue(!uniq.contains(each), "Not unique");
uniq.add(each);
}
}
public static<T> void assertContents(Iterable<T> actual, Iterable<T> expected) {
if (actual instanceof Collection && expected instanceof Collection) {
assertIterableEquals(actual, expected);
} else {
assertContents(actual.iterator(), expected.iterator());
}
}
public static<T> void assertContents(Iterator<T> actual, Iterator<T> expected) {
assertEquals(toBoxedList(actual), toBoxedList(expected));
}
// Workaround excessive String creation in inner loop in org.testng.Assert.assertEquals(Iterable<?>, Iterable<?>)
static public void assertIterableEquals(Iterable<?> actual, Iterable<?> expected) {
if(actual == expected) {
return;
}
if(actual == null || expected == null) {
fail("Iterables not equal: expected: " + expected + " and actual: " + actual);
}
assertIteratorsEquals(actual.iterator(), expected.iterator());
}
// Workaround excessive String creation in inner loop in org.testng.Assert.assertEquals(Iterator<?>, Iterator<?>)
static public void assertIteratorsEquals(Iterator<?> actual, Iterator<?> expected) {
if (actual == expected) {
return;
}
if (actual == null || expected == null) {
fail("Iterators not equal: expected: " + expected + " and actual: " + actual);
}
while (actual.hasNext() && expected.hasNext()) {
Object e = expected.next();
Object a = actual.next();
assertEquals(a, e, "Iterator contents differ");
}
if(actual.hasNext()) {
fail("Actual iterator returned more elements than the expected iterator.");
} else if(expected.hasNext()) {
fail("Expected iterator returned more elements than the actual iterator.");
}
}
@SafeVarargs
@SuppressWarnings("varargs")
public static<T> void assertContents(Iterator<T> actual, T... expected) {
assertContents(actual, Arrays.asList(expected).iterator());
}
/**
* The all consuming consumer (rampant capitalist) that can accepting a reference or any primitive value.
*/
private static interface OmnivorousConsumer<T>
extends Consumer<T>, IntConsumer, LongConsumer, DoubleConsumer { }
@SuppressWarnings({"rawtypes", "unchecked"})
public static<T> Consumer<T> toBoxingConsumer(Consumer<? super T> c) {
return (Consumer<T>) new OmnivorousConsumer() {
@Override
public void accept(Object t) {
c.accept((T) t);
}
@Override
public void accept(int t) {
accept((Object) t);
}
@Override
public void accept(long t) {
accept((Object) t);
}
@Override
public void accept(double t) {
accept((Object) t);
}
};
}
/**
* Convert an iterator to a list using forEach with an implementation of
* {@link java.util.stream.LambdaTestHelpers.OmnivorousConsumer}.
*
* This ensures equality comparisons for test results do not trip
* the boxing trip-wires.
*/
private static<T> List<T> toBoxedList(Iterator<T> it) {
List<T> l = new ArrayList<>();
it.forEachRemaining(toBoxingConsumer(l::add));
return l;
}
/**
* Convert a spliterator to a list using forEach with an implementation of
* {@link java.util.stream.LambdaTestHelpers.OmnivorousConsumer}.
*
* This ensures equality comparisons for test results do not trip
* the boxing trip-wires.
*/
public static<T> List<T> toBoxedList(Spliterator<T> sp) {
List<T> l = new ArrayList<>();
sp.forEachRemaining(toBoxingConsumer(l::add));
return l;
}
/**
* Convert an iterator to a multi-set, represented as a Map, using forEach with an implementation of
* {@link java.util.stream.LambdaTestHelpers.OmnivorousConsumer}.
*
* This ensures equality comparisons for test results do not trip
* the boxing trip-wires.
*/
@SuppressWarnings("unchecked")
private static<T> Map<T, Integer> toBoxedMultiset(Iterator<T> it) {
Map<Object, Integer> result = new HashMap<>();
it.forEachRemaining(toBoxingConsumer(o -> {
if (result.containsKey(o))
result.put(o, result.get(o) + 1);
else
result.put(o, 1);
}));
return (Map<T, Integer>) result;
}
@SuppressWarnings("unchecked")
public static<T> Map<T, Integer> toBoxedMultiset(Spliterator<T> it) {
Map<Object, Integer> result = new HashMap<>();
it.forEachRemaining(toBoxingConsumer(o -> {
if (result.containsKey(o))
result.put(o, result.get(o) + 1);
else
result.put(o, 1);
}));
return (Map<T, Integer>) result;
}
@SuppressWarnings("unchecked")
public static void assertContentsEqual(Object a, Object b) {
if (a instanceof Iterable && b instanceof Iterable)
assertContents((Iterable) a, (Iterable) b);
else
assertEquals(a, b);
}
public static<T> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected) {
assertContentsUnordered(actual.iterator(), expected.iterator());
}
public static<T> void assertContentsUnordered(Iterator<T> actual, Iterator<T> expected) {
assertEquals(toBoxedMultiset(actual), toBoxedMultiset(expected));
}
public static<T> void assertContains(Optional<T> actual, Iterator<T> it) {
actual.ifPresentOrElse(r -> {
boolean contained = false;
while (!contained && it.hasNext()) {
contained = Objects.equals(r, it.next());
}
assertTrue(contained, "Not found: "+r);
}, () -> assertFalse(it.hasNext()));
}
public static void launderAssertion(Runnable r, Supplier<String> additionalInfo) {
try {
r.run();
}
catch (AssertionError ae) {
AssertionError cloned = new AssertionError(ae.getMessage() + String.format("%n%s", additionalInfo.get()));
cloned.setStackTrace(ae.getStackTrace());
if (ae.getCause() != null)
cloned.initCause(ae.getCause());
throw cloned;
}
}
public static <T, S extends BaseStream<T, S>>
List<Function<S, S>> permuteStreamFunctions(List<Function<S, S>> opFunctions) {
List<List<Function<S, S>>> opFunctionPermutations = perm(opFunctions);
List<Function<S, S>> appliedFunctions = new ArrayList<>();
for (List<Function<S, S>> fs : opFunctionPermutations) {
Function<S, S> applied = s -> {
for (Function<S, S> f : fs) {
s = f.apply(s);
}
return s;
};
appliedFunctions.add(applied);
}
return appliedFunctions;
}
private static <T> List<T> sub(List<T> l, int index) {
List<T> subL = new ArrayList<>(l);
subL.remove(index);
return subL;
}
public static <T> List<List<T>> perm(List<T> l) {
List<List<T>> result = new ArrayList<>();
for (int i = 0; i < l.size(); i++) {
for (List<T> perm : perm(sub(l, i))) {
perm.add(0, l.get(i));
result.add(perm);
}
}
result.add(new ArrayList<T>());
return result;
}
public static String flagsToString(int flags) {
StringJoiner sj = new StringJoiner(", ", "StreamOpFlag[", "]");
if (StreamOpFlag.DISTINCT.isKnown(flags)) sj.add("IS_DISTINCT");
if (StreamOpFlag.ORDERED.isKnown(flags)) sj.add("IS_ORDERED");
if (StreamOpFlag.SIZED.isKnown(flags)) sj.add("IS_SIZED");
if (StreamOpFlag.SORTED.isKnown(flags)) sj.add("IS_SORTED");
if (StreamOpFlag.SHORT_CIRCUIT.isKnown(flags)) sj.add("IS_SHORT_CIRCUIT");
return sj.toString();
}
}

View file

@ -0,0 +1,71 @@
/*
* 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 java.util.stream;
/**
* Runtime modes of test execution.
*/
public enum LambdaTestMode {
/**
* Execution mode with no particular runtime constraints.
*/
NORMAL,
/**
* Execution mode where tests are executed for testing lambda serialization
* and deserialization.
*
* <p>This mode may be queried by tests or data supplied by data
* providers, which cannot otherwise be assigned to the test group
* <em>serialization-hostile</em>, to not execute or declare
* serialization-hostile code or data.
*
* <p>This mode is enabled if the boolean system property
* {@code org.openjdk.java.util.stream.sand.mode} is declared with a
* {@code true} value.
*/
SERIALIZATION;
/**
* {@code true} if tests are executed in the mode for testing lambda
* Serialization ANd Deserialization (SAND).
*/
private static final boolean IS_LAMBDA_SERIALIZATION_MODE =
Boolean.getBoolean("org.openjdk.java.util.stream.sand.mode");
/**
*
* @return the mode of test execution.
*/
public static LambdaTestMode getMode() {
return IS_LAMBDA_SERIALIZATION_MODE ? SERIALIZATION : NORMAL;
}
/**
*
* @return {@code true} if normal test mode.
*/
public static boolean isNormalMode() {
return getMode() == NORMAL;
}
}

View file

@ -0,0 +1,67 @@
/*
* 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 java.util.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.testng.Assert;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* LoggingTestCase
*
*/
@Test
public class LoggingTestCase extends Assert {
private Map<String, Object> context = new HashMap<>();
@BeforeMethod
public void before() {
context.clear();
}
@AfterMethod
public void after(ITestResult result) {
if (!result.isSuccess()) {
List<Object> list = new ArrayList<>();
Collections.addAll(list, result.getParameters());
list.add(context.toString());
result.setParameters(list.toArray(new Object[list.size()]));
}
}
protected void setContext(String key, Object value) {
context.put(key, value);
}
protected void clearContext(String key) {
context.remove(key);
}
}

View file

@ -0,0 +1,173 @@
/*
* Copyright (c) 2013, 2016, 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 java.util.stream;
import org.testng.annotations.DataProvider;
import java.util.*;
import java.util.Spliterators;
import java.util.function.Supplier;
/** TestNG DataProvider for long-valued streams */
public class LongStreamTestDataProvider {
private static final long[] to0 = new long[0];
private static final long[] to1 = new long[1];
private static final long[] to10 = new long[10];
private static final long[] to100 = new long[100];
private static final long[] to1000 = new long[1000];
private static final long[] reversed = new long[100];
private static final long[] ones = new long[100];
private static final long[] twice = new long[200];
private static final long[] pseudoRandom;
private static final Object[][] testData;
private static final Object[][] testSmallData;
private static final Object[][] spliteratorTestData;
static {
long[][] arrays = {to0, to1, to10, to100, to1000};
for (long[] arr : arrays) {
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
}
for (int i = 0; i < reversed.length; i++) {
reversed[i] = reversed.length - i;
}
for (int i = 0; i < ones.length; i++) {
ones[i] = 1;
}
System.arraycopy(to100, 0, twice, 0, to100.length);
System.arraycopy(to100, 0, twice, to100.length, to100.length);
pseudoRandom = new long[LambdaTestHelpers.LONG_STRING.length()];
for (int i = 0; i < LambdaTestHelpers.LONG_STRING.length(); i++) {
pseudoRandom[i] = (long) LambdaTestHelpers.LONG_STRING.charAt(i);
}
}
static final Object[][] arrays = {
{"empty", to0},
{"0..1", to1},
{"0..10", to10},
{"0..100", to100},
{"0..1000", to1000},
{"100x[1]", ones},
{"2x[0..100]", twice},
{"reverse 0..100", reversed},
{"pseudorandom", pseudoRandom}
};
static {
{
List<Object[]> listSmall = new ArrayList<>();
List<Object[]> list1000 = new ArrayList<>();
List<Object[]> list = null;
for (Object[] data : arrays) {
final Object name = data[0];
final long[] longs = (long[]) data[1];
list = longs.length >= 1000 ? list1000 : listSmall;
list.add(new Object[]{"array:" + name,
TestData.Factory.ofArray("array:" + name, longs)});
SpinedBuffer.OfLong isl = new SpinedBuffer.OfLong();
for (long i : longs) {
isl.accept(i);
}
list.add(new Object[]{"SpinedList:" + name,
TestData.Factory.ofSpinedBuffer("SpinedList:" + name, isl)});
list.add(streamDataDescr("LongStream.longRange(0,l): " + longs.length,
() -> LongStream.range(0, longs.length)));
list.add(streamDataDescr("LongStream.longRangeClosed(0,l): " + longs.length,
() -> LongStream.rangeClosed(0, longs.length)));
}
testSmallData = listSmall.toArray(new Object[0][]);
list1000.addAll(listSmall);
testData = list1000.toArray(new Object[0][]);
}
{
List<Object[]> spliterators = new ArrayList<>();
for (Object[] data : arrays) {
final Object name = data[0];
final long[] longs = (long[]) data[1];
SpinedBuffer.OfLong isl = new SpinedBuffer.OfLong();
for (long i : longs) {
isl.accept(i);
}
spliterators.add(splitDescr("Arrays.s(array):" + name,
() -> Arrays.spliterator(longs)));
spliterators.add(splitDescr("Arrays.s(array,o,l):" + name,
() -> Arrays.spliterator(longs, 0, longs.length / 2)));
spliterators.add(splitDescr("SpinedBuffer.s():" + name,
() -> isl.spliterator()));
spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator(), size):" + name,
() -> Spliterators.spliterator(isl.iterator(), longs.length, 0)));
spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0)));
spliterators.add(splitDescr("LongStream.longRange(0,l):" + name,
() -> LongStream.range(0, longs.length).spliterator()));
spliterators.add(splitDescr("LongStream.longRangeClosed(0,l):" + name,
() -> LongStream.rangeClosed(0, longs.length).spliterator()));
spliterators.add(splitDescr("LongStream.iterate(0,x->x<l;x->x+1):" + name,
() -> LongStream.iterate(0L, x -> x < longs.length, x -> x + 1L)
.spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
}
}
static <T> Object[] streamDataDescr(String description, Supplier<LongStream> s) {
return new Object[] { description, TestData.Factory.ofLongSupplier(description, s) };
}
static <T> Object[] splitDescr(String description, Supplier<Spliterator.OfLong> s) {
return new Object[] { description, s };
}
// Return an array of ( String name, LongStreamTestData )
@DataProvider(name = "LongStreamTestData")
public static Object[][] makeLongStreamTestData() {
return testData;
}
@DataProvider(name = "LongStreamTestData.small")
public static Object[][] makeSmallLongStreamTestData() {
return testSmallData;
}
// returns an array of (String name, Supplier<PrimitiveSpliterator<Long>>)
@DataProvider(name = "LongSpliterator")
public static Object[][] spliteratorProvider() {
return spliteratorTestData;
}
}

View file

@ -0,0 +1,233 @@
/*
* Copyright (c) 2013, 2017, 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 java.util.stream;
import java.util.Collections;
import java.util.EnumSet;
import java.util.PrimitiveIterator;
import java.util.Set;
import java.util.Spliterator;
import java.util.SpliteratorTestHelper;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.LongConsumer;
/**
* Test scenarios for long streams.
*
* Each scenario is provided with a data source, a function that maps a fresh
* stream (as provided by the data source) to a new stream, and a sink to
* receive results. Each scenario describes a different way of computing the
* stream contents. The test driver will ensure that all scenarios produce
* the same output (modulo allowable differences in ordering).
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public enum LongStreamTestScenario implements OpTestCase.BaseStreamTestScenario {
STREAM_FOR_EACH(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
LongStream s = m.apply(source);
if (s.isParallel()) {
s = s.sequential();
}
s.forEach(b);
}
},
STREAM_TO_ARRAY(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
for (long t : m.apply(source).toArray()) {
b.accept(t);
}
}
},
STREAM_ITERATOR(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
for (PrimitiveIterator.OfLong seqIter = m.apply(source).iterator(); seqIter.hasNext(); )
b.accept(seqIter.nextLong());
}
},
// Wrap as stream, and spliterate then iterate in pull mode
STREAM_SPLITERATOR(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
for (Spliterator.OfLong spl = m.apply(source).spliterator(); spl.tryAdvance(b); ) {
}
}
},
// Wrap as stream, spliterate, then split a few times mixing advances with forEach
STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(source).spliterator());
}
},
// Wrap as stream, and spliterate then iterate in pull mode
STREAM_SPLITERATOR_FOREACH(false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
m.apply(source).spliterator().forEachRemaining(b);
}
},
PAR_STREAM_SEQUENTIAL_FOR_EACH(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
m.apply(source).sequential().forEach(b);
}
},
// Wrap as parallel stream + forEachOrdered
PAR_STREAM_FOR_EACH_ORDERED(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
// @@@ Want to explicitly select ordered equalator
m.apply(source).forEachOrdered(b);
}
},
// Wrap as stream, and spliterate then iterate sequentially
PAR_STREAM_SPLITERATOR(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
for (Spliterator.OfLong spl = m.apply(source).spliterator(); spl.tryAdvance(b); ) {
}
}
},
// Wrap as stream, and spliterate then iterate sequentially
PAR_STREAM_SPLITERATOR_FOREACH(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
m.apply(source).spliterator().forEachRemaining(b);
}
},
PAR_STREAM_TO_ARRAY(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
for (long t : m.apply(source).toArray())
b.accept(t);
}
},
// Wrap as parallel stream, get the spliterator, wrap as a stream + toArray
PAR_STREAM_SPLITERATOR_STREAM_TO_ARRAY(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
LongStream s = m.apply(source);
Spliterator.OfLong sp = s.spliterator();
LongStream ss = StreamSupport.longStream(() -> sp,
StreamOpFlag.toCharacteristics(OpTestCase.getStreamFlags(s))
| (sp.getExactSizeIfKnown() < 0 ? 0 : Spliterator.SIZED), true);
for (long t : ss.toArray())
b.accept(t);
}
},
PAR_STREAM_TO_ARRAY_CLEAR_SIZED(true) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
S_IN pipe1 = (S_IN) OpTestCase.chain(source,
new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape()));
LongStream pipe2 = m.apply(pipe1);
for (long t : pipe2.toArray())
b.accept(t);
}
},
// Wrap as parallel stream + forEach synchronizing
PAR_STREAM_FOR_EACH(true, false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
m.apply(source).forEach(e -> {
synchronized (data) {
b.accept(e);
}
});
}
},
// Wrap as parallel stream + forEach synchronizing and clear SIZED flag
PAR_STREAM_FOR_EACH_CLEAR_SIZED(true, false) {
<T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m) {
S_IN pipe1 = (S_IN) OpTestCase.chain(source,
new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape()));
m.apply(pipe1).forEach(e -> {
synchronized (data) {
b.accept(e);
}
});
}
},
;
// The set of scenarios that clean the SIZED flag
public static final Set<LongStreamTestScenario> CLEAR_SIZED_SCENARIOS = Collections.unmodifiableSet(
EnumSet.of(PAR_STREAM_TO_ARRAY_CLEAR_SIZED, PAR_STREAM_FOR_EACH_CLEAR_SIZED));
private boolean isParallel;
private final boolean isOrdered;
LongStreamTestScenario(boolean isParallel) {
this(isParallel, true);
}
LongStreamTestScenario(boolean isParallel, boolean isOrdered) {
this.isParallel = isParallel;
this.isOrdered = isOrdered;
}
public StreamShape getShape() {
return StreamShape.LONG_VALUE;
}
public boolean isParallel() {
return isParallel;
}
public boolean isOrdered() {
return isOrdered;
}
public <T, U, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>>
void run(TestData<T, S_IN> data, Consumer<U> b, Function<S_IN, S_OUT> m) {
try (S_IN source = getStream(data)) {
run(data, source, (LongConsumer) b, (Function<S_IN, LongStream>) m);
}
}
abstract <T, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, LongConsumer b, Function<S_IN, LongStream> m);
}

View file

@ -0,0 +1,682 @@
/*
* Copyright (c) 2012, 2015, 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 java.util.stream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import org.testng.annotations.Test;
/**
* Base class for streams test cases. Provides 'exercise' methods for taking
* lambdas that construct and modify streams, and evaluates them in different
* ways and asserts that they produce equivalent results.
*/
@Test
public abstract class OpTestCase extends LoggingTestCase {
private final Map<StreamShape, Set<? extends BaseStreamTestScenario>> testScenarios;
protected OpTestCase() {
testScenarios = new EnumMap<>(StreamShape.class);
testScenarios.put(StreamShape.REFERENCE, Collections.unmodifiableSet(EnumSet.allOf(StreamTestScenario.class)));
testScenarios.put(StreamShape.INT_VALUE, Collections.unmodifiableSet(EnumSet.allOf(IntStreamTestScenario.class)));
testScenarios.put(StreamShape.LONG_VALUE, Collections.unmodifiableSet(EnumSet.allOf(LongStreamTestScenario.class)));
testScenarios.put(StreamShape.DOUBLE_VALUE, Collections.unmodifiableSet(EnumSet.allOf(DoubleStreamTestScenario.class)));
}
@SuppressWarnings("rawtypes")
public static int getStreamFlags(BaseStream s) {
return ((AbstractPipeline) s).getStreamFlags();
}
/**
* An asserter for results produced when exercising of stream or terminal
* tests.
*
* @param <R> the type of result to assert on
*/
public interface ResultAsserter<R> {
/**
* Assert a result produced when exercising of stream or terminal
* test.
*
* @param actual the actual result
* @param expected the expected result
* @param isOrdered true if the pipeline is ordered
* @param isParallel true if the pipeline is parallel
*/
void assertResult(R actual, R expected, boolean isOrdered, boolean isParallel);
}
// Exercise stream operations
public interface BaseStreamTestScenario {
StreamShape getShape();
boolean isParallel();
boolean isOrdered();
default <T, S_IN extends BaseStream<T, S_IN>>
S_IN getStream(TestData<T, S_IN> data) {
return isParallel()
? data.parallelStream()
: data.stream();
}
<T, U, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>>
void run(TestData<T, S_IN> data, Consumer<U> b, Function<S_IN, S_OUT> m);
}
protected <T, U, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>>
Collection<U> exerciseOps(TestData<T, S_IN> data, Function<S_IN, S_OUT> m) {
return withData(data).stream(m).exercise();
}
// Run multiple versions of exercise(), returning the result of the first, and asserting that others return the same result
// If the first version is s -> s.foo(), can be used with s -> s.mapToInt(i -> i).foo().mapToObj(i -> i) to test all shape variants
@SafeVarargs
protected final<T, U, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>>
Collection<U> exerciseOpsMulti(TestData<T, S_IN> data,
Function<S_IN, S_OUT>... ms) {
Collection<U> result = null;
for (Function<S_IN, S_OUT> m : ms) {
if (result == null)
result = withData(data).stream(m).exercise();
else {
Collection<U> r2 = withData(data).stream(m).exercise();
assertEquals(result, r2);
}
}
return result;
}
// Run multiple versions of exercise() for an Integer stream, returning the result of the first, and asserting that others return the same result
// Automates the conversion between Stream<Integer> and {Int,Long,Double}Stream and back, so client sites look like you are passing the same
// lambda four times, but in fact they are four different lambdas since they are transforming four different kinds of streams
protected final
Collection<Integer> exerciseOpsInt(TestData.OfRef<Integer> data,
Function<Stream<Integer>, Stream<Integer>> mRef,
Function<IntStream, IntStream> mInt,
Function<LongStream, LongStream> mLong,
Function<DoubleStream, DoubleStream> mDouble) {
@SuppressWarnings({ "rawtypes", "unchecked" })
Function<Stream<Integer>, Stream<Integer>>[] ms = new Function[4];
ms[0] = mRef;
ms[1] = s -> mInt.apply(s.mapToInt(e -> e)).mapToObj(e -> e);
ms[2] = s -> mLong.apply(s.mapToLong(e -> e)).mapToObj(e -> (int) e);
ms[3] = s -> mDouble.apply(s.mapToDouble(e -> e)).mapToObj(e -> (int) e);
return exerciseOpsMulti(data, ms);
}
// Run multiple versions of exercise() with multiple terminal operations for all kinds of stream, , and asserting against the expected result
// If the first version is s -> s.foo(), can be used with s -> s.mapToInt(i -> i).foo().mapToObj(i -> i) to test all shape variants
protected final<T, U, R, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>>
void exerciseTerminalOpsMulti(TestData<T, S_IN> data,
R expected,
Map<String, Function<S_IN, S_OUT>> streams,
Map<String, Function<S_OUT, R>> terminals) {
for (Map.Entry<String, Function<S_IN, S_OUT>> se : streams.entrySet()) {
setContext("Intermediate stream", se.getKey());
for (Map.Entry<String, Function<S_OUT, R>> te : terminals.entrySet()) {
setContext("Terminal stream", te.getKey());
withData(data)
.terminal(se.getValue(), te.getValue())
.expectedResult(expected)
.exercise();
}
}
}
// Run multiple versions of exercise() with multiple terminal operation for all kinds of stream, and asserting against the expected result
// Automates the conversion between Stream<Integer> and {Int,Long,Double}Stream and back, so client sites look like you are passing the same
// lambda four times, but in fact they are four different lambdas since they are transforming four different kinds of streams
protected final
void exerciseTerminalOpsInt(TestData<Integer, Stream<Integer>> data,
Collection<Integer> expected,
String desc,
Function<Stream<Integer>, Stream<Integer>> mRef,
Function<IntStream, IntStream> mInt,
Function<LongStream, LongStream> mLong,
Function<DoubleStream, DoubleStream> mDouble,
Map<String, Function<Stream<Integer>, Collection<Integer>>> terminals) {
Map<String, Function<Stream<Integer>, Stream<Integer>>> m = new HashMap<>();
m.put("Ref " + desc, mRef);
m.put("Int " + desc, s -> mInt.apply(s.mapToInt(e -> e)).mapToObj(e -> e));
m.put("Long " + desc, s -> mLong.apply(s.mapToLong(e -> e)).mapToObj(e -> (int) e));
m.put("Double " + desc, s -> mDouble.apply(s.mapToDouble(e -> e)).mapToObj(e -> (int) e));
exerciseTerminalOpsMulti(data, expected, m, terminals);
}
protected <T, U, S_OUT extends BaseStream<U, S_OUT>>
Collection<U> exerciseOps(Collection<T> data, Function<Stream<T>, S_OUT> m) {
TestData.OfRef<T> data1 = TestData.Factory.ofCollection("Collection of type " + data.getClass().getName(), data);
return withData(data1).stream(m).exercise();
}
protected <T, U, S_OUT extends BaseStream<U, S_OUT>, I extends Iterable<U>>
Collection<U> exerciseOps(Collection<T> data, Function<Stream<T>, S_OUT> m, I expected) {
TestData.OfRef<T> data1 = TestData.Factory.ofCollection("Collection of type " + data.getClass().getName(), data);
return withData(data1).stream(m).expectedResult(expected).exercise();
}
@SuppressWarnings("unchecked")
protected <U, S_OUT extends BaseStream<U, S_OUT>>
Collection<U> exerciseOps(int[] data, Function<IntStream, S_OUT> m) {
return withData(TestData.Factory.ofArray("int array", data)).stream(m).exercise();
}
protected Collection<Integer> exerciseOps(int[] data, Function<IntStream, IntStream> m, int[] expected) {
TestData.OfInt data1 = TestData.Factory.ofArray("int array", data);
return withData(data1).stream(m).expectedResult(expected).exercise();
}
protected <T, S_IN extends BaseStream<T, S_IN>> DataStreamBuilder<T, S_IN> withData(TestData<T, S_IN> data) {
Objects.requireNonNull(data);
return new DataStreamBuilder<>(data);
}
@SuppressWarnings({"rawtypes", "unchecked"})
public class DataStreamBuilder<T, S_IN extends BaseStream<T, S_IN>> {
final TestData<T, S_IN> data;
private DataStreamBuilder(TestData<T, S_IN> data) {
this.data = Objects.requireNonNull(data);
}
public <U, S_OUT extends BaseStream<U, S_OUT>>
ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> ops(IntermediateTestOp... ops) {
return new ExerciseDataStreamBuilder<>(data, (S_IN s) -> (S_OUT) chain(s, ops));
}
public <U, S_OUT extends BaseStream<U, S_OUT>> ExerciseDataStreamBuilder<T, U, S_IN, S_OUT>
stream(Function<S_IN, S_OUT> m) {
return new ExerciseDataStreamBuilder<>(data, m);
}
public <U, S_OUT extends BaseStream<U, S_OUT>> ExerciseDataStreamBuilder<T, U, S_IN, S_OUT>
stream(Function<S_IN, S_OUT> m, IntermediateTestOp<U, U> additionalOp) {
return new ExerciseDataStreamBuilder<>(data, s -> (S_OUT) chain(m.apply(s), additionalOp));
}
public <R> ExerciseDataTerminalBuilder<T, T, R, S_IN, S_IN>
terminal(Function<S_IN, R> terminalF) {
return new ExerciseDataTerminalBuilder<>(data, s -> s, terminalF);
}
public <U, R, S_OUT extends BaseStream<U, S_OUT>> ExerciseDataTerminalBuilder<T, U, R, S_IN, S_OUT>
terminal(Function<S_IN, S_OUT> streamF, Function<S_OUT, R> terminalF) {
return new ExerciseDataTerminalBuilder<>(data, streamF, terminalF);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
public class ExerciseDataStreamBuilder<T, U, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>> {
final TestData<T, S_IN> data;
final Function<S_IN, S_OUT> m;
final StreamShape shape;
Set<BaseStreamTestScenario> testSet = new HashSet<>();
Collection<U> refResult;
Consumer<TestData<T, S_IN>> before = LambdaTestHelpers.bEmpty;
Consumer<TestData<T, S_IN>> after = LambdaTestHelpers.bEmpty;
ResultAsserter<Iterable<U>> resultAsserter = (act, exp, ord, par) -> {
if (par & !ord) {
LambdaTestHelpers.assertContentsUnordered(act, exp);
}
else {
LambdaTestHelpers.assertContentsEqual(act, exp);
}
};
private ExerciseDataStreamBuilder(TestData<T, S_IN> data, Function<S_IN, S_OUT> m) {
this.data = data;
this.m = Objects.requireNonNull(m);
this.shape = ((AbstractPipeline<?, U, ?>) m.apply(data.stream())).getOutputShape();
// Have to initiate from the output shape of the last stream
// This means the stream mapper is required first rather than last
testSet.addAll(testScenarios.get(shape));
}
//
public <I extends Iterable<U>> ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> expectedResult(I expectedResult) {
List<U> l = new ArrayList<>();
expectedResult.forEach(l::add);
refResult = l;
return this;
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> expectedResult(int[] expectedResult) {
List l = new ArrayList();
for (int anExpectedResult : expectedResult) {
l.add(anExpectedResult);
}
refResult = l;
return this;
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> expectedResult(long[] expectedResult) {
List l = new ArrayList();
for (long anExpectedResult : expectedResult) {
l.add(anExpectedResult);
}
refResult = l;
return this;
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> expectedResult(double[] expectedResult) {
List l = new ArrayList();
for (double anExpectedResult : expectedResult) {
l.add(anExpectedResult);
}
refResult = l;
return this;
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> before(Consumer<TestData<T, S_IN>> before) {
this.before = Objects.requireNonNull(before);
return this;
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> after(Consumer<TestData<T, S_IN>> after) {
this.after = Objects.requireNonNull(after);
return this;
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> without(BaseStreamTestScenario... tests) {
return without(Arrays.asList(tests));
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> without(Collection<? extends BaseStreamTestScenario> tests) {
for (BaseStreamTestScenario ts : tests) {
if (ts.getShape() == shape) {
testSet.remove(ts);
}
}
if (testSet.isEmpty()) {
throw new IllegalStateException("Test scenario set is empty");
}
return this;
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> with(BaseStreamTestScenario... tests) {
return with(Arrays.asList(tests));
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> with(Collection<? extends BaseStreamTestScenario> tests) {
testSet = new HashSet<>();
for (BaseStreamTestScenario ts : tests) {
if (ts.getShape() == shape) {
testSet.add(ts);
}
}
if (testSet.isEmpty()) {
throw new IllegalStateException("Test scenario set is empty");
}
return this;
}
public ExerciseDataStreamBuilder<T, U, S_IN, S_OUT> resultAsserter(ResultAsserter<Iterable<U>> resultAsserter) {
this.resultAsserter = resultAsserter;
return this;
}
// Build method
public Collection<U> exercise() {
final boolean isStreamOrdered;
if (refResult == null) {
// Induce the reference result
before.accept(data);
try (S_OUT sOut = m.apply(data.stream())) {
isStreamOrdered = StreamOpFlag.ORDERED.isKnown(((AbstractPipeline) sOut).getStreamFlags());
Node<U> refNodeResult = ((AbstractPipeline<?, U, ?>) sOut).evaluateToArrayNode(size -> (U[]) new Object[size]);
refResult = LambdaTestHelpers.toBoxedList(refNodeResult.spliterator());
}
after.accept(data);
}
else {
try (S_OUT sOut = m.apply(data.stream())) {
isStreamOrdered = StreamOpFlag.ORDERED.isKnown(((AbstractPipeline) sOut).getStreamFlags());
}
}
List<Error> errors = new ArrayList<>();
for (BaseStreamTestScenario test : testSet) {
try {
before.accept(data);
List<U> result = new ArrayList<>();
test.run(data, LambdaTestHelpers.<U>toBoxingConsumer(result::add), m);
Runnable asserter = () -> resultAsserter.assertResult(result, refResult, isStreamOrdered && test.isOrdered(), test.isParallel());
if (refResult.size() > 1000) {
LambdaTestHelpers.launderAssertion(
asserter,
() -> String.format("%n%s: [actual size=%d] != [expected size=%d]", test, result.size(), refResult.size()));
}
else {
LambdaTestHelpers.launderAssertion(
asserter,
() -> String.format("%n%s: [actual] %s != [expected] %s", test, result, refResult));
}
after.accept(data);
} catch (Throwable t) {
errors.add(new Error(String.format("%s: %s", test, t), t));
}
}
if (!errors.isEmpty()) {
StringBuilder sb = new StringBuilder();
int i = 1;
for (Error t : errors) {
sb.append(i++).append(": ");
if (t instanceof AssertionError) {
sb.append(t).append("\n");
}
else {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.getCause().printStackTrace(pw);
pw.flush();
sb.append(t).append("\n").append(sw);
}
}
sb.append("--");
fail(String.format("%d failure(s) for test data: %s\n%s", i - 1, data.toString(), sb));
}
return refResult;
}
}
// Exercise terminal operations
interface BaseTerminalTestScenario<U, R, S_OUT extends BaseStream<U, S_OUT>> {
boolean requiresSingleStageSource();
boolean requiresParallelSource();
default R run(Function<S_OUT, R> terminalF, S_OUT source, StreamShape shape) {
return terminalF.apply(source);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
enum TerminalTestScenario implements BaseTerminalTestScenario {
SINGLE_SEQUENTIAL(true, false),
SINGLE_SEQUENTIAL_SHORT_CIRCUIT(true, false) {
@Override
public Object run(Function terminalF, BaseStream source, StreamShape shape) {
source = (BaseStream) chain(source, new ShortCircuitOp(shape));
return terminalF.apply(source);
}
},
SINGLE_PARALLEL(true, true),
ALL_SEQUENTIAL(false, false),
ALL_SEQUENTIAL_SHORT_CIRCUIT(false, false) {
@Override
public Object run(Function terminalF, BaseStream source, StreamShape shape) {
source = (BaseStream) chain(source, new ShortCircuitOp(shape));
return terminalF.apply(source);
}
},
ALL_PARALLEL(false, true),
ALL_PARALLEL_SEQUENTIAL(false, false) {
@Override
public Object run(Function terminalF, BaseStream source, StreamShape shape) {
return terminalF.apply(source.sequential());
}
},
;
private final boolean requiresSingleStageSource;
private final boolean isParallel;
TerminalTestScenario(boolean requiresSingleStageSource, boolean isParallel) {
this.requiresSingleStageSource = requiresSingleStageSource;
this.isParallel = isParallel;
}
@Override
public boolean requiresSingleStageSource() {
return requiresSingleStageSource;
}
@Override
public boolean requiresParallelSource() {
return isParallel;
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
public class ExerciseDataTerminalBuilder<T, U, R, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>> {
final TestData<T, S_IN> data;
final Function<S_IN, S_OUT> streamF;
final Function<S_OUT, R> terminalF;
R refResult;
ResultAsserter<R> resultAsserter = (act, exp, ord, par) -> LambdaTestHelpers.assertContentsEqual(act, exp);
private ExerciseDataTerminalBuilder(TestData<T, S_IN> data, Function<S_IN, S_OUT> streamF, Function<S_OUT, R> terminalF) {
this.data = data;
this.streamF = Objects.requireNonNull(streamF);
this.terminalF = Objects.requireNonNull(terminalF);
}
//
public ExerciseDataTerminalBuilder<T, U, R, S_IN, S_OUT> expectedResult(R expectedResult) {
this.refResult = expectedResult;
return this;
}
public ExerciseDataTerminalBuilder<T, U, R, S_IN, S_OUT> equalator(BiConsumer<R, R> equalityAsserter) {
resultAsserter = (act, exp, ord, par) -> equalityAsserter.accept(act, exp);
return this;
}
public ExerciseDataTerminalBuilder<T, U, R, S_IN, S_OUT> resultAsserter(ResultAsserter<R> resultAsserter) {
this.resultAsserter = resultAsserter;
return this;
}
// Build method
public R exercise() {
boolean isOrdered;
StreamShape shape;
Node<U> node;
try (S_OUT out = streamF.apply(data.stream()).sequential()) {
AbstractPipeline ap = (AbstractPipeline) out;
isOrdered = StreamOpFlag.ORDERED.isKnown(ap.getStreamFlags());
shape = ap.getOutputShape();
// Sequentially collect the output that will be input to the terminal op
node = ap.evaluateToArrayNode(size -> (U[]) new Object[size]);
}
EnumSet<TerminalTestScenario> tests = EnumSet.allOf(TerminalTestScenario.class);
if (refResult == null) {
// Induce the reference result
S_OUT source = (S_OUT) createPipeline(shape, node.spliterator(),
StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SIZED,
false);
refResult = (R) TerminalTestScenario.SINGLE_SEQUENTIAL.run(terminalF, source, shape);
tests.remove(TerminalTestScenario.SINGLE_SEQUENTIAL);
}
for (BaseTerminalTestScenario test : tests) {
S_OUT source;
if (test.requiresSingleStageSource()) {
source = (S_OUT) createPipeline(shape, node.spliterator(),
StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SIZED,
test.requiresParallelSource());
}
else {
source = streamF.apply(test.requiresParallelSource()
? data.parallelStream() : data.stream());
}
R result;
try (source) {
result = (R) test.run(terminalF, source, shape);
}
LambdaTestHelpers.launderAssertion(
() -> resultAsserter.assertResult(result, refResult, isOrdered, test.requiresParallelSource()),
() -> String.format("%s: %s != %s", test, refResult, result));
}
return refResult;
}
AbstractPipeline createPipeline(StreamShape shape, Spliterator s, int flags, boolean parallel) {
switch (shape) {
case REFERENCE: return new ReferencePipeline.Head<>(s, flags, parallel);
case INT_VALUE: return new IntPipeline.Head(s, flags, parallel);
case LONG_VALUE: return new LongPipeline.Head(s, flags, parallel);
case DOUBLE_VALUE: return new DoublePipeline.Head(s, flags, parallel);
default: throw new IllegalStateException("Unknown shape: " + shape);
}
}
}
protected <T, R> R exerciseTerminalOps(Collection<T> data, Function<Stream<T>, R> m, R expected) {
TestData.OfRef<T> data1
= TestData.Factory.ofCollection("Collection of type " + data.getClass().getName(), data);
return withData(data1).terminal(m).expectedResult(expected).exercise();
}
protected <T, R, S_IN extends BaseStream<T, S_IN>> R
exerciseTerminalOps(TestData<T, S_IN> data,
Function<S_IN, R> terminalF) {
return withData(data).terminal(terminalF).exercise();
}
protected <T, U, R, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>> R
exerciseTerminalOps(TestData<T, S_IN> data,
Function<S_IN, S_OUT> streamF,
Function<S_OUT, R> terminalF) {
return withData(data).terminal(streamF, terminalF).exercise();
}
//
@SuppressWarnings({"rawtypes", "unchecked"})
private static <T> AbstractPipeline<?, T, ?> chain(AbstractPipeline upstream, IntermediateTestOp<?, T> op) {
return (AbstractPipeline<?, T, ?>) IntermediateTestOp.chain(upstream, op);
}
@SuppressWarnings({"rawtypes", "unchecked"})
private static AbstractPipeline<?, ?, ?> chain(AbstractPipeline pipe, IntermediateTestOp... ops) {
for (IntermediateTestOp op : ops)
pipe = chain(pipe, op);
return pipe;
}
@SuppressWarnings("rawtypes")
private static <T> AbstractPipeline<?, T, ?> chain(BaseStream pipe, IntermediateTestOp<?, T> op) {
return chain((AbstractPipeline) pipe, op);
}
@SuppressWarnings("rawtypes")
public static AbstractPipeline<?, ?, ?> chain(BaseStream pipe, IntermediateTestOp... ops) {
return chain((AbstractPipeline) pipe, ops);
}
// Test data
static class ShortCircuitOp<T> implements StatelessTestOp<T,T> {
private final StreamShape shape;
ShortCircuitOp(StreamShape shape) {
this.shape = shape;
}
@Override
public Sink<T> opWrapSink(int flags, boolean parallel, Sink<T> sink) {
return sink;
}
@Override
public int opGetFlags() {
return StreamOpFlag.IS_SHORT_CIRCUIT;
}
@Override
public StreamShape outputShape() {
return shape;
}
@Override
public StreamShape inputShape() {
return shape;
}
}
}

View file

@ -0,0 +1,138 @@
/*
* 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 java.util.stream;
import java.util.Spliterator;
import java.util.function.IntFunction;
/**
* The base type for a stateful test operation.
*/
interface StatefulTestOp<E> extends IntermediateTestOp<E, E> {
@SuppressWarnings({"rawtypes", "unchecked"})
public static<T> AbstractPipeline chain(AbstractPipeline upstream,
StatefulTestOp op) {
switch (op.outputShape()) {
case REFERENCE:
return new ReferencePipeline.StatefulOp<Object, T>(upstream, op.inputShape(), op.opGetFlags()) {
@Override
Sink opWrapSink(int flags, Sink sink) {
return op.opWrapSink(flags, isParallel(), sink);
}
@Override
<P_IN> Spliterator<T> opEvaluateParallelLazy(PipelineHelper<T> helper,
Spliterator<P_IN> spliterator) {
return op.opEvaluateParallelLazy(helper, spliterator);
}
@Override
<P_IN> Node<T> opEvaluateParallel(PipelineHelper<T> helper,
Spliterator<P_IN> spliterator,
IntFunction<T[]> generator) {
return op.opEvaluateParallel(helper, spliterator, generator);
}
};
case INT_VALUE:
return new IntPipeline.StatefulOp<Object>(upstream, op.inputShape(), op.opGetFlags()) {
@Override
Sink opWrapSink(int flags, Sink sink) {
return op.opWrapSink(flags, isParallel(), sink);
}
@Override
<P_IN> Spliterator<Integer> opEvaluateParallelLazy(PipelineHelper<Integer> helper,
Spliterator<P_IN> spliterator) {
return op.opEvaluateParallelLazy(helper, spliterator);
}
@Override
<P_IN> Node<Integer> opEvaluateParallel(PipelineHelper<Integer> helper,
Spliterator<P_IN> spliterator,
IntFunction<Integer[]> generator) {
return (Node<Integer>) op.opEvaluateParallel(helper, spliterator, generator);
}
};
case LONG_VALUE:
return new LongPipeline.StatefulOp<Object>(upstream, op.inputShape(), op.opGetFlags()) {
@Override
Sink opWrapSink(int flags, Sink sink) {
return op.opWrapSink(flags, isParallel(), sink);
}
@Override
<P_IN> Spliterator<Long> opEvaluateParallelLazy(PipelineHelper<Long> helper,
Spliterator<P_IN> spliterator) {
return op.opEvaluateParallelLazy(helper, spliterator);
}
@Override
<P_IN> Node<Long> opEvaluateParallel(PipelineHelper<Long> helper,
Spliterator<P_IN> spliterator,
IntFunction<Long[]> generator) {
return (Node<Long>) op.opEvaluateParallel(helper, spliterator, generator);
}
};
case DOUBLE_VALUE:
return new DoublePipeline.StatefulOp<Object>(upstream, op.inputShape(), op.opGetFlags()) {
@Override
Sink opWrapSink(int flags, Sink sink) {
return op.opWrapSink(flags, isParallel(), sink);
}
@Override
<P_IN> Spliterator<Double> opEvaluateParallelLazy(PipelineHelper<Double> helper,
Spliterator<P_IN> spliterator) {
return op.opEvaluateParallelLazy(helper, spliterator);
}
@Override
<P_IN> Node<Double> opEvaluateParallel(PipelineHelper<Double> helper,
Spliterator<P_IN> spliterator,
IntFunction<Double[]> generator) {
return (Node<Double>) op.opEvaluateParallel(helper, spliterator, generator);
}
};
default: throw new IllegalStateException(op.outputShape().toString());
}
}
default StreamShape inputShape() { return StreamShape.REFERENCE; }
default StreamShape outputShape() { return StreamShape.REFERENCE; }
default int opGetFlags() { return 0; }
Sink<E> opWrapSink(int flags, boolean parallel, Sink<E> sink);
@SuppressWarnings("unchecked")
default <P_IN> Spliterator<E> opEvaluateParallelLazy(PipelineHelper<E> helper,
Spliterator<P_IN> spliterator) {
return opEvaluateParallel(helper, spliterator, i -> (E[]) new Object[i]).spliterator();
}
<P_IN> Node<E> opEvaluateParallel(PipelineHelper<E> helper,
Spliterator<P_IN> spliterator,
IntFunction<E[]> generator);
}

View file

@ -0,0 +1,73 @@
/*
* 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 java.util.stream;
/**
* The base type of a stateless test operation
*/
interface StatelessTestOp<E_IN, E_OUT> extends IntermediateTestOp<E_IN, E_OUT> {
@SuppressWarnings({"rawtypes", "unchecked"})
public static<T> AbstractPipeline chain(AbstractPipeline upstream,
StatelessTestOp<?, T> op) {
int flags = op.opGetFlags();
switch (op.outputShape()) {
case REFERENCE:
return new ReferencePipeline.StatelessOp<Object, T>(upstream, op.inputShape(), flags) {
public Sink opWrapSink(int flags, Sink<T> sink) {
return op.opWrapSink(flags, isParallel(), sink);
}
};
case INT_VALUE:
return new IntPipeline.StatelessOp<Object>(upstream, op.inputShape(), flags) {
public Sink opWrapSink(int flags, Sink sink) {
return op.opWrapSink(flags, isParallel(), sink);
}
};
case LONG_VALUE:
return new LongPipeline.StatelessOp<Object>(upstream, op.inputShape(), flags) {
@Override
Sink opWrapSink(int flags, Sink sink) {
return op.opWrapSink(flags, isParallel(), sink);
}
};
case DOUBLE_VALUE:
return new DoublePipeline.StatelessOp<Object>(upstream, op.inputShape(), flags) {
@Override
Sink opWrapSink(int flags, Sink sink) {
return op.opWrapSink(flags, isParallel(), sink);
}
};
default: throw new IllegalStateException(op.outputShape().toString());
}
}
default StreamShape inputShape() { return StreamShape.REFERENCE; }
default StreamShape outputShape() { return StreamShape.REFERENCE; }
default int opGetFlags() { return 0; }
Sink<E_IN> opWrapSink(int flags, boolean parallel, Sink<E_OUT> sink);
}

View file

@ -0,0 +1,48 @@
/*
* 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 java.util.stream;
import java.util.EnumSet;
public class StreamOpFlagTestHelper {
/** EnumSet containing stream flags */
private static final EnumSet<StreamOpFlag> allStreamFlags;
static {
allStreamFlags = EnumSet.allOf(StreamOpFlag.class);
for (StreamOpFlag f : EnumSet.allOf(StreamOpFlag.class))
if (!f.isStreamFlag())
allStreamFlags.remove(f);
}
static EnumSet<StreamOpFlag> allStreamFlags() {
// EnumSet is mutable
return allStreamFlags.clone();
}
public static boolean isStreamOrdered(Stream<?> s) {
return StreamOpFlag.ORDERED.isKnown(OpTestCase.getStreamFlags(s));
}
}

View file

@ -0,0 +1,228 @@
/*
* Copyright (c) 2012, 2016, 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 java.util.stream;
import org.testng.annotations.DataProvider;
import java.util.*;
import java.util.Spliterators;
import java.util.function.Supplier;
/**
* StreamTestDataProvider
*
* @author Brian Goetz
*/
/** TestNG DataProvider for ref-valued streams */
public class StreamTestDataProvider {
private static final Integer[] to0 = new Integer[0];
private static final Integer[] to1 = new Integer[1];
private static final Integer[] to10 = new Integer[10];
private static final Integer[] to100 = new Integer[100];
private static final Integer[] to1000 = new Integer[1000];
private static final Integer[] reversed = new Integer[100];
private static final Integer[] ones = new Integer[100];
private static final Integer[] twice = new Integer[200];
private static final Integer[] pseudoRandom;
private static final Object[][] testData;
private static final Object[][] testSmallData;
private static final Object[][] testMiniData;
private static final Object[][] withNullTestData;
private static final Object[][] spliteratorTestData;
static {
Integer[][] arrays = {to0, to1, to10, to100, to1000};
for (Integer[] arr : arrays) {
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
}
for (int i = 0; i < reversed.length; i++) {
reversed[i] = reversed.length - i;
}
for (int i = 0; i < ones.length; i++) {
ones[i] = 1;
}
System.arraycopy(to100, 0, twice, 0, to100.length);
System.arraycopy(to100, 0, twice, to100.length, to100.length);
pseudoRandom = new Integer[LambdaTestHelpers.LONG_STRING.length()];
for (int i = 0; i < LambdaTestHelpers.LONG_STRING.length(); i++) {
pseudoRandom[i] = (int) LambdaTestHelpers.LONG_STRING.charAt(i);
}
}
static final Object[][] arrays = {
{"empty", to0},
{"0..1", to1},
{"0..10", to10},
{"0..100", to100},
{"0..1000", to1000},
{"100x[1]", ones},
{"2x[0..100]", twice},
{"reverse 0..100", reversed},
{"pseudorandom", pseudoRandom}
};
static {
{
List<Object[]> listMini = new ArrayList<>();
List<Object[]> listSmall = new ArrayList<>();
List<Object[]> list1000 = new ArrayList<>();
List<Object[]> list = null;
for (Object[] data : arrays) {
final Object name = data[0];
final Integer[] ints = (Integer[])data[1];
final List<Integer> intsAsList = Arrays.asList(ints);
list = ints.length >= 1000 ? list1000 : (ints.length >= 100 ? listSmall : listMini);
list.add(arrayDataDescr("array:" + name, ints));
list.add(collectionDataDescr("ArrayList.asList:" + name, intsAsList));
list.add(collectionDataDescr("ArrayList:" + name, new ArrayList<>(intsAsList)));
list.add(streamDataDescr("DelegatingStream(ArrayList):" + name,
() -> new ArrayList<>(intsAsList).stream()));
List<Integer> aList = new ArrayList<>(intsAsList);
if (LambdaTestMode.isNormalMode()) {
// Only include sub-lists for normal test execution mode
// This data is serialization-hostile since the state of the
// deserialized sub-list will be out of sync with the
// enclosing list.
list.add(collectionDataDescr("ArrayList.Sublist:" + name,
(ints.length) <= 1 ? aList.subList(0, 0) : aList.subList(1, ints.length / 2)));
}
list.add(collectionDataDescr("LinkedList:" + name, new LinkedList<>(intsAsList)));
list.add(collectionDataDescr("HashSet:" + name, new HashSet<>(intsAsList)));
list.add(collectionDataDescr("LinkedHashSet:" + name, new LinkedHashSet<>(intsAsList)));
list.add(collectionDataDescr("TreeSet:" + name, new TreeSet<>(intsAsList)));
SpinedBuffer<Integer> spinedBuffer = new SpinedBuffer<>();
intsAsList.forEach(spinedBuffer);
list.add(sbDataDescr("SpinedBuffer:" + name, spinedBuffer));
// @@@ Add more
}
testMiniData = listMini.toArray(new Object[0][]);
listSmall.addAll(listMini);
testSmallData = listSmall.toArray(new Object[0][]);
list1000.addAll(listSmall);
testData = list1000.toArray(new Object[0][]);
}
// Simple combination of numbers and null values, probably excessive but may catch
// errors for initialization/termination/sequence
// @@@ This is separate from the other data for now until nulls are consistently supported by
// all operations
{
List<Object[]> list = new ArrayList<>();
int size = 5;
for (int i = 0; i < (1 << size) - 2; i++) {
Integer[] content = new Integer[size];
for (int e = 0; e < size; e++) {
content[e] = (i & (1 << e)) > 0 ? e + 1 : null;
}
// ORDERED
list.add(arrayDataDescr("array:" + i, content));
// not ORDERED, DISTINCT
list.add(collectionDataDescr("HashSet:" + i, new HashSet<>(Arrays.asList(content))));
}
withNullTestData = list.toArray(new Object[0][]);
}
{
List<Object[]> spliterators = new ArrayList<>();
for (Object[] data : arrays) {
final Object name = data[0];
final Integer[] ints = (Integer[])data[1];
spliterators.add(splitDescr("Arrays.s(array):" + name,
() -> Arrays.spliterator(ints)));
spliterators.add(splitDescr("arrays.s(array,o,l):" + name,
() -> Arrays.spliterator(ints, 0, ints.length/2)));
spliterators.add(splitDescr("SpinedBuffer.s():" + name,
() -> {
SpinedBuffer<Integer> sb = new SpinedBuffer<>();
for (Integer i : ints)
sb.accept(i);
return sb.spliterator();
}));
spliterators.add(splitDescr("Iterators.s(Arrays.s(array).iterator(), size):" + name,
() -> Spliterators.spliterator(Arrays.asList(ints).iterator(), ints.length, 0)));
spliterators.add(splitDescr("Iterators.s(Arrays.s(array).iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(Arrays.asList(ints).iterator(), 0)));
spliterators.add(splitDescr("Stream.iterate(0,x->x<l,x->x+1): " + name,
() -> Stream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator()));
// @@@ Add map and collection spliterators when spliterator() is exposed on Collection or Iterable
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
}
}
static <T> Object[] arrayDataDescr(String description, T[] data) {
return new Object[] { description, TestData.Factory.ofArray(description, data)};
}
static <T> Object[] streamDataDescr(String description, Supplier<Stream<T>> supplier) {
return new Object[] { description, TestData.Factory.ofSupplier(description, supplier)};
}
static <T> Object[] collectionDataDescr(String description, Collection<T> data) {
return new Object[] { description, TestData.Factory.ofCollection(description, data)};
}
static <T> Object[] sbDataDescr(String description, SpinedBuffer<T> data) {
return new Object[] { description, TestData.Factory.ofSpinedBuffer(description, data)};
}
static <T> Object[] splitDescr(String description, Supplier<Spliterator<T>> ss) {
return new Object[] { description, ss };
}
// Return an array of ( String name, StreamTestData<Integer> )
@DataProvider(name = "StreamTestData<Integer>")
public static Object[][] makeStreamTestData() {
return testData;
}
@DataProvider(name = "StreamTestData<Integer>.small")
public static Object[][] makeSmallStreamTestData() {
return testSmallData;
}
@DataProvider(name = "StreamTestData<Integer>.mini")
public static Object[][] makeMiniStreamTestData() {
return testMiniData;
}
@DataProvider(name = "withNull:StreamTestData<Integer>")
public static Object[][] makeStreamWithNullTestData() {
return withNullTestData;
}
// returns an array of (String name, Supplier<Spliterator<Integer>>)
@DataProvider(name = "Spliterator<Integer>")
public static Object[][] spliteratorProvider() {
return spliteratorTestData;
}
}

View file

@ -0,0 +1,279 @@
/*
* Copyright (c) 2012, 2017, 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 java.util.stream;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Spliterator;
import java.util.SpliteratorTestHelper;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Test scenarios for reference streams.
*
* Each scenario is provided with a data source, a function that maps a fresh
* stream (as provided by the data source) to a new stream, and a sink to
* receive results. Each scenario describes a different way of computing the
* stream contents. The test driver will ensure that all scenarios produce
* the same output (modulo allowable differences in ordering).
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public enum StreamTestScenario implements OpTestCase.BaseStreamTestScenario {
STREAM_FOR_EACH(false) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
Stream<U> s = m.apply(source);
if (s.isParallel()) {
s = s.sequential();
}
s.forEach(b);
}
},
// Collec to list
STREAM_COLLECT(false) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
for (U t : m.apply(source).collect(Collectors.toList())) {
b.accept(t);
}
}
},
// To array
STREAM_TO_ARRAY(false) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
for (Object t : m.apply(source).toArray()) {
b.accept((U) t);
}
}
},
// Wrap as stream, and iterate in pull mode
STREAM_ITERATOR(false) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
for (Iterator<U> seqIter = m.apply(source).iterator(); seqIter.hasNext(); )
b.accept(seqIter.next());
}
},
// Wrap as stream, and spliterate then iterate in pull mode
STREAM_SPLITERATOR(false) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
for (Spliterator<U> spl = m.apply(source).spliterator(); spl.tryAdvance(b); ) {
}
}
},
// Wrap as stream, spliterate, then split a few times mixing advances with forEach
STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(source).spliterator());
}
},
// Wrap as stream, and spliterate then iterate in pull mode
STREAM_SPLITERATOR_FOREACH(false) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
m.apply(source).spliterator().forEachRemaining(b);
}
},
// Wrap as parallel stream + sequential
PAR_STREAM_SEQUENTIAL_FOR_EACH(true) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
m.apply(source).sequential().forEach(b);
}
},
// Wrap as parallel stream + forEachOrdered
PAR_STREAM_FOR_EACH_ORDERED(true) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
// @@@ Want to explicitly select ordered equalator
m.apply(source).forEachOrdered(b);
}
},
// Wrap as stream, and spliterate then iterate sequentially
PAR_STREAM_SPLITERATOR(true) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
for (Spliterator<U> spl = m.apply(source).spliterator(); spl.tryAdvance(b); ) {
}
}
},
// Wrap as stream, and spliterate then iterate sequentially
PAR_STREAM_SPLITERATOR_FOREACH(true) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
m.apply(source).spliterator().forEachRemaining(b);
}
},
// Wrap as parallel stream + toArray
PAR_STREAM_TO_ARRAY(true) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
for (Object t : m.apply(source).toArray())
b.accept((U) t);
}
},
// Wrap as parallel stream, get the spliterator, wrap as a stream + toArray
PAR_STREAM_SPLITERATOR_STREAM_TO_ARRAY(true) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
Stream<U> s = m.apply(source);
Spliterator<U> sp = s.spliterator();
Stream<U> ss = StreamSupport.stream(() -> sp,
StreamOpFlag.toCharacteristics(OpTestCase.getStreamFlags(s))
| (sp.getExactSizeIfKnown() < 0 ? 0 : Spliterator.SIZED), true);
for (Object t : ss.toArray())
b.accept((U) t);
}
},
// Wrap as parallel stream + toArray and clear SIZED flag
PAR_STREAM_TO_ARRAY_CLEAR_SIZED(true) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
S_IN pipe1 = (S_IN) OpTestCase.chain(source,
new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape()));
Stream<U> pipe2 = m.apply(pipe1);
for (Object t : pipe2.toArray())
b.accept((U) t);
}
},
// Wrap as parallel + collect to list
PAR_STREAM_COLLECT_TO_LIST(true) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
for (U u : m.apply(source).collect(Collectors.toList()))
b.accept(u);
}
},
// Wrap sequential as parallel, + collect to list
STREAM_TO_PAR_STREAM_COLLECT_TO_LIST(true) {
public <T, S_IN extends BaseStream<T, S_IN>>
S_IN getStream(TestData<T, S_IN> data) {
return data.stream().parallel();
}
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
for (U u : m.apply(source).collect(Collectors.toList()))
b.accept(u);
}
},
// Wrap parallel as sequential,, + collect
PAR_STREAM_TO_STREAM_COLLECT_TO_LIST(true) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
for (U u : m.apply(source).collect(Collectors.toList()))
b.accept(u);
}
},
// Wrap as parallel stream + forEach synchronizing
PAR_STREAM_FOR_EACH(true, false) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
m.apply(source).forEach(e -> {
synchronized (data) {
b.accept(e);
}
});
}
},
// Wrap as parallel stream + forEach synchronizing and clear SIZED flag
PAR_STREAM_FOR_EACH_CLEAR_SIZED(true, false) {
<T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m) {
S_IN pipe1 = (S_IN) OpTestCase.chain(source,
new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape()));
m.apply(pipe1).forEach(e -> {
synchronized (data) {
b.accept(e);
}
});
}
},
;
// The set of scenarios that clean the SIZED flag
public static final Set<StreamTestScenario> CLEAR_SIZED_SCENARIOS = Collections.unmodifiableSet(
EnumSet.of(PAR_STREAM_TO_ARRAY_CLEAR_SIZED, PAR_STREAM_FOR_EACH_CLEAR_SIZED));
private final boolean isParallel;
private final boolean isOrdered;
StreamTestScenario(boolean isParallel) {
this(isParallel, true);
}
StreamTestScenario(boolean isParallel, boolean isOrdered) {
this.isParallel = isParallel;
this.isOrdered = isOrdered;
}
public StreamShape getShape() {
return StreamShape.REFERENCE;
}
public boolean isParallel() {
return isParallel;
}
public boolean isOrdered() {
return isOrdered;
}
public <T, U, S_IN extends BaseStream<T, S_IN>, S_OUT extends BaseStream<U, S_OUT>>
void run(TestData<T, S_IN> data, Consumer<U> b, Function<S_IN, S_OUT> m) {
try (S_IN source = getStream(data)) {
run(data, source, b, (Function<S_IN, Stream<U>>) m);
}
}
abstract <T, U, S_IN extends BaseStream<T, S_IN>>
void run(TestData<T, S_IN> data, S_IN source, Consumer<U> b, Function<S_IN, Stream<U>> m);
}

View file

@ -0,0 +1,355 @@
/*
* 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 java.util.stream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.Spliterators;
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.ToIntFunction;
/** Describes a test data set for use in stream tests */
public interface TestData<T, S extends BaseStream<T, S>>
extends Iterable<T> {
default int size() {
throw new UnsupportedOperationException();
}
@Override
default Iterator<T> iterator() {
return Spliterators.iterator(spliterator());
}
Spliterator<T> spliterator();
default boolean isOrdered() {
return spliterator().hasCharacteristics(Spliterator.ORDERED);
}
StreamShape getShape();
default <A extends Collection<? super T>> A into(A target) {
spliterator().forEachRemaining(target::add);
return target;
}
S stream();
S parallelStream();
public interface OfRef<T> extends TestData<T, Stream<T>> { }
public interface OfInt extends TestData<Integer, IntStream> { }
public interface OfLong extends TestData<Long, LongStream> { }
public interface OfDouble extends TestData<Double, DoubleStream> { }
// @@@ Temporary garbage class to avoid triggering bugs with lambdas in static methods in interfaces
public static class Factory {
public static <T> OfRef<T> ofArray(String name, T[] array) {
return new AbstractTestData.RefTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(),
Arrays::spliterator, a -> a.length);
}
public static <T> OfRef<T> ofCollection(String name, Collection<T> collection) {
return new AbstractTestData.RefTestData<>(name, collection, Collection::stream, Collection::parallelStream,
Collection::spliterator, Collection::size);
}
public static <T> OfRef<T> ofSpinedBuffer(String name, SpinedBuffer<T> buffer) {
return new AbstractTestData.RefTestData<>(name, buffer,
b -> StreamSupport.stream(b.spliterator(), false),
b -> StreamSupport.stream(b.spliterator(), true),
SpinedBuffer::spliterator,
b -> (int) b.count());
}
public static <T> OfRef<T> ofSupplier(String name, Supplier<Stream<T>> supplier) {
return new AbstractTestData.RefTestData<>(name, supplier,
Supplier::get,
s -> s.get().parallel(),
s -> s.get().spliterator(),
s -> (int) s.get().spliterator().getExactSizeIfKnown());
}
public static <T> OfRef<T> ofRefNode(String name, Node<T> node) {
return new AbstractTestData.RefTestData<>(name, node,
n -> StreamSupport.stream(n::spliterator, Spliterator.SIZED | Spliterator.ORDERED, false),
n -> StreamSupport.stream(n::spliterator, Spliterator.SIZED | Spliterator.ORDERED, true),
Node::spliterator,
n -> (int) n.count());
}
// int factories
public static <T> OfInt ofArray(String name, int[] array) {
return new AbstractTestData.IntTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(),
Arrays::spliterator, a -> a.length);
}
public static OfInt ofSpinedBuffer(String name, SpinedBuffer.OfInt buffer) {
return new AbstractTestData.IntTestData<>(name, buffer,
b -> StreamSupport.intStream(b.spliterator(), false),
b -> StreamSupport.intStream(b.spliterator(), true),
SpinedBuffer.OfInt::spliterator,
b -> (int) b.count());
}
public static OfInt ofIntSupplier(String name, Supplier<IntStream> supplier) {
return new AbstractTestData.IntTestData<>(name, supplier,
Supplier::get,
s -> s.get().parallel(),
s -> s.get().spliterator(),
s -> (int) s.get().spliterator().getExactSizeIfKnown());
}
public static OfInt ofNode(String name, Node.OfInt node) {
int characteristics = Spliterator.SIZED | Spliterator.ORDERED;
return new AbstractTestData.IntTestData<>(name, node,
n -> StreamSupport.intStream(n::spliterator, characteristics, false),
n -> StreamSupport.intStream(n::spliterator, characteristics, true),
Node.OfInt::spliterator,
n -> (int) n.count());
}
// long factories
public static <T> OfLong ofArray(String name, long[] array) {
return new AbstractTestData.LongTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(),
Arrays::spliterator, a -> a.length);
}
public static OfLong ofSpinedBuffer(String name, SpinedBuffer.OfLong buffer) {
return new AbstractTestData.LongTestData<>(name, buffer,
b -> StreamSupport.longStream(b.spliterator(), false),
b -> StreamSupport.longStream(b.spliterator(), true),
SpinedBuffer.OfLong::spliterator,
b -> (int) b.count());
}
public static OfLong ofLongSupplier(String name, Supplier<LongStream> supplier) {
return new AbstractTestData.LongTestData<>(name, supplier,
Supplier::get,
s -> s.get().parallel(),
s -> s.get().spliterator(),
s -> (int) s.get().spliterator().getExactSizeIfKnown());
}
public static OfLong ofNode(String name, Node.OfLong node) {
int characteristics = Spliterator.SIZED | Spliterator.ORDERED;
return new AbstractTestData.LongTestData<>(name, node,
n -> StreamSupport.longStream(n::spliterator, characteristics, false),
n -> StreamSupport.longStream(n::spliterator, characteristics, true),
Node.OfLong::spliterator,
n -> (int) n.count());
}
// double factories
public static <T> OfDouble ofArray(String name, double[] array) {
return new AbstractTestData.DoubleTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(),
Arrays::spliterator, a -> a.length);
}
public static OfDouble ofSpinedBuffer(String name, SpinedBuffer.OfDouble buffer) {
return new AbstractTestData.DoubleTestData<>(name, buffer,
b -> StreamSupport.doubleStream(b.spliterator(), false),
b -> StreamSupport.doubleStream(b.spliterator(), true),
SpinedBuffer.OfDouble::spliterator,
b -> (int) b.count());
}
public static OfDouble ofDoubleSupplier(String name, Supplier<DoubleStream> supplier) {
return new AbstractTestData.DoubleTestData<>(name, supplier,
Supplier::get,
s -> s.get().parallel(),
s -> s.get().spliterator(),
s -> (int) s.get().spliterator().getExactSizeIfKnown());
}
public static OfDouble ofNode(String name, Node.OfDouble node) {
int characteristics = Spliterator.SIZED | Spliterator.ORDERED;
return new AbstractTestData.DoubleTestData<>(name, node,
n -> StreamSupport.doubleStream(n::spliterator, characteristics, false),
n -> StreamSupport.doubleStream(n::spliterator, characteristics, true),
Node.OfDouble::spliterator,
n -> (int) n.count());
}
}
abstract class AbstractTestData<T, S extends BaseStream<T, S>,
T_STATE,
T_SPLITR extends Spliterator<T>>
implements TestData<T, S> {
private final String name;
private final StreamShape shape;
protected final T_STATE state;
private final ToIntFunction<T_STATE> sizeFn;
private final Function<T_STATE, S> streamFn;
private final Function<T_STATE, S> parStreamFn;
private final Function<T_STATE, T_SPLITR> splitrFn;
AbstractTestData(String name,
StreamShape shape,
T_STATE state,
Function<T_STATE, S> streamFn,
Function<T_STATE, S> parStreamFn,
Function<T_STATE, T_SPLITR> splitrFn,
ToIntFunction<T_STATE> sizeFn) {
this.name = name;
this.shape = shape;
this.state = state;
this.streamFn = streamFn;
this.parStreamFn = parStreamFn;
this.splitrFn = splitrFn;
this.sizeFn = sizeFn;
}
@Override
public StreamShape getShape() {
return shape;
}
@Override
public String toString() {
return getClass().getSimpleName() + "[" + name + "]";
}
@Override
public int size() {
return sizeFn.applyAsInt(state);
}
@Override
public T_SPLITR spliterator() {
return splitrFn.apply(state);
}
@Override
public S stream() {
return streamFn.apply(state);
}
@Override
public S parallelStream() {
return parStreamFn.apply(state);
}
public static class RefTestData<T, I>
extends AbstractTestData<T, Stream<T>, I, Spliterator<T>>
implements TestData.OfRef<T> {
protected RefTestData(String name,
I state,
Function<I, Stream<T>> streamFn,
Function<I, Stream<T>> parStreamFn,
Function<I, Spliterator<T>> splitrFn,
ToIntFunction<I> sizeFn) {
super(name, StreamShape.REFERENCE, state, streamFn, parStreamFn, splitrFn, sizeFn);
}
}
static class IntTestData<I>
extends AbstractTestData<Integer, IntStream, I, Spliterator.OfInt>
implements TestData.OfInt {
protected IntTestData(String name,
I state,
Function<I, IntStream> streamFn,
Function<I, IntStream> parStreamFn,
Function<I, Spliterator.OfInt> splitrFn,
ToIntFunction<I> sizeFn) {
super(name, StreamShape.INT_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn);
}
@Override
public PrimitiveIterator.OfInt iterator() {
return Spliterators.iterator(spliterator());
}
@Override
public <A extends Collection<? super Integer>> A into(A target) {
spliterator().forEachRemaining((IntConsumer) target::add);
return target;
}
}
static class LongTestData<I>
extends AbstractTestData<Long, LongStream, I, Spliterator.OfLong>
implements TestData.OfLong {
protected LongTestData(String name,
I state,
Function<I, LongStream> streamFn,
Function<I, LongStream> parStreamFn,
Function<I, Spliterator.OfLong> splitrFn,
ToIntFunction<I> sizeFn) {
super(name, StreamShape.LONG_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn);
}
@Override
public PrimitiveIterator.OfLong iterator() {
return Spliterators.iterator(spliterator());
}
@Override
public <A extends Collection<? super Long>> A into(A target) {
spliterator().forEachRemaining((LongConsumer) target::add);
return target;
}
}
static class DoubleTestData<I>
extends AbstractTestData<Double, DoubleStream, I, Spliterator.OfDouble>
implements OfDouble {
protected DoubleTestData(String name,
I state,
Function<I, DoubleStream> streamFn,
Function<I, DoubleStream> parStreamFn,
Function<I, Spliterator.OfDouble> splitrFn,
ToIntFunction<I> sizeFn) {
super(name, StreamShape.DOUBLE_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn);
}
@Override
public PrimitiveIterator.OfDouble iterator() {
return Spliterators.iterator(spliterator());
}
@Override
public <A extends Collection<? super Double>> A into(A target) {
spliterator().forEachRemaining((DoubleConsumer) target::add);
return target;
}
}
}
}

View file

@ -0,0 +1,125 @@
/*
* 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 java.util.stream;
import org.testng.Assert;
import java.util.EnumSet;
class TestFlagExpectedOp<T> extends FlagDeclaringOp<T> {
static class Builder<T> {
final int flags;
StreamShape shape = StreamShape.REFERENCE;
EnumSet<StreamOpFlag> known = EnumSet.noneOf(StreamOpFlag.class);
EnumSet<StreamOpFlag> preserve = EnumSet.noneOf(StreamOpFlag.class);
EnumSet<StreamOpFlag> notKnown = EnumSet.noneOf(StreamOpFlag.class);
Builder(int flags) {
this.flags = flags;
}
Builder<T> known(EnumSet<StreamOpFlag> known) {
this.known = known;
return this;
}
Builder<T> preserve(EnumSet<StreamOpFlag> preserve) {
this.preserve = preserve;
return this;
}
Builder<T> notKnown(EnumSet<StreamOpFlag> notKnown) {
this.notKnown = notKnown;
return this;
}
Builder<T> shape(StreamShape shape) {
this.shape = shape;
return this;
}
TestFlagExpectedOp<T> build() {
return new TestFlagExpectedOp<>(flags, known, preserve, notKnown, shape);
}
}
final EnumSet<StreamOpFlag> known;
final EnumSet<StreamOpFlag> preserve;
final EnumSet<StreamOpFlag> notKnown;
final StreamShape shape;
TestFlagExpectedOp(int flags,
EnumSet<StreamOpFlag> known,
EnumSet<StreamOpFlag> preserve,
EnumSet<StreamOpFlag> notKnown) {
this(flags, known, preserve, notKnown, StreamShape.REFERENCE);
}
TestFlagExpectedOp(int flags,
EnumSet<StreamOpFlag> known,
EnumSet<StreamOpFlag> preserve,
EnumSet<StreamOpFlag> notKnown,
StreamShape shape) {
super(flags);
this.known = known;
this.preserve = preserve;
this.notKnown = notKnown;
this.shape = shape;
}
@Override
public StreamShape outputShape() {
return shape;
}
@Override
public StreamShape inputShape() {
return shape;
}
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public Sink<T> opWrapSink(int flags, boolean parallel, Sink upstream) {
assertFlags(flags);
return upstream;
}
private void assertFlags(int flags) {
for (StreamOpFlag f : known) {
Assert.assertTrue(f.isKnown(flags),
String.format("Flag %s is not known, but should be known.", f.toString()));
}
for (StreamOpFlag f : preserve) {
Assert.assertTrue(f.isPreserved(flags),
String.format("Flag %s is not preserved, but should be preserved.", f.toString()));
}
for (StreamOpFlag f : notKnown) {
Assert.assertFalse(f.isKnown(flags),
String.format("Flag %s is known, but should be not known.", f.toString()));
}
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2014, 2016, 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 java.util.stream;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
public final class ThrowableHelper {
public static void checkException(Class<? extends Exception> ce, Runnable r) {
Exception caught = null;
try {
r.run();
} catch (Exception e) {
caught = e;
}
assertNotNull(caught);
assertTrue(ce.isInstance(caught));
}
public static void checkNPE(Runnable r) {
checkException(NullPointerException.class, r);
}
public static void checkISE(Runnable r) {
checkException(IllegalStateException.class, r);
}
}