--- jsr166/src/test/tck/SplittableRandomTest.java 2014/12/31 21:28:49 1.17 +++ jsr166/src/test/tck/SplittableRandomTest.java 2017/10/13 16:14:40 1.24 @@ -4,9 +4,14 @@ * 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.util.function.Predicate; +import java.util.stream.Collectors; import junit.framework.Test; import junit.framework.TestSuite; @@ -14,7 +19,7 @@ import junit.framework.TestSuite; public class SplittableRandomTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run(suite()); + main(suite(), args); } public static Test suite() { return new TestSuite(SplittableRandomTest.class); @@ -160,6 +165,7 @@ public class SplittableRandomTest extend */ 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); @@ -229,6 +235,7 @@ public class SplittableRandomTest extend */ 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); @@ -523,4 +530,64 @@ public class SplittableRandomTest extend assertEquals(size, counter.sum()); } + /** + * SplittableRandom should implement most of Random's public methods + */ + public void testShouldImplementMostRandomMethods() throws Throwable { + Predicate 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 forgotten = + Arrays.stream(java.util.Random.class.getMethods()) + .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) {} + } + }