Merge
This commit is contained in:
commit
fafec2b66c
@ -44,6 +44,10 @@ ifneq "x$(SEED)" "x"
|
||||
APPLICATION_ARGS += --seed $(SEED)
|
||||
endif
|
||||
|
||||
ifneq "x$(EXTRA_SRC_DIR)" "x"
|
||||
EXTRA_SRC_FILES := $(shell find $(EXTRA_SRC_DIR) -name '*.java')
|
||||
endif
|
||||
|
||||
JAVA = $(JDK_HOME)/bin/java
|
||||
JAVAC = $(JDK_HOME)/bin/javac
|
||||
JAR = $(JDK_HOME)/bin/jar
|
||||
@ -99,6 +103,7 @@ COMPILE: INIT filelist compile_testlib
|
||||
filelist: $(SRC_FILES)
|
||||
@rm -f $@
|
||||
@echo $(SRC_FILES) > $@
|
||||
@echo $(EXTRA_SRC_FILES) >> $@
|
||||
|
||||
INIT: $(DIST_DIR)
|
||||
$(shell if [ ! -d $(CLASSES_DIR) ]; then mkdir -p $(CLASSES_DIR); fi)
|
||||
|
@ -9,3 +9,5 @@ exclude-methods-file=conf/exclude.methods.lst
|
||||
print-complexity=true
|
||||
print-hierarchy=true
|
||||
disable-static=true
|
||||
generatorsFactories=jdk.test.lib.jittester.TestGeneratorsFactory
|
||||
generators=JavaCode,ByteCode
|
||||
|
@ -25,50 +25,19 @@ package jdk.test.lib.jittester;
|
||||
|
||||
import jdk.test.lib.Pair;
|
||||
import jdk.test.lib.jittester.factories.IRNodeBuilder;
|
||||
import jdk.test.lib.jittester.jtreg.Printer;
|
||||
import jdk.test.lib.jittester.types.TypeKlass;
|
||||
import jdk.test.lib.jittester.utils.FixedTrees;
|
||||
import jdk.test.lib.jittester.utils.OptionResolver;
|
||||
import jdk.test.lib.jittester.utils.OptionResolver.Option;
|
||||
import jdk.test.lib.jittester.utils.PseudoRandom;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class Automatic {
|
||||
private static final int MINUTES_TO_WAIT = Integer.getInteger("jdk.test.lib.jittester", 3);
|
||||
|
||||
static String getJtregHeader(String mainClass, boolean addCompile) {
|
||||
String synopsis = "seed = '" + ProductionParams.seed.value() + "'"
|
||||
+ ", specificSeed = '" + PseudoRandom.getCurrentSeed() + "'";
|
||||
StringBuilder header = new StringBuilder();
|
||||
header.append("/*\n * @test\n * @summary ")
|
||||
.append(synopsis)
|
||||
.append(" \n* @library / ../\n");
|
||||
if (addCompile) {
|
||||
header.append("\n * @compile ")
|
||||
.append(mainClass)
|
||||
.append(".java\n");
|
||||
}
|
||||
header.append(" * @run build jdk.test.lib.jittester.jtreg.JitTesterDriver "
|
||||
+ "jdk.test.lib.jittester.jtreg.Printer\n")
|
||||
.append(" * @run driver jdk.test.lib.jittester.jtreg.JitTesterDriver ")
|
||||
.append(mainClass)
|
||||
.append("\n */\n\n");
|
||||
if (ProductionParams.printHierarchy.value()) {
|
||||
header.append("/*\n")
|
||||
.append(Automatic.printHierarchy())
|
||||
.append("*/\n");
|
||||
}
|
||||
return header.toString();
|
||||
}
|
||||
public static final int MINUTES_TO_WAIT = Integer.getInteger("jdk.test.lib.jittester", 3);
|
||||
|
||||
private static Pair<IRNode, IRNode> generateIRTree(String name) {
|
||||
SymbolTable.removeAll();
|
||||
@ -120,123 +89,48 @@ public class Automatic {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<TestsGenerator> getTestGenerators() {
|
||||
List<TestsGenerator> result = new ArrayList<>();
|
||||
Class<?> factoryClass;
|
||||
Function<String[], List<TestsGenerator>> factory;
|
||||
String[] factoryClassNames = ProductionParams.generatorsFactories.value().split(",");
|
||||
String[] generatorNames = ProductionParams.generators.value().split(",");
|
||||
for (String factoryClassName : factoryClassNames) {
|
||||
try {
|
||||
factoryClass = Class.forName(factoryClassName);
|
||||
factory = (Function<String[], List<TestsGenerator>>) factoryClass.newInstance();
|
||||
} catch (ReflectiveOperationException roe) {
|
||||
throw new Error("Can't instantiate generators factory", roe);
|
||||
}
|
||||
result.addAll(factory.apply(generatorNames));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
initializeTestGenerator(args);
|
||||
int counter = 0;
|
||||
try {
|
||||
Path testbaseDir = Paths.get(ProductionParams.testbaseDir.value());
|
||||
System.out.printf(" %13s | %8s | %8s | %8s |%n", "start time", "count", "generat",
|
||||
"running");
|
||||
System.out.printf(" %13s | %8s | %8s | %8s |%n", "---", "---", "---","---");
|
||||
String path = getJavaPath();
|
||||
String javacPath = Paths.get(path, "javac").toString();
|
||||
String javaPath = Paths.get(path, "java").toString();
|
||||
|
||||
// compile Printer class first. A common one for all tests
|
||||
ensureExisting(testbaseDir);
|
||||
ProcessBuilder pbPrinter = new ProcessBuilder(javacPath,
|
||||
Paths.get(testbaseDir.toString(), "jdk", "test", "lib", "jittester",
|
||||
"jtreg", "Printer.java").toString());
|
||||
runProcess(pbPrinter, testbaseDir.resolve("Printer").toString());
|
||||
do {
|
||||
double start = System.currentTimeMillis();
|
||||
System.out.print("[" + LocalTime.now() + "] |");
|
||||
String name = "Test_" + counter;
|
||||
Pair<IRNode, IRNode> irTree = generateIRTree(name);
|
||||
System.out.printf(" %8d |", counter);
|
||||
double generationTime = System.currentTimeMillis() - start;
|
||||
System.out.printf(" %8.0f |", generationTime);
|
||||
if (!ProductionParams.disableJavacodeGeneration.value()) {
|
||||
JavaCodeGenerator generator = new JavaCodeGenerator();
|
||||
String javaFile = generator.apply(irTree.first, irTree.second);
|
||||
ProcessBuilder pb = new ProcessBuilder(javacPath, "-cp", testbaseDir.toString()
|
||||
+ ":" + generator.getTestbase().toString(), javaFile);
|
||||
runProcess(pb, generator.getTestbase().resolve(name).toString());
|
||||
start = System.currentTimeMillis();
|
||||
|
||||
// Run compiled class files
|
||||
pb = new ProcessBuilder(javaPath, "-Xint", "-cp", testbaseDir.toString()
|
||||
+ ":" + generator.getTestbase().toString(), name);
|
||||
String goldFile = name + ".gold";
|
||||
runProcess(pb, generator.getTestbase().resolve(goldFile).toString());
|
||||
}
|
||||
|
||||
if (!ProductionParams.disableBytecodeGeneration.value()) {
|
||||
ByteCodeGenerator generator = new ByteCodeGenerator();
|
||||
generator.apply(irTree.first, irTree.second);
|
||||
generator.writeJtregBytecodeRunner(name);
|
||||
// Run generated bytecode
|
||||
ProcessBuilder pb = new ProcessBuilder(javaPath, "-Xint", "-Xverify", "-cp",
|
||||
testbaseDir.toString() + ":" + generator.getTestbase().toString(),
|
||||
name);
|
||||
String goldFile = name + ".gold";
|
||||
start = System.currentTimeMillis();
|
||||
runProcess(pb, generator.getTestbase().resolve(goldFile).toString());
|
||||
}
|
||||
|
||||
double runningTime = System.currentTimeMillis() - start;
|
||||
System.out.printf(" %8.0f |%n", runningTime);
|
||||
if (runningTime < TimeUnit.MINUTES.toMillis(MINUTES_TO_WAIT)) {
|
||||
++counter;
|
||||
}
|
||||
} while (counter < ProductionParams.numberOfTests.value());
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getJavaPath() {
|
||||
String[] env = { "JDK_HOME", "JAVA_HOME", "BOOTDIR" };
|
||||
for (String name : env) {
|
||||
String path = System.getenv(name);
|
||||
if (path != null) {
|
||||
return path + "/bin/";
|
||||
System.out.printf(" %13s | %8s | %8s | %8s |%n", "start time", "count", "generat",
|
||||
"running");
|
||||
System.out.printf(" %13s | %8s | %8s | %8s |%n", "---", "---", "---", "---");
|
||||
List<TestsGenerator> generators = getTestGenerators();
|
||||
do {
|
||||
double start = System.currentTimeMillis();
|
||||
System.out.print("[" + LocalTime.now() + "] |");
|
||||
String name = "Test_" + counter;
|
||||
Pair<IRNode, IRNode> irTree = generateIRTree(name);
|
||||
System.out.printf(" %8d |", counter);
|
||||
double generationTime = System.currentTimeMillis() - start;
|
||||
System.out.printf(" %8.0f |", generationTime);
|
||||
start = System.currentTimeMillis();
|
||||
for (TestsGenerator generator : generators) {
|
||||
generator.accept(irTree.first, irTree.second);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static int runProcess(ProcessBuilder pb, String name)
|
||||
throws IOException, InterruptedException {
|
||||
pb.redirectError(new File(name + ".err"));
|
||||
pb.redirectOutput(new File(name + ".out"));
|
||||
Process process = pb.start();
|
||||
if (process.waitFor(MINUTES_TO_WAIT, TimeUnit.MINUTES)) {
|
||||
try (FileWriter file = new FileWriter(name + ".exit")) {
|
||||
file.write(Integer.toString(process.exitValue()));
|
||||
double runningTime = System.currentTimeMillis() - start;
|
||||
System.out.printf(" %8.0f |%n", runningTime);
|
||||
if (runningTime < TimeUnit.MINUTES.toMillis(MINUTES_TO_WAIT)) {
|
||||
++counter;
|
||||
}
|
||||
return process.exitValue();
|
||||
} else {
|
||||
process.destroyForcibly();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static String printHierarchy() {
|
||||
return TypeList.getAll().stream()
|
||||
.filter(t -> t instanceof TypeKlass)
|
||||
.map(t -> typeDescription((TypeKlass) t))
|
||||
.collect(Collectors.joining("\n","CLASS HIERARCHY:\n", "\n"));
|
||||
}
|
||||
|
||||
private static String typeDescription(TypeKlass type) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
String parents = type.getParentsNames().stream().collect(Collectors.joining(","));
|
||||
result.append(type.isAbstract() ? "abstract " : "")
|
||||
.append(type.isFinal() ? "final " : "")
|
||||
.append(type.isInterface() ? "interface " : "class ")
|
||||
.append(type.getName())
|
||||
.append(parents.isEmpty() ? "" : ": " + parents);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
static void ensureExisting(Path path) {
|
||||
if (Files.notExists(path)) {
|
||||
try {
|
||||
Files.createDirectories(path);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} while (counter < ProductionParams.numberOfTests.value());
|
||||
}
|
||||
}
|
||||
|
@ -23,54 +23,60 @@
|
||||
|
||||
package jdk.test.lib.jittester;
|
||||
|
||||
import jdk.test.lib.jittester.visitors.ByteCodeVisitor;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import jdk.test.lib.jittester.visitors.ByteCodeVisitor;
|
||||
|
||||
/**
|
||||
* Generates class files from bytecode
|
||||
* Generates class files from IRTree
|
||||
*/
|
||||
class ByteCodeGenerator implements BiFunction<IRNode, IRNode, String> {
|
||||
private final Path testbase = Paths.get(ProductionParams.testbaseDir.value(),
|
||||
"bytecode_tests");
|
||||
class ByteCodeGenerator extends TestsGenerator {
|
||||
private static final String DEFAULT_SUFFIX = "bytecode_tests";
|
||||
|
||||
public void writeJtregBytecodeRunner(String name) {
|
||||
try (FileWriter file = new FileWriter(testbase.resolve(name + ".java").toFile())) {
|
||||
file.write(Automatic.getJtregHeader(name, false));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
ByteCodeGenerator() {
|
||||
super(DEFAULT_SUFFIX);
|
||||
}
|
||||
|
||||
public String apply(IRNode mainClass, IRNode privateClasses) {
|
||||
Automatic.ensureExisting(testbase);
|
||||
ByteCodeGenerator(String suffix, Function<String, String[]> preRunActions, String jtDriverOptions) {
|
||||
super(suffix, preRunActions, jtDriverOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(IRNode mainClass, IRNode privateClasses) {
|
||||
generateClassFiles(mainClass, privateClasses);
|
||||
generateSeparateJtregHeader(mainClass);
|
||||
compilePrinter();
|
||||
generateGoldenOut(mainClass.getName());
|
||||
}
|
||||
|
||||
private void generateSeparateJtregHeader(IRNode mainClass) {
|
||||
String mainClassName = mainClass.getName();
|
||||
writeFile(generatorDir, mainClassName + ".java", getJtregHeader(mainClassName));
|
||||
}
|
||||
|
||||
private void generateClassFiles(IRNode mainClass, IRNode privateClasses) {
|
||||
String mainClassName = mainClass.getName();
|
||||
ensureExisting(generatorDir);
|
||||
try {
|
||||
ByteCodeVisitor vis = new ByteCodeVisitor();
|
||||
if (privateClasses != null) {
|
||||
privateClasses.accept(vis);
|
||||
}
|
||||
mainClass.accept(vis);
|
||||
|
||||
Path mainClassPath = testbase.resolve(mainClass.getName() + ".class");
|
||||
writeToClassFile(mainClassPath, vis.getByteCode(mainClass.getName()));
|
||||
writeFile(mainClassName + ".class", vis.getByteCode(mainClassName));
|
||||
if (privateClasses != null) {
|
||||
privateClasses.getChildren().forEach(c -> {
|
||||
String name = c.getName();
|
||||
Path classPath = testbase.resolve(name + ".class");
|
||||
writeToClassFile(classPath, vis.getByteCode(name));
|
||||
writeFile(name + ".class", vis.getByteCode(name));
|
||||
});
|
||||
}
|
||||
return mainClassPath.toString();
|
||||
} catch (Throwable t) {
|
||||
Path errFile = testbase.resolve(mainClass.getName() + ".err");
|
||||
Path errFile = generatorDir.resolve(mainClassName + ".err");
|
||||
try (PrintWriter pw = new PrintWriter(Files.newOutputStream(errFile,
|
||||
StandardOpenOption.CREATE_NEW))) {
|
||||
t.printStackTrace(pw);
|
||||
@ -78,16 +84,11 @@ class ByteCodeGenerator implements BiFunction<IRNode, IRNode, String> {
|
||||
t.printStackTrace();
|
||||
throw new Error("can't write error to error file " + errFile, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Path getTestbase() {
|
||||
return testbase;
|
||||
}
|
||||
|
||||
private void writeToClassFile(Path path, byte[] bytecode) {
|
||||
try (FileOutputStream file = new FileOutputStream(path.toString())) {
|
||||
private void writeFile(String fileName, byte[] bytecode) {
|
||||
try (FileOutputStream file = new FileOutputStream(generatorDir.resolve(fileName).toFile())) {
|
||||
file.write(bytecode);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
|
@ -23,48 +23,59 @@
|
||||
|
||||
package jdk.test.lib.jittester;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.function.Function;
|
||||
import jdk.test.lib.jittester.visitors.JavaCodeVisitor;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Generates class files from java source code
|
||||
* Generates java source code from IRTree
|
||||
*/
|
||||
class JavaCodeGenerator implements BiFunction<IRNode, IRNode, String> {
|
||||
private final Path testbase = Paths.get(ProductionParams.testbaseDir.value(), "java_tests");
|
||||
public class JavaCodeGenerator extends TestsGenerator {
|
||||
private static final String DEFAULT_SUFFIX = "java_tests";
|
||||
|
||||
private String generateJavaCode(IRNode mainClass, IRNode privateClasses) {
|
||||
JavaCodeGenerator() {
|
||||
this(DEFAULT_SUFFIX, JavaCodeGenerator::generatePrerunAction, "");
|
||||
}
|
||||
|
||||
JavaCodeGenerator(String prefix, Function<String, String[]> preRunActions, String jtDriverOptions) {
|
||||
super(prefix, preRunActions, jtDriverOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(IRNode mainClass, IRNode privateClasses) {
|
||||
String mainClassName = mainClass.getName();
|
||||
generateSources(mainClass, privateClasses);
|
||||
compilePrinter();
|
||||
compileJavaFile(mainClassName);
|
||||
generateGoldenOut(mainClassName);
|
||||
}
|
||||
|
||||
private void generateSources(IRNode mainClass, IRNode privateClasses) {
|
||||
String mainClassName = mainClass.getName();
|
||||
StringBuilder code = new StringBuilder();
|
||||
JavaCodeVisitor vis = new JavaCodeVisitor();
|
||||
|
||||
code.append(Automatic.getJtregHeader(mainClass.getName(), true));
|
||||
code.append(getJtregHeader(mainClassName));
|
||||
if (privateClasses != null) {
|
||||
code.append(privateClasses.accept(vis));
|
||||
}
|
||||
code.append(mainClass.accept(vis));
|
||||
|
||||
return code.toString();
|
||||
ensureExisting(generatorDir);
|
||||
writeFile(generatorDir, mainClassName + ".java", code.toString());
|
||||
}
|
||||
|
||||
public Path getTestbase() {
|
||||
return testbase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(IRNode mainClass, IRNode privateClasses) {
|
||||
String code = generateJavaCode(mainClass, privateClasses);
|
||||
Automatic.ensureExisting(testbase);
|
||||
Path fileName = testbase.resolve(mainClass.getName() + ".java");
|
||||
try (FileWriter file = new FileWriter(fileName.toFile())) {
|
||||
file.write(code);
|
||||
return fileName.toString();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
private void compileJavaFile(String mainClassName) {
|
||||
String classPath = getRoot() + File.pathSeparator + generatorDir;
|
||||
ProcessBuilder pb = new ProcessBuilder(JAVAC, "-cp", classPath,
|
||||
generatorDir.resolve(mainClassName + ".java").toString());
|
||||
try {
|
||||
runProcess(pb, generatorDir.resolve(mainClassName).toString());
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new Error("Can't compile sources ", e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String[] generatePrerunAction(String mainClassName) {
|
||||
return new String[] {"@compile " + mainClassName + ".java"};
|
||||
}
|
||||
}
|
||||
|
@ -68,8 +68,6 @@ public class ProductionParams {
|
||||
public static Option<Boolean> disableNestedBlocks = null;
|
||||
public static Option<Boolean> disableArrays = null;
|
||||
public static Option<Boolean> enableFinalizers = null;
|
||||
public static Option<Boolean> disableBytecodeGeneration = null;
|
||||
public static Option<Boolean> disableJavacodeGeneration = null;
|
||||
// workaraound: to reduce chance throwing ArrayIndexOutOfBoundsException
|
||||
public static Option<Integer> chanceExpressionIndex = null;
|
||||
public static Option<String> testbaseDir = null;
|
||||
@ -78,6 +76,8 @@ public class ProductionParams {
|
||||
public static Option<Long> specificSeed = null;
|
||||
public static Option<String> classesFile = null;
|
||||
public static Option<String> excludeMethodsFile = null;
|
||||
public static Option<String> generators = null;
|
||||
public static Option<String> generatorsFactories = null;
|
||||
|
||||
public static void register(OptionResolver optionResolver) {
|
||||
productionLimit = optionResolver.addIntegerOption('l', "production-limit", 100, "Limit on steps in the production of an expression");
|
||||
@ -120,8 +120,6 @@ public class ProductionParams {
|
||||
disableNestedBlocks = optionResolver.addBooleanOption("disable-nested-blocks", "Disable generation of nested blocks");
|
||||
disableArrays = optionResolver.addBooleanOption("disable-arrays", "Disable generation of arrays");
|
||||
enableFinalizers = optionResolver.addBooleanOption("enable-finalizers", "Enable finalizers (for stress testing)");
|
||||
disableBytecodeGeneration = optionResolver.addBooleanOption("disable-bytecode-generation", "Disable generation of bytecode output");
|
||||
disableJavacodeGeneration = optionResolver.addBooleanOption("disable-javacode-generation", "Disable generation of java source code output");
|
||||
chanceExpressionIndex = optionResolver.addIntegerOption("chance-expression-index", 0, "A non negative decimal integer used to restrict chane of generating expression in array index while creating or accessing by index");
|
||||
testbaseDir = optionResolver.addStringOption("testbase-dir", ".", "Testbase dir");
|
||||
numberOfTests = optionResolver.addIntegerOption('n', "number-of-tests", 0, "Number of test classes to generate");
|
||||
@ -129,5 +127,7 @@ public class ProductionParams {
|
||||
specificSeed = optionResolver.addLongOption('z', "specificSeed", 0L, "A seed to be set for specific test generation(regular seed still needed for initialization)");
|
||||
classesFile = optionResolver.addStringOption('f', "classes-file", "conf/classes.lst", "File to read classes from");
|
||||
excludeMethodsFile = optionResolver.addStringOption('r', "exclude-methods-file", "conf/exclude.methods.lst", "File to read excluded methods from");
|
||||
generators = optionResolver.addStringOption("generators", "", "Comma-separated list of generator names");
|
||||
generatorsFactories = optionResolver.addStringOption("generatorsFactories", "", "Comma-separated list of generators factories class names");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
package jdk.test.lib.jittester;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class TestGeneratorsFactory implements Function<String[], List<TestsGenerator>> {
|
||||
|
||||
@Override
|
||||
public List<TestsGenerator> apply(String[] input) {
|
||||
List<TestsGenerator> result = new ArrayList<>();
|
||||
for (String generatorName : input) {
|
||||
switch (generatorName) {
|
||||
case "JavaCode":
|
||||
result.add(new JavaCodeGenerator());
|
||||
break;
|
||||
case "ByteCode":
|
||||
result.add(new ByteCodeGenerator());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown generator: " + generatorName);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
package jdk.test.lib.jittester;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import jdk.test.lib.jittester.types.TypeKlass;
|
||||
import jdk.test.lib.jittester.utils.PseudoRandom;
|
||||
|
||||
public abstract class TestsGenerator implements BiConsumer<IRNode, IRNode> {
|
||||
protected static final String JAVA_BIN = getJavaPath();
|
||||
protected static final String JAVAC = Paths.get(JAVA_BIN, "javac").toString();
|
||||
protected static final String JAVA = Paths.get(JAVA_BIN, "java").toString();
|
||||
protected final Path generatorDir;
|
||||
protected final Function<String, String[]> preRunActions;
|
||||
protected final String jtDriverOptions;
|
||||
|
||||
protected TestsGenerator(String suffix) {
|
||||
this(suffix, s -> new String[0], "");
|
||||
}
|
||||
|
||||
protected TestsGenerator(String suffix, Function<String, String[]> preRunActions,
|
||||
String jtDriverOptions) {
|
||||
generatorDir = getRoot().resolve(suffix);
|
||||
this.preRunActions = preRunActions;
|
||||
this.jtDriverOptions = jtDriverOptions;
|
||||
}
|
||||
|
||||
protected void generateGoldenOut(String mainClassName) {
|
||||
String classPath = getRoot() + File.pathSeparator + generatorDir;
|
||||
ProcessBuilder pb = new ProcessBuilder(JAVA, "-Xint", "-Xverify", "-cp", classPath,
|
||||
mainClassName);
|
||||
String goldFile = mainClassName + ".gold";
|
||||
try {
|
||||
runProcess(pb, generatorDir.resolve(goldFile).toString());
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new Error("Can't run generated test ", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static int runProcess(ProcessBuilder pb, String name)
|
||||
throws IOException, InterruptedException {
|
||||
pb.redirectError(new File(name + ".err"));
|
||||
pb.redirectOutput(new File(name + ".out"));
|
||||
Process process = pb.start();
|
||||
if (process.waitFor(Automatic.MINUTES_TO_WAIT, TimeUnit.MINUTES)) {
|
||||
try (FileWriter file = new FileWriter(name + ".exit")) {
|
||||
file.write(Integer.toString(process.exitValue()));
|
||||
}
|
||||
return process.exitValue();
|
||||
} else {
|
||||
process.destroyForcibly();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
protected static void compilePrinter() {
|
||||
Path root = getRoot();
|
||||
ProcessBuilder pbPrinter = new ProcessBuilder(JAVAC,
|
||||
root.resolve("jdk")
|
||||
.resolve("test")
|
||||
.resolve("lib")
|
||||
.resolve("jittester")
|
||||
.resolve("jtreg")
|
||||
.resolve("Printer.java")
|
||||
.toString());
|
||||
try {
|
||||
int exitCode = runProcess(pbPrinter, root.resolve("Printer").toString());
|
||||
if (exitCode != 0) {
|
||||
throw new Error("Printer compilation returned exit code " + exitCode);
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new Error("Can't compile printer", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void ensureExisting(Path path) {
|
||||
if (Files.notExists(path)) {
|
||||
try {
|
||||
Files.createDirectories(path);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String getJtregHeader(String mainClassName) {
|
||||
String synopsis = "seed = '" + ProductionParams.seed.value() + "'"
|
||||
+ ", specificSeed = '" + PseudoRandom.getCurrentSeed() + "'";
|
||||
StringBuilder header = new StringBuilder();
|
||||
header.append("/*\n * @test\n * @summary ")
|
||||
.append(synopsis)
|
||||
.append(" \n * @library / ../\n");
|
||||
header.append(" * @run build jdk.test.lib.jittester.jtreg.JitTesterDriver "
|
||||
+ "jdk.test.lib.jittester.jtreg.Printer\n");
|
||||
for (String action : preRunActions.apply(mainClassName)) {
|
||||
header.append(" * ")
|
||||
.append(action)
|
||||
.append("\n");
|
||||
}
|
||||
header.append(" * @run driver jdk.test.lib.jittester.jtreg.JitTesterDriver ")
|
||||
.append(jtDriverOptions)
|
||||
.append(" ")
|
||||
.append(mainClassName)
|
||||
.append("\n */\n\n");
|
||||
if (ProductionParams.printHierarchy.value()) {
|
||||
header.append("/*\n")
|
||||
.append(printHierarchy())
|
||||
.append("*/\n");
|
||||
}
|
||||
return header.toString();
|
||||
}
|
||||
|
||||
protected static Path getRoot() {
|
||||
return Paths.get(ProductionParams.testbaseDir.value());
|
||||
}
|
||||
|
||||
protected static void writeFile(Path targetDir, String fileName, String content) {
|
||||
try (FileWriter file = new FileWriter(targetDir.resolve(fileName).toFile())) {
|
||||
file.write(content);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static String printHierarchy() {
|
||||
return TypeList.getAll()
|
||||
.stream()
|
||||
.filter(t -> t instanceof TypeKlass)
|
||||
.map(t -> typeDescription((TypeKlass) t))
|
||||
.collect(Collectors.joining("\n","CLASS HIERARCHY:\n", "\n"));
|
||||
}
|
||||
|
||||
private static String typeDescription(TypeKlass type) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
String parents = type.getParentsNames().stream().collect(Collectors.joining(","));
|
||||
result.append(type.isAbstract() ? "abstract " : "")
|
||||
.append(type.isFinal() ? "final " : "")
|
||||
.append(type.isInterface() ? "interface " : "class ")
|
||||
.append(type.getName())
|
||||
.append(parents.isEmpty() ? "" : ": " + parents);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static String getJavaPath() {
|
||||
String[] env = { "JDK_HOME", "JAVA_HOME", "BOOTDIR" };
|
||||
for (String name : env) {
|
||||
String path = System.getenv(name);
|
||||
if (path != null) {
|
||||
return path + "/bin/";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
@ -40,30 +40,31 @@ import java.util.stream.Stream;
|
||||
public class JitTesterDriver {
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (args.length != 1) {
|
||||
if (args.length < 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"[TESTBUG]: wrong number of argument : " + args.length
|
||||
+ ". Expected 1 argument -- jit-tester test name.");
|
||||
+ ". Expected at least 1 argument -- jit-tester test name.");
|
||||
}
|
||||
OutputAnalyzer oa;
|
||||
try {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, args[0]);
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, args);
|
||||
oa = new OutputAnalyzer(pb.start());
|
||||
} catch (Exception e) {
|
||||
throw new Error("Unexpected exception on test jvm start :" + e, e);
|
||||
}
|
||||
|
||||
String name = args[args.length - 1];
|
||||
Pattern splitOut = Pattern.compile("\\n"); // tests use \n only in stdout
|
||||
Pattern splitErr = Pattern.compile("\\r?\\n"); // can handle both \r\n and \n
|
||||
Path testDir = Paths.get(Utils.TEST_SRC);
|
||||
String goldOut = formatOutput(streamGoldFile(testDir, args[0], "out"));
|
||||
String goldOut = formatOutput(streamGoldFile(testDir, name, "out"));
|
||||
String anlzOut = formatOutput(Arrays.stream(splitOut.split(oa.getStdout())));
|
||||
Asserts.assertEQ(anlzOut, goldOut, "Actual stdout isn't equal to golden one");
|
||||
String goldErr = formatOutput(streamGoldFile(testDir, args[0], "err"));
|
||||
String goldErr = formatOutput(streamGoldFile(testDir, name, "err"));
|
||||
String anlzErr = formatOutput(Arrays.stream(splitErr.split(oa.getStderr())));
|
||||
Asserts.assertEQ(anlzErr, goldErr, "Actual stderr isn't equal to golden one");
|
||||
|
||||
int exitValue = Integer.parseInt(streamGoldFile(testDir, args[0], "exit").findFirst().get());
|
||||
int exitValue = Integer.parseInt(streamGoldFile(testDir, name, "exit").findFirst().get());
|
||||
oa.shouldHaveExitValue(exitValue);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user