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