/*
 * 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.
 */

/*
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file:
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

import java.util.Arrays;
import java.util.List;
import java.util.SplittableRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

import junit.framework.Test;
import junit.framework.TestSuite;

public class SplittableRandomTest extends JSR166TestCase {

    public static void main(String[] args) {
        main(suite(), args);
    }
    public static Test suite() {
        return new TestSuite(SplittableRandomTest.class);
    }

    /*
     * Testing coverage notes:
     *
     * 1. Many of the test methods are adapted from ThreadLocalRandomTest.
     *
     * 2. These tests do not check for random number generator quality.
     * But we check for minimal API compliance by requiring that
     * repeated calls to nextX methods, up to NCALLS tries, produce at
     * least two distinct results. (In some possible universe, a
     * "correct" implementation might fail, but the odds are vastly
     * less than that of encountering a hardware failure while running
     * the test.) For bounded nextX methods, we sample various
     * intervals across multiples of primes. In other tests, we repeat
     * under REPS different values.
     */

    // max numbers of calls to detect getting stuck on one value
    static final int NCALLS = 10000;

    // max sampled int bound
    static final int MAX_INT_BOUND = (1 << 26);

    // max sampled long bound
    static final long MAX_LONG_BOUND = (1L << 40);

    // Number of replications for other checks
    static final int REPS =
        Integer.getInteger("SplittableRandomTest.reps", 4);

    /**
     * Repeated calls to nextInt produce at least two distinct results
     */
    public void testNextInt() {
        SplittableRandom sr = new SplittableRandom();
        int f = sr.nextInt();
        int i = 0;
        while (i < NCALLS && sr.nextInt() == f)
            ++i;
        assertTrue(i < NCALLS);
    }

    /**
     * Repeated calls to nextLong produce at least two distinct results
     */
    public void testNextLong() {
        SplittableRandom sr = new SplittableRandom();
        long f = sr.nextLong();
        int i = 0;
        while (i < NCALLS && sr.nextLong() == f)
            ++i;
        assertTrue(i < NCALLS);
    }

    /**
     * Repeated calls to nextDouble produce at least two distinct results
     */
    public void testNextDouble() {
        SplittableRandom sr = new SplittableRandom();
        double f = sr.nextDouble();
        int i = 0;
        while (i < NCALLS && sr.nextDouble() == f)
            ++i;
        assertTrue(i < NCALLS);
    }

    /**
     * Two SplittableRandoms created with the same seed produce the
     * same values for nextLong.
     */
    public void testSeedConstructor() {
        for (long seed = 2; seed < MAX_LONG_BOUND; seed += 15485863) {
            SplittableRandom sr1 = new SplittableRandom(seed);
            SplittableRandom sr2 = new SplittableRandom(seed);
            for (int i = 0; i < REPS; ++i)
                assertEquals(sr1.nextLong(), sr2.nextLong());
        }
    }

    /**
     * A SplittableRandom produced by split() of a default-constructed
     * SplittableRandom generates a different sequence
     */
    public void testSplit1() {
        SplittableRandom sr = new SplittableRandom();
        for (int reps = 0; reps < REPS; ++reps) {
            SplittableRandom sc = sr.split();
            int i = 0;
            while (i < NCALLS && sr.nextLong() == sc.nextLong())
                ++i;
            assertTrue(i < NCALLS);
        }
    }

    /**
     * A SplittableRandom produced by split() of a seeded-constructed
     * SplittableRandom generates a different sequence
     */
    public void testSplit2() {
        SplittableRandom sr = new SplittableRandom(12345);
        for (int reps = 0; reps < REPS; ++reps) {
            SplittableRandom sc = sr.split();
            int i = 0;
            while (i < NCALLS && sr.nextLong() == sc.nextLong())
                ++i;
            assertTrue(i < NCALLS);
        }
    }

    /**
     * nextInt(non-positive) throws IllegalArgumentException
     */
    public void testNextIntBoundNonPositive() {
        SplittableRandom sr = new SplittableRandom();
        assertThrows(
            IllegalArgumentException.class,
            () -> sr.nextInt(-17),
            () -> sr.nextInt(0),
            () -> sr.nextInt(Integer.MIN_VALUE));
    }

    /**
     * nextInt(least >= bound) throws IllegalArgumentException
     */
    public void testNextIntBadBounds() {
        SplittableRandom sr = new SplittableRandom();
        assertThrows(
            IllegalArgumentException.class,
            () -> sr.nextInt(17, 2),
            () -> sr.nextInt(-42, -42),
            () -> sr.nextInt(Integer.MAX_VALUE, Integer.MIN_VALUE));
    }

    /**
     * nextInt(bound) returns 0 <= value < bound;
     * repeated calls produce at least two distinct results
     */
    public void testNextIntBounded() {
        SplittableRandom sr = new SplittableRandom();
        for (int i = 0; i < 2; i++) assertEquals(0, sr.nextInt(1));
        // sample bound space across prime number increments
        for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
            int f = sr.nextInt(bound);
            assertTrue(0 <= f && f < bound);
            int i = 0;
            int j;
            while (i < NCALLS &&
                   (j = sr.nextInt(bound)) == f) {
                assertTrue(0 <= j && j < bound);
                ++i;
            }
            assertTrue(i < NCALLS);
        }
    }

    /**
     * nextInt(least, bound) returns least <= value < bound;
     * repeated calls produce at least two distinct results
     */
    public void testNextIntBounded2() {
        SplittableRandom sr = new SplittableRandom();
        for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
            for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
                int f = sr.nextInt(least, bound);
                assertTrue(least <= f && f < bound);
                int i = 0;
                int j;
                while (i < NCALLS &&
                       (j = sr.nextInt(least, bound)) == f) {
                    assertTrue(least <= j && j < bound);
                    ++i;
                }
                assertTrue(i < NCALLS);
            }
        }
    }

    /**
     * nextLong(non-positive) throws IllegalArgumentException
     */
    public void testNextLongBoundNonPositive() {
        SplittableRandom sr = new SplittableRandom();
        assertThrows(
            IllegalArgumentException.class,
            () -> sr.nextLong(-17L),
            () -> sr.nextLong(0L),
            () -> sr.nextLong(Long.MIN_VALUE));
    }

    /**
     * nextLong(least >= bound) throws IllegalArgumentException
     */
    public void testNextLongBadBounds() {
        SplittableRandom sr = new SplittableRandom();
        assertThrows(
            IllegalArgumentException.class,
            () -> sr.nextLong(17L, 2L),
            () -> sr.nextLong(-42L, -42L),
            () -> sr.nextLong(Long.MAX_VALUE, Long.MIN_VALUE));
    }

    /**
     * nextLong(bound) returns 0 <= value < bound;
     * repeated calls produce at least two distinct results
     */
    public void testNextLongBounded() {
        SplittableRandom sr = new SplittableRandom();
        for (int i = 0; i < 2; i++) assertEquals(0L, sr.nextLong(1L));
        for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
            long f = sr.nextLong(bound);
            assertTrue(0 <= f && f < bound);
            int i = 0;
            long j;
            while (i < NCALLS &&
                   (j = sr.nextLong(bound)) == f) {
                assertTrue(0 <= j && j < bound);
                ++i;
            }
            assertTrue(i < NCALLS);
        }
    }

    /**
     * nextLong(least, bound) returns least <= value < bound;
     * repeated calls produce at least two distinct results
     */
    public void testNextLongBounded2() {
        SplittableRandom sr = new SplittableRandom();
        for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
            for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
                long f = sr.nextLong(least, bound);
                assertTrue(least <= f && f < bound);
                int i = 0;
                long j;
                while (i < NCALLS &&
                       (j = sr.nextLong(least, bound)) == f) {
                    assertTrue(least <= j && j < bound);
                    ++i;
                }
                assertTrue(i < NCALLS);
            }
        }
    }

    /**
     * nextDouble(non-positive) throws IllegalArgumentException
     */
    public void testNextDoubleBoundNonPositive() {
        SplittableRandom sr = new SplittableRandom();
        assertThrows(
            IllegalArgumentException.class,
            () -> sr.nextDouble(-17.0d),
            () -> sr.nextDouble(0.0d),
            () -> sr.nextDouble(-Double.MIN_VALUE),
            () -> sr.nextDouble(Double.NEGATIVE_INFINITY),
            () -> sr.nextDouble(Double.NaN));
    }

    /**
     * nextDouble(! (least < bound)) throws IllegalArgumentException
     */
    public void testNextDoubleBadBounds() {
        SplittableRandom sr = new SplittableRandom();
        assertThrows(
            IllegalArgumentException.class,
            () -> sr.nextDouble(17.0d, 2.0d),
            () -> sr.nextDouble(-42.0d, -42.0d),
            () -> sr.nextDouble(Double.MAX_VALUE, Double.MIN_VALUE),
            () -> sr.nextDouble(Double.NaN, 0.0d),
            () -> sr.nextDouble(0.0d, Double.NaN));
    }

    // TODO: Test infinite bounds!
    //() -> sr.nextDouble(Double.NEGATIVE_INFINITY, 0.0d),
    //() -> sr.nextDouble(0.0d, Double.POSITIVE_INFINITY),

    /**
     * nextDouble(least, bound) returns least <= value < bound;
     * repeated calls produce at least two distinct results
     */
    public void testNextDoubleBounded2() {
        SplittableRandom sr = new SplittableRandom();
        for (double least = 0.0001; least < 1.0e20; least *= 8) {
            for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
                double f = sr.nextDouble(least, bound);
                assertTrue(least <= f && f < bound);
                int i = 0;
                double j;
                while (i < NCALLS &&
                       (j = sr.nextDouble(least, bound)) == f) {
                    assertTrue(least <= j && j < bound);
                    ++i;
                }
                assertTrue(i < NCALLS);
            }
        }
    }

    /**
     * Invoking sized ints, long, doubles, with negative sizes throws
     * IllegalArgumentException
     */
    public void testBadStreamSize() {
        SplittableRandom r = new SplittableRandom();
        assertThrows(
            IllegalArgumentException.class,
            () -> { IntStream unused = r.ints(-1L); },
            () -> { IntStream unused = r.ints(-1L, 2, 3); },
            () -> { LongStream unused = r.longs(-1L); },
            () -> { LongStream unused = r.longs(-1L, -1L, 1L); },
            () -> { DoubleStream unused = r.doubles(-1L); },
            () -> { DoubleStream unused = r.doubles(-1L, .5, .6); });
    }

    /**
     * Invoking bounded ints, long, doubles, with illegal bounds throws
     * IllegalArgumentException
     */
    public void testBadStreamBounds() {
        SplittableRandom r = new SplittableRandom();
        assertThrows(
            IllegalArgumentException.class,
            () -> { IntStream unused = r.ints(2, 1); },
            () -> { IntStream unused = r.ints(10, 42, 42); },
            () -> { LongStream unused = r.longs(-1L, -1L); },
            () -> { LongStream unused = r.longs(10, 1L, -2L); },
            () -> { DoubleStream unused = r.doubles(0.0, 0.0); },
            () -> { DoubleStream unused = r.doubles(10, .5, .4); });
    }

    /**
     * A parallel sized stream of ints generates the given number of values
     */
    public void testIntsCount() {
        LongAdder counter = new LongAdder();
        SplittableRandom r = new SplittableRandom();
        long size = 0;
        for (int reps = 0; reps < REPS; ++reps) {
            counter.reset();
            r.ints(size).parallel().forEach(x -> counter.increment());
            assertEquals(size, counter.sum());
            size += 524959;
        }
    }

    /**
     * A parallel sized stream of longs generates the given number of values
     */
    public void testLongsCount() {
        LongAdder counter = new LongAdder();
        SplittableRandom r = new SplittableRandom();
        long size = 0;
        for (int reps = 0; reps < REPS; ++reps) {
            counter.reset();
            r.longs(size).parallel().forEach(x -> counter.increment());
            assertEquals(size, counter.sum());
            size += 524959;
        }
    }

    /**
     * A parallel sized stream of doubles generates the given number of values
     */
    public void testDoublesCount() {
        LongAdder counter = new LongAdder();
        SplittableRandom r = new SplittableRandom();
        long size = 0;
        for (int reps = 0; reps < REPS; ++reps) {
            counter.reset();
            r.doubles(size).parallel().forEach(x -> counter.increment());
            assertEquals(size, counter.sum());
            size += 524959;
        }
    }

    /**
     * Each of a parallel sized stream of bounded ints is within bounds
     */
    public void testBoundedInts() {
        AtomicInteger fails = new AtomicInteger(0);
        SplittableRandom r = new SplittableRandom();
        long size = 12345L;
        for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
            for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
                final int lo = least, hi = bound;
                r.ints(size, lo, hi).parallel().forEach(
                    x -> {
                        if (x < lo || x >= hi)
                            fails.getAndIncrement(); });
            }
        }
        assertEquals(0, fails.get());
    }

    /**
     * Each of a parallel sized stream of bounded longs is within bounds
     */
    public void testBoundedLongs() {
        AtomicInteger fails = new AtomicInteger(0);
        SplittableRandom r = new SplittableRandom();
        long size = 123L;
        for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
            for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
                final long lo = least, hi = bound;
                r.longs(size, lo, hi).parallel().forEach(
                    x -> {
                        if (x < lo || x >= hi)
                            fails.getAndIncrement(); });
            }
        }
        assertEquals(0, fails.get());
    }

    /**
     * Each of a parallel sized stream of bounded doubles is within bounds
     */
    public void testBoundedDoubles() {
        AtomicInteger fails = new AtomicInteger(0);
        SplittableRandom r = new SplittableRandom();
        long size = 456;
        for (double least = 0.00011; least < 1.0e20; least *= 9) {
            for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
                final double lo = least, hi = bound;
                r.doubles(size, lo, hi).parallel().forEach(
                    x -> {
                        if (x < lo || x >= hi)
                            fails.getAndIncrement(); });
            }
        }
        assertEquals(0, fails.get());
    }

    /**
     * A parallel unsized stream of ints generates at least 100 values
     */
    public void testUnsizedIntsCount() {
        LongAdder counter = new LongAdder();
        SplittableRandom r = new SplittableRandom();
        long size = 100;
        r.ints().limit(size).parallel().forEach(x -> counter.increment());
        assertEquals(size, counter.sum());
    }

    /**
     * A parallel unsized stream of longs generates at least 100 values
     */
    public void testUnsizedLongsCount() {
        LongAdder counter = new LongAdder();
        SplittableRandom r = new SplittableRandom();
        long size = 100;
        r.longs().limit(size).parallel().forEach(x -> counter.increment());
        assertEquals(size, counter.sum());
    }

    /**
     * A parallel unsized stream of doubles generates at least 100 values
     */
    public void testUnsizedDoublesCount() {
        LongAdder counter = new LongAdder();
        SplittableRandom r = new SplittableRandom();
        long size = 100;
        r.doubles().limit(size).parallel().forEach(x -> counter.increment());
        assertEquals(size, counter.sum());
    }

    /**
     * A sequential unsized stream of ints generates at least 100 values
     */
    public void testUnsizedIntsCountSeq() {
        LongAdder counter = new LongAdder();
        SplittableRandom r = new SplittableRandom();
        long size = 100;
        r.ints().limit(size).forEach(x -> counter.increment());
        assertEquals(size, counter.sum());
    }

    /**
     * A sequential unsized stream of longs generates at least 100 values
     */
    public void testUnsizedLongsCountSeq() {
        LongAdder counter = new LongAdder();
        SplittableRandom r = new SplittableRandom();
        long size = 100;
        r.longs().limit(size).forEach(x -> counter.increment());
        assertEquals(size, counter.sum());
    }

    /**
     * A sequential unsized stream of doubles generates at least 100 values
     */
    public void testUnsizedDoublesCountSeq() {
        LongAdder counter = new LongAdder();
        SplittableRandom r = new SplittableRandom();
        long size = 100;
        r.doubles().limit(size).forEach(x -> counter.increment());
        assertEquals(size, counter.sum());
    }

    /**
     * SplittableRandom should implement most of Random's public methods
     */
    public void testShouldImplementMostRandomMethods() throws Throwable {
        Predicate<Method> wasForgotten = method -> {
            String name = method.getName();
            // some methods deliberately not implemented
            if (name.equals("setSeed")) return false;
            if (name.equals("nextFloat")) return false;
            if (name.equals("nextGaussian")) return false;
            try {
                SplittableRandom.class.getMethod(
                    method.getName(), method.getParameterTypes());
            } catch (ReflectiveOperationException ex) {
                return true;
            }
            return false;
        };
        List<Method> forgotten =
            Arrays.stream(java.util.Random.class.getMethods())
            .filter(method -> (method.getModifiers() & Modifier.STATIC) == 0)
            .filter(wasForgotten)
            .collect(Collectors.toList());
        if (!forgotten.isEmpty())
            throw new AssertionError("Please implement: " + forgotten);
    }

    /**
     * Repeated calls to nextBytes produce at least values of different signs for every byte
     */
    public void testNextBytes() {
        SplittableRandom sr = new SplittableRandom();
        int n = sr.nextInt(1, 20);
        byte[] bytes = new byte[n];
        outer:
        for (int i = 0; i < n; i++) {
            for (int tries = NCALLS; tries-->0; ) {
                byte before = bytes[i];
                sr.nextBytes(bytes);
                byte after = bytes[i];
                if (after * before < 0)
                    continue outer;
            }
            fail("not enough variation in random bytes");
        }
    }

    /**
     * Filling an empty array with random bytes succeeds without effect.
     */
    public void testNextBytes_emptyArray() {
        new SplittableRandom().nextBytes(new byte[0]);
    }

    public void testNextBytes_nullArray() {
        try {
            new SplittableRandom().nextBytes(null);
            shouldThrow();
        } catch (NullPointerException success) {}
    }

}
