8242314: use reproducible random in vmTestbase shared code

Reviewed-by: kbarrett, lmesnik
This commit is contained in:
Igor Ignatyev 2020-04-28 20:49:28 -07:00
parent 9320f9c60a
commit 6ff66db553
7 changed files with 107 additions and 52 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020, 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
@ -21,16 +21,16 @@
* questions.
*/
import jdk.test.lib.Platform;
import jdk.test.lib.Utils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Starts a new process to execute a command.
@ -48,6 +48,10 @@ import java.util.Arrays;
* {@code --java}, i.e. 0 or 95 means pass.
*/
public class ExecDriver {
// copied from jdk.test.lib.Utils.TEST_CLASS_PATH
private static final String TEST_CLASS_PATH = System.getProperty("test.class.path", ".");
// copied from jdk.test.lib.Utils.TEST_CLASS_PATH
private static final String TEST_JDK = System.getProperty("test.jdk");
public static void main(String[] args) throws IOException, InterruptedException {
boolean java = false;
boolean launcher = false;
@ -68,7 +72,7 @@ public class ExecDriver {
}
args[0] = javaBin();
args[1] = "-cp";
args[2] = Utils.TEST_CLASS_PATH;
args[2] = TEST_CLASS_PATH;
System.arraycopy(oldArgs, 1, args, count, oldArgs.length - 1);
java = true;
break;
@ -84,7 +88,7 @@ public class ExecDriver {
// adding 'test.vm.opts' and 'test.java.opts'
if (java) {
String[] oldArgs = args;
String[] testJavaOpts = Utils.getTestJavaOpts();
String[] testJavaOpts = getTestJavaOpts();
if (testJavaOpts.length > 0) {
args = new String[args.length + testJavaOpts.length];
// bin/java goes before options
@ -101,10 +105,11 @@ public class ExecDriver {
ProcessBuilder pb = new ProcessBuilder(args);
// adding jvm.so to library path
if (launcher) {
Path dir = Paths.get(Utils.TEST_JDK);
Path dir = Paths.get(TEST_JDK);
String value;
String name = Platform.sharedLibraryPathVariableName();
if (Platform.isWindows()) {
String name = sharedLibraryPathVariableName();
// if (jdk.test.lib.Platform.isWindows()) {
if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
value = dir.resolve("bin")
.resolve(variant())
.toAbsolutePath()
@ -125,7 +130,7 @@ public class ExecDriver {
.merge(name, value, (x, y) -> y + File.pathSeparator + x));
System.out.println(" with CLASSPATH = " +
pb.environment()
.put("CLASSPATH", Utils.TEST_CLASS_PATH));
.put("CLASSPATH", TEST_CLASS_PATH));
}
Process p = pb.start();
// inheritIO does not work as expected for @run driver
@ -138,19 +143,52 @@ public class ExecDriver {
}
}
// copied from jdk.test.lib.Platform::sharedLibraryPathVariableName
private static String sharedLibraryPathVariableName() {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.startsWith("win")) {
return "PATH";
} else if (osName.startsWith("mac")) {
return "DYLD_LIBRARY_PATH";
} else if (osName.startsWith("aix")) {
return "LIBPATH";
} else {
return "LD_LIBRARY_PATH";
}
}
// copied from jdk.test.lib.Utils::getTestJavaOpts()
private static String[] getTestJavaOpts() {
List<String> opts = new ArrayList<String>();
{
String v = System.getProperty("test.vm.opts", "").trim();
if (!v.isEmpty()) {
Collections.addAll(opts, v.split("\\s+"));
}
}
{
String v = System.getProperty("test.java.opts", "").trim();
if (!v.isEmpty()) {
Collections.addAll(opts, v.split("\\s+"));
}
}
return opts.toArray(new String[0]);
}
// copied jdk.test.lib.Platform::variant
private static String variant() {
if (Platform.isServer()) {
String vmName = System.getProperty("java.vm.name");
if (vmName.endsWith(" Server VM")) {
return "server";
} else if (Platform.isClient()) {
} else if (vmName.endsWith(" Client VM")) {
return "client";
} else if (Platform.isMinimal()) {
} else if (vmName.endsWith(" Minimal VM")) {
return "minimal";
} else {
throw new Error("TESTBUG: unsuppported vm variant");
}
}
private static void copy(InputStream is, OutputStream os) {
byte[] buffer = new byte[1024];
int n;
@ -165,7 +203,7 @@ public class ExecDriver {
}
private static String javaBin() {
return Paths.get(Utils.TEST_JDK)
return Paths.get(TEST_JDK)
.resolve("bin")
.resolve("java")
.toAbsolutePath()

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, 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
@ -27,6 +27,7 @@ import java.io.*;
import java.util.*;
import nsk.share.test.ExecutionController;
import nsk.share.test.LocalRandom;
/**
* <tt>NonbranchyTree</tt> defines a tree structure. Each node of the tree
@ -38,7 +39,6 @@ public class NonbranchyTree {
/** Minimal size of each node (in bytes) */
public final static int MIN_NODE_SIZE = 20;
private Node root;
private Random random;
private int numberOfNodes;
private float branchiness;
private int size;
@ -61,21 +61,16 @@ public class NonbranchyTree {
*
*/
public NonbranchyTree(int numberOfNodes, float branchiness, int size) {
this(numberOfNodes, branchiness, size, new Random(System.currentTimeMillis()), null);
this(numberOfNodes, branchiness, size, null);
initTree();
}
public NonbranchyTree(int numberOfNodes, float branchiness, int size, ExecutionController controller) {
this(numberOfNodes, branchiness, size, new Random(System.currentTimeMillis()), controller);
initTree();
}
private NonbranchyTree(int numberOfNodes, float branchiness, int size, Random random, ExecutionController controller) {
this.numberOfNodes = numberOfNodes;
this.branchiness = branchiness;
this.size = size;
this.random = random;
this.controller = controller;
initTree();
}
private void initTree() {
@ -94,6 +89,8 @@ public class NonbranchyTree {
throw new IllegalArgumentException("Illegal size of nodes: "
+ size + ", must be at least 1.");
}
// ensure that LocalRandom is loaded and has enough memory
LocalRandom.nextBoolean();
root = createTree(numberOfNodes, size);
}
@ -119,7 +116,7 @@ public class NonbranchyTree {
// Create a few nodes
if (makeRightNode()) {
// The node will have two sons
int leftNodes = 1 + random.nextInt(numberOfNodes - 2);
int leftNodes = 1 + LocalRandom.nextInt(numberOfNodes - 2);
int rightNodes = numberOfNodes - 1 - leftNodes;
node.left = createTree(leftNodes, size);
@ -142,7 +139,7 @@ public class NonbranchyTree {
// Define the "branchiness" of the tree
private boolean makeRightNode() {
return (random.nextFloat() < branchiness);
return (LocalRandom.nextFloat() < branchiness);
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2020, 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
@ -27,6 +27,7 @@ import nsk.share.TestBug;
import nsk.share.jpda.AbstractDebuggeeTest;
import java.io.*;
import java.util.*;
import jdk.test.lib.Utils;
/*
* This class serial executes several JDI tests based on nsk.share.jdi.TestDebuggerType2 in single VM
@ -192,7 +193,7 @@ public class SerialExecutionDebugger extends TestDebuggerType2 {
if (testWorkDir == null)
throw new TestBug("Debugger requires -testWorkDir parameter");
Collections.shuffle(result);
Collections.shuffle(result, Utils.getRandomInstance());
// save resulted tests sequence in file (to simplify reproducing)
try {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2020, 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
@ -26,13 +26,13 @@ package nsk.share.runner;
import nsk.share.log.Log;
import nsk.share.test.StressOptions;
import java.io.PrintStream;
import jdk.test.lib.Utils;
public class RunParams {
private StressOptions stressOptions;
private long sleepTime = 500;
private long iterations = 0;
private int numberOfThreads;
private long seed = System.currentTimeMillis();
private boolean runGCThread = false;
private boolean runFinThread = false;
private boolean runMemDiagThread = false;
@ -126,11 +126,9 @@ public class RunParams {
}
public final long getSeed() {
return seed;
}
public final void setSeed(long seed) {
this.seed = seed;
// ensure that seed got printed out
Utils.getRandomInstance();
return Utils.SEED;
}
public final boolean isRunGCThread() {
@ -212,8 +210,6 @@ public class RunParams {
runFinDiagThread = true;
else if (args[i].equals("-Df"))
runFinDiagThread = true;
else if (args[i].equals("-s"))
seed = Long.parseLong(args[++i]);
else if (args[i].equals("-t"))
numberOfThreads = Integer.parseInt(args[++i]);
else if (args[i].equals("-it"))
@ -233,7 +229,6 @@ public class RunParams {
out.println("Sleep time: " + sleepTime);
out.println("Iterations: " + iterations);
out.println("Number of threads: " + numberOfThreads);
out.println("Seed: " + seed);
out.println("Run GC thread: " + runGCThread);
out.println("Run mem diag thread: " + runMemDiagThread);
out.println("Run forever: " + runForever);
@ -244,7 +239,6 @@ public class RunParams {
log.debug("Sleep time: " + sleepTime);
log.debug("Iterations: " + iterations);
log.debug("Number of threads: " + numberOfThreads);
log.debug("Seed: " + seed);
log.debug("Run GC thread: " + runGCThread);
log.debug("Run mem diag thread: " + runMemDiagThread);
log.debug("Run forever: " + runForever);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2020, 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,28 +23,50 @@
package nsk.share.test;
import java.util.concurrent.ThreadLocalRandom;
import java.util.Random;
import jdk.test.lib.Utils;
import nsk.share.TestFailure;
/**
* Utility class which encapsulates all useful static methods.
*/
public class LocalRandom {
static {
// ensure seed got printed out
Utils.getRandomInstance();
}
private final static ThreadLocal<Random> random = new ThreadLocal<>() {
protected Random initialValue() {
// each thread gets its own seed independendly on the order they
// use LocalRandom, yet it depends on the order threads are created.
// main thread uses original seed
return new Random(Utils.SEED ^ (Thread.currentThread().getId() - 1));
}
};
private static int minPauseTime = 3000;
private static int maxPauseTime = 5000;
private static int maxRandomCount = 65536;
/*
* Initializes a thread-local instance to ensure that there is enough memory.
* Useful for tests that exhaust memory.
*/
public static void init() {
random.get();
}
/*
* Return next random double number.
*
* @return random double
*/
public static double random() {
return ThreadLocalRandom.current().nextDouble();
return random.get().nextDouble();
}
public static double nextDouble() {
return ThreadLocalRandom.current().nextDouble();
return random.get().nextDouble();
}
public static byte nextByte() {
@ -60,7 +82,7 @@ public class LocalRandom {
}
public static boolean nextBoolean() {
return ThreadLocalRandom.current().nextBoolean();
return random.get().nextBoolean();
}
public static void nextBytes(byte[] arr) {
@ -252,7 +274,7 @@ public class LocalRandom {
}
public static int nextInt() {
return ThreadLocalRandom.current().nextInt();
return random.get().nextInt();
}
/**
@ -262,11 +284,11 @@ public class LocalRandom {
* @return random integer
*/
public static int nextInt(int n) {
return ThreadLocalRandom.current().nextInt(n);
return random.get().nextInt(n);
}
public static long nextLong() {
return ThreadLocalRandom.current().nextLong();
return random.get().nextLong();
}
/**
@ -286,7 +308,7 @@ public class LocalRandom {
* @return random double
*/
public static float nextFloat() {
return ThreadLocalRandom.current().nextFloat();
return random.get().nextFloat();
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2020, 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
@ -30,12 +30,12 @@ import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import nsk.share.ClassUnloader;
import nsk.share.TestFailure;
import nsk.share.gc.ThreadedGCTest;
import nsk.share.gc.gp.GarbageUtils;
import nsk.share.test.ExecutionController;
import nsk.share.test.LocalRandom;
/**
* This is the base class for btree & chain tests. It is a standard GCThreaded Test.
@ -114,7 +114,7 @@ public abstract class SysDictTest extends ThreadedGCTest {
List<String> listNames = new ArrayList<String>(classnames.length);
listNames.addAll(Arrays.asList(classnames));
for (int i = 0; i < classnames.length; i++) {
int idx1 = new Random().nextInt(listNames.size());
int idx1 = LocalRandom.nextInt(listNames.size());
this.names[i] = listNames.remove(idx1);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, 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
@ -28,6 +28,8 @@ import java.util.Random;
import java.util.function.Predicate;
import java.util.function.Supplier;
import jdk.test.lib.Utils;
public class RandomEx extends Random {
private final Map<Class<?>, Supplier<?>> map = new HashMap<>();
@ -51,6 +53,7 @@ public class RandomEx extends Random {
}
public RandomEx() {
super(Utils.getRandomInstance().nextLong());
}
public RandomEx(long seed) {