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 */
23package java.util.stream;
24
25import java.util.Arrays;
26import java.util.Collection;
27import java.util.Iterator;
28import java.util.PrimitiveIterator;
29import java.util.Spliterator;
30import java.util.Spliterators;
31import java.util.function.DoubleConsumer;
32import java.util.function.Function;
33import java.util.function.IntConsumer;
34import java.util.function.LongConsumer;
35import java.util.function.Supplier;
36import java.util.function.ToIntFunction;
37
38/** Describes a test data set for use in stream tests */
39public interface TestData<T, S extends BaseStream<T, S>>
40        extends Iterable<T> {
41
42    default int size() {
43        throw new UnsupportedOperationException();
44    }
45
46    @Override
47    default Iterator<T> iterator() {
48        return Spliterators.iterator(spliterator());
49    }
50
51    Spliterator<T> spliterator();
52
53    default boolean isOrdered() {
54        return spliterator().hasCharacteristics(Spliterator.ORDERED);
55    }
56
57    StreamShape getShape();
58
59    default <A extends Collection<? super T>> A into(A target) {
60        spliterator().forEachRemaining(target::add);
61        return target;
62    }
63
64    S stream();
65
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 {
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
236        public StreamShape getShape() {
237            return shape;
238        }
239
240        @Override
241        public String toString() {
242            return getClass().getSimpleName() + "[" + name + "]";
243        }
244
245        @Override
246        public int size() {
247            return sizeFn.applyAsInt(state);
248        }
249
250        @Override
251        public T_SPLITR spliterator() {
252            return splitrFn.apply(state);
253        }
254
255        @Override
256        public S stream() {
257            return streamFn.apply(state);
258        }
259
260        @Override
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
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
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
294            public PrimitiveIterator.OfInt iterator() {
295                return Spliterators.iterator(spliterator());
296            }
297
298            @Override
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
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
319            public PrimitiveIterator.OfLong iterator() {
320                return Spliterators.iterator(spliterator());
321            }
322
323            @Override
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
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
344            public PrimitiveIterator.OfDouble iterator() {
345                return Spliterators.iterator(spliterator());
346            }
347
348            @Override
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