1 /* 2 * Copyright (c) 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.util.stream; 26 27 import org.testng.annotations.Test; 28 29 import java.util.Arrays; 30 import java.util.List; 31 import java.util.function.BiConsumer; 32 import java.util.function.Function; 33 import java.util.function.UnaryOperator; 34 35 @Test 36 public class UnorderedTest extends OpTestCase { 37 38 @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) 39 public void testTerminalOps(String name, TestData<Integer, Stream<Integer>> data) { 40 testTerminal(data, s -> { s.forEach(x -> { }); return 0; }); 41 42 testTerminal(data, s -> s.findAny(), (a, b) -> assertEquals(a.isPresent(), b.isPresent())); 43 44 testTerminal(data, s -> s.anyMatch(e -> true)); 45 } 46 47 48 private <T, R> void testTerminal(TestData<T, Stream<T>> data, Function<Stream<T>, R> terminalF) { 49 testTerminal(data, terminalF, LambdaTestHelpers::assertContentsEqual); 50 } 51 52 static class WrappingUnaryOperator<S> implements UnaryOperator<S> { 53 54 final boolean isLimit; 55 final UnaryOperator<S> uo; 56 57 WrappingUnaryOperator(UnaryOperator<S> uo) { 58 this(uo, false); 59 } 60 61 WrappingUnaryOperator(UnaryOperator<S> uo, boolean isLimit) { 62 this.uo = uo; 63 this.isLimit = isLimit; 64 } 65 66 @Override 67 public S apply(S s) { 68 return uo.apply(s); 69 } 70 } 71 72 static <S> WrappingUnaryOperator<S> wrap(UnaryOperator<S> uo) { 73 return new WrappingUnaryOperator<>(uo); 74 } 75 76 static <S> WrappingUnaryOperator<S> wrap(UnaryOperator<S> uo, boolean isLimit) { 77 return new WrappingUnaryOperator<>(uo, isLimit); 78 } 79 80 @SuppressWarnings("rawtypes") 81 private List permutationOfFunctions = 82 LambdaTestHelpers.perm(Arrays.<WrappingUnaryOperator<Stream<Object>>>asList( 83 wrap(s -> s.sorted()), 84 wrap(s -> s.distinct()), 85 wrap(s -> s.limit(5), true) 86 )); 87 88 @SuppressWarnings("unchecked") 89 private <T, R> void testTerminal(TestData<T, Stream<T>> data, 90 Function<Stream<T>, R> terminalF, 91 BiConsumer<R, R> equalityAsserter) { 92 testTerminal(data, terminalF, equalityAsserter, permutationOfFunctions, StreamShape.REFERENCE); 93 } 94 95 // 96 97 @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) 98 public void testIntTerminalOps(String name, TestData.OfInt data) { 99 testIntTerminal(data, s -> { s.forEach(x -> { }); return 0; }); 100 testIntTerminal(data, s -> s.findAny(), (a, b) -> assertEquals(a.isPresent(), b.isPresent())); 101 testIntTerminal(data, s -> s.anyMatch(e -> true)); 102 } 103 104 105 private <T, R> void testIntTerminal(TestData.OfInt data, Function<IntStream, R> terminalF) { 106 testIntTerminal(data, terminalF, LambdaTestHelpers::assertContentsEqual); 107 } 108 109 private List<List<WrappingUnaryOperator<IntStream>>> intPermutationOfFunctions = 110 LambdaTestHelpers.perm(Arrays.asList( 111 wrap(s -> s.sorted()), 112 wrap(s -> s.distinct()), 113 wrap(s -> s.limit(5), true) 114 )); 115 116 private <R> void testIntTerminal(TestData.OfInt data, 117 Function<IntStream, R> terminalF, 118 BiConsumer<R, R> equalityAsserter) { 119 testTerminal(data, terminalF, equalityAsserter, intPermutationOfFunctions, StreamShape.INT_VALUE); 120 } 121 122 // 123 124 @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) 125 public void testLongTerminalOps(String name, TestData.OfLong data) { 126 testLongTerminal(data, s -> { s.forEach(x -> { }); return 0; }); 127 testLongTerminal(data, s -> s.findAny(), (a, b) -> assertEquals(a.isPresent(), b.isPresent())); 128 testLongTerminal(data, s -> s.anyMatch(e -> true)); 129 } 130 131 132 private <T, R> void testLongTerminal(TestData.OfLong data, Function<LongStream, R> terminalF) { 133 testLongTerminal(data, terminalF, LambdaTestHelpers::assertContentsEqual); 134 } 135 136 private List<List<WrappingUnaryOperator<LongStream>>> longPermutationOfFunctions = 137 LambdaTestHelpers.perm(Arrays.asList( 138 wrap(s -> s.sorted()), 139 wrap(s -> s.distinct()), 140 wrap(s -> s.limit(5), true) 141 )); 142 143 private <R> void testLongTerminal(TestData.OfLong data, 144 Function<LongStream, R> terminalF, 145 BiConsumer<R, R> equalityAsserter) { 146 testTerminal(data, terminalF, equalityAsserter, longPermutationOfFunctions, StreamShape.LONG_VALUE); 147 } 148 149 // 150 151 @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) 152 public void testDoubleTerminalOps(String name, TestData.OfDouble data) { 153 testDoubleTerminal(data, s -> { s.forEach(x -> { }); return 0; }); 154 testDoubleTerminal(data, s -> s.findAny(), (a, b) -> assertEquals(a.isPresent(), b.isPresent())); 155 testDoubleTerminal(data, s -> s.anyMatch(e -> true)); 156 } 157 158 159 private <T, R> void testDoubleTerminal(TestData.OfDouble data, Function<DoubleStream, R> terminalF) { 160 testDoubleTerminal(data, terminalF, LambdaTestHelpers::assertContentsEqual); 161 } 162 163 private List<List<WrappingUnaryOperator<DoubleStream>>> doublePermutationOfFunctions = 164 LambdaTestHelpers.perm(Arrays.asList( 165 wrap(s -> s.sorted()), 166 wrap(s -> s.distinct()), 167 wrap(s -> s.limit(5), true) 168 )); 169 170 private <R> void testDoubleTerminal(TestData.OfDouble data, 171 Function<DoubleStream, R> terminalF, 172 BiConsumer<R, R> equalityAsserter) { 173 testTerminal(data, terminalF, equalityAsserter, doublePermutationOfFunctions, StreamShape.DOUBLE_VALUE); 174 } 175 176 // 177 178 private <T, S extends BaseStream<T, S>, R> void testTerminal(TestData<T, S> data, 179 Function<S, R> terminalF, 180 BiConsumer<R, R> equalityAsserter, 181 List<List<WrappingUnaryOperator<S>>> pFunctions, 182 StreamShape shape) { 183 CheckClearOrderedOp<T> checkClearOrderedOp = new CheckClearOrderedOp<>(shape); 184 for (List<WrappingUnaryOperator<S>> f : pFunctions) { 185 @SuppressWarnings("unchecked") 186 UnaryOperator<S> fi = interpose(f, (S s) -> (S) chain(s, checkClearOrderedOp)); 187 withData(data). 188 terminal(fi, terminalF). 189 without(TerminalTestScenario.ALL_PARALLEL_SEQUENTIAL). 190 equalator(equalityAsserter). 191 exercise(); 192 } 193 194 CheckSetOrderedOp<T> checkSetOrderedOp = new CheckSetOrderedOp<>(shape); 195 for (List<WrappingUnaryOperator<S>> f : pFunctions) { 196 @SuppressWarnings("unchecked") 197 UnaryOperator<S> fi = interpose(f, (S s) -> (S) chain(s, checkSetOrderedOp)); 198 withData(data). 199 terminal(fi, s -> terminalF.apply(s.sequential())). 200 without(TerminalTestScenario.ALL_PARALLEL_SEQUENTIAL). 201 equalator(equalityAsserter). 202 exercise(); 203 } 204 } 205 206 static class CheckClearOrderedOp<T> implements StatelessTestOp<T, T> { 207 private final StreamShape shape; 208 209 CheckClearOrderedOp(StreamShape shape) { 210 this.shape = shape; 211 } 212 213 @Override 214 public StreamShape outputShape() { 215 return shape; 216 } 217 218 @Override 219 public StreamShape inputShape() { 220 return shape; 221 } 222 223 @Override 224 public Sink<T> opWrapSink(int flags, boolean parallel, Sink<T> sink) { 225 if (parallel) { 226 assertTrue(StreamOpFlag.ORDERED.isCleared(flags)); 227 } 228 229 return sink; 230 } 231 } 232 233 static class CheckSetOrderedOp<T> extends CheckClearOrderedOp<T> { 234 235 CheckSetOrderedOp(StreamShape shape) { 236 super(shape); 237 } 238 239 @Override 240 public Sink<T> opWrapSink(int flags, boolean parallel, Sink<T> sink) { 241 assertTrue(StreamOpFlag.ORDERED.isKnown(flags) || StreamOpFlag.ORDERED.isPreserved(flags)); 242 243 return sink; 244 } 245 } 246 247 private <T, S extends BaseStream<T, S>> 248 UnaryOperator<S> interpose(List<WrappingUnaryOperator<S>> fs, UnaryOperator<S> fi) { 249 int l = -1; 250 for (int i = 0; i < fs.size(); i++) { 251 if (fs.get(i).isLimit) { 252 l = i; 253 } 254 } 255 256 final int lastLimitIndex = l; 257 return s -> { 258 if (lastLimitIndex == -1) 259 s = fi.apply(s); 260 for (int i = 0; i < fs.size(); i++) { 261 s = fs.get(i).apply(s); 262 if (i >= lastLimitIndex) { 263 s = fi.apply(s); 264 } 265 } 266 return s; 267 }; 268 } 269 }