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