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