1 /*
2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 package java.util.stream;
24 
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Iterator;
28 import java.util.PrimitiveIterator;
29 import java.util.Spliterator;
30 import java.util.Spliterators;
31 import java.util.function.DoubleConsumer;
32 import java.util.function.Function;
33 import java.util.function.IntConsumer;
34 import java.util.function.LongConsumer;
35 import java.util.function.Supplier;
36 import java.util.function.ToIntFunction;
37 
38 /** Describes a test data set for use in stream tests */
39 public interface TestData<T, S extends BaseStream<T, S>>
40         extends Iterable<T> {
41 
size()42     default int size() {
43         throw new UnsupportedOperationException();
44     }
45 
46     @Override
iterator()47     default Iterator<T> iterator() {
48         return Spliterators.iterator(spliterator());
49     }
50 
spliterator()51     Spliterator<T> spliterator();
52 
isOrdered()53     default boolean isOrdered() {
54         return spliterator().hasCharacteristics(Spliterator.ORDERED);
55     }
56 
getShape()57     StreamShape getShape();
58 
into(A target)59     default <A extends Collection<? super T>> A into(A target) {
60         spliterator().forEachRemaining(target::add);
61         return target;
62     }
63 
stream()64     S stream();
65 
parallelStream()66     S parallelStream();
67 
68     public interface OfRef<T> extends TestData<T, Stream<T>> { }
69 
70     public interface OfInt extends TestData<Integer, IntStream> { }
71 
72     public interface OfLong extends TestData<Long, LongStream> { }
73 
74     public interface OfDouble extends TestData<Double, DoubleStream> { }
75 
76     // @@@ Temporary garbage class to avoid triggering bugs with lambdas in static methods in interfaces
77     public static class Factory {
ofArray(String name, T[] array)78         public static <T> OfRef<T> ofArray(String name, T[] array) {
79             return new AbstractTestData.RefTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(),
80                                                       Arrays::spliterator, a -> a.length);
81         }
82 
ofCollection(String name, Collection<T> collection)83         public static <T> OfRef<T> ofCollection(String name, Collection<T> collection) {
84             return new AbstractTestData.RefTestData<>(name, collection, Collection::stream, Collection::parallelStream,
85                                                       Collection::spliterator, Collection::size);
86         }
87 
ofSpinedBuffer(String name, SpinedBuffer<T> buffer)88         public static <T> OfRef<T> ofSpinedBuffer(String name, SpinedBuffer<T> buffer) {
89             return new AbstractTestData.RefTestData<>(name, buffer,
90                                                       b -> StreamSupport.stream(b.spliterator(), false),
91                                                       b -> StreamSupport.stream(b.spliterator(), true),
92                                                       SpinedBuffer::spliterator,
93                                                       b -> (int) b.count());
94         }
95 
ofSupplier(String name, Supplier<Stream<T>> supplier)96         public static <T> OfRef<T> ofSupplier(String name, Supplier<Stream<T>> supplier) {
97             return new AbstractTestData.RefTestData<>(name, supplier,
98                                                       Supplier::get,
99                                                       s -> s.get().parallel(),
100                                                       s -> s.get().spliterator(),
101                                                       s -> (int) s.get().spliterator().getExactSizeIfKnown());
102         }
103 
ofRefNode(String name, Node<T> node)104         public static <T> OfRef<T> ofRefNode(String name, Node<T> node) {
105             return new AbstractTestData.RefTestData<>(name, node,
106                                                       n -> StreamSupport.stream(n::spliterator, Spliterator.SIZED | Spliterator.ORDERED, false),
107                                                       n -> StreamSupport.stream(n::spliterator, Spliterator.SIZED | Spliterator.ORDERED, true),
108                                                       Node::spliterator,
109                                                       n -> (int) n.count());
110         }
111 
112         // int factories
ofArray(String name, int[] array)113         public static <T> OfInt ofArray(String name, int[] array) {
114             return new AbstractTestData.IntTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(),
115                                                       Arrays::spliterator, a -> a.length);
116         }
117 
ofSpinedBuffer(String name, SpinedBuffer.OfInt buffer)118         public static OfInt ofSpinedBuffer(String name, SpinedBuffer.OfInt buffer) {
119             return new AbstractTestData.IntTestData<>(name, buffer,
120                                                       b -> StreamSupport.intStream(b.spliterator(), false),
121                                                       b -> StreamSupport.intStream(b.spliterator(), true),
122                                                       SpinedBuffer.OfInt::spliterator,
123                                                       b -> (int) b.count());
124         }
125 
ofIntSupplier(String name, Supplier<IntStream> supplier)126         public static OfInt ofIntSupplier(String name, Supplier<IntStream> supplier) {
127             return new AbstractTestData.IntTestData<>(name, supplier,
128                                                       Supplier::get,
129                                                       s -> s.get().parallel(),
130                                                       s -> s.get().spliterator(),
131                                                       s -> (int) s.get().spliterator().getExactSizeIfKnown());
132         }
133 
ofNode(String name, Node.OfInt node)134         public static OfInt ofNode(String name, Node.OfInt node) {
135             int characteristics = Spliterator.SIZED | Spliterator.ORDERED;
136             return new AbstractTestData.IntTestData<>(name, node,
137                                                       n -> StreamSupport.intStream(n::spliterator, characteristics, false),
138                                                       n -> StreamSupport.intStream(n::spliterator, characteristics, true),
139                                                       Node.OfInt::spliterator,
140                                                       n -> (int) n.count());
141         }
142 
143         // long factories
ofArray(String name, long[] array)144         public static <T> OfLong ofArray(String name, long[] array) {
145             return new AbstractTestData.LongTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(),
146                                                        Arrays::spliterator, a -> a.length);
147         }
148 
ofSpinedBuffer(String name, SpinedBuffer.OfLong buffer)149         public static OfLong ofSpinedBuffer(String name, SpinedBuffer.OfLong buffer) {
150             return new AbstractTestData.LongTestData<>(name, buffer,
151                                                       b -> StreamSupport.longStream(b.spliterator(), false),
152                                                       b -> StreamSupport.longStream(b.spliterator(), true),
153                                                       SpinedBuffer.OfLong::spliterator,
154                                                       b -> (int) b.count());
155         }
156 
ofLongSupplier(String name, Supplier<LongStream> supplier)157         public static OfLong ofLongSupplier(String name, Supplier<LongStream> supplier) {
158             return new AbstractTestData.LongTestData<>(name, supplier,
159                                                       Supplier::get,
160                                                       s -> s.get().parallel(),
161                                                       s -> s.get().spliterator(),
162                                                       s -> (int) s.get().spliterator().getExactSizeIfKnown());
163         }
164 
ofNode(String name, Node.OfLong node)165         public static OfLong ofNode(String name, Node.OfLong node) {
166             int characteristics = Spliterator.SIZED | Spliterator.ORDERED;
167             return new AbstractTestData.LongTestData<>(name, node,
168                                                       n -> StreamSupport.longStream(n::spliterator, characteristics, false),
169                                                       n -> StreamSupport.longStream(n::spliterator, characteristics, true),
170                                                       Node.OfLong::spliterator,
171                                                       n -> (int) n.count());
172         }
173 
174         // double factories
ofArray(String name, double[] array)175         public static <T> OfDouble ofArray(String name, double[] array) {
176             return new AbstractTestData.DoubleTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(),
177                                                          Arrays::spliterator, a -> a.length);
178         }
179 
ofSpinedBuffer(String name, SpinedBuffer.OfDouble buffer)180         public static OfDouble ofSpinedBuffer(String name, SpinedBuffer.OfDouble buffer) {
181             return new AbstractTestData.DoubleTestData<>(name, buffer,
182                                                          b -> StreamSupport.doubleStream(b.spliterator(), false),
183                                                          b -> StreamSupport.doubleStream(b.spliterator(), true),
184                                                          SpinedBuffer.OfDouble::spliterator,
185                                                          b -> (int) b.count());
186         }
187 
ofDoubleSupplier(String name, Supplier<DoubleStream> supplier)188         public static OfDouble ofDoubleSupplier(String name, Supplier<DoubleStream> supplier) {
189             return new AbstractTestData.DoubleTestData<>(name, supplier,
190                                                          Supplier::get,
191                                                          s -> s.get().parallel(),
192                                                          s -> s.get().spliterator(),
193                                                          s -> (int) s.get().spliterator().getExactSizeIfKnown());
194         }
195 
ofNode(String name, Node.OfDouble node)196         public static OfDouble ofNode(String name, Node.OfDouble node) {
197             int characteristics = Spliterator.SIZED | Spliterator.ORDERED;
198             return new AbstractTestData.DoubleTestData<>(name, node,
199                                                          n -> StreamSupport.doubleStream(n::spliterator, characteristics, false),
200                                                          n -> StreamSupport.doubleStream(n::spliterator, characteristics, true),
201                                                          Node.OfDouble::spliterator,
202                                                          n -> (int) n.count());
203         }
204     }
205 
206 
207     abstract class AbstractTestData<T, S extends BaseStream<T, S>,
208             T_STATE,
209                                     T_SPLITR extends Spliterator<T>>
210             implements TestData<T, S> {
211         private final String name;
212         private final StreamShape shape;
213         protected final T_STATE state;
214         private final ToIntFunction<T_STATE> sizeFn;
215         private final Function<T_STATE, S> streamFn;
216         private final Function<T_STATE, S> parStreamFn;
217         private final Function<T_STATE, T_SPLITR> splitrFn;
218 
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)219         AbstractTestData(String name,
220                          StreamShape shape,
221                          T_STATE state,
222                          Function<T_STATE, S> streamFn,
223                          Function<T_STATE, S> parStreamFn,
224                          Function<T_STATE, T_SPLITR> splitrFn,
225                          ToIntFunction<T_STATE> sizeFn) {
226             this.name = name;
227             this.shape = shape;
228             this.state = state;
229             this.streamFn = streamFn;
230             this.parStreamFn = parStreamFn;
231             this.splitrFn = splitrFn;
232             this.sizeFn = sizeFn;
233         }
234 
235         @Override
getShape()236         public StreamShape getShape() {
237             return shape;
238         }
239 
240         @Override
toString()241         public String toString() {
242             return getClass().getSimpleName() + "[" + name + "]";
243         }
244 
245         @Override
size()246         public int size() {
247             return sizeFn.applyAsInt(state);
248         }
249 
250         @Override
spliterator()251         public T_SPLITR spliterator() {
252             return splitrFn.apply(state);
253         }
254 
255         @Override
stream()256         public S stream() {
257             return streamFn.apply(state);
258         }
259 
260         @Override
parallelStream()261         public S parallelStream() {
262             return parStreamFn.apply(state);
263         }
264 
265         public static class RefTestData<T, I>
266                 extends AbstractTestData<T, Stream<T>, I, Spliterator<T>>
267                 implements TestData.OfRef<T> {
268 
RefTestData(String name, I state, Function<I, Stream<T>> streamFn, Function<I, Stream<T>> parStreamFn, Function<I, Spliterator<T>> splitrFn, ToIntFunction<I> sizeFn)269             protected RefTestData(String name,
270                                   I state,
271                                   Function<I, Stream<T>> streamFn,
272                                   Function<I, Stream<T>> parStreamFn,
273                                   Function<I, Spliterator<T>> splitrFn,
274                                   ToIntFunction<I> sizeFn) {
275                 super(name, StreamShape.REFERENCE, state, streamFn, parStreamFn, splitrFn, sizeFn);
276             }
277 
278         }
279 
280         static class IntTestData<I>
281                 extends AbstractTestData<Integer, IntStream, I, Spliterator.OfInt>
282                 implements TestData.OfInt {
283 
IntTestData(String name, I state, Function<I, IntStream> streamFn, Function<I, IntStream> parStreamFn, Function<I, Spliterator.OfInt> splitrFn, ToIntFunction<I> sizeFn)284             protected IntTestData(String name,
285                                   I state,
286                                   Function<I, IntStream> streamFn,
287                                   Function<I, IntStream> parStreamFn,
288                                   Function<I, Spliterator.OfInt> splitrFn,
289                                   ToIntFunction<I> sizeFn) {
290                 super(name, StreamShape.INT_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn);
291             }
292 
293             @Override
iterator()294             public PrimitiveIterator.OfInt iterator() {
295                 return Spliterators.iterator(spliterator());
296             }
297 
298             @Override
into(A target)299             public <A extends Collection<? super Integer>> A into(A target) {
300                 spliterator().forEachRemaining((IntConsumer) target::add);
301                 return target;
302             }
303         }
304 
305         static class LongTestData<I>
306                 extends AbstractTestData<Long, LongStream, I, Spliterator.OfLong>
307                 implements TestData.OfLong {
308 
LongTestData(String name, I state, Function<I, LongStream> streamFn, Function<I, LongStream> parStreamFn, Function<I, Spliterator.OfLong> splitrFn, ToIntFunction<I> sizeFn)309             protected LongTestData(String name,
310                                    I state,
311                                    Function<I, LongStream> streamFn,
312                                    Function<I, LongStream> parStreamFn,
313                                    Function<I, Spliterator.OfLong> splitrFn,
314                                    ToIntFunction<I> sizeFn) {
315                 super(name, StreamShape.LONG_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn);
316             }
317 
318             @Override
iterator()319             public PrimitiveIterator.OfLong iterator() {
320                 return Spliterators.iterator(spliterator());
321             }
322 
323             @Override
into(A target)324             public <A extends Collection<? super Long>> A into(A target) {
325                 spliterator().forEachRemaining((LongConsumer) target::add);
326                 return target;
327             }
328         }
329 
330         static class DoubleTestData<I>
331                 extends AbstractTestData<Double, DoubleStream, I, Spliterator.OfDouble>
332                 implements OfDouble {
333 
DoubleTestData(String name, I state, Function<I, DoubleStream> streamFn, Function<I, DoubleStream> parStreamFn, Function<I, Spliterator.OfDouble> splitrFn, ToIntFunction<I> sizeFn)334             protected DoubleTestData(String name,
335                                      I state,
336                                      Function<I, DoubleStream> streamFn,
337                                      Function<I, DoubleStream> parStreamFn,
338                                      Function<I, Spliterator.OfDouble> splitrFn,
339                                      ToIntFunction<I> sizeFn) {
340                 super(name, StreamShape.DOUBLE_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn);
341             }
342 
343             @Override
iterator()344             public PrimitiveIterator.OfDouble iterator() {
345                 return Spliterators.iterator(spliterator());
346             }
347 
348             @Override
into(A target)349             public <A extends Collection<? super Double>> A into(A target) {
350                 spliterator().forEachRemaining((DoubleConsumer) target::add);
351                 return target;
352             }
353         }
354     }
355 }
356