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 org.openjdk.testlib.java.util.stream.CollectorOps; 28 import org.openjdk.testlib.java.util.stream.DoubleStreamTestDataProvider; 29 import org.openjdk.testlib.java.util.stream.IntStreamTestDataProvider; 30 import org.openjdk.testlib.java.util.stream.LongStreamTestDataProvider; 31 import org.openjdk.testlib.java.util.stream.OpTestCase; 32 import org.openjdk.testlib.java.util.stream.StreamTestDataProvider; 33 import org.openjdk.testlib.java.util.stream.TestData; 34 35 import java.util.*; 36 import java.util.Spliterators; 37 import java.util.concurrent.atomic.AtomicInteger; 38 import java.util.function.BiFunction; 39 import java.util.function.Consumer; 40 import java.util.function.Function; 41 import java.util.function.Supplier; 42 import java.util.stream.BaseStream; 43 import java.util.stream.DoubleStream; 44 import java.util.stream.IntStream; 45 import java.util.stream.LongStream; 46 import java.util.stream.Stream; 47 import java.util.stream.StreamSupport; 48 49 import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.*; 50 import java.util.stream.*; 51 52 /** 53 * SortedOpTest 54 * 55 * @author Brian Goetz 56 */ 57 @Test 58 public class SortedOpTest extends OpTestCase { 59 testRefStreamTooLarge()60 public void testRefStreamTooLarge() { 61 Function<LongStream, Stream<Long>> f = s -> 62 // Clear the SORTED flag 63 s.mapToObj(i -> i) 64 .sorted(); 65 66 testStreamTooLarge(f, Stream::findFirst); 67 } 68 testIntStreamTooLarge()69 public void testIntStreamTooLarge() { 70 Function<LongStream, IntStream> f = s -> 71 // Clear the SORTED flag 72 s.mapToInt(i -> (int) i) 73 .sorted(); 74 75 testStreamTooLarge(f, IntStream::findFirst); 76 } 77 testLongStreamTooLarge()78 public void testLongStreamTooLarge() { 79 Function<LongStream, LongStream> f = s -> 80 // Clear the SORTED flag 81 s.map(i -> i) 82 .sorted(); 83 84 testStreamTooLarge(f, LongStream::findFirst); 85 } 86 testDoubleStreamTooLarge()87 public void testDoubleStreamTooLarge() { 88 Function<LongStream, DoubleStream> f = s -> 89 // Clear the SORTED flag 90 s.mapToDouble(i -> (double) i) 91 .sorted(); 92 93 testStreamTooLarge(f, DoubleStream::findFirst); 94 } 95 testStreamTooLarge(Function<LongStream, S> s, Function<S, ?> terminal)96 <T, S extends BaseStream<T, S>> void testStreamTooLarge(Function<LongStream, S> s, 97 Function<S, ?> terminal) { 98 // Set up conditions for a large input > maximum array size 99 Supplier<LongStream> input = () -> LongStream.range(0, 1L + Integer.MAX_VALUE); 100 101 // Transformation functions 102 List<Function<LongStream, LongStream>> transforms = Arrays.asList( 103 ls -> ls, 104 ls -> ls.parallel(), 105 // Clear the SIZED flag 106 ls -> ls.limit(Long.MAX_VALUE), 107 ls -> ls.limit(Long.MAX_VALUE).parallel()); 108 109 for (Function<LongStream, LongStream> transform : transforms) { 110 RuntimeException caught = null; 111 try { 112 terminal.apply(s.apply(transform.apply(input.get()))); 113 } catch (RuntimeException e) { 114 caught = e; 115 } 116 assertNotNull(caught, "Expected an instance of exception IllegalArgumentException but no exception thrown"); 117 assertTrue(caught instanceof IllegalArgumentException, 118 String.format("Expected an instance of exception IllegalArgumentException but got %s", caught)); 119 } 120 } 121 testSorted()122 public void testSorted() { 123 assertCountSum(countTo(0).stream().sorted(), 0, 0); 124 assertCountSum(countTo(10).stream().sorted(), 10, 55); 125 assertCountSum(countTo(10).stream().sorted(cInteger.reversed()), 10, 55); 126 127 List<Integer> to10 = countTo(10); 128 assertSorted(to10.stream().sorted(cInteger.reversed()).iterator(), cInteger.reversed()); 129 130 Collections.reverse(to10); 131 assertSorted(to10.stream().sorted().iterator()); 132 133 Spliterator<Integer> s = to10.stream().sorted().spliterator(); 134 assertTrue(s.hasCharacteristics(Spliterator.SORTED)); 135 136 s = to10.stream().sorted(cInteger.reversed()).spliterator(); 137 assertFalse(s.hasCharacteristics(Spliterator.SORTED)); 138 } 139 140 @Test(groups = { "serialization-hostile" }) testSequentialShortCircuitTerminal()141 public void testSequentialShortCircuitTerminal() { 142 // The sorted op for sequential evaluation will buffer all elements when 143 // accepting then at the end sort those elements and push those elements 144 // downstream 145 // A peek operation is added in-between the sorted() and terminal 146 // operation that counts the number of calls to its consumer and 147 // asserts that the number of calls is at most the required quantity 148 149 List<Integer> l = Arrays.asList(5, 4, 3, 2, 1); 150 151 Function<Integer, Stream<Integer>> knownSize = i -> assertNCallsOnly( 152 l.stream().sorted(), Stream::peek, i); 153 Function<Integer, Stream<Integer>> unknownSize = i -> assertNCallsOnly 154 (unknownSizeStream(l).sorted(), Stream::peek, i); 155 156 // Find 157 assertEquals(knownSize.apply(1).findFirst(), Optional.of(1)); 158 assertEquals(knownSize.apply(1).findAny(), Optional.of(1)); 159 assertEquals(unknownSize.apply(1).findFirst(), Optional.of(1)); 160 assertEquals(unknownSize.apply(1).findAny(), Optional.of(1)); 161 162 // Match 163 assertEquals(knownSize.apply(2).anyMatch(i -> i == 2), true); 164 assertEquals(knownSize.apply(2).noneMatch(i -> i == 2), false); 165 assertEquals(knownSize.apply(2).allMatch(i -> i == 2), false); 166 assertEquals(unknownSize.apply(2).anyMatch(i -> i == 2), true); 167 assertEquals(unknownSize.apply(2).noneMatch(i -> i == 2), false); 168 assertEquals(unknownSize.apply(2).allMatch(i -> i == 2), false); 169 } 170 unknownSizeStream(List<T> l)171 private <T> Stream<T> unknownSizeStream(List<T> l) { 172 return StreamSupport.stream(Spliterators.spliteratorUnknownSize(l.iterator(), 0), false); 173 } 174 175 @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) testOps(String name, TestData.OfRef<Integer> data)176 public void testOps(String name, TestData.OfRef<Integer> data) { 177 Collection<Integer> result = exerciseOpsInt(data, Stream::sorted, IntStream::sorted, LongStream::sorted, DoubleStream::sorted); 178 assertSorted(result.iterator()); 179 assertContentsUnordered(data, result); 180 181 result = exerciseOps(data, s -> s.sorted(cInteger.reversed())); 182 assertSorted(result.iterator(), cInteger.reversed()); 183 assertContentsUnordered(data, result); 184 } 185 186 @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) testSortSort(String name, TestData.OfRef<Integer> data)187 public void testSortSort(String name, TestData.OfRef<Integer> data) { 188 // For parallel cases ensure the size is known 189 Collection<Integer> result = withData(data) 190 .stream(s -> s.sorted().sorted(), 191 new CollectorOps.TestParallelSizedOp<Integer>()) 192 .exercise(); 193 194 assertSorted(result); 195 assertContentsUnordered(data, result); 196 197 result = withData(data) 198 .stream(s -> s.sorted(cInteger.reversed()).sorted(cInteger.reversed()), 199 new CollectorOps.TestParallelSizedOp<Integer>()) 200 .exercise(); 201 202 assertSorted(result, cInteger.reversed()); 203 assertContentsUnordered(data, result); 204 205 result = withData(data) 206 .stream(s -> s.sorted().sorted(cInteger.reversed()), 207 new CollectorOps.TestParallelSizedOp<Integer>()) 208 .exercise(); 209 210 assertSorted(result, cInteger.reversed()); 211 assertContentsUnordered(data, result); 212 213 result = withData(data) 214 .stream(s -> s.sorted(cInteger.reversed()).sorted(), 215 new CollectorOps.TestParallelSizedOp<Integer>()) 216 .exercise(); 217 218 assertSorted(result); 219 assertContentsUnordered(data, result); 220 } 221 222 // 223 224 @Test(groups = { "serialization-hostile" }) testIntSequentialShortCircuitTerminal()225 public void testIntSequentialShortCircuitTerminal() { 226 int[] a = new int[]{5, 4, 3, 2, 1}; 227 228 Function<Integer, IntStream> knownSize = i -> assertNCallsOnly( 229 Arrays.stream(a).sorted(), (s, c) -> s.peek(c::accept), i); 230 Function<Integer, IntStream> unknownSize = i -> assertNCallsOnly 231 (unknownSizeIntStream(a).sorted(), (s, c) -> s.peek(c::accept), i); 232 233 // Find 234 assertEquals(knownSize.apply(1).findFirst(), OptionalInt.of(1)); 235 assertEquals(knownSize.apply(1).findAny(), OptionalInt.of(1)); 236 assertEquals(unknownSize.apply(1).findFirst(), OptionalInt.of(1)); 237 assertEquals(unknownSize.apply(1).findAny(), OptionalInt.of(1)); 238 239 // Match 240 assertEquals(knownSize.apply(2).anyMatch(i -> i == 2), true); 241 assertEquals(knownSize.apply(2).noneMatch(i -> i == 2), false); 242 assertEquals(knownSize.apply(2).allMatch(i -> i == 2), false); 243 assertEquals(unknownSize.apply(2).anyMatch(i -> i == 2), true); 244 assertEquals(unknownSize.apply(2).noneMatch(i -> i == 2), false); 245 assertEquals(unknownSize.apply(2).allMatch(i -> i == 2), false); 246 } 247 unknownSizeIntStream(int[] a)248 private IntStream unknownSizeIntStream(int[] a) { 249 return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(Spliterators.iterator(Arrays.spliterator(a)), 0), false); 250 } 251 252 @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) testIntOps(String name, TestData.OfInt data)253 public void testIntOps(String name, TestData.OfInt data) { 254 Collection<Integer> result = exerciseOps(data, s -> s.sorted()); 255 assertSorted(result); 256 assertContentsUnordered(data, result); 257 } 258 259 @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) testIntSortSort(String name, TestData.OfInt data)260 public void testIntSortSort(String name, TestData.OfInt data) { 261 // For parallel cases ensure the size is known 262 Collection<Integer> result = withData(data) 263 .stream(s -> s.sorted().sorted(), new CollectorOps.TestParallelSizedOp.OfInt()) 264 .exercise(); 265 266 assertSorted(result); 267 assertContentsUnordered(data, result); 268 } 269 270 // 271 272 @Test(groups = { "serialization-hostile" }) testLongSequentialShortCircuitTerminal()273 public void testLongSequentialShortCircuitTerminal() { 274 long[] a = new long[]{5, 4, 3, 2, 1}; 275 276 Function<Integer, LongStream> knownSize = i -> assertNCallsOnly( 277 Arrays.stream(a).sorted(), (s, c) -> s.peek(c::accept), i); 278 Function<Integer, LongStream> unknownSize = i -> assertNCallsOnly 279 (unknownSizeLongStream(a).sorted(), (s, c) -> s.peek(c::accept), i); 280 281 // Find 282 assertEquals(knownSize.apply(1).findFirst(), OptionalLong.of(1)); 283 assertEquals(knownSize.apply(1).findAny(), OptionalLong.of(1)); 284 assertEquals(unknownSize.apply(1).findFirst(), OptionalLong.of(1)); 285 assertEquals(unknownSize.apply(1).findAny(), OptionalLong.of(1)); 286 287 // Match 288 assertEquals(knownSize.apply(2).anyMatch(i -> i == 2), true); 289 assertEquals(knownSize.apply(2).noneMatch(i -> i == 2), false); 290 assertEquals(knownSize.apply(2).allMatch(i -> i == 2), false); 291 assertEquals(unknownSize.apply(2).anyMatch(i -> i == 2), true); 292 assertEquals(unknownSize.apply(2).noneMatch(i -> i == 2), false); 293 assertEquals(unknownSize.apply(2).allMatch(i -> i == 2), false); 294 } 295 unknownSizeLongStream(long[] a)296 private LongStream unknownSizeLongStream(long[] a) { 297 return StreamSupport.longStream(Spliterators.spliteratorUnknownSize(Spliterators.iterator(Arrays.spliterator(a)), 0), false); 298 } 299 300 @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) testLongOps(String name, TestData.OfLong data)301 public void testLongOps(String name, TestData.OfLong data) { 302 Collection<Long> result = exerciseOps(data, s -> s.sorted()); 303 assertSorted(result); 304 assertContentsUnordered(data, result); 305 } 306 307 @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) testLongSortSort(String name, TestData.OfLong data)308 public void testLongSortSort(String name, TestData.OfLong data) { 309 // For parallel cases ensure the size is known 310 Collection<Long> result = withData(data) 311 .stream(s -> s.sorted().sorted(), new CollectorOps.TestParallelSizedOp.OfLong()) 312 .exercise(); 313 314 assertSorted(result); 315 assertContentsUnordered(data, result); 316 } 317 318 // 319 320 @Test(groups = { "serialization-hostile" }) testDoubleSequentialShortCircuitTerminal()321 public void testDoubleSequentialShortCircuitTerminal() { 322 double[] a = new double[]{5.0, 4.0, 3.0, 2.0, 1.0}; 323 324 Function<Integer, DoubleStream> knownSize = i -> assertNCallsOnly( 325 Arrays.stream(a).sorted(), (s, c) -> s.peek(c::accept), i); 326 Function<Integer, DoubleStream> unknownSize = i -> assertNCallsOnly 327 (unknownSizeDoubleStream(a).sorted(), (s, c) -> s.peek(c::accept), i); 328 329 // Find 330 assertEquals(knownSize.apply(1).findFirst(), OptionalDouble.of(1)); 331 assertEquals(knownSize.apply(1).findAny(), OptionalDouble.of(1)); 332 assertEquals(unknownSize.apply(1).findFirst(), OptionalDouble.of(1)); 333 assertEquals(unknownSize.apply(1).findAny(), OptionalDouble.of(1)); 334 335 // Match 336 assertEquals(knownSize.apply(2).anyMatch(i -> i == 2.0), true); 337 assertEquals(knownSize.apply(2).noneMatch(i -> i == 2.0), false); 338 assertEquals(knownSize.apply(2).allMatch(i -> i == 2.0), false); 339 assertEquals(unknownSize.apply(2).anyMatch(i -> i == 2.0), true); 340 assertEquals(unknownSize.apply(2).noneMatch(i -> i == 2.0), false); 341 assertEquals(unknownSize.apply(2).allMatch(i -> i == 2.0), false); 342 } 343 unknownSizeDoubleStream(double[] a)344 private DoubleStream unknownSizeDoubleStream(double[] a) { 345 return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(Spliterators.iterator(Arrays.spliterator(a)), 0), false); 346 } 347 348 @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) testDoubleOps(String name, TestData.OfDouble data)349 public void testDoubleOps(String name, TestData.OfDouble data) { 350 Collection<Double> result = exerciseOps(data, s -> s.sorted()); 351 assertSorted(result); 352 assertContentsUnordered(data, result); 353 } 354 355 @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) testDoubleSortSort(String name, TestData.OfDouble data)356 public void testDoubleSortSort(String name, TestData.OfDouble data) { 357 // For parallel cases ensure the size is known 358 Collection<Double> result = withData(data) 359 .stream(s -> s.sorted().sorted(), new CollectorOps.TestParallelSizedOp.OfDouble()) 360 .exercise(); 361 362 assertSorted(result); 363 assertContentsUnordered(data, result); 364 } 365 366 /** 367 * Interpose a consumer that asserts it is called at most N times. 368 */ assertNCallsOnly(S s, BiFunction<S, Consumer<T>, S> pf, int n)369 <T, S extends BaseStream<T, S>, R> S assertNCallsOnly(S s, BiFunction<S, Consumer<T>, S> pf, int n) { 370 AtomicInteger boxedInt = new AtomicInteger(); 371 return pf.apply(s, i -> { 372 assertFalse(boxedInt.incrementAndGet() > n, "Intermediate op called more than " + n + " time(s)"); 373 }); 374 } 375 } 376