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