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