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.SpliteratorTestHelper;
31import org.openjdk.testlib.java.util.stream.StreamTestDataProvider;
32import org.openjdk.testlib.java.util.stream.TestData;
33
34import java.util.Arrays;
35import java.util.Comparator;
36import java.util.List;
37import java.util.Spliterator;
38import java.util.function.Consumer;
39import java.util.function.DoubleConsumer;
40import java.util.function.Function;
41import java.util.function.IntConsumer;
42import java.util.function.LongConsumer;
43import java.util.function.UnaryOperator;
44import java.util.stream.DoubleStream;
45import java.util.stream.IntStream;
46import java.util.stream.LongStream;
47import java.util.stream.Stream;
48import java.util.stream.StreamSupport;
49
50import org.testng.Assert;
51import org.testng.annotations.Test;
52
53import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.countTo;
54import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.dpEven;
55import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.ipEven;
56import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.irDoubler;
57import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.lpEven;
58import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.mDoubler;
59import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.pEven;
60import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.permuteStreamFunctions;
61
62@Test
63public class StreamSpliteratorTest extends OpTestCase {
64
65    private static class ProxyNoExactSizeSpliterator<T> implements Spliterator<T> {
66        final Spliterator<T> sp;
67        final boolean proxyEstimateSize;
68        int splits = 0;
69        int prefixSplits = 0;
70
71        long sizeOnTraversal = -1;
72
73        ProxyNoExactSizeSpliterator(Spliterator<T> sp, boolean proxyEstimateSize) {
74            this.sp = sp;
75            this.proxyEstimateSize = proxyEstimateSize;
76        }
77
78        @Override
79        public Spliterator<T> trySplit() {
80            splits++;
81            Spliterator<T> prefix = sp.trySplit();
82            if (prefix != null)
83                prefixSplits++;
84            return prefix;
85        }
86
87        @Override
88        public boolean tryAdvance(Consumer<? super T> consumer) {
89            if (sizeOnTraversal == -1)
90                sizeOnTraversal = sp.getExactSizeIfKnown();
91            return sp.tryAdvance(consumer);
92        }
93
94        @Override
95        public void forEachRemaining(Consumer<? super T> consumer) {
96            sizeOnTraversal = sp.getExactSizeIfKnown();
97            sp.forEachRemaining(consumer);
98        }
99
100        @Override
101        public long estimateSize() {
102            return proxyEstimateSize ? sp.estimateSize() : Long.MAX_VALUE;
103        }
104
105        @Override
106        public Comparator<? super T> getComparator() {
107            return sp.getComparator();
108        }
109
110        @Override
111        public int characteristics() {
112            if (proxyEstimateSize)
113                return sp.characteristics();
114            else
115                return sp.characteristics() & ~(Spliterator.SUBSIZED | Spliterator.SIZED);
116        }
117
118        private static class OfInt extends ProxyNoExactSizeSpliterator<Integer> implements Spliterator.OfInt {
119            final Spliterator.OfInt psp;
120
121            private OfInt(Spliterator.OfInt sp, boolean proxyEstimateSize) {
122                super(sp, proxyEstimateSize);
123                this.psp = sp;
124            }
125
126            @Override
127            public Spliterator.OfInt trySplit() {
128                splits++;
129                Spliterator.OfInt prefix = psp.trySplit();
130                if (prefix != null)
131                    prefixSplits++;
132                return prefix;
133            }
134
135            @Override
136            public boolean tryAdvance(Consumer<? super Integer> consumer) {
137                return Spliterator.OfInt.super.tryAdvance(consumer);
138            }
139
140            @Override
141            public void forEachRemaining(Consumer<? super Integer> consumer) {
142                Spliterator.OfInt.super.forEachRemaining(consumer);
143            }
144
145            @Override
146            public boolean tryAdvance(IntConsumer consumer) {
147                if (sizeOnTraversal == -1)
148                    sizeOnTraversal = sp.getExactSizeIfKnown();
149                return psp.tryAdvance(consumer);
150            }
151
152            @Override
153            public void forEachRemaining(IntConsumer consumer) {
154                sizeOnTraversal = sp.getExactSizeIfKnown();
155                psp.forEachRemaining(consumer);
156            }
157        }
158
159        private static class OfLong extends ProxyNoExactSizeSpliterator<Long> implements Spliterator.OfLong {
160            final Spliterator.OfLong psp;
161
162            private OfLong(Spliterator.OfLong sp, boolean proxyEstimateSize) {
163                super(sp, proxyEstimateSize);
164                this.psp = sp;
165            }
166
167            @Override
168            public Spliterator.OfLong trySplit() {
169                splits++;
170                Spliterator.OfLong prefix = psp.trySplit();
171                if (prefix != null)
172                    prefixSplits++;
173                return prefix;
174            }
175
176            @Override
177            public boolean tryAdvance(Consumer<? super Long> consumer) {
178                return Spliterator.OfLong.super.tryAdvance(consumer);
179            }
180
181            @Override
182            public void forEachRemaining(Consumer<? super Long> consumer) {
183                Spliterator.OfLong.super.forEachRemaining(consumer);
184            }
185
186            @Override
187            public boolean tryAdvance(LongConsumer consumer) {
188                if (sizeOnTraversal == -1)
189                    sizeOnTraversal = sp.getExactSizeIfKnown();
190                return psp.tryAdvance(consumer);
191            }
192
193            @Override
194            public void forEachRemaining(LongConsumer consumer) {
195                sizeOnTraversal = sp.getExactSizeIfKnown();
196                psp.forEachRemaining(consumer);
197            }
198        }
199
200        private static class OfDouble extends ProxyNoExactSizeSpliterator<Double>
201                implements Spliterator.OfDouble {
202            final Spliterator.OfDouble psp;
203
204            private OfDouble(Spliterator.OfDouble sp, boolean proxyEstimateSize) {
205                super(sp, proxyEstimateSize);
206                this.psp = sp;
207            }
208
209            @Override
210            public Spliterator.OfDouble trySplit() {
211                splits++;
212                Spliterator.OfDouble prefix = psp.trySplit();
213                if (prefix != null)
214                    prefixSplits++;
215                return prefix;
216            }
217
218            @Override
219            public boolean tryAdvance(Consumer<? super Double> consumer) {
220                return Spliterator.OfDouble.super.tryAdvance(consumer);
221            }
222
223            @Override
224            public void forEachRemaining(Consumer<? super Double> consumer) {
225                Spliterator.OfDouble.super.forEachRemaining(consumer);
226            }
227
228            @Override
229            public boolean tryAdvance(DoubleConsumer consumer) {
230                if (sizeOnTraversal == -1)
231                    sizeOnTraversal = sp.getExactSizeIfKnown();
232                return psp.tryAdvance(consumer);
233            }
234
235            @Override
236            public void forEachRemaining(DoubleConsumer consumer) {
237                sizeOnTraversal = sp.getExactSizeIfKnown();
238                psp.forEachRemaining(consumer);
239            }
240        }
241    }
242
243    public void testSplitting() {
244        // Size is assumed to be larger than the target size for no splitting
245        // @@@ Need way to obtain the target size
246        List<Integer> l = countTo(1000);
247
248        List<Consumer<Stream<Integer>>> terminalOps = Arrays.asList(
249                s -> s.toArray(),
250                s -> s.forEach(e -> { }),
251                s -> s.reduce(Integer::sum)
252        );
253
254        List<UnaryOperator<Stream<Integer>>> intermediateOps = Arrays.asList(
255                s -> s.parallel(),
256                // The following ensures the wrapping spliterator is tested
257                s -> s.map(LambdaTestHelpers.identity()).parallel()
258        );
259
260        for (int i = 0; i < terminalOps.size(); i++) {
261            setContext("termOpIndex", i);
262            Consumer<Stream<Integer>> terminalOp = terminalOps.get(i);
263            for (int j = 0; j < intermediateOps.size(); j++) {
264                setContext("intOpIndex", j);
265                UnaryOperator<Stream<Integer>> intermediateOp = intermediateOps.get(j);
266                for (boolean proxyEstimateSize : new boolean[] {false, true}) {
267                    setContext("proxyEstimateSize", proxyEstimateSize);
268                    Spliterator<Integer> sp = intermediateOp.apply(l.stream()).spliterator();
269                    ProxyNoExactSizeSpliterator<Integer> psp = new ProxyNoExactSizeSpliterator<>(sp, proxyEstimateSize);
270                    Stream<Integer> s = StreamSupport.stream(psp, true);
271                    terminalOp.accept(s);
272                    Assert.assertTrue(psp.splits > 0,
273                                      String.format("Number of splits should be greater that zero when proxyEstimateSize is %s",
274                                                    proxyEstimateSize));
275                    Assert.assertTrue(psp.prefixSplits > 0,
276                                      String.format("Number of non-null prefix splits should be greater that zero when proxyEstimateSize is %s",
277                                                    proxyEstimateSize));
278                    Assert.assertTrue(psp.sizeOnTraversal < l.size(),
279                                      String.format("Size on traversal of last split should be less than the size of the list, %d, when proxyEstimateSize is %s",
280                                                    l.size(), proxyEstimateSize));
281                }
282            }
283        }
284    }
285
286    @Test(dataProvider = "StreamTestData<Integer>",
287          dataProviderClass = StreamTestDataProvider.class,
288          groups = { "serialization-hostile" })
289    public void testStreamSpliterators(String name, TestData.OfRef<Integer> data) {
290        for (Function<Stream<Integer>, Stream<Integer>> f : streamFunctions()) {
291            withData(data).
292                    stream((Stream<Integer> in) -> {
293                        Stream<Integer> out = f.apply(in);
294                        return StreamSupport.stream(() -> out.spliterator(), OpTestCase.getStreamFlags(out), false);
295                    }).
296                    exercise();
297
298            withData(data).
299                    stream((Stream<Integer> in) -> {
300                        Stream<Integer> out = f.apply(in);
301                        return StreamSupport.stream(() -> out.spliterator(), OpTestCase.getStreamFlags(out), true);
302                    }).
303                    exercise();
304        }
305    }
306
307    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
308    public void testSpliterators(String name, TestData.OfRef<Integer> data) {
309        for (Function<Stream<Integer>, Stream<Integer>> f : streamFunctions()) {
310            SpliteratorTestHelper.testSpliterator(() -> f.apply(data.stream()).spliterator());
311        }
312    }
313
314    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
315    public void testParSpliterators(String name, TestData.OfRef<Integer> data) {
316        for (Function<Stream<Integer>, Stream<Integer>> f : streamFunctions()) {
317            SpliteratorTestHelper.testSpliterator(() -> f.apply(data.parallelStream()).spliterator());
318        }
319    }
320
321    private List<Function<Stream<Integer>, Stream<Integer>>> streamFunctions;
322
323    List<Function<Stream<Integer>, Stream<Integer>>> streamFunctions() {
324        if (streamFunctions == null) {
325            List<Function<Stream<Integer>, Stream<Integer>>> opFunctions = Arrays.asList(
326                    s -> s.filter(pEven),
327                    s -> s.map(mDoubler),
328                    // @@@ Add distinct once asserting results with or without order
329                    //     is correctly supported
330//                    s -> s.distinct(),
331                    s -> s.sorted());
332
333            streamFunctions = permuteStreamFunctions(opFunctions);
334        }
335
336        return streamFunctions;
337    }
338
339    //
340
341    public void testIntSplitting() {
342        List<Consumer<IntStream>> terminalOps = Arrays.asList(
343                s -> s.toArray(),
344                s -> s.forEach(e -> {}),
345                s -> s.reduce(Integer::sum)
346        );
347
348        List<UnaryOperator<IntStream>> intermediateOps = Arrays.asList(
349                s -> s.parallel(),
350                // The following ensures the wrapping spliterator is tested
351                s -> s.map(i -> i).parallel()
352        );
353
354        for (int i = 0; i < terminalOps.size(); i++) {
355            setContext("termOpIndex", i);
356            Consumer<IntStream> terminalOp = terminalOps.get(i);
357            for (int j = 0; j < intermediateOps.size(); j++) {
358                setContext("intOpIndex", j);
359                UnaryOperator<IntStream> intermediateOp = intermediateOps.get(j);
360                for (boolean proxyEstimateSize : new boolean[] {false, true}) {
361                    setContext("proxyEstimateSize", proxyEstimateSize);
362                    // Size is assumed to be larger than the target size for no splitting
363                    // @@@ Need way to obtain the target size
364                    Spliterator.OfInt sp = intermediateOp.apply(IntStream.range(0, 1000)).spliterator();
365                    ProxyNoExactSizeSpliterator.OfInt psp = new ProxyNoExactSizeSpliterator.OfInt(sp, proxyEstimateSize);
366                    IntStream s = StreamSupport.intStream(psp, true);
367                    terminalOp.accept(s);
368                    Assert.assertTrue(psp.splits > 0,
369                                      String.format("Number of splits should be greater that zero when proxyEstimateSize is %s",
370                                                    proxyEstimateSize));
371                    Assert.assertTrue(psp.prefixSplits > 0,
372                                      String.format("Number of non-null prefix splits should be greater that zero when proxyEstimateSize is %s",
373                                                    proxyEstimateSize));
374                    Assert.assertTrue(psp.sizeOnTraversal < 1000,
375                                      String.format("Size on traversal of last split should be less than the size of the list, %d, when proxyEstimateSize is %s",
376                                                    1000, proxyEstimateSize));
377                }
378            }
379        }
380    }
381
382    @Test(dataProvider = "IntStreamTestData",
383          dataProviderClass = IntStreamTestDataProvider.class,
384          groups = { "serialization-hostile" })
385    public void testIntStreamSpliterators(String name, TestData.OfInt data) {
386        for (Function<IntStream, IntStream> f : intStreamFunctions()) {
387            withData(data).
388                    stream(in -> {
389                        IntStream out = f.apply(in);
390                        return StreamSupport.intStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out), false);
391                    }).
392                    exercise();
393
394            withData(data).
395                    stream((in) -> {
396                        IntStream out = f.apply(in);
397                        return StreamSupport.intStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out), true);
398                    }).
399                    exercise();
400        }
401    }
402
403    @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
404    public void testIntSpliterators(String name, TestData.OfInt data) {
405        for (Function<IntStream, IntStream> f : intStreamFunctions()) {
406            SpliteratorTestHelper.testIntSpliterator(() -> f.apply(data.stream()).spliterator());
407        }
408    }
409
410    @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
411    public void testIntParSpliterators(String name, TestData.OfInt data) {
412        for (Function<IntStream, IntStream> f : intStreamFunctions()) {
413            SpliteratorTestHelper.testIntSpliterator(() -> f.apply(data.parallelStream()).spliterator());
414        }
415    }
416
417    private List<Function<IntStream, IntStream>> intStreamFunctions;
418
419    List<Function<IntStream, IntStream>> intStreamFunctions() {
420        if (intStreamFunctions == null) {
421            List<Function<IntStream, IntStream>> opFunctions = Arrays.asList(
422                    s -> s.filter(ipEven),
423                    s -> s.map(irDoubler),
424                    s -> s.sorted());
425
426            intStreamFunctions = permuteStreamFunctions(opFunctions);
427        }
428
429        return intStreamFunctions;
430    }
431
432    //
433
434    public void testLongSplitting() {
435        List<Consumer<LongStream>> terminalOps = Arrays.asList(
436                s -> s.toArray(),
437                s -> s.forEach(e -> {}),
438                s -> s.reduce(Long::sum)
439        );
440
441        List<UnaryOperator<LongStream>> intermediateOps = Arrays.asList(
442                s -> s.parallel(),
443                // The following ensures the wrapping spliterator is tested
444                s -> s.map(i -> i).parallel()
445        );
446
447        for (int i = 0; i < terminalOps.size(); i++) {
448            Consumer<LongStream> terminalOp = terminalOps.get(i);
449            setContext("termOpIndex", i);
450            for (int j = 0; j < intermediateOps.size(); j++) {
451                setContext("intOpIndex", j);
452                UnaryOperator<LongStream> intermediateOp = intermediateOps.get(j);
453                for (boolean proxyEstimateSize : new boolean[] {false, true}) {
454                    setContext("proxyEstimateSize", proxyEstimateSize);
455                    // Size is assumed to be larger than the target size for no splitting
456                    // @@@ Need way to obtain the target size
457                    Spliterator.OfLong sp = intermediateOp.apply(LongStream.range(0, 1000)).spliterator();
458                    ProxyNoExactSizeSpliterator.OfLong psp = new ProxyNoExactSizeSpliterator.OfLong(sp, proxyEstimateSize);
459                    LongStream s = StreamSupport.longStream(psp, true);
460                    terminalOp.accept(s);
461                    Assert.assertTrue(psp.splits > 0,
462                                      String.format("Number of splits should be greater that zero when proxyEstimateSize is %s",
463                                                    proxyEstimateSize));
464                    Assert.assertTrue(psp.prefixSplits > 0,
465                                      String.format("Number of non-null prefix splits should be greater that zero when proxyEstimateSize is %s",
466                                                    proxyEstimateSize));
467                    Assert.assertTrue(psp.sizeOnTraversal < 1000,
468                                      String.format("Size on traversal of last split should be less than the size of the list, %d, when proxyEstimateSize is %s",
469                                                    1000, proxyEstimateSize));
470                }
471            }
472        }
473    }
474
475    @Test(dataProvider = "LongStreamTestData",
476          dataProviderClass = LongStreamTestDataProvider.class,
477          groups = { "serialization-hostile" })
478    public void testLongStreamSpliterators(String name, TestData.OfLong data) {
479        for (Function<LongStream, LongStream> f : longStreamFunctions()) {
480            withData(data).
481                    stream(in -> {
482                        LongStream out = f.apply(in);
483                        return StreamSupport.longStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out), false);
484                    }).
485                    exercise();
486
487            withData(data).
488                    stream((in) -> {
489                        LongStream out = f.apply(in);
490                        return StreamSupport.longStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out), true);
491                    }).
492                    exercise();
493        }
494    }
495
496    @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
497    public void testLongSpliterators(String name, TestData.OfLong data) {
498        for (Function<LongStream, LongStream> f : longStreamFunctions()) {
499            SpliteratorTestHelper.testLongSpliterator(() -> f.apply(data.stream()).spliterator());
500        }
501    }
502
503    @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
504    public void testLongParSpliterators(String name, TestData.OfLong data) {
505        for (Function<LongStream, LongStream> f : longStreamFunctions()) {
506            SpliteratorTestHelper.testLongSpliterator(() -> f.apply(data.parallelStream()).spliterator());
507        }
508    }
509
510    private List<Function<LongStream, LongStream>> longStreamFunctions;
511
512    List<Function<LongStream, LongStream>> longStreamFunctions() {
513        if (longStreamFunctions == null) {
514            List<Function<LongStream, LongStream>> opFunctions = Arrays.asList(
515                    s -> s.filter(lpEven),
516                    s -> s.map(x -> x * 2L),
517                    s -> s.sorted());
518
519            longStreamFunctions = permuteStreamFunctions(opFunctions);
520        }
521
522        return longStreamFunctions;
523    }
524
525    //
526
527    public void testDoubleSplitting() {
528        List<Consumer<DoubleStream>> terminalOps = Arrays.asList(
529                s -> s.toArray(),
530                s -> s.forEach(e -> {}),
531                s -> s.reduce(Double::sum)
532        );
533
534        List<UnaryOperator<DoubleStream>> intermediateOps = Arrays.asList(
535                s -> s.parallel(),
536                // The following ensures the wrapping spliterator is tested
537                s -> s.map(i -> i).parallel()
538        );
539
540        for (int i = 0; i < terminalOps.size(); i++) {
541            Consumer<DoubleStream> terminalOp = terminalOps.get(i);
542            setContext("termOpIndex", i);
543            for (int j = 0; j < intermediateOps.size(); j++) {
544                UnaryOperator<DoubleStream> intermediateOp = intermediateOps.get(j);
545                setContext("intOpIndex", j);
546                for (boolean proxyEstimateSize : new boolean[] {false, true}) {
547                    setContext("proxyEstimateSize", proxyEstimateSize);
548                    // Size is assumed to be larger than the target size for no splitting
549                    // @@@ Need way to obtain the target size
550                    Spliterator.OfDouble sp = intermediateOp.apply(IntStream.range(0, 1000).asDoubleStream()).spliterator();
551                    ProxyNoExactSizeSpliterator.OfDouble psp = new ProxyNoExactSizeSpliterator.OfDouble(sp, proxyEstimateSize);
552                    DoubleStream s = StreamSupport.doubleStream(psp, true);
553                    terminalOp.accept(s);
554                    Assert.assertTrue(psp.splits > 0,
555                                      String.format("Number of splits should be greater that zero when proxyEstimateSize is %s",
556                                                    proxyEstimateSize));
557                    Assert.assertTrue(psp.prefixSplits > 0,
558                                      String.format("Number of non-null prefix splits should be greater that zero when proxyEstimateSize is %s",
559                                                    proxyEstimateSize));
560                    Assert.assertTrue(psp.sizeOnTraversal < 1000,
561                                      String.format("Size on traversal of last split should be less than the size of the list, %d, when proxyEstimateSize is %s",
562                                                    1000, proxyEstimateSize));
563                }
564            }
565        }
566    }
567
568    @Test(dataProvider = "DoubleStreamTestData",
569          dataProviderClass = DoubleStreamTestDataProvider.class,
570          groups = { "serialization-hostile" })
571    public void testDoubleStreamSpliterators(String name, TestData.OfDouble data) {
572        for (Function<DoubleStream, DoubleStream> f : doubleStreamFunctions()) {
573            withData(data).
574                    stream(in -> {
575                        DoubleStream out = f.apply(in);
576                        return StreamSupport.doubleStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out), false);
577                    }).
578                    exercise();
579
580            withData(data).
581                    stream((in) -> {
582                        DoubleStream out = f.apply(in);
583                        return StreamSupport.doubleStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out), true);
584                    }).
585                    exercise();
586        }
587    }
588
589    @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
590    public void testDoubleSpliterators(String name, TestData.OfDouble data) {
591        for (Function<DoubleStream, DoubleStream> f : doubleStreamFunctions()) {
592            SpliteratorTestHelper.testDoubleSpliterator(() -> f.apply(data.stream()).spliterator());
593        }
594    }
595
596    @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
597    public void testDoubleParSpliterators(String name, TestData.OfDouble data) {
598        for (Function<DoubleStream, DoubleStream> f : doubleStreamFunctions()) {
599            SpliteratorTestHelper.testDoubleSpliterator(() -> f.apply(data.parallelStream()).spliterator());
600        }
601    }
602
603    private List<Function<DoubleStream, DoubleStream>> doubleStreamFunctions;
604
605    List<Function<DoubleStream, DoubleStream>> doubleStreamFunctions() {
606        if (doubleStreamFunctions == null) {
607            List<Function<DoubleStream, DoubleStream>> opFunctions = Arrays.asList(
608                    s -> s.filter(dpEven),
609                    s -> s.map(x -> x * 2.0),
610                    s -> s.sorted());
611
612            doubleStreamFunctions = permuteStreamFunctions(opFunctions);
613        }
614
615        return doubleStreamFunctions;
616    }
617}
618