blob: 59c38f325662cb2c2e71138f64dbd0a96cd2ff04 [file] [log] [blame]
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.testlib.java.util.stream;
import 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;
import java.util.stream.*;
/** 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;
}
}
}
}