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 */
23package org.openjdk.tests.java.util.stream;
24
25import org.openjdk.testlib.java.util.stream.DoubleStreamTestDataProvider;
26import org.openjdk.testlib.java.util.stream.IntStreamTestDataProvider;
27import org.openjdk.testlib.java.util.stream.LambdaTestHelpers;
28import org.openjdk.testlib.java.util.stream.LongStreamTestDataProvider;
29import org.openjdk.testlib.java.util.stream.OpTestCase;
30import org.openjdk.testlib.java.util.stream.StreamTestDataProvider;
31import org.openjdk.testlib.java.util.stream.TestData;
32
33import org.testng.annotations.Test;
34
35import java.util.*;
36import java.util.function.Function;
37import java.util.stream.BaseStream;
38import java.util.stream.Stream;
39import java.util.stream.IntStream;
40import java.util.stream.LongStream;
41import java.util.stream.DoubleStream;
42
43import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.*;
44import static org.testng.Assert.assertEquals;
45
46
47/**
48 * ToArrayOpTest
49 *
50 */
51@Test
52public class ToArrayOpTest extends OpTestCase {
53
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)
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)
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)
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)
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)
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
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)
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
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