| /* |
| * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package org.openjdk.tests.java.util; |
| |
| import org.testng.annotations.DataProvider; |
| import org.testng.annotations.Test; |
| |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.Spliterator; |
| import java.util.SplittableRandom; |
| import java.util.function.Consumer; |
| import java.util.function.Function; |
| import java.util.stream.DoubleStream; |
| import java.util.stream.DoubleStreamTestScenario; |
| import java.util.stream.IntStream; |
| import java.util.stream.IntStreamTestScenario; |
| import java.util.stream.LongStream; |
| import java.util.stream.LongStreamTestScenario; |
| import java.util.stream.OpTestCase; |
| import java.util.stream.StreamSupport; |
| import java.util.stream.TestData; |
| |
| @Test |
| public class SplittableRandomTest extends OpTestCase { |
| |
| static class RandomBoxedSpliterator<T> implements Spliterator<T> { |
| final SplittableRandom rng; |
| long index; |
| final long fence; |
| final Function<SplittableRandom, T> rngF; |
| |
| RandomBoxedSpliterator(SplittableRandom rng, long index, long fence, Function<SplittableRandom, T> rngF) { |
| this.rng = rng; |
| this.index = index; |
| this.fence = fence; |
| this.rngF = rngF; |
| } |
| |
| public RandomBoxedSpliterator<T> trySplit() { |
| long i = index, m = (i + fence) >>> 1; |
| return (m <= i) ? null : |
| new RandomBoxedSpliterator<>(rng.split(), i, index = m, rngF); |
| } |
| |
| public long estimateSize() { |
| return fence - index; |
| } |
| |
| public int characteristics() { |
| return (Spliterator.SIZED | Spliterator.SUBSIZED | |
| Spliterator.NONNULL | Spliterator.IMMUTABLE); |
| } |
| |
| @Override |
| public boolean tryAdvance(Consumer<? super T> consumer) { |
| if (consumer == null) throw new NullPointerException(); |
| long i = index, f = fence; |
| if (i < f) { |
| consumer.accept(rngF.apply(rng)); |
| index = i + 1; |
| return true; |
| } |
| return false; |
| } |
| } |
| |
| static final int SIZE = 1 << 16; |
| |
| // Ensure there is a range of a power of 2 |
| static final int[] BOUNDS = {256}; |
| static final int[] ORIGINS = {-16, 0, 16}; |
| |
| static <T extends Comparable<T>> ResultAsserter<Iterable<T>> randomAsserter(int size, T origin, T bound) { |
| return (act, exp, ord, par) -> { |
| int count = 0; |
| Set<Comparable<T>> values = new HashSet<>(); |
| for (Comparable<T> t : act) { |
| if (origin.compareTo(bound) < 0) { |
| assertTrue(t.compareTo(origin) >= 0); |
| assertTrue(t.compareTo(bound) < 0); |
| } |
| values.add(t); |
| count++; |
| } |
| assertEquals(count, size); |
| // Assert that at least one different result is produced |
| // For the size of the data it is highly improbable that this |
| // will cause a false negative (i.e. a false failure) |
| assertTrue(values.size() > 1); |
| }; |
| } |
| |
| @DataProvider(name = "ints") |
| public static Object[][] intsDataProvider() { |
| List<Object[]> data = new ArrayList<>(); |
| |
| // Function to create a stream using a RandomBoxedSpliterator |
| |
| Function<Function<SplittableRandom, Integer>, IntStream> rbsf = |
| sf -> StreamSupport.stream(new RandomBoxedSpliterator<>(new SplittableRandom(), 0, SIZE, sf), false). |
| mapToInt(i -> i); |
| |
| // Unbounded |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofIntSupplier( |
| String.format("new SplittableRandom().ints().limit(%d)", SIZE), |
| () -> new SplittableRandom().ints().limit(SIZE)), |
| randomAsserter(SIZE, Integer.MAX_VALUE, 0) |
| }); |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofIntSupplier( |
| String.format("new SplittableRandom().ints(%d)", SIZE), |
| () -> new SplittableRandom().ints(SIZE)), |
| randomAsserter(SIZE, Integer.MAX_VALUE, 0) |
| }); |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofIntSupplier( |
| String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextInt())", SIZE), |
| () -> rbsf.apply(sr -> sr.nextInt())), |
| randomAsserter(SIZE, Integer.MAX_VALUE, 0) |
| }); |
| |
| // Bounded |
| |
| for (int b : BOUNDS) { |
| for (int o : ORIGINS) { |
| final int origin = o; |
| final int bound = b; |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofIntSupplier( |
| String.format("new SplittableRandom().ints(%d, %d).limit(%d)", origin, bound, SIZE), |
| () -> new SplittableRandom().ints(origin, bound).limit(SIZE)), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofIntSupplier( |
| String.format("new SplittableRandom().ints(%d, %d, %d)", SIZE, origin, bound), |
| () -> new SplittableRandom().ints(SIZE, origin, bound)), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| |
| if (origin == 0) { |
| data.add(new Object[]{ |
| TestData.Factory.ofIntSupplier( |
| String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextInt(%d))", SIZE, bound), |
| () -> rbsf.apply(sr -> sr.nextInt(bound))), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| } |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofIntSupplier( |
| String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextInt(%d, %d))", SIZE, origin, bound), |
| () -> rbsf.apply(sr -> sr.nextInt(origin, bound))), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| } |
| } |
| |
| return data.toArray(new Object[0][]); |
| } |
| |
| @Test(dataProvider = "ints") |
| public void testInts(TestData.OfInt data, ResultAsserter<Iterable<Integer>> ra) { |
| withData(data). |
| stream(s -> s). |
| without(IntStreamTestScenario.CLEAR_SIZED_SCENARIOS). |
| resultAsserter(ra). |
| exercise(); |
| } |
| |
| @DataProvider(name = "longs") |
| public static Object[][] longsDataProvider() { |
| List<Object[]> data = new ArrayList<>(); |
| |
| // Function to create a stream using a RandomBoxedSpliterator |
| |
| Function<Function<SplittableRandom, Long>, LongStream> rbsf = |
| sf -> StreamSupport.stream(new RandomBoxedSpliterator<>(new SplittableRandom(), 0, SIZE, sf), false). |
| mapToLong(i -> i); |
| |
| // Unbounded |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofLongSupplier( |
| String.format("new SplittableRandom().longs().limit(%d)", SIZE), |
| () -> new SplittableRandom().longs().limit(SIZE)), |
| randomAsserter(SIZE, Long.MAX_VALUE, 0L) |
| }); |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofLongSupplier( |
| String.format("new SplittableRandom().longs(%d)", SIZE), |
| () -> new SplittableRandom().longs(SIZE)), |
| randomAsserter(SIZE, Long.MAX_VALUE, 0L) |
| }); |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofLongSupplier( |
| String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextLong())", SIZE), |
| () -> rbsf.apply(sr -> sr.nextLong())), |
| randomAsserter(SIZE, Long.MAX_VALUE, 0L) |
| }); |
| |
| // Bounded |
| |
| for (int b : BOUNDS) { |
| for (int o : ORIGINS) { |
| final long origin = o; |
| final long bound = b; |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofLongSupplier( |
| String.format("new SplittableRandom().longs(%d, %d).limit(%d)", origin, bound, SIZE), |
| () -> new SplittableRandom().longs(origin, bound).limit(SIZE)), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofLongSupplier( |
| String.format("new SplittableRandom().longs(%d, %d, %d)", SIZE, origin, bound), |
| () -> new SplittableRandom().longs(SIZE, origin, bound)), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| |
| if (origin == 0) { |
| data.add(new Object[]{ |
| TestData.Factory.ofLongSupplier( |
| String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextLong(%d))", SIZE, bound), |
| () -> rbsf.apply(sr -> sr.nextLong(bound))), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| } |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofLongSupplier( |
| String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextLong(%d, %d))", SIZE, origin, bound), |
| () -> rbsf.apply(sr -> sr.nextLong(origin, bound))), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| } |
| } |
| |
| return data.toArray(new Object[0][]); |
| } |
| |
| @Test(dataProvider = "longs") |
| public void testLongs(TestData.OfLong data, ResultAsserter<Iterable<Long>> ra) { |
| withData(data). |
| stream(s -> s). |
| without(LongStreamTestScenario.CLEAR_SIZED_SCENARIOS). |
| resultAsserter(ra). |
| exercise(); |
| } |
| |
| @DataProvider(name = "doubles") |
| public static Object[][] doublesDataProvider() { |
| List<Object[]> data = new ArrayList<>(); |
| |
| // Function to create a stream using a RandomBoxedSpliterator |
| |
| Function<Function<SplittableRandom, Double>, DoubleStream> rbsf = |
| sf -> StreamSupport.stream(new RandomBoxedSpliterator<>(new SplittableRandom(), 0, SIZE, sf), false). |
| mapToDouble(i -> i); |
| |
| // Unbounded |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofDoubleSupplier( |
| String.format("new SplittableRandom().doubles().limit(%d)", SIZE), |
| () -> new SplittableRandom().doubles().limit(SIZE)), |
| randomAsserter(SIZE, Double.MAX_VALUE, 0d) |
| }); |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofDoubleSupplier( |
| String.format("new SplittableRandom().doubles(%d)", SIZE), |
| () -> new SplittableRandom().doubles(SIZE)), |
| randomAsserter(SIZE, Double.MAX_VALUE, 0d) |
| }); |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofDoubleSupplier( |
| String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextDouble())", SIZE), |
| () -> rbsf.apply(sr -> sr.nextDouble())), |
| randomAsserter(SIZE, Double.MAX_VALUE, 0d) |
| }); |
| |
| // Bounded |
| |
| for (int b : BOUNDS) { |
| for (int o : ORIGINS) { |
| final double origin = o; |
| final double bound = b; |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofDoubleSupplier( |
| String.format("new SplittableRandom().doubles(%f, %f).limit(%d)", origin, bound, SIZE), |
| () -> new SplittableRandom().doubles(origin, bound).limit(SIZE)), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofDoubleSupplier( |
| String.format("new SplittableRandom().doubles(%d, %f, %f)", SIZE, origin, bound), |
| () -> new SplittableRandom().doubles(SIZE, origin, bound)), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| |
| if (origin == 0) { |
| data.add(new Object[]{ |
| TestData.Factory.ofDoubleSupplier( |
| String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextDouble(%f))", SIZE, bound), |
| () -> rbsf.apply(sr -> sr.nextDouble(bound))), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| } |
| |
| data.add(new Object[]{ |
| TestData.Factory.ofDoubleSupplier( |
| String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextDouble(%f, %f))", SIZE, origin, bound), |
| () -> rbsf.apply(sr -> sr.nextDouble(origin, bound))), |
| randomAsserter(SIZE, origin, bound) |
| }); |
| } |
| } |
| |
| return data.toArray(new Object[0][]); |
| } |
| |
| @Test(dataProvider = "doubles") |
| public void testDoubles(TestData.OfDouble data, ResultAsserter<Iterable<Double>> ra) { |
| withData(data). |
| stream(s -> s). |
| without(DoubleStreamTestScenario.CLEAR_SIZED_SCENARIOS). |
| resultAsserter(ra). |
| exercise(); |
| } |
| } |