From f9a9e68c05a9b72e907e70e81059fd9f89089c72 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 6 Mar 2015 16:00:58 -0800 Subject: [PATCH] 8074460: Always print seeds used in [Splittable]Random instances in java.math tests Create a utility class which creates a pseudorandom number generator (PRNG) and retains the seed. Use this class in java.math tests which use a PRNG. Always print the seed value before the PRNG is used. Reviewed-by: darcy --- .../math/BigDecimal/StringConstructor.java | 22 ++--- .../java/math/BigInteger/BigIntegerTest.java | 96 ++++++++++--------- .../java/math/BigInteger/ModPow65537.java | 12 ++- jdk/test/java/math/BigInteger/PrimeTest.java | 12 ++- .../math/BigInteger/SymmetricRangeTests.java | 13 +-- jdk/test/java/math/RandomSeed.java | 81 ++++++++++++++++ 6 files changed, 162 insertions(+), 74 deletions(-) create mode 100644 jdk/test/java/math/RandomSeed.java diff --git a/jdk/test/java/math/BigDecimal/StringConstructor.java b/jdk/test/java/math/BigDecimal/StringConstructor.java index 992eb9dc1b8..c8051eb98a5 100644 --- a/jdk/test/java/math/BigDecimal/StringConstructor.java +++ b/jdk/test/java/math/BigDecimal/StringConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -23,19 +23,20 @@ /* * @test - * @bug 4103117 4331084 4488017 4490929 6255285 6268365 - * @summary Tests the BigDecimal string constructor. + * @library .. + * @bug 4103117 4331084 4488017 4490929 6255285 6268365 8074460 + * @summary Tests the BigDecimal string constructor (use -Dseed=X to set PRNG seed). */ import java.math.*; -import java.util.Random; public class StringConstructor { - private static int seed = new Random().nextInt(); - private static Random rnd = new Random(seed); + private static RandomSeed rndSeed = new RandomSeed(false); public static void main(String[] args) throws Exception { + System.out.println("Random number generator seed = " + rndSeed.getSeed()); + constructWithError(""); constructWithError("+"); constructWithError("-"); @@ -71,19 +72,18 @@ public class StringConstructor { // Roundtrip tests for (int i=0; i<100; i++) { - int size = rnd.nextInt(100) + 1; - BigInteger bi = new BigInteger(size, rnd); - if (rnd.nextBoolean()) + int size = rndSeed.getRandom().nextInt(100) + 1; + BigInteger bi = new BigInteger(size, rndSeed.getRandom()); + if (rndSeed.getRandom().nextBoolean()) bi = bi.negate(); int decimalLength = bi.toString().length(); - int scale = rnd.nextInt(decimalLength); + int scale = rndSeed.getRandom().nextInt(decimalLength); BigDecimal bd = new BigDecimal(bi, scale); String bdString = bd.toString(); // System.err.println("bi" + bi.toString() + "\tscale " + scale); // System.err.println("bd string: " + bdString); BigDecimal bdDoppel = new BigDecimal(bdString); if (!bd.equals(bdDoppel)) { - System.err.println("Random number seed = " + seed); System.err.println("bd string: scale: " + bd.scale() + "\t" + bdString); System.err.println("bd doppel: scale: " + bdDoppel.scale() + diff --git a/jdk/test/java/math/BigInteger/BigIntegerTest.java b/jdk/test/java/math/BigInteger/BigIntegerTest.java index 4de80fad4fd..e1b36c0812b 100644 --- a/jdk/test/java/math/BigInteger/BigIntegerTest.java +++ b/jdk/test/java/math/BigInteger/BigIntegerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -23,8 +23,9 @@ /* * @test - * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 - * @summary tests methods in BigInteger + * @library .. + * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 + * @summary tests methods in BigInteger (use -Dseed=X to set PRNG seed) * @run main/timeout=400 BigIntegerTest * @author madbot */ @@ -35,7 +36,6 @@ import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.math.BigInteger; -import java.util.Random; /** * This is a simple test class created to ensure that the results @@ -86,7 +86,8 @@ public class BigIntegerTest { static final int SIZE = 1000; // numbers per batch - static Random rnd = new Random(); + private static RandomSeed rndSeed = new RandomSeed(false); + static boolean failure = false; public static void constructor() { @@ -97,7 +98,7 @@ public class BigIntegerTest { int arrayLength = 23; int halfLength = arrayLength/2; byte[] array = new byte[arrayLength]; - rnd.nextBytes(array); + rndSeed.getRandom().nextBytes(array); int[][] offLen = new int[][] { // offset, length, num exceptions {-1, arrayLength, 1}, // negative offset @@ -161,7 +162,7 @@ public class BigIntegerTest { } byte[] magNonZeroLength = new byte[42]; - rnd.nextBytes(magNonZeroLength); + rndSeed.getRandom().nextBytes(magNonZeroLength); for (int signum = -1; signum <= 1; signum++) { BigInteger bi = new BigInteger(signum, magNonZeroLength, 0, 0); if (bi.compareTo(BigInteger.ZERO) != 0) { @@ -174,13 +175,13 @@ public class BigIntegerTest { for (int i = 0; i < SIZE; i++) { // create reference value via a different code path from those tested - BigInteger reference = new BigInteger(2 + rnd.nextInt(336), 4, rnd); + BigInteger reference = new BigInteger(2 + rndSeed.getRandom().nextInt(336), 4, rndSeed.getRandom()); byte[] refArray = reference.toByteArray(); int refLen = refArray.length; - int factor = rnd.nextInt(5); - int objLen = refArray.length + factor*rnd.nextInt(refArray.length) + 1; - int offset = rnd.nextInt(objLen - refLen); + int factor = rndSeed.getRandom().nextInt(5); + int objLen = refArray.length + factor*rndSeed.getRandom().nextInt(refArray.length) + 1; + int offset = rndSeed.getRandom().nextInt(objLen - refLen); byte[] objArray = new byte[objLen]; System.arraycopy(refArray, 0, objArray, offset, refLen); @@ -191,7 +192,7 @@ public class BigIntegerTest { failCount++; } - boolean isNegative = rnd.nextBoolean(); + boolean isNegative = rndSeed.getRandom().nextBoolean(); BigInteger signMag = new BigInteger(isNegative ? -1 : 1, objArray, offset, refLen); if (signMag.compareTo(isNegative ? reference.negate() : reference) != 0) { System.err.println("Sign-magnitude BigInteger not equal for offset " + @@ -208,7 +209,7 @@ public class BigIntegerTest { for (int i=0; i= lower; bits--) { for (int i = 0; i < 50; i++) { - BigInteger x = BigInteger.ONE.shiftLeft(bits - 1).or(new BigInteger(bits - 2, rnd)); + BigInteger x = BigInteger.ONE.shiftLeft(bits - 1).or(new BigInteger(bits - 2, rndSeed.getRandom())); for (int radix = Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) { String result = x.toString(radix); @@ -764,9 +765,9 @@ public class BigIntegerTest { int failCount = 0; for (int i=0; i<10; i++) { - BigInteger m = new BigInteger(100, 5, rnd); + BigInteger m = new BigInteger(100, 5, rndSeed.getRandom()); while(m.compareTo(BigInteger.ONE) != 1) - m = new BigInteger(100, 5, rnd); + m = new BigInteger(100, 5, rndSeed.getRandom()); BigInteger exp = m.subtract(BigInteger.ONE); BigInteger base = fetchNumber(order).abs(); while(base.compareTo(m) != -1) @@ -826,7 +827,7 @@ public class BigIntegerTest { // Test consistency for(int i=0; i<10; i++) { - p1 = BigInteger.probablePrime(100, rnd); + p1 = BigInteger.probablePrime(100, rndSeed.getRandom()); if (!p1.isProbablePrime(100)) { System.err.println("Consistency "+p1.toString(16)); failCount++; @@ -867,7 +868,7 @@ public class BigIntegerTest { // Numbers of the form (6k+1)(12k+1)(18k+1) are Carmichael numbers if // each of the factors is prime int found = 0; - BigInteger f1 = new BigInteger(40, 100, rnd); + BigInteger f1 = new BigInteger(40, 100, rndSeed.getRandom()); while (found < NUM_CARMICHAELS_TO_TEST) { BigInteger k = null; BigInteger f2, f3; @@ -894,8 +895,8 @@ public class BigIntegerTest { // Test some composites that are products of 2 primes for (int i=0; i<50; i++) { - p1 = BigInteger.probablePrime(100, rnd); - p2 = BigInteger.probablePrime(100, rnd); + p1 = BigInteger.probablePrime(100, rndSeed.getRandom()); + p2 = BigInteger.probablePrime(100, rndSeed.getRandom()); c1 = p1.multiply(p2); if (c1.isProbablePrime(100)) { System.err.println("Composite failed "+c1.toString(16)); @@ -904,8 +905,8 @@ public class BigIntegerTest { } for (int i=0; i<4; i++) { - p1 = BigInteger.probablePrime(600, rnd); - p2 = BigInteger.probablePrime(600, rnd); + p1 = BigInteger.probablePrime(600, rndSeed.getRandom()); + p2 = BigInteger.probablePrime(600, rndSeed.getRandom()); c1 = p1.multiply(p2); if (c1.isProbablePrime(100)) { System.err.println("Composite failed "+c1.toString(16)); @@ -960,7 +961,7 @@ public class BigIntegerTest { // Next, pick some large primes, use nextProbablePrime to find the // next one, and make sure there are no primes in between for (int i=0; i<100; i+=10) { - p1 = BigInteger.probablePrime(50 + i, rnd); + p1 = BigInteger.probablePrime(50 + i, rndSeed.getRandom()); p2 = p1.add(ONE); p3 = p1.nextProbablePrime(); while(p2.compareTo(p3) < 0) { @@ -1025,7 +1026,7 @@ public class BigIntegerTest { } for(int i=0; i<10; i++) { - BigInteger b1 = fetchNumber(rnd.nextInt(100)); + BigInteger b1 = fetchNumber(rndSeed.getRandom().nextInt(100)); BigInteger b2 = null; File f = new File("serialtest"); try (FileOutputStream fos = new FileOutputStream(f)) { @@ -1059,6 +1060,7 @@ public class BigIntegerTest { * */ public static void main(String[] args) throws Exception { + System.out.println("Random number generator seed = " + rndSeed.getSeed()); // Some variables for sizing test numbers in bits int order1 = ORDER_MEDIUM; @@ -1131,8 +1133,8 @@ public class BigIntegerTest { * If order is less than 2, order is changed to 2. */ private static BigInteger fetchNumber(int order) { - boolean negative = rnd.nextBoolean(); - int numType = rnd.nextInt(7); + boolean negative = rndSeed.getRandom().nextBoolean(); + int numType = rndSeed.getRandom().nextInt(7); BigInteger result = null; if (order < 2) order = 2; @@ -1156,14 +1158,14 @@ public class BigIntegerTest { break; case 3: // One bit in number - result = BigInteger.ONE.shiftLeft(rnd.nextInt(order)); + result = BigInteger.ONE.shiftLeft(rndSeed.getRandom().nextInt(order)); break; case 4: // Random bit density byte[] val = new byte[(order+7)/8]; - int iterations = rnd.nextInt(order); + int iterations = rndSeed.getRandom().nextInt(order); for (int i=0; i 0) { - int runLength = Math.min(remaining, rnd.nextInt(order)); + int runLength = Math.min(remaining, rndSeed.getRandom().nextInt(order)); result = result.shiftLeft(runLength); if (bit > 0) result = result.add(ONE.shiftLeft(runLength).subtract(ONE)); @@ -1183,7 +1185,7 @@ public class BigIntegerTest { break; default: // random bits - result = new BigInteger(order, rnd); + result = new BigInteger(order, rndSeed.getRandom()); } if (negative) diff --git a/jdk/test/java/math/BigInteger/ModPow65537.java b/jdk/test/java/math/BigInteger/ModPow65537.java index ec962e2a5ff..f8e4a5422d1 100644 --- a/jdk/test/java/math/BigInteger/ModPow65537.java +++ b/jdk/test/java/math/BigInteger/ModPow65537.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -23,13 +23,13 @@ /* * @test - * @bug 4891312 - * @summary verify that modPow() not broken by the special case for 65537 + * @library .. + * @bug 4891312 8074460 + * @summary verify that modPow() not broken by the special case for 65537 (use -Dseed=X to set PRNG seed) * @author Andreas Sterbenz */ import java.math.BigInteger; -import java.util.*; import java.security.*; import java.security.spec.*; @@ -78,7 +78,9 @@ public class ModPow65537 { private static void testSigning(KeyPair kp) throws Exception { System.out.println(kp.getPublic()); byte[] data = new byte[1024]; - new Random().nextBytes(data); + RandomSeed rndSeed = new RandomSeed(false); + System.out.println("Random number generator seed = " + rndSeed.getSeed()); + rndSeed.getRandom().nextBytes(data); Signature sig = Signature.getInstance("SHA1withRSA", "SunRsaSign"); sig.initSign(kp.getPrivate()); diff --git a/jdk/test/java/math/BigInteger/PrimeTest.java b/jdk/test/java/math/BigInteger/PrimeTest.java index 5f5affeb240..fae4fd7979b 100644 --- a/jdk/test/java/math/BigInteger/PrimeTest.java +++ b/jdk/test/java/math/BigInteger/PrimeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -25,13 +25,13 @@ /* * @test - * @bug 8026236 - * @summary test primality verification methods in BigInteger + * @library .. + * @bug 8026236 8074460 + * @summary test primality verification methods in BigInteger (use -Dseed=X to set PRNG seed) * @author bpb */ import java.math.BigInteger; import java.util.BitSet; -import java.util.HashSet; import java.util.List; import java.util.NavigableSet; import java.util.Set; @@ -178,7 +178,9 @@ public class PrimeTest { } // Create a list of non-prime BigIntegers. - List nonPrimeBigInts = (new SplittableRandom()) + RandomSeed rndSeed = new RandomSeed(true); + System.out.println("Random number generator seed = " + rndSeed.getSeed()); + List nonPrimeBigInts = (rndSeed.getSplittableRandom()) .ints(NUM_NON_PRIMES, 2, maxPrime).mapToObj(BigInteger::valueOf) .filter(b -> !b.isProbablePrime(certainty)).collect(toList()); diff --git a/jdk/test/java/math/BigInteger/SymmetricRangeTests.java b/jdk/test/java/math/BigInteger/SymmetricRangeTests.java index b944a95d32f..d3cb73cbef2 100644 --- a/jdk/test/java/math/BigInteger/SymmetricRangeTests.java +++ b/jdk/test/java/math/BigInteger/SymmetricRangeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 1025, 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 @@ -24,9 +24,10 @@ /* * @test * @ignore This test has huge memory requirements + * @library .. * @run main/timeout=180/othervm -Xmx8g SymmetricRangeTests - * @bug 6910473 8021204 8021203 9005933 - * @summary Test range of BigInteger values + * @bug 6910473 8021204 8021203 9005933 8074460 + * @summary Test range of BigInteger values (use -Dseed=X to set PRNG seed) * @author Dmitry Nadezhin */ import java.io.ByteArrayInputStream; @@ -35,7 +36,6 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Arrays; -import java.util.Random; import java.math.BigInteger; public class SymmetricRangeTests { @@ -114,8 +114,9 @@ public class SymmetricRangeTests { System.out.println("Testing overflow in BitSieve.sieveSingle"); int bitLength = (5 << 27) - 1; try { - Random rnd = new Random(); - BigInteger actual = new BigInteger(bitLength, 0, rnd); + RandomSeed rndSeed = new RandomSeed(false); + System.out.println("Random number generator seed = " + rndSeed.getSeed()); + BigInteger actual = new BigInteger(bitLength, 0, rndSeed.getRandom()); throw new RuntimeException("new BigInteger(bitLength, 0, null).bitLength()=" + actual.bitLength()); } catch (ArithmeticException e) { // expected diff --git a/jdk/test/java/math/RandomSeed.java b/jdk/test/java/math/RandomSeed.java new file mode 100644 index 00000000000..494705c5fd6 --- /dev/null +++ b/jdk/test/java/math/RandomSeed.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 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. + */ + +import java.util.Random; +import java.util.SplittableRandom; + +public class RandomSeed { + private long seed = 0L; + private Random rnd = null; + private SplittableRandom srnd = null; + + public RandomSeed(boolean isSplittableRandom) { + init(isSplittableRandom); + } + + private void init(boolean isSplittableRandom) { + // obtain seed from environment if supplied + boolean isSeedProvided = false; + try { + // note that Long.valueOf(null) also throws a NumberFormatException + // so if the property is undefined this will still work correctly + seed = Long.valueOf(System.getProperty("seed")); + isSeedProvided = true; + } catch (NumberFormatException e) { + // do nothing: isSeedProvided is already false + } + + // if no seed from environment, create a fresh one + Random tmpRnd = null; + if (!isSeedProvided) { + tmpRnd = new Random(); + seed = tmpRnd.nextLong(); + } + + // create the PRNG + if (isSplittableRandom) { + srnd = new SplittableRandom(seed); + } else { + rnd = tmpRnd != null ? tmpRnd : new Random(); + rnd.setSeed(seed); + } + } + + public Random getRandom() { + if (rnd == null) { + throw new IllegalStateException("Variable of type Random not initialized"); + } + return rnd; + } + + public SplittableRandom getSplittableRandom() { + if (srnd == null) { + throw new IllegalStateException("Variable of type SplittableRandom not initialized"); + } + return srnd; + } + + public long getSeed() { + return seed; + } +}