daa3f2ce32
Reviewed-by: kvn
272 lines
10 KiB
Java
272 lines
10 KiB
Java
/*
|
|
* Copyright (c) 2018, 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 compiler.graalunit.common;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.*;
|
|
import java.nio.file.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
import jdk.test.lib.process.OutputAnalyzer;
|
|
import jdk.test.lib.process.ProcessTools;
|
|
|
|
/*
|
|
* This is helper class used to run Graal unit tests.
|
|
* It accepts two arguments:
|
|
* -prefix TEST_PREFIX_TO_DEFINE_SET_OF_TESTS_TO_RUN (Ex: -prefix org.graalvm.compiler.api.test)
|
|
* -exclude EXCLUDED_TESTS_FILE_NAME
|
|
*/
|
|
public class GraalUnitTestLauncher {
|
|
|
|
static final String MXTOOL_JARFILE = "com.oracle.mxtool.junit.jar";
|
|
static final String GRAAL_UNITTESTS_JARFILE = "jdk.vm.compiler.tests.jar";
|
|
|
|
static final String[] GRAAL_EXTRA_JARS = {"junit-4.12.jar", "asm-5.0.4.jar", "asm-tree-5.0.4.jar",
|
|
"hamcrest-core-1.3.jar", "java-allocation-instrumenter.jar"};
|
|
|
|
static final String GENERATED_TESTCLASSES_FILENAME = "list.testclasses";
|
|
|
|
// Library dir used to find Graal specific jar files.
|
|
static String libsDir;
|
|
static {
|
|
libsDir = System.getProperty("graalunit.libs");
|
|
if (libsDir == null || libsDir.isEmpty()) {
|
|
libsDir = System.getenv("TEST_IMAGE_GRAAL_DIR");
|
|
}
|
|
|
|
if (libsDir == null || libsDir.isEmpty())
|
|
throw new RuntimeException("ERROR: Graal library directory is not specified, use -Dgraalunit.libs or TEST_IMAGE_GRAAL_DIR environment variable.");
|
|
|
|
System.out.println("INFO: graal libs dir is '" + libsDir + "'");
|
|
}
|
|
|
|
/*
|
|
* Generates --add-exports <module>/<package>=<target-module> flags and
|
|
* returns them as array list.
|
|
*
|
|
* @param moduleName
|
|
* Name of the module to update export data
|
|
*
|
|
* @param targetModule
|
|
* Name of the module to whom to export
|
|
*/
|
|
static ArrayList<String> getModuleExports(String moduleName, String targetModule) {
|
|
ArrayList<String> exports = new ArrayList<String>();
|
|
|
|
Optional<Module> mod = ModuleLayer.boot().findModule(moduleName);
|
|
Set<String> packages;
|
|
if (mod.isPresent()) {
|
|
packages = mod.get().getPackages();
|
|
|
|
for (String pName : packages) {
|
|
exports.add("--add-exports");
|
|
exports.add(moduleName + "/" + pName + "=" + targetModule);
|
|
}
|
|
}
|
|
|
|
return exports;
|
|
}
|
|
|
|
/*
|
|
* Return list of tests which match specified prefix
|
|
*
|
|
* @param testPrefix
|
|
* String prefix to select tests
|
|
*/
|
|
static ArrayList<String> getListOfTestsByPrefix(String testPrefix, Set<String> excludeTests) throws Exception {
|
|
ArrayList<String> classes = new ArrayList<String>();
|
|
|
|
final String testAnnotationName = "@Test";
|
|
|
|
// return empty list in case no selection prefix specified
|
|
if (testPrefix == null || testPrefix.isEmpty())
|
|
return classes;
|
|
|
|
// replace "." by "\." in test pattern
|
|
testPrefix = testPrefix.replaceAll("\\.", "\\\\.") + ".*";
|
|
System.out.println("INFO: use following pattern to find tests: " + testPrefix);
|
|
|
|
String graalUnitTestFilePath = String.join(File.separator, libsDir, GRAAL_UNITTESTS_JARFILE);
|
|
String classPath = String.join(File.pathSeparator, System.getProperty("java.class.path"),
|
|
String.join(File.separator, libsDir, MXTOOL_JARFILE));
|
|
|
|
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false,
|
|
"-cp", classPath,
|
|
"com.oracle.mxtool.junit.FindClassesByAnnotatedMethods", graalUnitTestFilePath, testAnnotationName);
|
|
|
|
System.out.println("INFO: run command " + String.join(" ", pb.command()));
|
|
|
|
OutputAnalyzer out = new OutputAnalyzer(pb.start());
|
|
int exitCode = out.getExitValue();
|
|
if (exitCode != 0) {
|
|
throw new Exception("Failed to find tests, VM crashed with exit code " + exitCode);
|
|
}
|
|
|
|
String outStr = out.getOutput().trim();
|
|
System.out.println("INFO: command output: [" + outStr + "]");
|
|
|
|
String[] lines = outStr.split(" ");
|
|
Arrays.sort(lines);
|
|
|
|
if (lines.length > 1) { // first line contains jar file name
|
|
for (int i = 1; i < lines.length; i++) {
|
|
String className = lines[i];
|
|
|
|
if (testPrefix.equals(".*") || className.matches(testPrefix)) {
|
|
// add the test only in case it is not in exclude list
|
|
if (excludeTests!= null && excludeTests.contains(className)) {
|
|
System.out.println("INFO: excluded test: " + className);
|
|
} else {
|
|
classes.add(className);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return classes;
|
|
}
|
|
|
|
/*
|
|
* Return set of excluded tests
|
|
*
|
|
* @param excludeFileName
|
|
* Name of the file to read excluded test list
|
|
*/
|
|
static Set loadExcludeList(String excludeFileName) {
|
|
Set<String> excludeTests;
|
|
|
|
Path excludeFilePath = Paths.get(excludeFileName);
|
|
try {
|
|
excludeTests = Files.readAllLines(excludeFilePath).stream()
|
|
.filter(l -> !l.trim().isEmpty())
|
|
.filter(l -> !l.trim().startsWith("#"))
|
|
.map(l -> l.split(" ")[0])
|
|
.collect(Collectors.toSet());
|
|
|
|
} catch (IOException ioe) {
|
|
throw new Error("TESTBUG: failed to read " + excludeFilePath);
|
|
}
|
|
|
|
return excludeTests;
|
|
}
|
|
|
|
static String getUsageString() {
|
|
return "Usage: " + GraalUnitTestLauncher.class.getName() + " " +
|
|
"-prefix (org.graalvm.compiler.api.test) " +
|
|
"-exclude <ExcludedTestsFileName>" + System.lineSeparator();
|
|
}
|
|
|
|
public static void main(String... args) throws Exception {
|
|
|
|
String testPrefix = null;
|
|
String excludeFileName = null;
|
|
|
|
int i=0;
|
|
String arg, val;
|
|
while (i+1 < args.length) {
|
|
arg = args[i++];
|
|
val = args[i++];
|
|
|
|
switch (arg) {
|
|
case "-prefix":
|
|
testPrefix = val;
|
|
break;
|
|
|
|
case "-exclude":
|
|
excludeFileName = val;
|
|
break;
|
|
|
|
default:
|
|
System.out.println("WARN: illegal option " + arg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (testPrefix == null)
|
|
throw new Error("TESTBUG: no tests to run specified." + System.lineSeparator() + getUsageString());
|
|
|
|
|
|
Set<String> excludeTests = null;
|
|
if (excludeFileName != null) {
|
|
excludeTests = loadExcludeList(excludeFileName);
|
|
}
|
|
|
|
// Find list of tests which match provided predicate and write into GENERATED_TESTCLASSES_FILENAME file
|
|
ArrayList<String> tests = getListOfTestsByPrefix(testPrefix, excludeTests);
|
|
if (tests.size() > 0) {
|
|
Files.write(Paths.get(GENERATED_TESTCLASSES_FILENAME), String.join(System.lineSeparator(), tests).getBytes());
|
|
} else {
|
|
throw new Error("TESTBUG: no tests found for prefix " + testPrefix);
|
|
}
|
|
|
|
ArrayList<String> javaFlags = new ArrayList<String>();
|
|
|
|
// add modules and exports
|
|
javaFlags.add("--add-modules");
|
|
javaFlags.add("jdk.internal.vm.compiler,jdk.internal.vm.ci");
|
|
javaFlags.add("--add-exports");
|
|
javaFlags.add("java.base/jdk.internal.module=ALL-UNNAMED");
|
|
javaFlags.addAll(getModuleExports("jdk.internal.vm.compiler", "ALL-UNNAMED"));
|
|
javaFlags.addAll(getModuleExports("jdk.internal.vm.ci", "ALL-UNNAMED,jdk.internal.vm.compiler"));
|
|
|
|
|
|
// add VM flags
|
|
javaFlags.add("-XX:+UnlockExperimentalVMOptions");
|
|
javaFlags.add("-XX:+EnableJVMCI");
|
|
javaFlags.add("-Djava.awt.headless=true");
|
|
javaFlags.add("-esa");
|
|
javaFlags.add("-ea");
|
|
|
|
|
|
// generate class path
|
|
ArrayList<String> graalJars = new ArrayList<String>(Arrays.asList(GRAAL_EXTRA_JARS));
|
|
graalJars.add(MXTOOL_JARFILE);
|
|
graalJars.add(GRAAL_UNITTESTS_JARFILE);
|
|
|
|
String graalJarsCP = graalJars.stream()
|
|
.map(s -> String.join(File.separator, libsDir, s))
|
|
.collect(Collectors.joining(File.pathSeparator));
|
|
|
|
javaFlags.add("-cp");
|
|
javaFlags.add(String.join(File.pathSeparator, System.getProperty("java.class.path"), graalJarsCP));
|
|
|
|
//
|
|
javaFlags.add("com.oracle.mxtool.junit.MxJUnitWrapper");
|
|
javaFlags.add("-JUnitVerbose");
|
|
javaFlags.add("-JUnitEagerStackTrace");
|
|
javaFlags.add("-JUnitEnableTiming");
|
|
|
|
javaFlags.add("@"+GENERATED_TESTCLASSES_FILENAME);
|
|
|
|
ProcessBuilder javaPB = ProcessTools.createJavaProcessBuilder(true,
|
|
javaFlags.toArray(new String[javaFlags.size()]));
|
|
System.out.println("INFO: run command: " + String.join(" ", javaPB.command()));
|
|
|
|
OutputAnalyzer outputAnalyzer = new OutputAnalyzer(javaPB.start());
|
|
System.out.println("INFO: execution result: " + outputAnalyzer.getOutput());
|
|
outputAnalyzer.shouldHaveExitValue(0);
|
|
}
|
|
}
|