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 java.util.stream;
24 
25 import org.testng.annotations.Test;
26 
27 import java.util.function.Function;
28 
29 import static org.testng.Assert.fail;
30 
31 /**
32  * StreamReuseTest
33  *
34  * @author Brian Goetz
35  */
36 @Test
37 public class StreamReuseTest {
38 
assertSecondFails( D data, Function<S, T> first, Function<S, U> second, Class<? extends Throwable> exception, String text)39     private <T, U, E, S extends BaseStream<E, S>, D extends TestData<E, S>> void assertSecondFails(
40             D data,
41             Function<S, T> first,
42             Function<S, U> second,
43             Class<? extends Throwable> exception,
44             String text) {
45         S stream = data.stream();
46         T fr = first.apply(stream);
47         try {
48             U sr = second.apply(stream);
49             fail(text + " (seq)");
50         }
51         catch (Throwable e) {
52             if (exception.isAssignableFrom(e.getClass())) {
53                 // Expected
54             }
55             else if (e instanceof Error)
56                 throw (Error) e;
57             else if (e instanceof RuntimeException)
58                 throw (RuntimeException) e;
59             else
60                 throw new AssertionError("Unexpected exception " + e.getClass(), e);
61         }
62 
63         stream = data.parallelStream();
64         fr = first.apply(stream);
65         try {
66             U sr = second.apply(stream);
67             fail(text + " (par)");
68         }
69         catch (Throwable e) {
70             if (exception.isAssignableFrom(e.getClass())) {
71                 // Expected
72             }
73             else if (e instanceof Error)
74                 throw (Error) e;
75             else if (e instanceof RuntimeException)
76                 throw (RuntimeException) e;
77             else
78                 throw new AssertionError("Unexpected exception " + e.getClass(), e);
79         }
80     }
81 
82     // Stream
83 
84     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testTwoStreams(String name, TestData<Integer, Stream<Integer>> data)85     public void testTwoStreams(String name, TestData<Integer, Stream<Integer>> data) {
86         assertSecondFails(data,
87                           (Stream<Integer> s) -> s.map(i -> i), (Stream<Integer> s) -> s.map(i -> i),
88                           IllegalStateException.class,
89                           "Stream map / map succeeded erroneously");
90         assertSecondFails(data,
91                           Stream::distinct, (Stream<Integer> s) -> s.map(i -> i),
92                           IllegalStateException.class,
93                           "Stream distinct / map succeeded erroneously");
94         assertSecondFails(data,
95                           (Stream<Integer> s) -> s.map(i -> i), Stream::distinct,
96                           IllegalStateException.class,
97                           "Stream map / distinct succeeded erroneously");
98         assertSecondFails(data,
99                           Stream::distinct, Stream::distinct,
100                           IllegalStateException.class,
101                           "Stream distinct / distinct succeeded erroneously");
102     }
103 
104     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testTwoTerminals(String name, TestData<Integer, Stream<Integer>> data)105     public void testTwoTerminals(String name, TestData<Integer, Stream<Integer>> data) {
106         assertSecondFails(data,
107                           Stream::findFirst, Stream::findFirst,
108                           IllegalStateException.class,
109                           "Stream findFirst / findFirst succeeded erroneously");
110     }
111 
112     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testTerminalStream(String name, TestData<Integer, Stream<Integer>> data)113     public void testTerminalStream(String name, TestData<Integer, Stream<Integer>> data) {
114         assertSecondFails(data,
115                           Stream::findFirst, (Stream<Integer> s) -> s.map(i -> i),
116                           IllegalStateException.class,
117                           "Stream findFirst / map succeeded erroneously");
118         assertSecondFails(data,
119                           (Stream<Integer> s) -> s.map(i -> i), Stream::findFirst,
120                           IllegalStateException.class,
121                           "Stream map / findFirst succeeded erroneously");
122         assertSecondFails(data,
123                           Stream::findFirst, Stream::distinct,
124                           IllegalStateException.class,
125                           "Stream findFirst / distinct succeeded erroneously");
126         assertSecondFails(data,
127                           Stream::distinct, Stream::findFirst,
128                           IllegalStateException.class,
129                           "Stream distinct / findFirst succeeded erroneously");
130     }
131 
132     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testTwoIterators(String name, TestData<Integer, Stream<Integer>> data)133     public void testTwoIterators(String name, TestData<Integer, Stream<Integer>> data) {
134         assertSecondFails(data,
135                           Stream::iterator, Stream::iterator,
136                           IllegalStateException.class,
137                           "Stream iterator / iterator succeeded erroneously");
138     }
139 
140     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testTerminalIterator(String name, TestData<Integer, Stream<Integer>> data)141     public void testTerminalIterator(String name, TestData<Integer, Stream<Integer>> data) {
142         assertSecondFails(data,
143                           Stream::iterator, Stream::findFirst,
144                           IllegalStateException.class,
145                           "Stream iterator / findFirst succeeded erroneously");
146         assertSecondFails(data,
147                           Stream::findFirst, Stream::iterator,
148                           IllegalStateException.class,
149                           "Stream findFirst / iterator succeeded erroneously");
150     }
151 
152     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
testStreamIterator(String name, TestData<Integer, Stream<Integer>> data)153     public void testStreamIterator(String name, TestData<Integer, Stream<Integer>> data) {
154         assertSecondFails(data,
155                           Stream::iterator, (Stream<Integer> s) -> s.map(i -> i),
156                           IllegalStateException.class,
157                           "Stream iterator / map succeeded erroneously");
158         assertSecondFails(data,
159                           (Stream<Integer> s) -> s.map(i -> i), Stream::iterator,
160                           IllegalStateException.class,
161                           "Stream map / iterator succeeded erroneously");
162         assertSecondFails(data,
163                           Stream::iterator, Stream::distinct,
164                           IllegalStateException.class,
165                           "Stream iterator / distinct succeeded erroneously");
166         assertSecondFails(data,
167                           Stream::distinct, Stream::iterator,
168                           IllegalStateException.class,
169                           "Stream distinct / iterator succeeded erroneously");
170     }
171 
172     // IntStream
173 
174     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
testTwoStreams(String name, TestData.OfInt data)175     public void testTwoStreams(String name, TestData.OfInt data) {
176         assertSecondFails(data,
177                           (IntStream s) -> s.mapToObj(i -> i), (IntStream s) -> s.mapToObj(i -> i),
178                           IllegalStateException.class,
179                           "IntStream map / map succeeded erroneously");
180         assertSecondFails(data,
181                           IntStream::distinct, (IntStream s) -> s.mapToObj(i -> i),
182                           IllegalStateException.class,
183                           "IntStream distinct / map succeeded erroneously");
184         assertSecondFails(data,
185                           (IntStream s) -> s.mapToObj(i -> i), IntStream::distinct,
186                           IllegalStateException.class,
187                           "IntStream map / distinct succeeded erroneously");
188         assertSecondFails(data,
189                           IntStream::distinct, IntStream::distinct,
190                           IllegalStateException.class,
191                           "IntStream distinct / distinct succeeded erroneously");
192     }
193 
194     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
testTwoTerminals(String name, TestData.OfInt data)195     public void testTwoTerminals(String name, TestData.OfInt data) {
196         assertSecondFails(data,
197                           IntStream::sum, IntStream::sum,
198                           IllegalStateException.class,
199                           "IntStream sum / sum succeeded erroneously");
200     }
201 
202     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
testTerminalStream(String name, TestData.OfInt data)203     public void testTerminalStream(String name, TestData.OfInt data) {
204         assertSecondFails(data,
205                           IntStream::sum, (IntStream s) -> s.mapToObj(i -> i),
206                           IllegalStateException.class,
207                           "IntStream sum / map succeeded erroneously");
208         assertSecondFails(data,
209                           (IntStream s) -> s.mapToObj(i -> i), IntStream::sum,
210                           IllegalStateException.class,
211                           "IntStream map / sum succeeded erroneously");
212         assertSecondFails(data,
213                           IntStream::sum, IntStream::distinct,
214                           IllegalStateException.class,
215                           "IntStream sum / distinct succeeded erroneously");
216         assertSecondFails(data,
217                           IntStream::distinct, IntStream::sum,
218                           IllegalStateException.class,
219                           "IntStream distinct / sum succeeded erroneously");
220     }
221 
222     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
testTwoIterators(String name, TestData.OfInt data)223     public void testTwoIterators(String name, TestData.OfInt data) {
224         assertSecondFails(data,
225                           IntStream::iterator, IntStream::iterator,
226                           IllegalStateException.class,
227                           "IntStream iterator / iterator succeeded erroneously");
228     }
229 
230     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
testTerminalIterator(String name, TestData.OfInt data)231     public void testTerminalIterator(String name, TestData.OfInt data) {
232         assertSecondFails(data,
233                           IntStream::iterator, IntStream::sum,
234                           IllegalStateException.class,
235                           "IntStream iterator / sum succeeded erroneously");
236         assertSecondFails(data,
237                           IntStream::sum, IntStream::iterator,
238                           IllegalStateException.class,
239                           "Stream sum / iterator succeeded erroneously");
240     }
241 
242     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
testStreamIterator(String name, TestData.OfInt data)243     public void testStreamIterator(String name, TestData.OfInt data) {
244         assertSecondFails(data,
245                           IntStream::iterator, (IntStream s) -> s.mapToObj(i -> i),
246                           IllegalStateException.class,
247                           "IntStream iterator / map succeeded erroneously");
248         assertSecondFails(data,
249                           (IntStream s) -> s.mapToObj(i -> i), IntStream::iterator,
250                           IllegalStateException.class,
251                           "IntStream map / iterator succeeded erroneously");
252         assertSecondFails(data,
253                           IntStream::iterator, IntStream::distinct,
254                           IllegalStateException.class,
255                           "IntStream iterator / distinct succeeded erroneously");
256         assertSecondFails(data,
257                           IntStream::distinct, IntStream::iterator,
258                           IllegalStateException.class,
259                           "IntStream distinct / iterator succeeded erroneously");
260     }
261 
262     // LongStream
263 
264     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
testTwoStreams(String name, TestData.OfLong data)265     public void testTwoStreams(String name, TestData.OfLong data) {
266         assertSecondFails(data,
267                           (LongStream s) -> s.mapToObj(i -> i), (LongStream s) -> s.mapToObj(i -> i),
268                           IllegalStateException.class,
269                           "LongStream map / map succeeded erroneously");
270         assertSecondFails(data,
271                           LongStream::distinct, (LongStream s) -> s.mapToObj(i -> i),
272                           IllegalStateException.class,
273                           "LongStream distinct / map succeeded erroneously");
274         assertSecondFails(data,
275                           (LongStream s) -> s.mapToObj(i -> i), LongStream::distinct,
276                           IllegalStateException.class,
277                           "LongStream map / distinct succeeded erroneously");
278         assertSecondFails(data,
279                           LongStream::distinct, LongStream::distinct,
280                           IllegalStateException.class,
281                           "LongStream distinct / distinct succeeded erroneously");
282     }
283 
284     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
testTwoTerminals(String name, TestData.OfLong data)285     public void testTwoTerminals(String name, TestData.OfLong data) {
286         assertSecondFails(data,
287                           LongStream::sum, LongStream::sum,
288                           IllegalStateException.class,
289                           "LongStream sum / sum succeeded erroneously");
290     }
291 
292     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
testTerminalStream(String name, TestData.OfLong data)293     public void testTerminalStream(String name, TestData.OfLong data) {
294         assertSecondFails(data,
295                           LongStream::sum, (LongStream s) -> s.mapToObj(i -> i),
296                           IllegalStateException.class,
297                           "LongStream sum / map succeeded erroneously");
298         assertSecondFails(data,
299                           (LongStream s) -> s.mapToObj(i -> i), LongStream::sum,
300                           IllegalStateException.class,
301                           "LongStream map / sum succeeded erroneously");
302         assertSecondFails(data,
303                           LongStream::sum, LongStream::distinct,
304                           IllegalStateException.class,
305                           "LongStream sum / distinct succeeded erroneously");
306         assertSecondFails(data,
307                           LongStream::distinct, LongStream::sum,
308                           IllegalStateException.class,
309                           "LongStream distinct / sum succeeded erroneously");
310     }
311 
312     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
testTwoIterators(String name, TestData.OfLong data)313     public void testTwoIterators(String name, TestData.OfLong data) {
314         assertSecondFails(data,
315                           LongStream::iterator, LongStream::iterator,
316                           IllegalStateException.class,
317                           "LongStream iterator / iterator succeeded erroneously");
318     }
319 
320     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
testTerminalIterator(String name, TestData.OfLong data)321     public void testTerminalIterator(String name, TestData.OfLong data) {
322         assertSecondFails(data,
323                           LongStream::iterator, LongStream::sum,
324                           IllegalStateException.class,
325                           "LongStream iterator / sum succeeded erroneously");
326         assertSecondFails(data,
327                           LongStream::sum, LongStream::iterator,
328                           IllegalStateException.class,
329                           "Stream sum / iterator succeeded erroneously");
330     }
331 
332     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
testStreamIterator(String name, TestData.OfLong data)333     public void testStreamIterator(String name, TestData.OfLong data) {
334         assertSecondFails(data,
335                           LongStream::iterator, (LongStream s) -> s.mapToObj(i -> i),
336                           IllegalStateException.class,
337                           "LongStream iterator / map succeeded erroneously");
338         assertSecondFails(data,
339                           (LongStream s) -> s.mapToObj(i -> i), LongStream::iterator,
340                           IllegalStateException.class,
341                           "LongStream map / iterator succeeded erroneously");
342         assertSecondFails(data,
343                           LongStream::iterator, LongStream::distinct,
344                           IllegalStateException.class,
345                           "LongStream iterator / distinct succeeded erroneously");
346         assertSecondFails(data,
347                           LongStream::distinct, LongStream::iterator,
348                           IllegalStateException.class,
349                           "LongStream distinct / iterator succeeded erroneously");
350     }
351 
352     // DoubleStream
353 
354     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
testTwoStreams(String name, TestData.OfDouble data)355     public void testTwoStreams(String name, TestData.OfDouble data) {
356         assertSecondFails(data,
357                           (DoubleStream s) -> s.mapToObj(i -> i), (DoubleStream s) -> s.mapToObj(i -> i),
358                           IllegalStateException.class,
359                           "DoubleStream map / map succeeded erroneously");
360         assertSecondFails(data,
361                           DoubleStream::distinct, (DoubleStream s) -> s.mapToObj(i -> i),
362                           IllegalStateException.class,
363                           "DoubleStream distinct / map succeeded erroneously");
364         assertSecondFails(data,
365                           (DoubleStream s) -> s.mapToObj(i -> i), DoubleStream::distinct,
366                           IllegalStateException.class,
367                           "DoubleStream map / distinct succeeded erroneously");
368         assertSecondFails(data,
369                           DoubleStream::distinct, DoubleStream::distinct,
370                           IllegalStateException.class,
371                           "DoubleStream distinct / distinct succeeded erroneously");
372     }
373 
374     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
testTwoTerminals(String name, TestData.OfDouble data)375     public void testTwoTerminals(String name, TestData.OfDouble data) {
376         assertSecondFails(data,
377                           DoubleStream::sum, DoubleStream::sum,
378                           IllegalStateException.class,
379                           "DoubleStream sum / sum succeeded erroneously");
380     }
381 
382     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
testTerminalStream(String name, TestData.OfDouble data)383     public void testTerminalStream(String name, TestData.OfDouble data) {
384         assertSecondFails(data,
385                           DoubleStream::sum, (DoubleStream s) -> s.mapToObj(i -> i),
386                           IllegalStateException.class,
387                           "DoubleStream sum / map succeeded erroneously");
388         assertSecondFails(data,
389                           (DoubleStream s) -> s.mapToObj(i -> i), DoubleStream::sum,
390                           IllegalStateException.class,
391                           "DoubleStream map / sum succeeded erroneously");
392         assertSecondFails(data,
393                           DoubleStream::sum, DoubleStream::distinct,
394                           IllegalStateException.class,
395                           "DoubleStream sum / distinct succeeded erroneously");
396         assertSecondFails(data,
397                           DoubleStream::distinct, DoubleStream::sum,
398                           IllegalStateException.class,
399                           "DoubleStream distinct / sum succeeded erroneously");
400     }
401 
402     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
testTwoIterators(String name, TestData.OfDouble data)403     public void testTwoIterators(String name, TestData.OfDouble data) {
404         assertSecondFails(data,
405                           DoubleStream::iterator, DoubleStream::iterator,
406                           IllegalStateException.class,
407                           "DoubleStream iterator / iterator succeeded erroneously");
408     }
409 
410     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
testTerminalIterator(String name, TestData.OfDouble data)411     public void testTerminalIterator(String name, TestData.OfDouble data) {
412         assertSecondFails(data,
413                           DoubleStream::iterator, DoubleStream::sum,
414                           IllegalStateException.class,
415                           "DoubleStream iterator / sum succeeded erroneously");
416         assertSecondFails(data,
417                           DoubleStream::sum, DoubleStream::iterator,
418                           IllegalStateException.class,
419                           "Stream sum / iterator succeeded erroneously");
420     }
421 
422     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
testStreamIterator(String name, TestData.OfDouble data)423     public void testStreamIterator(String name, TestData.OfDouble data) {
424         assertSecondFails(data,
425                           DoubleStream::iterator, (DoubleStream s) -> s.mapToObj(i -> i),
426                           IllegalStateException.class,
427                           "DoubleStream iterator / map succeeded erroneously");
428         assertSecondFails(data,
429                           (DoubleStream s) -> s.mapToObj(i -> i), DoubleStream::iterator,
430                           IllegalStateException.class,
431                           "DoubleStream map / iterator succeeded erroneously");
432         assertSecondFails(data,
433                           DoubleStream::iterator, DoubleStream::distinct,
434                           IllegalStateException.class,
435                           "DoubleStream iterator / distinct succeeded erroneously");
436         assertSecondFails(data,
437                           DoubleStream::distinct, DoubleStream::iterator,
438                           IllegalStateException.class,
439                           "DoubleStream distinct / iterator succeeded erroneously");
440     }
441 }
442