RFR(M): 8044186 Introduce a reproducible random generator
Sergei Kovalev
sergei.kovalev at oracle.com
Thu Oct 30 11:57:06 UTC 2014
Hi Vladimir,
Would you like to see webrev or diff would be enough? Just in case diff
is ok, I'm attaching it. If you'd like published webrev, please let me know.
On 29.10.2014 20:49, Vladimir Kozlov wrote:
> Hi Sergei,
>
> Please create webrev of differences between last webrev.03, which we
> reviewed, and new webrev.00.
>
> Thanks,
> Vladimir
>
> On 10/29/14 2:02 AM, Sergei Kovalev wrote:
>> Hello team.
>>
>> Next round of review:
>>
>> http://cr.openjdk.java.net/~iignatyev/skovalev/8044186/webrev.00/
>>
>> Main changes:
>> - introduced new test that testing new testlibrary functionality:
>> test/testlibrary_tests/RandomGeneratorTest.java
>> - slightly improved Utility.java in part of SEED variable access.
>>
>> All affected tests passed locally on Linux host.
>>
>> On 24.09.2014 22:36, Igor Veresov wrote:
>>> Looks good.
>>>
>>> igor
>>>
>>> On Sep 24, 2014, at 7:21 AM, Sergei Kovalev
>>> <sergei.kovalev at oracle.com> wrote:
>>>
>>>> Update:
>>>> http://cr.openjdk.java.net/~vlivanov/kovalev/8044186/webrev.03/
>>>>
>>>> Added new testcase test/testlibrary_tests/RandomGeneratorTest.java
>>>> that verify correctness of work for Utils.getRandomInstance() method.
>>>>
>>>> On 24.09.2014 13:09, Sergei Kovalev wrote:
>>>>> Update:
>>>>> http://cr.openjdk.java.net/~vlivanov/kovalev/8044186/webrev.02/
>>>>>
>>>>> Added new test.
>>>>> Fixed misprint.
>>>>>
>>>>> On 24.09.2014 12:50, Vladimir Ivanov wrote:
>>>>>> Sergei,
>>>>>>
>>>>>> Please, update recently introduced
>>>>>> test/compiler/unsafe/UnsafeRaw.java.
>>>>>>
>>>>>> Best regards,
>>>>>> Vladimir Ivanov
>>>>>>
>>>>>> On 9/23/14, 7:04 PM, Sergei Kovalev wrote:
>>>>>>> Hello all,
>>>>>>>
>>>>>>> Looking for volunteers for review.
>>>>>>>
>>>>>>> I'm working for CR
>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8044186 that
>>>>>>> submitted against tests.
>>>>>>>
>>>>>>> There's the several tests which use randomly generated numbers.
>>>>>>> It's
>>>>>>> needed to introduce a way that provide a common manner to
>>>>>>> reproduce the
>>>>>>> same random sequence, set seed.
>>>>>>>
>>>>>>> There are two possible way to provide seed value:
>>>>>>> - system property
>>>>>>> - command line arguments.
>>>>>>>
>>>>>>> I chose system property to provide seed value because it could be
>>>>>>> obtained in any part of code without additional effort. In case
>>>>>>> passing
>>>>>>> seed value as command line argument we have to introduce additional
>>>>>>> logic (and unwanted code) to pass this value in appropriate method.
>>>>>>>
>>>>>>> I introduced factory method getRandomInstance in the file
>>>>>>> Utility.java
>>>>>>> and make reference to this method in all applicable tests.
>>>>>>> There is other utility class: Verifier.java. It used in several
>>>>>>> other
>>>>>>> testcases from test/compiler/intrinsics/mathexact/ package.
>>>>>>> Therefore
>>>>>>> many files contains modifications only for jtreg annotations.
>>>>>>>
>>>>>>> I've tested all related tests locally. All tests passed and seed
>>>>>>> value
>>>>>>> printed to the logs.
>>>>>>>
>>>>>>> links:
>>>>>>> bug: https://bugs.openjdk.java.net/browse/JDK-8044186
>>>>>>> webrev:
>>>>>>> http://cr.openjdk.java.net/~vlivanov/kovalev/8044186/webrev.01/
>>>>>>>
>>>>>>
>>>> --
>>>> With best regards,
>>>> Sergei
>>>>
>>>
>>>
>>
>
>
--
With best regards,
Sergei
-------------- next part --------------
diff -r 63d7b4f9285b test/compiler/8005956/PolynomialRoot.java
--- a/test/compiler/8005956/PolynomialRoot.java Thu Oct 30 14:54:58 2014 +0400
+++ b/test/compiler/8005956/PolynomialRoot.java Thu Oct 30 15:54:47 2014 +0400
@@ -60,7 +60,7 @@
public static int root4(final double [] p,final double [] re_root,final double [] im_root)
{
- if(PRINT_DEBUG) System.err.println("=====================root4:p="+Arrays.toString(p));
+ if (PRINT_DEBUG) { System.err.println("=====================root4:p=" + Arrays.toString(p)); }
final double vs=p[4];
if(PRINT_DEBUG) System.err.println("p[4]="+p[4]);
if(!(Math.abs(vs)>EPS))
@@ -370,7 +370,7 @@
- static void setRandomP(final double [] p,final int n,Random r)
+ static void setRandomP(final double [] p, final int n, Random r)
{
if(r.nextDouble()<0.1)
{
diff -r 63d7b4f9285b test/testlibrary/com/oracle/java/testlibrary/Utils.java
--- a/test/testlibrary/com/oracle/java/testlibrary/Utils.java Thu Oct 30 14:54:58 2014 +0400
+++ b/test/testlibrary/com/oracle/java/testlibrary/Utils.java Thu Oct 30 15:54:47 2014 +0400
@@ -64,7 +64,7 @@
private static Unsafe unsafe = null;
/**
- * The constant defines property name for seed value.
+ * Defines property name for seed value.
*/
public static final String SEED_PROPERTY_NAME = "com.oracle.java.testlibrary.random.seed";
@@ -73,7 +73,11 @@
* "com.oracle.java.testlibrary.random.seed" property value.
*/
private static volatile Random RANDOM_GENERATOR;
- public static final long SEED;
+
+ /**
+ * Contains the seed value used for {@link java.util.Random} creation.
+ */
+ public static final long SEED = Long.getLong(SEED_PROPERTY_NAME, new Random().nextLong());
/**
* Returns the value of 'test.timeout.factor' system property
* converted to {@code double}.
@@ -82,7 +86,6 @@
static {
String toFactor = System.getProperty("test.timeout.factor", "1.0");
TIMEOUT_FACTOR = Double.parseDouble(toFactor);
- SEED = Long.valueOf(System.getProperty(SEED_PROPERTY_NAME, "" + new Random().nextLong()));
}
private Utils() {
@@ -346,10 +349,10 @@
}
/**
- * The method returns {@link java.util.Random} generator with particular seed.
- * Seed could be provided via system property <strong>com.oracle.java.testlibrary.random.seed</strong>.
- * In case no seed provided, method will generate random seed.
- * The value of used seed printed to logs.
+ * Returns {@link java.util.Random} generator initialized with particular seed.
+ * The seed could be provided via system property {@link Utils#SEED_PROPERTY_NAME}
+ * In case no seed is provided, the method uses a random number.
+ * The used seed printed to stdout.
* @return {@link java.util.Random} generator with particular seed.
*/
public static Random getRandomInstance() {
diff -r 63d7b4f9285b test/testlibrary_tests/RandomGeneratorTest.java
--- a/test/testlibrary_tests/RandomGeneratorTest.java Thu Oct 30 14:54:58 2014 +0400
+++ b/test/testlibrary_tests/RandomGeneratorTest.java Thu Oct 30 15:54:47 2014 +0400
@@ -25,9 +25,9 @@
* @test
* @summary Verify correctnes of the random generator from Utility.java
* @library /testlibrary
- * @run main RandomGeneratorTest same
- * @run main RandomGeneratorTest noseed
- * @run main RandomGeneratorTest different
+ * @run driver RandomGeneratorTest SAME_SEED
+ * @run driver RandomGeneratorTest NO_SEED
+ * @run driver RandomGeneratorTest DIFFERENT_SEED
*/
import com.oracle.java.testlibrary.ProcessTools;
@@ -37,100 +37,119 @@
import java.util.Random;
/**
- * The test verify correctness of work Utils.getRandonInstance().
- * Test work in three modes: sqme seed provided, no seed provided and
- * different seed provided. In first case test expect that all random numbers
+ * The test verifies correctness of work {@link com.oracle.java.testlibrary.Utils#getRandomInstance()}.
+ * Test works in three modes: same seed provided, no seed provided and
+ * different seed provided. In the first case the test expects that all random numbers
* will be repeated in all next iterations. For other two modes test expects that
- * no one randomly generated long value will repeated in next iterations.
- * @author skovalev
+ * randomly generated numbers differ from original.
*/
public class RandomGeneratorTest {
- private static final String SAME_SEED = "same";
- private static final String NO_SEED = "noseed";
- private static final String DIFFERENT_SEED = "different";
private static final String SEED_VM_OPTION = "-D" + Utils.SEED_PROPERTY_NAME + "=";
public static void main( String[] args) throws Throwable {
- String mode = NO_SEED;
- if (args.length > 0) {
- mode = args[0];
+ if (args.length == 0) {
+ throw new Error("TESTBUG: No test mode provided.");
}
- System.out.printf("<-------- Run test in %s mode ---------------->\n", mode);
- SeedOption seedOpt = new SeedOption(mode);
+ SeedOption seedOpt = SeedOption.valueOf(args[0]);
List<String> jvmArgs = new ArrayList<String>();
String optStr = seedOpt.getSeedOption();
- int seedOptsIdx = -1;
if (optStr != null) {
jvmArgs.add(optStr);
- seedOptsIdx = jvmArgs.size() - 1;
}
jvmArgs.add(RandomRunner.class.getName());
String[] cmdLineArgs = jvmArgs.toArray(new String[jvmArgs.size()]);
String etalon = ProcessTools.executeTestJvm(cmdLineArgs).getOutput().trim();
- for (int idx = 0; idx < 10; idx++) {
- if (SAME_SEED.equals(mode)) {
- ProcessTools.executeTestJvm(cmdLineArgs).shouldMatch(etalon);
- } else {
- if (DIFFERENT_SEED.equals(mode)) {
- jvmArgs.set(seedOptsIdx, seedOpt.getSeedOption());
- cmdLineArgs = jvmArgs.toArray(new String[jvmArgs.size()]);
- }
- String iterStr = ProcessTools.executeTestJvm(cmdLineArgs).getOutput();
- for (String number : etalon.split("\n")[2].split(" ")) { //first two lines of output contains Utils class output
- //therefore we are interested in 3rd line only.
- if (iterStr.contains(number)) {
- throw new RuntimeException("Number:" + number + " repeated in next iterration.");
- }
- }
+ seedOpt.verify(etalon, cmdLineArgs);
+ }
+
+ /**
+ * The utility enum helps to generate an appropriate string that should be passed
+ * to the command line depends on the testing mode. It is also responsible for the result
+ * validation.
+ */
+ private enum SeedOption {
+ SAME_SEED {
+ @Override
+ public String getSeedOption() {
+ return SEED_VM_OPTION + Utils.SEED;
}
+
+ @Override
+ protected boolean isOutputExpected(String orig, String output) {
+ return output.equals(orig);
+ }
+ },
+ DIFFERENT_SEED {
+ @Override
+ public String getSeedOption() {
+ return SEED_VM_OPTION + Utils.getRandomInstance().nextLong();
+ }
+
+ @Override
+ public void verify(String orig, String[] cmdLine) {
+ cmdLine[0] = getSeedOption();
+ super.verify(orig, cmdLine);
+ }
+ },
+ NO_SEED {
+ @Override
+ public String getSeedOption() {
+ return null;
+ }
+ };
+
+ /**
+ * Generates a string to be added as a command line argument.
+ * It contains "-D" prefix, system property name, '=' sign
+ * and seed value.
+ * @return command line argument
+ */
+ public abstract String getSeedOption();
+
+ protected boolean isOutputExpected(String orig, String output) {
+ return !output.equals(orig);
+ }
+
+ /**
+ * Verifies that the original output meets expectations
+ * depending on the test mode. It compares the output of second execution
+ * to original one.
+ * @param orig original output
+ * @param cmdLine command line arguments
+ * @throws Throwable - Throws an exception in case test failure.
+ */
+ public void verify(String orig, String[] cmdLine) {
+ String lastLineOrig = getLastLine(orig);
+ String lastLine;
+ try {
+ lastLine = getLastLine(ProcessTools.executeTestJvm(cmdLine).getOutput().trim());
+ } catch (Throwable t) {
+ throw new Error("TESTBUG: Unexpedted exception during jvm execution.", t);
+ }
+ if (!isOutputExpected(lastLineOrig, lastLine)) {
+ throw new AssertionError("Unexpected random number sequence for mode: " + this.name());
+ }
+ }
+
+ private static String getLastLine(String output) {
+ return output.substring(output.lastIndexOf(Utils.NEW_LINE)).trim();
}
}
/**
- * The utility class helps to generate appropriate string that should be passed
- * to the command line depends on testing mode.
- */
- public static class SeedOption {
- private final String mode;
- private final long seed = Utils.SEED;
- public SeedOption (String value) {
- this.mode = value;
- }
-
- /**
- * The methods generates a string to be added as an
- * command line argument. It contains -D prefix,
- * system property name, '=' sight and seed value.
- * @return Command line argument
- */
- public String getSeedOption() {
- switch (mode) {
- case SAME_SEED:
- return SEED_VM_OPTION + seed;
- case DIFFERENT_SEED:
- return SEED_VM_OPTION + Utils.getRandomInstance().nextLong();
- default:
- throw new IllegalArgumentException("Unsapported test mode: " + mode);
- case NO_SEED:
- }
- return null;
- }
- }
-
- /**
- * The helper class that gets {@link java.util.Random} class
- * from {@link Utils#getRandomInstance()}, generate several random numbers
- * and prints it into stdout.
+ * The helper class generates several random numbers
+ * and prints them out.
*/
public static class RandomRunner {
- private static int COUNT = 10;
+ private static final int COUNT = 10;
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
Random rng = Utils.getRandomInstance();
- for (int idx = 0; idx < COUNT; idx++) {
+ for (int i = 0; i < COUNT; i++) {
sb.append(rng.nextLong()).append(' ');
}
System.out.println(sb.toString());
}
}
-}
\ No newline at end of file
+}
+
More information about the hotspot-compiler-dev
mailing list