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 org.openjdk.testlib.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; 37import java.util.stream.*; 38 39/** Describes a test data set for use in stream tests */ 40public interface TestData<T, S extends BaseStream<T, S>> 41 extends Iterable<T> { 42 43 default int size() { 44 throw new UnsupportedOperationException(); 45 } 46 47 @Override 48 default Iterator<T> iterator() { 49 return Spliterators.iterator(spliterator()); 50 } 51 52 Spliterator<T> spliterator(); 53 54 default boolean isOrdered() { 55 return spliterator().hasCharacteristics(Spliterator.ORDERED); 56 } 57 58 StreamShape getShape(); 59 60 default <A extends Collection<? super T>> A into(A target) { 61 spliterator().forEachRemaining(target::add); 62 return target; 63 } 64 65 S stream(); 66 67 S parallelStream(); 68 69 public interface OfRef<T> extends TestData<T, Stream<T>> { } 70 71 public interface OfInt extends TestData<Integer, IntStream> { } 72 73 public interface OfLong extends TestData<Long, LongStream> { } 74 75 public interface OfDouble extends TestData<Double, DoubleStream> { } 76 77 // @@@ Temporary garbage class to avoid triggering bugs with lambdas in static methods in interfaces 78 public static class Factory { 79 public static <T> OfRef<T> ofArray(String name, T[] array) { 80 return new AbstractTestData.RefTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(), 81 Arrays::spliterator, a -> a.length); 82 } 83 84 public static <T> OfRef<T> ofCollection(String name, Collection<T> collection) { 85 return new AbstractTestData.RefTestData<>(name, collection, Collection::stream, Collection::parallelStream, 86 Collection::spliterator, Collection::size); 87 } 88 89 public static <T> OfRef<T> ofSpinedBuffer(String name, SpinedBuffer<T> buffer) { 90 return new AbstractTestData.RefTestData<>(name, buffer, 91 b -> StreamSupport.stream(b.spliterator(), false), 92 b -> StreamSupport.stream(b.spliterator(), true), 93 SpinedBuffer::spliterator, 94 b -> (int) b.count()); 95 } 96 97 public static <T> OfRef<T> ofSupplier(String name, Supplier<Stream<T>> supplier) { 98 return new AbstractTestData.RefTestData<>(name, supplier, 99 Supplier::get, 100 s -> s.get().parallel(), 101 s -> s.get().spliterator(), 102 s -> (int) s.get().spliterator().getExactSizeIfKnown()); 103 } 104 105 public static <T> OfRef<T> ofRefNode(String name, Node<T> node) { 106 return new AbstractTestData.RefTestData<>(name, node, 107 n -> StreamSupport.stream(n::spliterator, Spliterator.SIZED | Spliterator.ORDERED, false), 108 n -> StreamSupport.stream(n::spliterator, Spliterator.SIZED | Spliterator.ORDERED, true), 109 Node::spliterator, 110 n -> (int) n.count()); 111 } 112 113 // int factories 114 public static <T> OfInt ofArray(String name, int[] array) { 115 return new AbstractTestData.IntTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(), 116 Arrays::spliterator, a -> a.length); 117 } 118 119 public static OfInt ofSpinedBuffer(String name, SpinedBuffer.OfInt buffer) { 120 return new AbstractTestData.IntTestData<>(name, buffer, 121 b -> StreamSupport.intStream(b.spliterator(), false), 122 b -> StreamSupport.intStream(b.spliterator(), true), 123 SpinedBuffer.OfInt::spliterator, 124 b -> (int) b.count()); 125 } 126 127 public static OfInt ofIntSupplier(String name, Supplier<IntStream> supplier) { 128 return new AbstractTestData.IntTestData<>(name, supplier, 129 Supplier::get, 130 s -> s.get().parallel(), 131 s -> s.get().spliterator(), 132 s -> (int) s.get().spliterator().getExactSizeIfKnown()); 133 } 134 135 public static OfInt ofNode(String name, Node.OfInt node) { 136 int characteristics = Spliterator.SIZED | Spliterator.ORDERED; 137 return new AbstractTestData.IntTestData<>(name, node, 138 n -> StreamSupport.intStream(n::spliterator, characteristics, false), 139 n -> StreamSupport.intStream(n::spliterator, characteristics, true), 140 Node.OfInt::spliterator, 141 n -> (int) n.count()); 142 } 143 144 // long factories 145 public static <T> OfLong ofArray(String name, long[] array) { 146 return new AbstractTestData.LongTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(), 147 Arrays::spliterator, a -> a.length); 148 } 149 150 public static OfLong ofSpinedBuffer(String name, SpinedBuffer.OfLong buffer) { 151 return new AbstractTestData.LongTestData<>(name, buffer, 152 b -> StreamSupport.longStream(b.spliterator(), false), 153 b -> StreamSupport.longStream(b.spliterator(), true), 154 SpinedBuffer.OfLong::spliterator, 155 b -> (int) b.count()); 156 } 157 158 public static OfLong ofLongSupplier(String name, Supplier<LongStream> supplier) { 159 return new AbstractTestData.LongTestData<>(name, supplier, 160 Supplier::get, 161 s -> s.get().parallel(), 162 s -> s.get().spliterator(), 163 s -> (int) s.get().spliterator().getExactSizeIfKnown()); 164 } 165 166 public static OfLong ofNode(String name, Node.OfLong node) { 167 int characteristics = Spliterator.SIZED | Spliterator.ORDERED; 168 return new AbstractTestData.LongTestData<>(name, node, 169 n -> StreamSupport.longStream(n::spliterator, characteristics, false), 170 n -> StreamSupport.longStream(n::spliterator, characteristics, true), 171 Node.OfLong::spliterator, 172 n -> (int) n.count()); 173 } 174 175 // double factories 176 public static <T> OfDouble ofArray(String name, double[] array) { 177 return new AbstractTestData.DoubleTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(), 178 Arrays::spliterator, a -> a.length); 179 } 180 181 public static OfDouble ofSpinedBuffer(String name, SpinedBuffer.OfDouble buffer) { 182 return new AbstractTestData.DoubleTestData<>(name, buffer, 183 b -> StreamSupport.doubleStream(b.spliterator(), false), 184 b -> StreamSupport.doubleStream(b.spliterator(), true), 185 SpinedBuffer.OfDouble::spliterator, 186 b -> (int) b.count()); 187 } 188 189 public static OfDouble ofDoubleSupplier(String name, Supplier<DoubleStream> supplier) { 190 return new AbstractTestData.DoubleTestData<>(name, supplier, 191 Supplier::get, 192 s -> s.get().parallel(), 193 s -> s.get().spliterator(), 194 s -> (int) s.get().spliterator().getExactSizeIfKnown()); 195 } 196 197 public static OfDouble ofNode(String name, Node.OfDouble node) { 198 int characteristics = Spliterator.SIZED | Spliterator.ORDERED; 199 return new AbstractTestData.DoubleTestData<>(name, node, 200 n -> StreamSupport.doubleStream(n::spliterator, characteristics, false), 201 n -> StreamSupport.doubleStream(n::spliterator, characteristics, true), 202 Node.OfDouble::spliterator, 203 n -> (int) n.count()); 204 } 205 } 206 207 208 abstract class AbstractTestData<T, S extends BaseStream<T, S>, 209 T_STATE, 210 T_SPLITR extends Spliterator<T>> 211 implements TestData<T, S> { 212 private final String name; 213 private final StreamShape shape; 214 protected final T_STATE state; 215 private final ToIntFunction<T_STATE> sizeFn; 216 private final Function<T_STATE, S> streamFn; 217 private final Function<T_STATE, S> parStreamFn; 218 private final Function<T_STATE, T_SPLITR> splitrFn; 219 220 AbstractTestData(String name, 221 StreamShape shape, 222 T_STATE state, 223 Function<T_STATE, S> streamFn, 224 Function<T_STATE, S> parStreamFn, 225 Function<T_STATE, T_SPLITR> splitrFn, 226 ToIntFunction<T_STATE> sizeFn) { 227 this.name = name; 228 this.shape = shape; 229 this.state = state; 230 this.streamFn = streamFn; 231 this.parStreamFn = parStreamFn; 232 this.splitrFn = splitrFn; 233 this.sizeFn = sizeFn; 234 } 235 236 @Override 237 public StreamShape getShape() { 238 return shape; 239 } 240 241 @Override 242 public String toString() { 243 return getClass().getSimpleName() + "[" + name + "]"; 244 } 245 246 @Override 247 public int size() { 248 return sizeFn.applyAsInt(state); 249 } 250 251 @Override 252 public T_SPLITR spliterator() { 253 return splitrFn.apply(state); 254 } 255 256 @Override 257 public S stream() { 258 return streamFn.apply(state); 259 } 260 261 @Override 262 public S parallelStream() { 263 return parStreamFn.apply(state); 264 } 265 266 public static class RefTestData<T, I> 267 extends AbstractTestData<T, Stream<T>, I, Spliterator<T>> 268 implements TestData.OfRef<T> { 269 270 protected RefTestData(String name, 271 I state, 272 Function<I, Stream<T>> streamFn, 273 Function<I, Stream<T>> parStreamFn, 274 Function<I, Spliterator<T>> splitrFn, 275 ToIntFunction<I> sizeFn) { 276 super(name, StreamShape.REFERENCE, state, streamFn, parStreamFn, splitrFn, sizeFn); 277 } 278 279 } 280 281 static class IntTestData<I> 282 extends AbstractTestData<Integer, IntStream, I, Spliterator.OfInt> 283 implements TestData.OfInt { 284 285 protected IntTestData(String name, 286 I state, 287 Function<I, IntStream> streamFn, 288 Function<I, IntStream> parStreamFn, 289 Function<I, Spliterator.OfInt> splitrFn, 290 ToIntFunction<I> sizeFn) { 291 super(name, StreamShape.INT_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn); 292 } 293 294 @Override 295 public PrimitiveIterator.OfInt iterator() { 296 return Spliterators.iterator(spliterator()); 297 } 298 299 @Override 300 public <A extends Collection<? super Integer>> A into(A target) { 301 spliterator().forEachRemaining((IntConsumer) target::add); 302 return target; 303 } 304 } 305 306 static class LongTestData<I> 307 extends AbstractTestData<Long, LongStream, I, Spliterator.OfLong> 308 implements TestData.OfLong { 309 310 protected LongTestData(String name, 311 I state, 312 Function<I, LongStream> streamFn, 313 Function<I, LongStream> parStreamFn, 314 Function<I, Spliterator.OfLong> splitrFn, 315 ToIntFunction<I> sizeFn) { 316 super(name, StreamShape.LONG_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn); 317 } 318 319 @Override 320 public PrimitiveIterator.OfLong iterator() { 321 return Spliterators.iterator(spliterator()); 322 } 323 324 @Override 325 public <A extends Collection<? super Long>> A into(A target) { 326 spliterator().forEachRemaining((LongConsumer) target::add); 327 return target; 328 } 329 } 330 331 static class DoubleTestData<I> 332 extends AbstractTestData<Double, DoubleStream, I, Spliterator.OfDouble> 333 implements OfDouble { 334 335 protected DoubleTestData(String name, 336 I state, 337 Function<I, DoubleStream> streamFn, 338 Function<I, DoubleStream> parStreamFn, 339 Function<I, Spliterator.OfDouble> splitrFn, 340 ToIntFunction<I> sizeFn) { 341 super(name, StreamShape.DOUBLE_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn); 342 } 343 344 @Override 345 public PrimitiveIterator.OfDouble iterator() { 346 return Spliterators.iterator(spliterator()); 347 } 348 349 @Override 350 public <A extends Collection<? super Double>> A into(A target) { 351 spliterator().forEachRemaining((DoubleConsumer) target::add); 352 return target; 353 } 354 } 355 } 356} 357