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