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