1 /*
2  * Copyright (c) 2015, 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.DefaultMethodStreams;
26 import org.openjdk.testlib.java.util.stream.OpTestCase;
27 import org.testng.annotations.Test;
28 
29 import java.util.HashMap;
30 import java.util.LinkedList;
31 import java.util.Map;
32 import java.util.concurrent.TimeUnit;
33 import java.util.concurrent.atomic.AtomicLong;
34 import java.util.function.BooleanSupplier;
35 import java.util.function.Consumer;
36 import java.util.function.Function;
37 import java.util.function.Supplier;
38 import java.util.stream.DoubleStream;
39 import java.util.stream.IntStream;
40 import java.util.stream.LongStream;
41 import java.util.stream.Stream;
42 
43 import static java.util.stream.Collectors.toCollection;
44 
45 import android.platform.test.annotations.LargeTest;
46 
47 /*
48  * @test
49  * @bug 8071597
50  */
51 @LargeTest
52 @Test
53 // Android-changed: this test checks while/drop ops on reference and primitive streams.
54 // But in Android U only reference streams have those APIs, hence primitive streams part
55 // are commented out.
56 public class WhileOpStatefulTest extends OpTestCase {
57     static final long COUNT_PERIOD = 100;
58 
59     static final long EXECUTION_TIME_LIMIT = TimeUnit.SECONDS.toMillis(10);
60 
61     static final long TAKE_WHILE_COUNT_LIMIT = 100_000;
62 
63     static final int DROP_SOURCE_SIZE = 10_000;
64 
65     static final long DROP_WHILE_COUNT_LIMIT = 5000;
66 
67     @Test
testTimedTakeWithCount()68     public void testTimedTakeWithCount() {
69         testTakeWhileMulti(
70                 s -> {
71                     BooleanSupplier isWithinTakePeriod =
72                             within(System.currentTimeMillis(), COUNT_PERIOD);
73                     s.takeWhile(e -> isWithinTakePeriod.getAsBoolean())
74                             .mapToLong(e -> 1).reduce(0, Long::sum);
75                 });
76         // BEGIN Android-removed: Drop primitive stream test.
77         /*
78                 s -> {
79                     BooleanSupplier isWithinTakePeriod =
80                             within(System.currentTimeMillis(), COUNT_PERIOD);
81                     s.takeWhile(e -> isWithinTakePeriod.getAsBoolean())
82                             .mapToLong(e -> 1).reduce(0, Long::sum);
83                 },
84                 s -> {
85                     BooleanSupplier isWithinTakePeriod =
86                             within(System.currentTimeMillis(), COUNT_PERIOD);
87                     s.takeWhile(e -> isWithinTakePeriod.getAsBoolean())
88                             .map(e -> 1).reduce(0, Long::sum);
89                 },
90                 s -> {
91                     BooleanSupplier isWithinTakePeriod =
92                             within(System.currentTimeMillis(), COUNT_PERIOD);
93                     s.takeWhile(e -> isWithinTakePeriod.getAsBoolean())
94                             .mapToLong(e -> 1).reduce(0, Long::sum);
95                 });
96         */
97         // END Android-removed: Drop primitive stream test.
98     }
99 
100     @Test(groups = { "serialization-hostile" })
testCountTakeWithCount()101     public void testCountTakeWithCount() {
102         testTakeWhileMulti(
103                 s -> {
104                     AtomicLong c = new AtomicLong();
105                     long rc = s.takeWhile(e -> c.getAndIncrement() < TAKE_WHILE_COUNT_LIMIT)
106                             .mapToLong(e -> 1).reduce(0, Long::sum);
107                     assertTrue(rc <= c.get());
108                 });
109         // BEGIN Android-removed: Drop primitive stream test.
110         /*
111                 s -> {
112                     AtomicLong c = new AtomicLong();
113                     long rc = s.takeWhile(e -> c.getAndIncrement() < TAKE_WHILE_COUNT_LIMIT)
114                             .mapToLong(e -> 1).reduce(0, Long::sum);
115                     assertTrue(rc <= c.get());
116                 },
117                 s -> {
118                     AtomicLong c = new AtomicLong();
119                     long rc = s.takeWhile(e -> c.getAndIncrement() < TAKE_WHILE_COUNT_LIMIT)
120                             .map(e -> 1).reduce(0, Long::sum);
121                     assertTrue(rc <= c.get());
122                 },
123                 s -> {
124                     AtomicLong c = new AtomicLong();
125                     long rc = s.takeWhile(e -> c.getAndIncrement() < TAKE_WHILE_COUNT_LIMIT)
126                             .mapToLong(e -> 1).reduce(0, Long::sum);
127                     assertTrue(rc <= c.get());
128                 });
129         */
130         // END Android-removed: Drop primitive stream test.
131     }
132 
133     @Test(groups = { "serialization-hostile" })
testCountTakeWithToArray()134     public void testCountTakeWithToArray() {
135         testTakeWhileMulti(
136                 s -> {
137                     AtomicLong c = new AtomicLong();
138                     Object[] ra = s.takeWhile(e -> c.getAndIncrement() < TAKE_WHILE_COUNT_LIMIT)
139                             .toArray();
140                     assertTrue(ra.length <= c.get());
141                 });
142         // BEGIN Android-removed: Drop primitive stream test.
143         /*
144                 s -> {
145                     AtomicLong c = new AtomicLong();
146                     int[] ra = s.takeWhile(e -> c.getAndIncrement() < TAKE_WHILE_COUNT_LIMIT)
147                             .toArray();
148                     assertTrue(ra.length <= c.get());
149                 },
150                 s -> {
151                     AtomicLong c = new AtomicLong();
152                     long[] ra = s.takeWhile(e -> c.getAndIncrement() < TAKE_WHILE_COUNT_LIMIT)
153                             .toArray();
154                     assertTrue(ra.length <= c.get());
155                 },
156                 s -> {
157                     AtomicLong c = new AtomicLong();
158                     double[] ra = s.takeWhile(e -> c.getAndIncrement() < TAKE_WHILE_COUNT_LIMIT)
159                             .toArray();
160                     assertTrue(ra.length <= c.get());
161                 });
162         */
163         // END Android-removed: Drop primitive stream test.
164     }
165 
166 
167     @Test(groups = { "serialization-hostile" })
testCountDropWithCount()168     public void testCountDropWithCount() {
169         testDropWhileMulti(
170                 s -> {
171                     AtomicLong c = new AtomicLong();
172                     long rc = s.dropWhile(e -> c.getAndIncrement() < DROP_WHILE_COUNT_LIMIT)
173                             .mapToLong(e -> 1).reduce(0, Long::sum);
174                     assertTrue(c.get() >= DROP_WHILE_COUNT_LIMIT);
175                     assertTrue(rc <= DROP_SOURCE_SIZE);
176                 });
177         // BEGIN Android-removed: Drop primitive stream test.
178         /*
179                 s -> {
180                     AtomicLong c = new AtomicLong();
181                     long rc = s.dropWhile(e -> c.getAndIncrement() < DROP_WHILE_COUNT_LIMIT)
182                             .mapToLong(e -> 1).reduce(0, Long::sum);
183                     assertTrue(c.get() >= DROP_WHILE_COUNT_LIMIT);
184                     assertTrue(rc <= DROP_SOURCE_SIZE);
185                 },
186                 s -> {
187                     AtomicLong c = new AtomicLong();
188                     long rc = s.dropWhile(e -> c.getAndIncrement() < DROP_WHILE_COUNT_LIMIT)
189                             .map(e -> 1).reduce(0, Long::sum);
190                     assertTrue(c.get() >= DROP_WHILE_COUNT_LIMIT);
191                     assertTrue(rc <= DROP_SOURCE_SIZE);
192                 },
193                 s -> {
194                     AtomicLong c = new AtomicLong();
195                     long rc = s.dropWhile(e -> c.getAndIncrement() < DROP_WHILE_COUNT_LIMIT)
196                             .mapToLong(e -> 1).reduce(0, Long::sum);
197                     assertTrue(c.get() >= DROP_WHILE_COUNT_LIMIT);
198                     assertTrue(rc <= DROP_SOURCE_SIZE);
199                 });
200         */
201         // END Android-removed: Drop primitive stream test.
202     }
203 
204     @Test(groups = { "serialization-hostile" })
testCountDropWithToArray()205     public void testCountDropWithToArray() {
206         testDropWhileMulti(
207                 s -> {
208                     AtomicLong c = new AtomicLong();
209                     Object[] ra = s.dropWhile(e -> c.getAndIncrement() < DROP_WHILE_COUNT_LIMIT)
210                             .toArray();
211                     assertTrue(c.get() >= DROP_WHILE_COUNT_LIMIT);
212                     assertTrue(ra.length <= DROP_SOURCE_SIZE);
213                 });
214         // BEGIN Android-removed: Drop primitive stream test.
215         /*
216                 s -> {
217                     AtomicLong c = new AtomicLong();
218                     int[] ra = s.dropWhile(e -> c.getAndIncrement() < DROP_WHILE_COUNT_LIMIT)
219                             .toArray();
220                     assertTrue(c.get() >= DROP_WHILE_COUNT_LIMIT);
221                     assertTrue(ra.length <= DROP_SOURCE_SIZE);
222                 },
223                 s -> {
224                     AtomicLong c = new AtomicLong();
225                     long[] ra = s.dropWhile(e -> c.getAndIncrement() < DROP_WHILE_COUNT_LIMIT)
226                             .toArray();
227                     assertTrue(c.get() >= DROP_WHILE_COUNT_LIMIT);
228                     assertTrue(ra.length <= DROP_SOURCE_SIZE);
229                 },
230                 s -> {
231                     AtomicLong c = new AtomicLong();
232                     double[] ra = s.dropWhile(e -> c.getAndIncrement() < DROP_WHILE_COUNT_LIMIT)
233                             .toArray();
234                     assertTrue(c.get() >= DROP_WHILE_COUNT_LIMIT);
235                     assertTrue(ra.length <= DROP_SOURCE_SIZE);
236                 });
237         */
238         // END Android-removed: Drop primitive stream test.
239     }
240 
241 
testTakeWhileMulti(Consumer<Stream<Integer>> mRef)242     private void testTakeWhileMulti(Consumer<Stream<Integer>> mRef) {
243         // Consumer<IntStream> mInt) {
244         // Consumer<LongStream> mLong,
245         // Consumer<DoubleStream> mDouble) {
246         Map<String, Supplier<Stream<Integer>>> sources = new HashMap<>();
247         sources.put("Stream.generate()", () -> Stream.generate(() -> 1));
248         sources.put("Stream.iterate()", () -> Stream.iterate(1, x -> 1));
249         sources.put("Stream.iterate().unordered()", () -> Stream.iterate(1, x -> 1));
250 
251         // Android-changed: Drop primitive stream test.
252         // testWhileMulti(sources, mRef, mInt, mLong, mDouble);
253         testWhileMulti(sources, mRef);
254     }
255 
256     // Android-changed: Drop primitive stream test.
257     /*
258     private void testDropWhileMulti(Consumer<Stream<Integer>> mRef,
259                                     Consumer<IntStream> mInt,
260                                     Consumer<LongStream> mLong,
261                                     Consumer<DoubleStream> mDouble) {
262     */
testDropWhileMulti(Consumer<Stream<Integer>> mRef)263     private void testDropWhileMulti(Consumer<Stream<Integer>> mRef) {
264         Map<String, Supplier<Stream<Integer>>> sources = new HashMap<>();
265         sources.put("IntStream.range().boxed()",
266                     () -> IntStream.range(0, DROP_SOURCE_SIZE).boxed());
267         sources.put("IntStream.range().boxed().unordered()",
268                     () -> IntStream.range(0, DROP_SOURCE_SIZE).boxed().unordered());
269         sources.put("LinkedList.stream()",
270                     () -> IntStream.range(0, DROP_SOURCE_SIZE).boxed()
271                             .collect(toCollection(LinkedList::new))
272                             .stream());
273         sources.put("LinkedList.stream().unordered()",
274                     () -> IntStream.range(0, DROP_SOURCE_SIZE).boxed()
275                             .collect(toCollection(LinkedList::new))
276                             .stream()
277                             .unordered());
278         // Android-changed: Drop primitive stream test.
279         // testWhileMulti(sources, mRef, mInt, mLong, mDouble);
280         testWhileMulti(sources, mRef);
281     }
282 
testWhileMulti(Map<String, Supplier<Stream<Integer>>> sources, Consumer<Stream<Integer>> mRef)283     private void testWhileMulti(Map<String, Supplier<Stream<Integer>>> sources,
284                                 Consumer<Stream<Integer>> mRef) {
285         // Android-removed: Drop primitive stream test.
286                                 // Consumer<IntStream> mInt,
287                                 // Consumer<LongStream> mLong,
288                                 // Consumer<DoubleStream> mDouble) {
289         Map<String, Function<Stream<Integer>, Stream<Integer>>> transforms = new HashMap<>();
290         transforms.put("Stream.sequential()", s -> {
291             BooleanSupplier isWithinExecutionPeriod = within(System.currentTimeMillis(),
292                                                              EXECUTION_TIME_LIMIT);
293             return s.peek(e -> {
294                 if (!isWithinExecutionPeriod.getAsBoolean()) {
295                     throw new RuntimeException();
296                 }
297             });
298         });
299         transforms.put("Stream.parallel()", s -> {
300             BooleanSupplier isWithinExecutionPeriod = within(System.currentTimeMillis(),
301                                                              EXECUTION_TIME_LIMIT);
302             return s.parallel()
303                     .peek(e -> {
304                         if (!isWithinExecutionPeriod.getAsBoolean()) {
305                             throw new RuntimeException();
306                         }
307                     });
308         });
309 
310         Map<String, Consumer<Stream<Integer>>> actions = new HashMap<>();
311         actions.put("Ref", mRef);
312         // Android-removed: Drop primitive stream test.
313         // actions.put("Int", s -> mInt.accept(s.mapToInt(e -> e)));
314         // actions.put("Long", s -> mLong.accept(s.mapToLong(e -> e)));
315         // actions.put("Double", s -> mDouble.accept(s.mapToDouble(e -> e)));
316         actions.put("Ref using defaults", s -> mRef.accept(DefaultMethodStreams.delegateTo(s)));
317         // Android-removed: Drop primitive stream test.
318         // actions.put("Int using defaults", s -> mInt.accept(DefaultMethodStreams.delegateTo(s.mapToInt(e -> e))));
319         // actions.put("Long using defaults", s -> mLong.accept(DefaultMethodStreams.delegateTo(s.mapToLong(e -> e))));
320         // actions.put("Double using defaults", s -> mDouble.accept(DefaultMethodStreams.delegateTo(s.mapToDouble(e -> e))));
321 
322         for (Map.Entry<String, Supplier<Stream<Integer>>> s : sources.entrySet()) {
323             setContext("source", s.getKey());
324 
325             for (Map.Entry<String, Function<Stream<Integer>, Stream<Integer>>> t : transforms.entrySet()) {
326                 setContext("transform", t.getKey());
327 
328                 for (Map.Entry<String, Consumer<Stream<Integer>>> a : actions.entrySet()) {
329                     setContext("shape", a.getKey());
330 
331                     Stream<Integer> stream = s.getValue().get();
332                     stream = t.getValue().apply(stream);
333                     a.getValue().accept(stream);
334                 }
335             }
336         }
337     }
338 
within(long start, long durationInMillis)339     static BooleanSupplier within(long start, long durationInMillis) {
340         return () -> (System.currentTimeMillis() - start) < durationInMillis;
341     }
342 }
343