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 }