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.stream.Collectors;
  30 import java.util.stream.OpTestCase;
  31 import java.util.stream.Stream;
  32 import java.util.stream.StreamTestDataProvider;
  33 import java.util.stream.TestData;
  34 
  35 import static java.util.stream.LambdaTestHelpers.*;
  36 
  37 /**
  38  * SliceOpTest
  39  *
  40  * @author Brian Goetz
  41  */
  42 @Test
  43 public class SliceOpTest extends OpTestCase {
  44 
  45     public void testSkip() {
  46         assertCountSum(countTo(0).stream().substream(0), 0, 0);
  47         assertCountSum(countTo(0).stream().substream(4), 0, 0);
  48         assertCountSum(countTo(4).stream().substream(4), 0, 0);
  49         assertCountSum(countTo(4).stream().substream(2), 2, 7);
  50         assertCountSum(countTo(4).stream().substream(0), 4, 10);
  51 
  52         assertCountSum(countTo(0).parallelStream().substream(0), 0, 0);
  53         assertCountSum(countTo(0).parallelStream().substream(4), 0, 0);
  54         assertCountSum(countTo(4).parallelStream().substream(4), 0, 0);
  55         assertCountSum(countTo(4).parallelStream().substream(2), 2, 7);
  56         assertCountSum(countTo(4).parallelStream().substream(0), 4, 10);
  57 
  58         exerciseOps(Collections.emptyList(), s -> s.substream(0), Collections.emptyList());
  59         exerciseOps(Collections.emptyList(), s -> s.substream(10), Collections.emptyList());
  60 
  61         exerciseOps(countTo(1), s -> s.substream(0), countTo(1));
  62         exerciseOps(countTo(1), s -> s.substream(1), Collections.emptyList());
  63         exerciseOps(countTo(100), s -> s.substream(0), countTo(100));
  64         exerciseOps(countTo(100), s -> s.substream(10), range(11, 100));
  65         exerciseOps(countTo(100), s -> s.substream(100), Collections.emptyList());
  66         exerciseOps(countTo(100), s -> s.substream(200), Collections.emptyList());
  67     }
  68 
  69     public void testLimit() {
  70         assertCountSum(countTo(0).stream().limit(4), 0, 0);
  71         assertCountSum(countTo(2).stream().limit(4), 2, 3);
  72         assertCountSum(countTo(4).stream().limit(4), 4, 10);
  73         assertCountSum(countTo(8).stream().limit(4), 4, 10);
  74 
  75         assertCountSum(countTo(0).parallelStream().limit(4), 0, 0);
  76         assertCountSum(countTo(2).parallelStream().limit(4), 2, 3);
  77         assertCountSum(countTo(4).parallelStream().limit(4), 4, 10);
  78         assertCountSum(countTo(8).parallelStream().limit(4), 4, 10);
  79 
  80         exerciseOps(Collections.emptyList(), s -> s.limit(0), Collections.emptyList());
  81         exerciseOps(Collections.emptyList(), s -> s.limit(10), Collections.emptyList());
  82         exerciseOps(countTo(1), s -> s.limit(0), Collections.emptyList());
  83         exerciseOps(countTo(1), s -> s.limit(1), countTo(1));
  84         exerciseOps(countTo(100), s -> s.limit(0), Collections.emptyList());
  85         exerciseOps(countTo(100), s -> s.limit(10), countTo(10));
  86         exerciseOps(countTo(100), s -> s.limit(10).limit(10), countTo(10));
  87         exerciseOps(countTo(100), s -> s.limit(100), countTo(100));
  88         exerciseOps(countTo(100), s -> s.limit(100).limit(10), countTo(10));
  89         exerciseOps(countTo(100), s -> s.limit(200), countTo(100));
  90     }
  91 
  92     public void testSkipLimit() {
  93         exerciseOps(Collections.emptyList(), s -> s.substream(0).limit(0), Collections.emptyList());
  94         exerciseOps(Collections.emptyList(), s -> s.substream(0).limit(10), Collections.emptyList());
  95         exerciseOps(Collections.emptyList(), s -> s.substream(10).limit(0), Collections.emptyList());
  96         exerciseOps(Collections.emptyList(), s -> s.substream(10).limit(10), Collections.emptyList());
  97 
  98         exerciseOps(countTo(100), s -> s.substream(0).limit(100), countTo(100));
  99         exerciseOps(countTo(100), s -> s.substream(0).limit(10), countTo(10));
 100         exerciseOps(countTo(100), s -> s.substream(0).limit(0), Collections.emptyList());
 101         exerciseOps(countTo(100), s -> s.substream(10).limit(100), range(11, 100));
 102         exerciseOps(countTo(100), s -> s.substream(10).limit(10), range(11, 20));
 103         exerciseOps(countTo(100), s -> s.substream(10).limit(0), Collections.emptyList());
 104         exerciseOps(countTo(100), s -> s.substream(100).limit(100), Collections.emptyList());
 105         exerciseOps(countTo(100), s -> s.substream(100).limit(10), Collections.emptyList());
 106         exerciseOps(countTo(100), s -> s.substream(100).limit(0), Collections.emptyList());
 107         exerciseOps(countTo(100), s -> s.substream(200).limit(100), Collections.emptyList());
 108         exerciseOps(countTo(100), s -> s.substream(200).limit(10), Collections.emptyList());
 109         exerciseOps(countTo(100), s -> s.substream(200).limit(0), Collections.emptyList());
 110     }
 111 
 112     public void testSlice() {
 113         exerciseOps(Collections.emptyList(), s -> s.substream(0, 0), Collections.emptyList());
 114         exerciseOps(Collections.emptyList(), s -> s.substream(0, 10), Collections.emptyList());
 115         exerciseOps(Collections.emptyList(), s -> s.substream(10, 10), Collections.emptyList());
 116         exerciseOps(Collections.emptyList(), s -> s.substream(10, 20), Collections.emptyList());
 117 
 118         exerciseOps(countTo(100), s -> s.substream(0, 100), countTo(100));
 119         exerciseOps(countTo(100), s -> s.substream(0, 10), countTo(10));
 120         exerciseOps(countTo(100), s -> s.substream(0, 0), Collections.emptyList());
 121         exerciseOps(countTo(100), s -> s.substream(10, 110), range(11, 100));
 122         exerciseOps(countTo(100), s -> s.substream(10, 20), range(11, 20));
 123         exerciseOps(countTo(100), s -> s.substream(10, 10), Collections.emptyList());
 124         exerciseOps(countTo(100), s -> s.substream(100, 200), Collections.emptyList());
 125         exerciseOps(countTo(100), s -> s.substream(100, 110), Collections.emptyList());
 126         exerciseOps(countTo(100), s -> s.substream(100, 100), Collections.emptyList());
 127         exerciseOps(countTo(100), s -> s.substream(200, 300), Collections.emptyList());
 128         exerciseOps(countTo(100), s -> s.substream(200, 210), Collections.emptyList());
 129         exerciseOps(countTo(100), s -> s.substream(200, 200), Collections.emptyList());
 130     }
 131 
 132     private int sliceSize(int dataSize, int skip, int limit) {
 133         int size = Math.max(0, dataSize - skip);
 134         if (limit >= 0)
 135             size = Math.min(size, limit);
 136         return size;
 137     }
 138 
 139     private int sliceSize(int dataSize, int skip) {
 140         return Math.max(0, dataSize - skip);
 141     }
 142 
 143     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
 144     public void testSkipOps(String name, TestData.OfRef<Integer> data) {
 145         List<Integer> skips = sizes(data.size());
 146 
 147         for (int s : skips) {
 148             Collection<Integer> sr = exerciseOpsInt(data,
 149                                                       st -> st.substream(s),
 150                                                       st -> st.substream(s),
 151                                                       st -> st.substream(s),
 152                                                       st -> st.substream(s));
 153             assertEquals(sr.size(), sliceSize(data.size(), s));
 154 
 155             sr = exerciseOpsInt(data,
 156                                   st -> st.substream(s).substream(s / 2),
 157                                   st -> st.substream(s).substream(s / 2),
 158                                   st -> st.substream(s).substream(s / 2),
 159                                   st -> st.substream(s).substream(s / 2));
 160             assertEquals(sr.size(), sliceSize(sliceSize(data.size(), s), s/2));
 161         }
 162     }
 163 
 164     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
 165     public void testSkipLimitOps(String name, TestData.OfRef<Integer> data) {
 166         List<Integer> skips = sizes(data.size());
 167         List<Integer> limits = skips;
 168 
 169         for (int s : skips) {
 170             for (int limit : limits) {
 171                 Collection<Integer> sr = exerciseOpsInt(data,
 172                                                         st -> st.substream(s).limit(limit),
 173                                                         st -> st.substream(s).limit(limit),
 174                                                         st -> st.substream(s).limit(limit),
 175                                                         st -> st.substream(s).limit(limit));
 176                 assertEquals(sr.size(), sliceSize(sliceSize(data.size(), s), 0, limit));
 177 
 178                 sr = exerciseOpsInt(data,
 179                                     st -> st.substream(s, limit+s),
 180                                     st -> st.substream(s, limit+s),
 181                                     st -> st.substream(s, limit+s),
 182                                     st -> st.substream(s, limit+s));
 183                 assertEquals(sr.size(), sliceSize(data.size(), s, limit));
 184             }
 185         }
 186     }
 187 
 188     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
 189     public void testLimitOps(String name, TestData.OfRef<Integer> data) {
 190         List<Integer> limits = sizes(data.size());
 191 
 192         for (int limit : limits) {
 193             Collection<Integer> sr = exerciseOpsInt(data,
 194                                                     st -> st.limit(limit),
 195                                                     st -> st.limit(limit),
 196                                                     st -> st.limit(limit),
 197                                                     st -> st.limit(limit));
 198             assertEquals(sr.size(), sliceSize(data.size(), 0, limit));
 199 
 200             sr = exerciseOpsInt(data,
 201                                 st -> st.limit(limit).limit(limit / 2),
 202                                 st -> st.limit(limit).limit(limit / 2),
 203                                 st -> st.limit(limit).limit(limit / 2),
 204                                 st -> st.limit(limit).limit(limit / 2));
 205             assertEquals(sr.size(), sliceSize(sliceSize(data.size(), 0, limit), 0, limit/2));
 206         }
 207     }
 208 
 209     public void testLimitSort() {
 210         List<Integer> l = countTo(100);
 211         Collections.reverse(l);
 212         exerciseOps(l, s -> s.limit(10).sorted(Comparators.naturalOrder()));
 213     }
 214 
 215     @Test(groups = { "serialization-hostile" })
 216     public void testLimitShortCircuit() {
 217         for (int l : Arrays.asList(0, 10)) {
 218             AtomicInteger ai = new AtomicInteger();
 219             countTo(100).stream()
 220                     .peek(i -> ai.getAndIncrement())
 221                     .limit(l).toArray();
 222             // For the case of a zero limit, one element will get pushed through the sink chain
 223             assertEquals(ai.get(), l, "tee block was called too many times");
 224         }
 225     }
 226 
 227     public void testSkipParallel() {
 228         List<Integer> l = countTo(1000).parallelStream().substream(200).limit(200).sequential().collect(Collectors.toList());
 229         assertEquals(l.size(), 200);
 230         assertEquals(l.get(l.size() -1).intValue(), 400);
 231     }
 232 
 233     public void testLimitParallel() {
 234         List<Integer> l = countTo(1000).parallelStream().limit(500).sequential().collect(Collectors.toList());
 235         assertEquals(l.size(), 500);
 236         assertEquals(l.get(l.size() -1).intValue(), 500);
 237     }
 238 
 239     private List<Integer> sizes(int size) {
 240         if (size < 4) {
 241             return Arrays.asList(0, 1, 2, 3, 4, 6);
 242         }
 243         else {
 244             return Arrays.asList(0, 1, size / 2, size - 1, size, size + 1, 2 * size);
 245         }
 246     }
 247 }