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 org.openjdk.tests.java.util.stream;
  24 
  25 import org.testng.annotations.DataProvider;
  26 import org.testng.annotations.Test;
  27 
  28 import java.lang.reflect.InvocationHandler;
  29 import java.lang.reflect.Method;
  30 import java.lang.reflect.Proxy;
  31 import java.util.ArrayList;
  32 import java.util.List;
  33 import java.util.Spliterator;
  34 import java.util.function.Function;
  35 import java.util.function.UnaryOperator;
  36 import java.util.stream.DoubleStream;
  37 import java.util.stream.DoubleStreamTestScenario;
  38 import java.util.stream.IntStream;
  39 import java.util.stream.IntStreamTestScenario;
  40 import java.util.stream.LambdaTestHelpers;
  41 import java.util.stream.LongStream;
  42 import java.util.stream.LongStreamTestScenario;
  43 import java.util.stream.OpTestCase;
  44 import java.util.stream.Stream;
  45 import java.util.stream.StreamSupport;
  46 import java.util.stream.StreamTestScenario;
  47 import java.util.stream.TestData;
  48 
  49 import static java.util.stream.LambdaTestHelpers.assertUnique;
  50 
  51 
  52 @Test
  53 public class InfiniteStreamWithLimitOpTest extends OpTestCase {
  54 
  55     private static final long SKIP_LIMIT_SIZE = 1 << 16;
  56 
  57     @DataProvider(name = "Stream.limit")
  58     @SuppressWarnings("rawtypes")
  59     public static Object[][] sliceFunctionsDataProvider() {
  60         Function<String, String> f = s -> String.format(s, SKIP_LIMIT_SIZE);
  61 
  62         List<Object[]> data = new ArrayList<>();
  63 
  64         data.add(new Object[]{f.apply("Stream.limit(%d)"),
  65                 (UnaryOperator<Stream>) s -> s.limit(SKIP_LIMIT_SIZE)});
  66         data.add(new Object[]{f.apply("Stream.substream(%d)"),
  67                 (UnaryOperator<Stream>) s -> s.substream(SKIP_LIMIT_SIZE, SKIP_LIMIT_SIZE * 2)});
  68         data.add(new Object[]{f.apply("Stream.substream(%1$d).limit(%1$d)"),
  69                 (UnaryOperator<Stream>) s -> s.substream(SKIP_LIMIT_SIZE).limit(SKIP_LIMIT_SIZE)});
  70 
  71         return data.toArray(new Object[0][]);
  72     }
  73 
  74     @DataProvider(name = "IntStream.limit")
  75     public static Object[][] intSliceFunctionsDataProvider() {
  76         Function<String, String> f = s -> String.format(s, SKIP_LIMIT_SIZE);
  77 
  78         List<Object[]> data = new ArrayList<>();
  79 
  80         data.add(new Object[]{f.apply("IntStream.limit(%d)"),
  81                 (UnaryOperator<IntStream>) s -> s.limit(SKIP_LIMIT_SIZE)});
  82         data.add(new Object[]{f.apply("IntStream.substream(%d)"),
  83                 (UnaryOperator<IntStream>) s -> s.substream(SKIP_LIMIT_SIZE, SKIP_LIMIT_SIZE * 2)});
  84         data.add(new Object[]{f.apply("IntStream.substream(%1$d).limit(%1$d)"),
  85                 (UnaryOperator<IntStream>) s -> s.substream(SKIP_LIMIT_SIZE).limit(SKIP_LIMIT_SIZE)});
  86 
  87         return data.toArray(new Object[0][]);
  88     }
  89 
  90     @DataProvider(name = "LongStream.limit")
  91     public static Object[][] longSliceFunctionsDataProvider() {
  92         Function<String, String> f = s -> String.format(s, SKIP_LIMIT_SIZE);
  93 
  94         List<Object[]> data = new ArrayList<>();
  95 
  96         data.add(new Object[]{f.apply("LongStream.limit(%d)"),
  97                 (UnaryOperator<LongStream>) s -> s.limit(SKIP_LIMIT_SIZE)});
  98         data.add(new Object[]{f.apply("LongStream.substream(%d)"),
  99                 (UnaryOperator<LongStream>) s -> s.substream(SKIP_LIMIT_SIZE, SKIP_LIMIT_SIZE * 2)});
 100         data.add(new Object[]{f.apply("LongStream.substream(%1$d).limit(%1$d)"),
 101                 (UnaryOperator<LongStream>) s -> s.substream(SKIP_LIMIT_SIZE).limit(SKIP_LIMIT_SIZE)});
 102 
 103         return data.toArray(new Object[0][]);
 104     }
 105 
 106     @DataProvider(name = "DoubleStream.limit")
 107     public static Object[][] doubleSliceFunctionsDataProvider() {
 108         Function<String, String> f = s -> String.format(s, SKIP_LIMIT_SIZE);
 109 
 110         List<Object[]> data = new ArrayList<>();
 111 
 112         data.add(new Object[]{f.apply("DoubleStream.limit(%d)"),
 113                 (UnaryOperator<DoubleStream>) s -> s.limit(SKIP_LIMIT_SIZE)});
 114         data.add(new Object[]{f.apply("DoubleStream.substream(%d)"),
 115                 (UnaryOperator<DoubleStream>) s -> s.substream(SKIP_LIMIT_SIZE, SKIP_LIMIT_SIZE * 2)});
 116         data.add(new Object[]{f.apply("DoubleStream.substream(%1$d).limit(%1$d)"),
 117                 (UnaryOperator<DoubleStream>) s -> s.substream(SKIP_LIMIT_SIZE).limit(SKIP_LIMIT_SIZE)});
 118 
 119         return data.toArray(new Object[0][]);
 120     }
 121 
 122     private <T> ResultAsserter<Iterable<T>> unorderedAsserter() {
 123         return (act, exp, ord, par) -> {
 124             if (par & !ord) {
 125                 // Can only assert that all elements of the actual result
 126                 // are distinct and that the count is the limit size
 127                 // any element within the range [0, Long.MAX_VALUE) may be
 128                 // present
 129                 assertUnique(act);
 130                 long count = 0;
 131                 for (T l : act) {
 132                     count++;
 133                 }
 134                 assertEquals(count, SKIP_LIMIT_SIZE, "size not equal");
 135             }
 136             else {
 137                 LambdaTestHelpers.assertContents(act, exp);
 138             }
 139         };
 140     }
 141 
 142     private TestData.OfRef<Long> refLongs() {
 143         return refLongRange(0, Long.MAX_VALUE);
 144     }
 145 
 146     private TestData.OfRef<Long> refLongRange(long l, long u) {
 147         return TestData.Factory.ofSupplier(
 148                 String.format("[%d, %d)", l, u),
 149                 () -> LongStream.range(l, u).boxed());
 150     }
 151 
 152     private TestData.OfInt ints() {
 153         return intRange(0, Integer.MAX_VALUE);
 154     }
 155 
 156     private TestData.OfInt intRange(int l, int u) {
 157         return TestData.Factory.ofIntSupplier(
 158                 String.format("[%d, %d)", l, u),
 159                 () -> IntStream.range(l, u));
 160     }
 161 
 162     private TestData.OfLong longs() {
 163         return longRange(0, Long.MAX_VALUE);
 164     }
 165 
 166     private TestData.OfLong longRange(long l, long u) {
 167         return TestData.Factory.ofLongSupplier(
 168                 String.format("[%d, %d)", l, u),
 169                 () -> LongStream.range(l, u));
 170     }
 171 
 172     private TestData.OfDouble doubles() {
 173         return doubleRange(0, 1L << 53);
 174     }
 175 
 176     private TestData.OfDouble doubleRange(long l, long u) {
 177         return TestData.Factory.ofDoubleSupplier(
 178                 String.format("[%d, %d)", l, u),
 179                 () -> LongStream.range(l, u).mapToDouble(i -> (double) i));
 180     }
 181 
 182 
 183     // Sized/subsized range
 184 
 185     @Test(dataProvider = "Stream.limit")
 186     public void testSubsizedWithRange(String description, UnaryOperator<Stream<Long>> fs) {
 187         // Range is [0, Long.MAX_VALUE), splits are SUBSIZED
 188         // Such a size will induce out of memory errors for incorrect
 189         // slice implementations
 190         withData(refLongs()).
 191                 stream(s -> fs.apply(s)).
 192                 without(StreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED).
 193                 exercise();
 194     }
 195 
 196     @Test(dataProvider = "IntStream.limit")
 197     public void testIntSubsizedWithRange(String description, UnaryOperator<IntStream> fs) {
 198         // Range is [0, Integer.MAX_VALUE), splits are SUBSIZED
 199         // Such a size will induce out of memory errors for incorrect
 200         // slice implementations
 201         withData(ints()).
 202                 stream(s -> fs.apply(s)).
 203                 without(IntStreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED).
 204                 exercise();
 205     }
 206 
 207     @Test(dataProvider = "LongStream.limit")
 208     public void testLongSubsizedWithRange(String description, UnaryOperator<LongStream> fs) {
 209         // Range is [0, Long.MAX_VALUE), splits are SUBSIZED
 210         // Such a size will induce out of memory errors for incorrect
 211         // slice implementations
 212         withData(longs()).
 213                 stream(s -> fs.apply(s)).
 214                 without(LongStreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED).
 215                 exercise();
 216     }
 217 
 218     @Test(dataProvider = "DoubleStream.limit")
 219     public void testDoubleSubsizedWithRange(String description, UnaryOperator<DoubleStream> fs) {
 220         // Range is [0, 2^53), splits are SUBSIZED
 221         // Such a size will induce out of memory errors for incorrect
 222         // slice implementations
 223         withData(doubles()).
 224                 stream(s -> fs.apply(s)).
 225                 without(DoubleStreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED).
 226                 exercise();
 227     }
 228 
 229 
 230     // Unordered finite not SIZED/SUBSIZED
 231 
 232     @Test(dataProvider = "Stream.limit")
 233     public void testUnorderedFinite(String description, UnaryOperator<Stream<Long>> fs) {
 234         // Range is [0, Long.MAX_VALUE), splits are SUBSIZED
 235         // Such a size will induce out of memory errors for incorrect
 236         // slice implementations
 237         withData(longs()).
 238                 stream(s -> fs.apply(s.filter(i -> true).unordered().boxed())).
 239                 resultAsserter(unorderedAsserter()).
 240                 exercise();
 241     }
 242 
 243     @Test(dataProvider = "IntStream.limit")
 244     public void testIntUnorderedFinite(String description, UnaryOperator<IntStream> fs) {
 245         // Range is [0, Integer.MAX_VALUE), splits are SUBSIZED
 246         // Such a size will induce out of memory errors for incorrect
 247         // slice implementations
 248         withData(ints()).
 249                 stream(s -> fs.apply(s.filter(i -> true).unordered())).
 250                 resultAsserter(unorderedAsserter()).
 251                 exercise();
 252     }
 253 
 254     @Test(dataProvider = "LongStream.limit")
 255     public void testLongUnorderedFinite(String description, UnaryOperator<LongStream> fs) {
 256         // Range is [0, Long.MAX_VALUE), splits are SUBSIZED
 257         // Such a size will induce out of memory errors for incorrect
 258         // slice implementations
 259         withData(longs()).
 260                 stream(s -> fs.apply(s.filter(i -> true).unordered())).
 261                 resultAsserter(unorderedAsserter()).
 262                 exercise();
 263     }
 264 
 265     @Test(dataProvider = "DoubleStream.limit")
 266     public void testDoubleUnorderedFinite(String description, UnaryOperator<DoubleStream> fs) {
 267         // Range is [0, 1L << 53), splits are SUBSIZED
 268         // Such a size will induce out of memory errors for incorrect
 269         // slice implementations
 270         // Upper bound ensures values mapped to doubles will be unique
 271         withData(doubles()).
 272                 stream(s -> fs.apply(s.filter(i -> true).unordered())).
 273                 resultAsserter(unorderedAsserter()).
 274                 exercise();
 275     }
 276 
 277 
 278     // Unordered finite not SUBSIZED
 279 
 280     @SuppressWarnings({"rawtypes", "unchecked"})
 281     private Spliterator.OfLong proxyNotSubsized(Spliterator.OfLong s) {
 282         InvocationHandler ih = new InvocationHandler() {
 283             @Override
 284             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 285                 switch (method.getName()) {
 286                     case "characteristics": {
 287                         int c = (Integer) method.invoke(s, args);
 288                         return c & ~Spliterator.SUBSIZED;
 289                     }
 290                     case "hasCharacteristics": {
 291                         int c = (Integer) args[0];
 292                         boolean b = (Boolean) method.invoke(s, args);
 293                         return b & ((c & Spliterator.SUBSIZED) == 0);
 294                     }
 295                     default:
 296                         return method.invoke(s, args);
 297                 }
 298             }
 299         };
 300 
 301         return (Spliterator.OfLong) Proxy.newProxyInstance(this.getClass().getClassLoader(),
 302                                                            new Class[]{Spliterator.OfLong.class},
 303                                                            ih);
 304     }
 305 
 306     private TestData.OfLong proxiedLongRange(long l, long u) {
 307         return TestData.Factory.ofLongSupplier(
 308                 String.format("[%d, %d)", l, u),
 309                 () -> StreamSupport.longStream(proxyNotSubsized(LongStream.range(l, u).spliterator()), false));
 310     }
 311 
 312     @Test(dataProvider = "Stream.limit")
 313     public void testUnorderedSizedNotSubsizedFinite(String description, UnaryOperator<Stream<Long>> fs) {
 314         // Range is [0, Long.MAX_VALUE), splits are not SUBSIZED (proxy clears
 315         // the SUBSIZED characteristic)
 316         // Such a size will induce out of memory errors for incorrect
 317         // slice implementations
 318         withData(proxiedLongRange(0, Long.MAX_VALUE)).
 319                 stream(s -> fs.apply(s.unordered().boxed())).
 320                 resultAsserter(unorderedAsserter()).
 321                 exercise();
 322     }
 323 
 324     @Test(dataProvider = "IntStream.limit")
 325     public void testIntUnorderedSizedNotSubsizedFinite(String description, UnaryOperator<IntStream> fs) {
 326         // Range is [0, Integer.MAX_VALUE), splits are not SUBSIZED (proxy clears
 327         // the SUBSIZED characteristic)
 328         // Such a size will induce out of memory errors for incorrect
 329         // slice implementations
 330         withData(proxiedLongRange(0, Integer.MAX_VALUE)).
 331                 stream(s -> fs.apply(s.unordered().mapToInt(i -> (int) i))).
 332                 resultAsserter(unorderedAsserter()).
 333                 exercise();
 334     }
 335 
 336     @Test(dataProvider = "LongStream.limit")
 337     public void testLongUnorderedSizedNotSubsizedFinite(String description, UnaryOperator<LongStream> fs) {
 338         // Range is [0, Long.MAX_VALUE), splits are not SUBSIZED (proxy clears
 339         // the SUBSIZED characteristic)
 340         // Such a size will induce out of memory errors for incorrect
 341         // slice implementations
 342         withData(proxiedLongRange(0, Long.MAX_VALUE)).
 343                 stream(s -> fs.apply(s.unordered())).
 344                 resultAsserter(unorderedAsserter()).
 345                 exercise();
 346     }
 347 
 348     @Test(dataProvider = "DoubleStream.limit")
 349     public void testDoubleUnorderedSizedNotSubsizedFinite(String description, UnaryOperator<DoubleStream> fs) {
 350         // Range is [0, Double.MAX_VALUE), splits are not SUBSIZED (proxy clears
 351         // the SUBSIZED characteristic)
 352         // Such a size will induce out of memory errors for incorrect
 353         // slice implementations
 354         withData(proxiedLongRange(0, 1L << 53)).
 355                 stream(s -> fs.apply(s.unordered().mapToDouble(i -> (double) i))).
 356                 resultAsserter(unorderedAsserter()).
 357                 exercise();
 358     }
 359 
 360 
 361     // Unordered generation
 362 
 363     @Test(dataProvider = "Stream.limit")
 364     public void testUnorderedGenerator(String description, UnaryOperator<Stream<Long>> fs) {
 365         // Source is spliterator of infinite size
 366         TestData.OfRef<Long> generator = TestData.Factory.ofSupplier(
 367                 "[1L, 1L, ...]", () -> Stream.generate(() -> 1L));
 368 
 369         withData(generator).
 370                 stream(s -> fs.apply(s.filter(i -> true).unordered())).
 371                 exercise();
 372     }
 373 
 374     @Test(dataProvider = "IntStream.limit")
 375     public void testIntUnorderedGenerator(String description, UnaryOperator<IntStream> fs) {
 376         // Source is spliterator of infinite size
 377         TestData.OfInt generator = TestData.Factory.ofIntSupplier(
 378                 "[1, 1, ...]", () -> IntStream.generate(() -> 1));
 379 
 380         withData(generator).
 381                 stream(s -> fs.apply(s.filter(i -> true).unordered())).
 382                 exercise();
 383     }
 384 
 385     @Test(dataProvider = "LongStream.limit")
 386     public void testLongUnorderedGenerator(String description, UnaryOperator<LongStream> fs) {
 387         // Source is spliterator of infinite size
 388         TestData.OfLong generator = TestData.Factory.ofLongSupplier(
 389                 "[1L, 1L, ...]", () -> LongStream.generate(() -> 1));
 390 
 391         withData(generator).
 392                 stream(s -> fs.apply(s.filter(i -> true).unordered())).
 393                 exercise();
 394     }
 395 
 396     @Test(dataProvider = "DoubleStream.limit")
 397     public void testDoubleUnorderedGenerator(String description, UnaryOperator<DoubleStream> fs) {
 398         // Source is spliterator of infinite size
 399         TestData.OfDouble generator = TestData.Factory.ofDoubleSupplier(
 400                 "[1.0, 1.0, ...]", () -> DoubleStream.generate(() -> 1.0));
 401 
 402         withData(generator).
 403                 stream(s -> fs.apply(s.filter(i -> true).unordered())).
 404                 exercise();
 405     }
 406 
 407 
 408     // Unordered iteration
 409 
 410     @Test(dataProvider = "Stream.limit")
 411     public void testUnorderedIteration(String description, UnaryOperator<Stream<Long>> fs) {
 412         // Source is a right-balanced tree of infinite size
 413         TestData.OfRef<Long> iterator = TestData.Factory.ofSupplier(
 414                 "[1L, 2L, 3L, ...]", () -> Stream.iterate(1L, i -> i + 1L));
 415 
 416         // Ref
 417         withData(iterator).
 418                 stream(s -> fs.apply(s.unordered())).
 419                 resultAsserter(unorderedAsserter()).
 420                 exercise();
 421     }
 422 
 423     @Test(dataProvider = "IntStream.limit")
 424     public void testIntUnorderedIteration(String description, UnaryOperator<IntStream> fs) {
 425         // Source is a right-balanced tree of infinite size
 426         TestData.OfInt iterator = TestData.Factory.ofIntSupplier(
 427                 "[1, 2, 3, ...]", () -> IntStream.iterate(1, i -> i + 1));
 428 
 429         // Ref
 430         withData(iterator).
 431                 stream(s -> fs.apply(s.unordered())).
 432                 resultAsserter(unorderedAsserter()).
 433                 exercise();
 434     }
 435 
 436     @Test(dataProvider = "LongStream.limit")
 437     public void testLongUnorderedIteration(String description, UnaryOperator<LongStream> fs) {
 438         // Source is a right-balanced tree of infinite size
 439         TestData.OfLong iterator = TestData.Factory.ofLongSupplier(
 440                 "[1L, 2L, 3L, ...]", () -> LongStream.iterate(1, i -> i + 1));
 441 
 442         // Ref
 443         withData(iterator).
 444                 stream(s -> fs.apply(s.unordered())).
 445                 resultAsserter(unorderedAsserter()).
 446                 exercise();
 447     }
 448 
 449     @Test(dataProvider = "DoubleStream.limit")
 450     public void testDoubleUnorderedIteration(String description, UnaryOperator<DoubleStream> fs) {
 451         // Source is a right-balanced tree of infinite size
 452         TestData.OfDouble iterator = TestData.Factory.ofDoubleSupplier(
 453                 "[1.0, 2.0, 3.0, ...]", () -> DoubleStream.iterate(1, i -> i + 1));
 454 
 455         // Ref
 456         withData(iterator).
 457                 stream(s -> fs.apply(s.unordered())).
 458                 resultAsserter(unorderedAsserter()).
 459                 exercise();
 460     }
 461 }