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 
  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 }