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.DoubleStreamTestDataProvider;
26 import org.openjdk.testlib.java.util.stream.IntStreamTestDataProvider;
27 import org.openjdk.testlib.java.util.stream.LambdaTestHelpers;
28 import org.openjdk.testlib.java.util.stream.LongStreamTestDataProvider;
29 import org.openjdk.testlib.java.util.stream.OpTestCase;
30 import org.openjdk.testlib.java.util.stream.StreamTestDataProvider;
31 import org.openjdk.testlib.java.util.stream.TestData;
32 
33 import org.testng.annotations.Test;
34 
35 import java.util.*;
36 import java.util.function.Function;
37 import java.util.stream.BaseStream;
38 import java.util.stream.Stream;
39 import java.util.stream.IntStream;
40 import java.util.stream.LongStream;
41 import java.util.stream.DoubleStream;
42 
43 import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.*;
44 import static org.testng.Assert.assertEquals;
45 
46 
47 /**
48  * ToArrayOpTest
49  *
50  */
51 @Test
52 public class ToArrayOpTest extends OpTestCase {
53 
testToArray()54     public void testToArray() {
55         assertCountSum(Arrays.asList(countTo(0).stream().toArray()), 0, 0);
56         assertCountSum(Arrays.asList(countTo(10).stream().toArray()), 10, 55);
57     }
58 
59     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOps(String name, TestData.OfRef<Integer> data)60     public void testOps(String name, TestData.OfRef<Integer> data) {
61         exerciseTerminalOps(data, s -> s.toArray());
62     }
63 
64     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOpsWithMap(String name, TestData.OfRef<Integer> data)65     public void testOpsWithMap(String name, TestData.OfRef<Integer> data) {
66         // Retain the size of the source
67         // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array
68 
69         Object[] objects = exerciseTerminalOps(data, s -> s.map(i -> (Integer) (i + i)), s -> s.toArray());
70         assertTrue(objects.length == data.size());
71     }
72 
73     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOpsWithSorted(String name, TestData.OfRef<Integer> data)74     public void testOpsWithSorted(String name, TestData.OfRef<Integer> data) {
75         // Retain the size of the source
76         // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array
77 
78         Object[] objects = exerciseTerminalOps(data, s -> s.sorted(), s -> s.toArray());
79         assertTrue(objects.length == data.size());
80     }
81 
82     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOpsWithFlatMap(String name, TestData.OfRef<Integer> data)83     public void testOpsWithFlatMap(String name, TestData.OfRef<Integer> data) {
84         // Double the size of the source
85         // Fixed size optimizations will not be used
86 
87         Object[] objects = exerciseTerminalOps(data,
88                                                s -> s.flatMap(e -> Arrays.stream(new Object[] { e, e })),
89                                                s -> s.toArray());
90         assertTrue(objects.length == data.size() * 2);
91     }
92 
93     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOpsWithFilter(String name, TestData.OfRef<Integer> data)94     public void testOpsWithFilter(String name, TestData.OfRef<Integer> data) {
95         // Reduce the size of the source
96         // Fixed size optimizations will not be used
97 
98         exerciseTerminalOps(data, s -> s.filter(LambdaTestHelpers.pEven), s -> s.toArray());
99     }
100 
testAsArrayWithType()101     public void testAsArrayWithType() {
102         exerciseTerminalOps(
103                 TestData.Factory.ofCollection("", Arrays.asList(1.1, 2.2, 3.4, 4.4)),
104                 s -> // First pipeline slice using Object[] with Double elements
105                     s.sorted()
106                     // Second pipeline slice using Integer[] with Integer elements
107                     .map((Double d) -> Integer.valueOf(d.intValue())).sorted(),
108                 s -> s.toArray(Integer[]::new));
109     }
110 
111     private List<Function<Stream<Integer>, Stream<Integer>>> uniqueAndSortedPermutations =
112             LambdaTestHelpers.permuteStreamFunctions(Arrays.asList(
113                     s -> s.distinct(),
114                     s -> s.distinct(),
115                     s -> s.sorted(),
116                     s -> s.sorted()
117             ));
118 
119     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testDistinctAndSortedPermutations(String name, TestData.OfRef<Integer> data)120     public void testDistinctAndSortedPermutations(String name, TestData.OfRef<Integer> data) {
121         for (Function<Stream<Integer>, Stream<Integer>> f : uniqueAndSortedPermutations) {
122             exerciseTerminalOps(data, f, s -> s.toArray());
123 
124             Integer[] is = exerciseTerminalOps(data, f, s -> s.toArray(Integer[]::new));
125             assertEquals(is.getClass(), Integer[].class);
126 
127             Number[] ns = exerciseTerminalOps(data, f, s -> s.toArray(Number[]::new));
128             assertEquals(ns.getClass(), Number[].class);
129 
130             if (data.size() > 0) {
131                 Exception caught = null;
132                 try {
133                     exerciseTerminalOps(data, f, s -> s.toArray(String[]::new));
134                 } catch (Exception e) {
135                     caught = e;
136                 }
137                 assertTrue(caught != null);
138                 assertEquals(caught.getClass(), ArrayStoreException.class);
139             }
140         }
141     }
142 
143     private List<Function<Stream<Integer>, Stream<Integer>>> statefulOpPermutations =
144             LambdaTestHelpers.permuteStreamFunctions(Arrays.asList(
145                     s -> s.limit(10),
146                     s -> s.distinct(),
147                     s -> s.sorted()
148             ));
149 
statefulOpResultAsserter(TestData.OfRef<Integer> data)150     private <T extends Object> ResultAsserter<T[]> statefulOpResultAsserter(TestData.OfRef<Integer> data) {
151         return (act, exp, ord, par) -> {
152             if (par) {
153                 if (!data.isOrdered()) {
154                     // Relax the checking if the data source is unordered
155                     // It is not exactly possible to determine if the limit
156                     // operation is present and if it is before or after
157                     // the sorted operation
158                     // If the limit operation is present and before the sorted
159                     // operation then the sub-set output after limit is a
160                     // non-deterministic sub-set of the source
161                     List<Integer> expected = new ArrayList<>();
162                     data.forEach(expected::add);
163 
164                     List<T> actual = Arrays.asList(act);
165 
166                     assertEquals(actual.size(), exp.length);
167                     assertTrue(expected.containsAll(actual));
168                     return;
169                 }
170                 else if (!ord) {
171                     LambdaTestHelpers.assertContentsUnordered(Arrays.asList(act),
172                                                               Arrays.asList(exp));
173                     return;
174                 }
175             }
176             assertEquals(act, exp);
177         };
178     }
179 
180     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class,
181           groups = { "serialization-hostile" })
182     public void testStatefulOpPermutations(String name, TestData.OfRef<Integer> data) {
183         for (Function<Stream<Integer>, Stream<Integer>> f : statefulOpPermutations) {
184             withData(data).terminal(f, s -> s.toArray())
185                     .resultAsserter(statefulOpResultAsserter(data))
186                     .exercise();
187 
188             Integer[] is = withData(data).terminal(f, s -> s.toArray(Integer[]::new))
189                     .resultAsserter(statefulOpResultAsserter(data))
190                     .exercise();
191             assertEquals(is.getClass(), Integer[].class);
192 
193             Number[] ns = withData(data).terminal(f, s -> s.toArray(Number[]::new))
194                     .resultAsserter(statefulOpResultAsserter(data))
195                     .exercise();
196             assertEquals(ns.getClass(), Number[].class);
197 
198             if (data.size() > 0) {
199                 Exception caught = null;
200                 try {
201                     exerciseTerminalOps(data, f, s -> s.toArray(String[]::new));
202                 } catch (Exception e) {
203                     caught = e;
204                 }
205                 assertTrue(caught != null);
206                 assertEquals(caught.getClass(), ArrayStoreException.class);
207             }
208         }
209     }
210 
211     //
212 
213     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
214     public void testIntOps(String name, TestData.OfInt data) {
215         exerciseTerminalOps(data, s -> s.toArray());
216     }
217 
218     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
219     public void testIntOpsWithMap(String name, TestData.OfInt data) {
220         // Retain the size of the source
221         // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array
222 
223         int[] ints = exerciseTerminalOps(data, s -> s.map(i -> i + i), s -> s.toArray());
224         assertTrue(ints.length == data.size());
225     }
226 
227     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
228     public void testIntOpsWithSorted(String name, TestData.OfInt data) {
229         // Retain the size of the source
230         // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array
231 
232         int[] ints = exerciseTerminalOps(data, s -> s.sorted(), (IntStream s) -> s.toArray());
233         assertTrue(ints.length == data.size());
234     }
235 
236     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
237     public void testIntOpsWithFlatMap(String name, TestData.OfInt data) {
238         // Int the size of the source
239         // Fixed size optimizations will not be used
240 
241         int[] objects = exerciseTerminalOps(data,
242                                                s -> s.flatMap(e -> Arrays.stream(new int[] { e, e })),
243                                                s -> s.toArray());
244         assertTrue(objects.length == data.size() * 2);
245     }
246 
247     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
248     public void testIntOpsWithFilter(String name, TestData.OfInt data) {
249         // Reduce the size of the source
250         // Fixed size optimizations will not be used
251 
252         exerciseTerminalOps(data, s -> s.filter(LambdaTestHelpers.ipEven), s -> s.toArray());
253     }
254 
255     private List<Function<IntStream, IntStream>> intUniqueAndSortedPermutations =
256             LambdaTestHelpers.permuteStreamFunctions(Arrays.asList(
257                     s -> s.distinct(),
258                     s -> s.distinct(),
259                     s -> s.sorted(),
260                     s -> s.sorted()
261             ));
262 
263     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
264     public void testIntDistinctAndSortedPermutations(String name, TestData.OfInt data) {
265         for (Function<IntStream, IntStream> f : intUniqueAndSortedPermutations) {
266             exerciseTerminalOps(data, f, s -> s.toArray());
267         }
268     }
269 
270     private List<Function<IntStream, IntStream>> intStatefulOpPermutations =
271             LambdaTestHelpers.permuteStreamFunctions(Arrays.asList(
272                     s -> s.limit(10),
273                     s -> s.distinct(),
274                     s -> s.sorted()
275             ));
276 
277     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
278     public void testIntStatefulOpPermutations(String name, TestData.OfInt data) {
279         for (Function<IntStream, IntStream> f : intStatefulOpPermutations) {
280             exerciseTerminalOps(data, f, s -> s.toArray());
281         }
282     }
283 
284     //
285 
286     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
287     public void testLongOps(String name, TestData.OfLong data) {
288         exerciseTerminalOps(data, s -> s.toArray());
289     }
290 
291     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
292     public void testLongOpsWithMap(String name, TestData.OfLong data) {
293         // Retain the size of the source
294         // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array
295 
296         long[] longs = exerciseTerminalOps(data, s -> s.map(i -> i + i), s -> s.toArray());
297         assertTrue(longs.length == data.size());
298     }
299 
300     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
301     public void testLongOpsWithSorted(String name, TestData.OfLong data) {
302         // Retain the size of the source
303         // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array
304 
305         long[] longs = exerciseTerminalOps(data, s -> s.sorted(), (LongStream s) -> s.toArray());
306         assertTrue(longs.length == data.size());
307     }
308 
309     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
310     public void testLongOpsWithFlatMap(String name, TestData.OfLong data) {
311         // Long the size of the source
312         // Fixed size optimizations will not be used
313 
314         long[] objects = exerciseTerminalOps(data,
315                                                s -> s.flatMap(e -> Arrays.stream(new long[] { e, e })),
316                                                s -> s.toArray());
317         assertTrue(objects.length == data.size() * 2);
318     }
319 
320     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
321     public void testLongOpsWithFilter(String name, TestData.OfLong data) {
322         // Reduce the size of the source
323         // Fixed size optimizations will not be used
324 
325         exerciseTerminalOps(data, s -> s.filter(LambdaTestHelpers.lpEven), s -> s.toArray());
326     }
327 
328     private List<Function<LongStream, LongStream>> longUniqueAndSortedPermutations =
329             LambdaTestHelpers.permuteStreamFunctions(Arrays.asList(
330                     s -> s.distinct(),
331                     s -> s.distinct(),
332                     s -> s.sorted(),
333                     s -> s.sorted()
334             ));
335 
336     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
337     public void testLongDistinctAndSortedPermutations(String name, TestData.OfLong data) {
338         for (Function<LongStream, LongStream> f : longUniqueAndSortedPermutations) {
339             exerciseTerminalOps(data, f, s -> s.toArray());
340         }
341     }
342 
343     private List<Function<LongStream, LongStream>> longStatefulOpPermutations =
344             LambdaTestHelpers.permuteStreamFunctions(Arrays.asList(
345                     s -> s.limit(10),
346                     s -> s.distinct(),
347                     s -> s.sorted()
348             ));
349 
350     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
351     public void testLongStatefulOpPermutations(String name, TestData.OfLong data) {
352         for (Function<LongStream, LongStream> f : longStatefulOpPermutations) {
353             exerciseTerminalOps(data, f, s -> s.toArray());
354         }
355     }
356 
357     //
358 
359     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
360     public void testDoubleOps(String name, TestData.OfDouble data) {
361         exerciseTerminalOps(data, s -> s.toArray());
362     }
363 
364     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
365     public void testDoubleOpsWithMap(String name, TestData.OfDouble data) {
366         // Retain the size of the source
367         // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array
368 
369         double[] doubles = exerciseTerminalOps(data, s -> s.map(i -> i + i), s -> s.toArray());
370         assertTrue(doubles.length == data.size());
371     }
372 
373     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
374     public void testDoubleOpsWithSorted(String name, TestData.OfDouble data) {
375         // Retain the size of the source
376         // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array
377 
378         double[] doubles = exerciseTerminalOps(data, s -> s.sorted(), (DoubleStream s) -> s.toArray());
379         assertTrue(doubles.length == data.size());
380     }
381 
382     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
383     public void testDoubleOpsWithFlatMap(String name, TestData.OfDouble data) {
384         // Double the size of the source
385         // Fixed size optimizations will not be used
386 
387         double[] objects = exerciseTerminalOps(data,
388                                                s -> s.flatMap(e -> Arrays.stream(new double[] { e, e })),
389                                                s -> s.toArray());
390         assertTrue(objects.length == data.size() * 2);
391     }
392 
393     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
394     public void testDoubleOpsWithFilter(String name, TestData.OfDouble data) {
395         // Reduce the size of the source
396         // Fixed size optimizations will not be used
397 
398         exerciseTerminalOps(data, s -> s.filter(LambdaTestHelpers.dpEven), s -> s.toArray());
399     }
400 
401     private List<Function<DoubleStream, DoubleStream>> doubleUniqueAndSortedPermutations =
402             LambdaTestHelpers.permuteStreamFunctions(Arrays.asList(
403                     s -> s.distinct(),
404                     s -> s.distinct(),
405                     s -> s.sorted(),
406                     s -> s.sorted()
407             ));
408 
409     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
410     public void testDoubleDistinctAndSortedPermutations(String name, TestData.OfDouble data) {
411         for (Function<DoubleStream, DoubleStream> f : doubleUniqueAndSortedPermutations) {
412             exerciseTerminalOps(data, f, s -> s.toArray());
413         }
414     }
415 
416     private List<Function<DoubleStream, DoubleStream>> doubleStatefulOpPermutations =
417             LambdaTestHelpers.permuteStreamFunctions(Arrays.asList(
418                     s -> s.limit(10),
419                     s -> s.distinct(),
420                     s -> s.sorted()
421             ));
422 
423     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
424     public void testDoubleStatefulOpPermutations(String name, TestData.OfDouble data) {
425         for (Function<DoubleStream, DoubleStream> f : doubleStatefulOpPermutations) {
426             exerciseTerminalOps(data, f, s -> s.toArray());
427         }
428     }
429 }
430