• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.openjdk.testlib.java.util.stream.LambdaTestHelpers;
26 import org.openjdk.testlib.java.util.stream.OpTestCase;
27 import org.openjdk.testlib.java.util.stream.StreamTestDataProvider;
28 import org.openjdk.testlib.java.util.stream.TestData;
29 
30 import org.testng.annotations.Test;
31 
32 import java.util.*;
33 import java.util.concurrent.atomic.AtomicInteger;
34 import java.util.function.Consumer;
35 import java.util.function.Function;
36 import java.util.stream.Collectors;
37 import java.util.stream.DoubleStream;
38 import java.util.stream.IntStream;
39 import java.util.stream.LongStream;
40 import java.util.stream.Stream;
41 import java.util.stream.StreamSupport;
42 
43 import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.*;
44 
45 /**
46  * SliceOpTest
47  *
48  * @author Brian Goetz
49  */
50 @Test
51 public class SliceOpTest extends OpTestCase {
52 
testSkip()53     public void testSkip() {
54         assertCountSum(countTo(0).stream().skip(0), 0, 0);
55         assertCountSum(countTo(0).stream().skip(4), 0, 0);
56         assertCountSum(countTo(4).stream().skip(4), 0, 0);
57         assertCountSum(countTo(4).stream().skip(2), 2, 7);
58         assertCountSum(countTo(4).stream().skip(0), 4, 10);
59 
60         assertCountSum(countTo(0).parallelStream().skip(0), 0, 0);
61         assertCountSum(countTo(0).parallelStream().skip(4), 0, 0);
62         assertCountSum(countTo(4).parallelStream().skip(4), 0, 0);
63         assertCountSum(countTo(4).parallelStream().skip(2), 2, 7);
64         assertCountSum(countTo(4).parallelStream().skip(0), 4, 10);
65 
66         exerciseOps(Collections.emptyList(), s -> s.skip(0), Collections.emptyList());
67         exerciseOps(Collections.emptyList(), s -> s.skip(10), Collections.emptyList());
68 
69         exerciseOps(countTo(1), s -> s.skip(0), countTo(1));
70         exerciseOps(countTo(1), s -> s.skip(1), Collections.emptyList());
71         exerciseOps(countTo(100), s -> s.skip(0), countTo(100));
72         exerciseOps(countTo(100), s -> s.skip(10), range(11, 100));
73         exerciseOps(countTo(100), s -> s.skip(100), Collections.emptyList());
74         exerciseOps(countTo(100), s -> s.skip(200), Collections.emptyList());
75     }
76 
testLimit()77     public void testLimit() {
78         assertCountSum(countTo(0).stream().limit(4), 0, 0);
79         assertCountSum(countTo(2).stream().limit(4), 2, 3);
80         assertCountSum(countTo(4).stream().limit(4), 4, 10);
81         assertCountSum(countTo(8).stream().limit(4), 4, 10);
82 
83         assertCountSum(countTo(0).parallelStream().limit(4), 0, 0);
84         assertCountSum(countTo(2).parallelStream().limit(4), 2, 3);
85         assertCountSum(countTo(4).parallelStream().limit(4), 4, 10);
86         assertCountSum(countTo(8).parallelStream().limit(4), 4, 10);
87 
88         exerciseOps(Collections.emptyList(), s -> s.limit(0), Collections.emptyList());
89         exerciseOps(Collections.emptyList(), s -> s.limit(10), Collections.emptyList());
90         exerciseOps(countTo(1), s -> s.limit(0), Collections.emptyList());
91         exerciseOps(countTo(1), s -> s.limit(1), countTo(1));
92         exerciseOps(countTo(100), s -> s.limit(0), Collections.emptyList());
93         exerciseOps(countTo(100), s -> s.limit(10), countTo(10));
94         exerciseOps(countTo(100), s -> s.limit(10).limit(10), countTo(10));
95         exerciseOps(countTo(100), s -> s.limit(100), countTo(100));
96         exerciseOps(countTo(100), s -> s.limit(100).limit(10), countTo(10));
97         exerciseOps(countTo(100), s -> s.limit(200), countTo(100));
98     }
99 
testSkipLimit()100     public void testSkipLimit() {
101         exerciseOps(Collections.emptyList(), s -> s.skip(0).limit(0), Collections.emptyList());
102         exerciseOps(Collections.emptyList(), s -> s.skip(0).limit(10), Collections.emptyList());
103         exerciseOps(Collections.emptyList(), s -> s.skip(10).limit(0), Collections.emptyList());
104         exerciseOps(Collections.emptyList(), s -> s.skip(10).limit(10), Collections.emptyList());
105 
106         exerciseOps(countTo(100), s -> s.skip(0).limit(100), countTo(100));
107         exerciseOps(countTo(100), s -> s.skip(0).limit(10), countTo(10));
108         exerciseOps(countTo(100), s -> s.skip(0).limit(0), Collections.emptyList());
109         exerciseOps(countTo(100), s -> s.skip(10).limit(100), range(11, 100));
110         exerciseOps(countTo(100), s -> s.skip(10).limit(10), range(11, 20));
111         exerciseOps(countTo(100), s -> s.skip(10).limit(0), Collections.emptyList());
112         exerciseOps(countTo(100), s -> s.skip(100).limit(100), Collections.emptyList());
113         exerciseOps(countTo(100), s -> s.skip(100).limit(10), Collections.emptyList());
114         exerciseOps(countTo(100), s -> s.skip(100).limit(0), Collections.emptyList());
115         exerciseOps(countTo(100), s -> s.skip(200).limit(100), Collections.emptyList());
116         exerciseOps(countTo(100), s -> s.skip(200).limit(10), Collections.emptyList());
117         exerciseOps(countTo(100), s -> s.skip(200).limit(0), Collections.emptyList());
118     }
119 
testSlice()120     public void testSlice() {
121         exerciseOps(Collections.emptyList(), s -> s.skip(0).limit(0), Collections.emptyList());
122         exerciseOps(Collections.emptyList(), s -> s.skip(0).limit(10), Collections.emptyList());
123         exerciseOps(Collections.emptyList(), s -> s.skip(10).limit(10), Collections.emptyList());
124         exerciseOps(Collections.emptyList(), s -> s.skip(10).limit(20), Collections.emptyList());
125 
126         exerciseOps(countTo(100), s -> s.skip(0).limit(100), countTo(100));
127         exerciseOps(countTo(100), s -> s.skip(0).limit(10), countTo(10));
128         exerciseOps(countTo(100), s -> s.skip(0).limit(0), Collections.emptyList());
129         exerciseOps(countTo(100), s -> s.skip(10).limit(100), range(11, 100));
130         exerciseOps(countTo(100), s -> s.skip(10).limit(10), range(11, 20));
131         exerciseOps(countTo(100), s -> s.skip(10).limit(0), Collections.emptyList());
132         exerciseOps(countTo(100), s -> s.skip(100).limit(100), Collections.emptyList());
133         exerciseOps(countTo(100), s -> s.skip(100).limit(10), Collections.emptyList());
134         exerciseOps(countTo(100), s -> s.skip(100).limit(0), Collections.emptyList());
135         exerciseOps(countTo(100), s -> s.skip(200).limit(100), Collections.emptyList());
136         exerciseOps(countTo(100), s -> s.skip(200).limit(10), Collections.emptyList());
137         exerciseOps(countTo(100), s -> s.skip(200).limit(0), Collections.emptyList());
138     }
139 
sliceSize(int dataSize, int skip, int limit)140     private int sliceSize(int dataSize, int skip, int limit) {
141         int size = Math.max(0, dataSize - skip);
142         if (limit >= 0)
143             size = Math.min(size, limit);
144         return size;
145     }
146 
sliceSize(int dataSize, int skip)147     private int sliceSize(int dataSize, int skip) {
148         return Math.max(0, dataSize - skip);
149     }
150 
151     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class,
152           groups = { "serialization-hostile" })
testSkipOps(String name, TestData.OfRef<Integer> data)153     public void testSkipOps(String name, TestData.OfRef<Integer> data) {
154         List<Integer> skips = sizes(data.size());
155 
156         for (int s : skips) {
157             setContext("skip", s);
158             testSliceMulti(data,
159                            sliceSize(data.size(), s),
160                            st -> st.skip(s),
161                            st -> st.skip(s),
162                            st -> st.skip(s),
163                            st -> st.skip(s));
164 
165             testSliceMulti(data,
166                            sliceSize(sliceSize(data.size(), s), s/2),
167                            st -> st.skip(s).skip(s / 2),
168                            st -> st.skip(s).skip(s / 2),
169                            st -> st.skip(s).skip(s / 2),
170                            st -> st.skip(s).skip(s / 2));
171         }
172     }
173 
174     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class,
175           groups = { "serialization-hostile" })
testSkipLimitOps(String name, TestData.OfRef<Integer> data)176     public void testSkipLimitOps(String name, TestData.OfRef<Integer> data) {
177         List<Integer> skips = sizes(data.size());
178         List<Integer> limits = skips;
179 
180         for (int s : skips) {
181             setContext("skip", s);
182             for (int l : limits) {
183                 setContext("limit", l);
184                 testSliceMulti(data,
185                                sliceSize(sliceSize(data.size(), s), 0, l),
186                                st -> st.skip(s).limit(l),
187                                st -> st.skip(s).limit(l),
188                                st -> st.skip(s).limit(l),
189                                st -> st.skip(s).limit(l));
190             }
191         }
192     }
193 
testSkipLimitOpsWithNonSplittingSpliterator()194     public void testSkipLimitOpsWithNonSplittingSpliterator() {
195         class NonSplittingNotSubsizedOrderedSpliterator<T> implements Spliterator<T> {
196             Spliterator<T> s;
197 
198             NonSplittingNotSubsizedOrderedSpliterator(Spliterator<T> s) {
199                 assert s.hasCharacteristics(Spliterator.ORDERED);
200                 this.s = s;
201             }
202 
203             @Override
204             public boolean tryAdvance(Consumer<? super T> action) {
205                 return s.tryAdvance(action);
206             }
207 
208             @Override
209             public void forEachRemaining(Consumer<? super T> action) {
210                 s.forEachRemaining(action);
211             }
212 
213             @Override
214             public Spliterator<T> trySplit() {
215                 return null;
216             }
217 
218             @Override
219             public long estimateSize() {
220                 return s.estimateSize();
221             }
222 
223             @Override
224             public int characteristics() {
225                 return s.characteristics() & ~(Spliterator.SUBSIZED);
226             }
227 
228             @Override
229             public Comparator<? super T> getComparator() {
230                 return s.getComparator();
231             }
232         }
233         List<Integer> list = IntStream.range(0, 100).boxed().collect(Collectors.toList());
234         TestData.OfRef<Integer> data = TestData.Factory.ofSupplier(
235                 "Non splitting, not SUBSIZED, ORDERED, stream",
236                 () -> StreamSupport.stream(new NonSplittingNotSubsizedOrderedSpliterator<>(list.spliterator()), false));
237 
238         testSkipLimitOps("testSkipLimitOpsWithNonSplittingSpliterator", data);
239     }
240 
241     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class,
242           groups = { "serialization-hostile" })
testLimitOps(String name, TestData.OfRef<Integer> data)243     public void testLimitOps(String name, TestData.OfRef<Integer> data) {
244         List<Integer> limits = sizes(data.size());
245 
246         for (int l : limits) {
247             setContext("limit", l);
248             testSliceMulti(data,
249                            sliceSize(data.size(), 0, l),
250                            st -> st.limit(l),
251                            st -> st.limit(l),
252                            st -> st.limit(l),
253                            st -> st.limit(l));
254         }
255 
256         for (int l : limits) {
257             setContext("limit", l);
258             testSliceMulti(data,
259                            sliceSize(sliceSize(data.size(), 0, l), 0, l / 2),
260                            st -> st.limit(l).limit(l / 2),
261                            st -> st.limit(l).limit(l / 2),
262                            st -> st.limit(l).limit(l / 2),
263                            st -> st.limit(l).limit(l / 2));
264         }
265     }
266 
sliceResultAsserter(Iterable<Integer> data, int expectedSize)267     private ResultAsserter<Iterable<Integer>> sliceResultAsserter(Iterable<Integer> data,
268                                                                   int expectedSize) {
269         return (act, exp, ord, par) -> {
270             if (par & !ord) {
271                 List<Integer> expected = new ArrayList<>();
272                 data.forEach(expected::add);
273 
274                 List<Integer> actual = new ArrayList<>();
275                 act.forEach(actual::add);
276 
277                 assertEquals(actual.size(), expectedSize);
278                 assertTrue(expected.containsAll(actual));
279             }
280             else {
281                 LambdaTestHelpers.assertContents(act, exp);
282             }
283         };
284     }
285 
286     private void testSliceMulti(TestData.OfRef<Integer> data,
287                                 int expectedSize,
288                                 Function<Stream<Integer>, Stream<Integer>> mRef,
289                                 Function<IntStream, IntStream> mInt,
290                                 Function<LongStream, LongStream> mLong,
291                                 Function<DoubleStream, DoubleStream> mDouble) {
292 
293         @SuppressWarnings({ "rawtypes", "unchecked" })
294         Function<Stream<Integer>, Stream<Integer>>[] ms = new Function[4];
295         ms[0] = mRef;
296         ms[1] = s -> mInt.apply(s.mapToInt(e -> e)).mapToObj(e -> e);
297         ms[2] = s -> mLong.apply(s.mapToLong(e -> e)).mapToObj(e -> (int) e);
298         ms[3] = s -> mDouble.apply(s.mapToDouble(e -> e)).mapToObj(e -> (int) e);
299         testSliceMulti(data, expectedSize, ms);
300     }
301 
302     @SafeVarargs
303     private final void testSliceMulti(TestData.OfRef<Integer> data,
304                                       int expectedSize,
305                                       Function<Stream<Integer>, Stream<Integer>>... ms) {
306         for (int i = 0; i < ms.length; i++) {
307             setContext("mIndex", i);
308             Function<Stream<Integer>, Stream<Integer>> m = ms[i];
309             Collection<Integer> sr = withData(data)
310                     .stream(m)
311                     .resultAsserter(sliceResultAsserter(data, expectedSize))
312                     .exercise();
313             assertEquals(sr.size(), expectedSize);
314         }
315     }
316 
317     public void testLimitSort() {
318         List<Integer> l = countTo(100);
319         Collections.reverse(l);
320         exerciseOps(l, s -> s.limit(10).sorted(Comparator.naturalOrder()));
321     }
322 
323     @Test(groups = { "serialization-hostile" })
324     public void testLimitShortCircuit() {
325         for (int l : Arrays.asList(0, 10)) {
326             setContext("l", l);
327             AtomicInteger ai = new AtomicInteger();
328             countTo(100).stream()
329                     .peek(i -> ai.getAndIncrement())
330                     .limit(l).toArray();
331             // For the case of a zero limit, one element will get pushed through the sink chain
332             assertEquals(ai.get(), l, "tee block was called too many times");
333         }
334     }
335 
336     private List<Integer> sizes(int size) {
337         if (size < 4) {
338             return Arrays.asList(0, 1, 2, 3, 4, 6);
339         }
340         else {
341             return Arrays.asList(0, 1, size / 2, size - 1, size, size + 1, 2 * size);
342         }
343     }
344 }
345