1 /*
2  * Copyright (c) 2012, 2017, 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 
24 /*
25  * @test
26  * @summary flat-map operations
27  * @bug 8044047 8076458 8075939
28  */
29 
30 package org.openjdk.tests.java.util.stream;
31 
32 import org.testng.annotations.Test;
33 
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.concurrent.atomic.AtomicInteger;
38 import java.util.function.Function;
39 import java.util.function.Supplier;
40 import java.util.stream.DoubleStream;
41 import java.util.stream.DoubleStreamTestDataProvider;
42 import java.util.stream.IntStream;
43 import java.util.stream.IntStreamTestDataProvider;
44 import java.util.stream.LongStream;
45 import java.util.stream.LongStreamTestDataProvider;
46 import java.util.stream.OpTestCase;
47 import java.util.stream.Stream;
48 import java.util.stream.StreamTestDataProvider;
49 import java.util.stream.TestData;
50 
51 import static java.util.stream.LambdaTestHelpers.*;
52 import static java.util.stream.ThrowableHelper.checkNPE;
53 
54 @Test
55 public class FlatMapOpTest extends OpTestCase {
56 
57     @Test
testNullMapper()58     public void testNullMapper() {
59         checkNPE(() -> Stream.of(1).flatMap(null));
60         checkNPE(() -> IntStream.of(1).flatMap(null));
61         checkNPE(() -> LongStream.of(1).flatMap(null));
62         checkNPE(() -> DoubleStream.of(1).flatMap(null));
63     }
64 
65     static final Function<Integer, Stream<Integer>> integerRangeMapper
66             = e -> IntStream.range(0, e).boxed();
67 
68     @Test
testFlatMap()69     public void testFlatMap() {
70         String[] stringsArray = {"hello", "there", "", "yada"};
71         Stream<String> strings = Arrays.asList(stringsArray).stream();
72         assertConcat(strings.flatMap(flattenChars).iterator(), "hellothereyada");
73 
74         assertCountSum(countTo(10).stream().flatMap(mfId), 10, 55);
75         assertCountSum(countTo(10).stream().flatMap(mfNull), 0, 0);
76         assertCountSum(countTo(3).stream().flatMap(mfLt), 6, 4);
77 
78         exerciseOps(TestData.Factory.ofArray("stringsArray", stringsArray), s -> s.flatMap(flattenChars));
79         exerciseOps(TestData.Factory.ofArray("LONG_STRING", new String[] {LONG_STRING}), s -> s.flatMap(flattenChars));
80     }
81 
82     @Test
testClose()83     public void testClose() {
84         AtomicInteger before = new AtomicInteger();
85         AtomicInteger onClose = new AtomicInteger();
86 
87         Supplier<Stream<Integer>> s = () -> {
88             before.set(0); onClose.set(0);
89             return Stream.of(1, 2).peek(e -> before.getAndIncrement());
90         };
91 
92         s.get().flatMap(i -> Stream.of(i, i).onClose(onClose::getAndIncrement)).count();
93         assertEquals(before.get(), onClose.get());
94 
95         s.get().flatMapToInt(i -> IntStream.of(i, i).onClose(onClose::getAndIncrement)).count();
96         assertEquals(before.get(), onClose.get());
97 
98         s.get().flatMapToLong(i -> LongStream.of(i, i).onClose(onClose::getAndIncrement)).count();
99         assertEquals(before.get(), onClose.get());
100 
101         s.get().flatMapToDouble(i -> DoubleStream.of(i, i).onClose(onClose::getAndIncrement)).count();
102         assertEquals(before.get(), onClose.get());
103     }
104 
105     @Test
testIntClose()106     public void testIntClose() {
107         AtomicInteger before = new AtomicInteger();
108         AtomicInteger onClose = new AtomicInteger();
109 
110         IntStream.of(1, 2).peek(e -> before.getAndIncrement()).
111                 flatMap(i -> IntStream.of(i, i).onClose(onClose::getAndIncrement)).count();
112         assertEquals(before.get(), onClose.get());
113     }
114 
115     @Test
testLongClose()116     public void testLongClose() {
117         AtomicInteger before = new AtomicInteger();
118         AtomicInteger onClose = new AtomicInteger();
119 
120         LongStream.of(1, 2).peek(e -> before.getAndIncrement()).
121                 flatMap(i -> LongStream.of(i, i).onClose(onClose::getAndIncrement)).count();
122         assertEquals(before.get(), onClose.get());
123     }
124 
125     @Test
testDoubleClose()126     public void testDoubleClose() {
127         AtomicInteger before = new AtomicInteger();
128         AtomicInteger onClose = new AtomicInteger();
129 
130         DoubleStream.of(1, 2).peek(e -> before.getAndIncrement()).
131                 flatMap(i -> DoubleStream.of(i, i).onClose(onClose::getAndIncrement)).count();
132         assertEquals(before.get(), onClose.get());
133     }
134 
135     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testOps(String name, TestData.OfRef<Integer> data)136     public void testOps(String name, TestData.OfRef<Integer> data) {
137         Collection<Integer> result = exerciseOps(data, s -> s.flatMap(mfId));
138         assertEquals(data.size(), result.size());
139 
140         result = exerciseOps(data, s -> s.flatMap(mfNull));
141         assertEquals(0, result.size());
142 
143         result = exerciseOps(data, s-> s.flatMap(e -> Stream.empty()));
144         assertEquals(0, result.size());
145     }
146 
147     @Test(dataProvider = "StreamTestData<Integer>.small", dataProviderClass = StreamTestDataProvider.class)
testOpsX(String name, TestData.OfRef<Integer> data)148     public void testOpsX(String name, TestData.OfRef<Integer> data) {
149         exerciseOps(data, s -> s.flatMap(mfLt));
150         exerciseOps(data, s -> s.flatMap(integerRangeMapper));
151         exerciseOps(data, s -> s.flatMap((Integer e) -> IntStream.range(0, e).boxed().limit(10)));
152     }
153 
154     @Test
testOpsShortCircuit()155     public void testOpsShortCircuit() {
156         AtomicInteger count = new AtomicInteger();
157         Stream.of(0).flatMap(i -> IntStream.range(0, 100).boxed()).
158                 peek(i -> count.incrementAndGet()).
159                 limit(10).toArray();
160         assertEquals(count.get(), 10);
161     }
162 
163     //
164 
165     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
testIntOps(String name, TestData.OfInt data)166     public void testIntOps(String name, TestData.OfInt data) {
167         Collection<Integer> result = exerciseOps(data, s -> s.flatMap(IntStream::of));
168         assertEquals(data.size(), result.size());
169         assertContents(data, result);
170 
171         result = exerciseOps(data, s -> s.boxed().flatMapToInt(IntStream::of));
172         assertEquals(data.size(), result.size());
173         assertContents(data, result);
174 
175         result = exerciseOps(data, s -> s.flatMap(i -> IntStream.empty()));
176         assertEquals(0, result.size());
177     }
178 
179     @Test(dataProvider = "IntStreamTestData.small", dataProviderClass = IntStreamTestDataProvider.class)
testIntOpsX(String name, TestData.OfInt data)180     public void testIntOpsX(String name, TestData.OfInt data) {
181         exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, e)));
182         exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, e).limit(10)));
183 
184         exerciseOps(data, s -> s.boxed().flatMapToInt(e -> IntStream.range(0, e)));
185         exerciseOps(data, s -> s.boxed().flatMapToInt(e -> IntStream.range(0, e).limit(10)));
186     }
187 
188     @Test
testIntOpsShortCircuit()189     public void testIntOpsShortCircuit() {
190         AtomicInteger count = new AtomicInteger();
191         IntStream.of(0).flatMap(i -> IntStream.range(0, 100)).
192                 peek(i -> count.incrementAndGet()).
193                 limit(10).toArray();
194         assertEquals(count.get(), 10);
195 
196         count.set(0);
197         Stream.of(0).flatMapToInt(i -> IntStream.range(0, 100)).
198                 peek(i -> count.incrementAndGet()).
199                 limit(10).toArray();
200         assertEquals(count.get(), 10);
201     }
202 
203     //
204 
205     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
testLongOps(String name, TestData.OfLong data)206     public void testLongOps(String name, TestData.OfLong data) {
207         Collection<Long> result = exerciseOps(data, s -> s.flatMap(LongStream::of));
208         assertEquals(data.size(), result.size());
209         assertContents(data, result);
210 
211         result = exerciseOps(data, s -> s.boxed().flatMapToLong(LongStream::of));
212         assertEquals(data.size(), result.size());
213         assertContents(data, result);
214 
215         result = exerciseOps(data, s -> LongStream.empty());
216         assertEquals(0, result.size());
217     }
218 
219     @Test(dataProvider = "LongStreamTestData.small", dataProviderClass = LongStreamTestDataProvider.class)
testLongOpsX(String name, TestData.OfLong data)220     public void testLongOpsX(String name, TestData.OfLong data) {
221         exerciseOps(data, s -> s.flatMap(e -> LongStream.range(0, e)));
222         exerciseOps(data, s -> s.flatMap(e -> LongStream.range(0, e).limit(10)));
223     }
224 
225     @Test
testLongOpsShortCircuit()226     public void testLongOpsShortCircuit() {
227         AtomicInteger count = new AtomicInteger();
228         LongStream.of(0).flatMap(i -> LongStream.range(0, 100)).
229                 peek(i -> count.incrementAndGet()).
230                 limit(10).toArray();
231         assertEquals(count.get(), 10);
232 
233         count.set(0);
234         Stream.of(0).flatMapToLong(i -> LongStream.range(0, 100)).
235                 peek(i -> count.incrementAndGet()).
236                 limit(10).toArray();
237         assertEquals(count.get(), 10);
238     }
239 
240     //
241 
242     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
testDoubleOps(String name, TestData.OfDouble data)243     public void testDoubleOps(String name, TestData.OfDouble data) {
244         Collection<Double> result = exerciseOps(data, s -> s.flatMap(DoubleStream::of));
245         assertEquals(data.size(), result.size());
246         assertContents(data, result);
247 
248         result = exerciseOps(data, s -> s.boxed().flatMapToDouble(DoubleStream::of));
249         assertEquals(data.size(), result.size());
250         assertContents(data, result);
251 
252         result = exerciseOps(data, s -> DoubleStream.empty());
253         assertEquals(0, result.size());
254     }
255 
256     @Test(dataProvider = "DoubleStreamTestData.small", dataProviderClass = DoubleStreamTestDataProvider.class)
testDoubleOpsX(String name, TestData.OfDouble data)257     public void testDoubleOpsX(String name, TestData.OfDouble data) {
258         exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, (int) e).asDoubleStream()));
259         exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, (int) e).limit(10).asDoubleStream()));
260     }
261 
262     @Test
testDoubleOpsShortCircuit()263     public void testDoubleOpsShortCircuit() {
264         AtomicInteger count = new AtomicInteger();
265         DoubleStream.of(0).flatMap(i -> IntStream.range(0, 100).asDoubleStream()).
266                 peek(i -> count.incrementAndGet()).
267                 limit(10).toArray();
268         assertEquals(count.get(), 10);
269 
270         count.set(0);
271         Stream.of(0).flatMapToDouble(i -> IntStream.range(0, 100).asDoubleStream()).
272                 peek(i -> count.incrementAndGet()).
273                 limit(10).toArray();
274         assertEquals(count.get(), 10);
275     }
276 }
277