50908
|
1 |
/*
|
|
2 |
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
|
7 |
* published by the Free Software Foundation.
|
|
8 |
*
|
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
13 |
* accompanied this code).
|
|
14 |
*
|
|
15 |
* You should have received a copy of the GNU General Public License version
|
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18 |
*
|
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
20 |
* or visit www.oracle.com if you need additional information or have any
|
|
21 |
* questions.
|
|
22 |
*/
|
|
23 |
|
|
24 |
package compiler.graalunit.common;
|
|
25 |
|
|
26 |
import java.io.File;
|
|
27 |
import java.io.IOException;
|
|
28 |
import java.util.*;
|
|
29 |
import java.nio.file.*;
|
|
30 |
import java.util.stream.Collectors;
|
|
31 |
|
|
32 |
import jdk.test.lib.process.OutputAnalyzer;
|
|
33 |
import jdk.test.lib.process.ProcessTools;
|
|
34 |
|
|
35 |
/*
|
|
36 |
* This is helper class used to run Graal unit tests.
|
|
37 |
* It accepts two arguments:
|
|
38 |
* -prefix TEST_PREFIX_TO_DEFINE_SET_OF_TESTS_TO_RUN (Ex: -prefix org.graalvm.compiler.api.test)
|
|
39 |
* -exclude EXCLUDED_TESTS_FILE_NAME
|
|
40 |
*/
|
|
41 |
public class GraalUnitTestLauncher {
|
|
42 |
|
|
43 |
static final String MXTOOL_JARFILE = "com.oracle.mxtool.junit.jar";
|
|
44 |
static final String GRAAL_UNITTESTS_JARFILE = "jdk.vm.compiler.tests.jar";
|
|
45 |
|
|
46 |
static final String[] GRAAL_EXTRA_JARS = {"junit-4.12.jar", "asm-5.0.4.jar", "asm-tree-5.0.4.jar",
|
|
47 |
"hamcrest-core-1.3.jar", "java-allocation-instrumenter.jar"};
|
|
48 |
|
|
49 |
static final String GENERATED_TESTCLASSES_FILENAME = "list.testclasses";
|
|
50 |
|
|
51 |
// Library dir used to find Graal specific jar files.
|
|
52 |
static String libsDir;
|
|
53 |
static {
|
|
54 |
libsDir = System.getProperty("graalunit.libs");
|
|
55 |
if (libsDir == null || libsDir.isEmpty()) {
|
|
56 |
libsDir = System.getenv("TEST_IMAGE_GRAAL_DIR");
|
|
57 |
}
|
|
58 |
|
|
59 |
if (libsDir == null || libsDir.isEmpty())
|
|
60 |
throw new RuntimeException("ERROR: Graal library directory is not specified, use -Dgraalunit.libs or TEST_IMAGE_GRAAL_DIR environment variable.");
|
|
61 |
|
|
62 |
System.out.println("INFO: graal libs dir is '" + libsDir + "'");
|
|
63 |
}
|
|
64 |
|
|
65 |
/*
|
|
66 |
* Generates --add-exports <module>/<package>=<target-module> flags and
|
|
67 |
* returns them as array list.
|
|
68 |
*
|
|
69 |
* @param moduleName
|
|
70 |
* Name of the module to update export data
|
|
71 |
*
|
|
72 |
* @param targetModule
|
|
73 |
* Name of the module to whom to export
|
|
74 |
*/
|
|
75 |
static ArrayList<String> getModuleExports(String moduleName, String targetModule) {
|
|
76 |
ArrayList<String> exports = new ArrayList<String>();
|
|
77 |
|
|
78 |
Optional<Module> mod = ModuleLayer.boot().findModule(moduleName);
|
|
79 |
Set<String> packages;
|
|
80 |
if (mod.isPresent()) {
|
|
81 |
packages = mod.get().getPackages();
|
|
82 |
|
|
83 |
for (String pName : packages) {
|
|
84 |
exports.add("--add-exports");
|
|
85 |
exports.add(moduleName + "/" + pName + "=" + targetModule);
|
|
86 |
}
|
|
87 |
}
|
|
88 |
|
|
89 |
return exports;
|
|
90 |
}
|
|
91 |
|
|
92 |
/*
|
|
93 |
* Return list of tests which match specified prefix
|
|
94 |
*
|
|
95 |
* @param testPrefix
|
|
96 |
* String prefix to select tests
|
|
97 |
*/
|
|
98 |
static ArrayList<String> getListOfTestsByPrefix(String testPrefix, Set<String> excludeTests) throws Exception {
|
|
99 |
ArrayList<String> classes = new ArrayList<String>();
|
|
100 |
|
|
101 |
final String testAnnotationName = "@Test";
|
|
102 |
|
|
103 |
// return empty list in case no selection prefix specified
|
|
104 |
if (testPrefix == null || testPrefix.isEmpty())
|
|
105 |
return classes;
|
|
106 |
|
|
107 |
// replace "." by "\." in test pattern
|
|
108 |
testPrefix = testPrefix.replaceAll("\\.", "\\\\.") + ".*";
|
|
109 |
System.out.println("INFO: use following pattern to find tests: " + testPrefix);
|
|
110 |
|
|
111 |
String graalUnitTestFilePath = String.join(File.separator, libsDir, GRAAL_UNITTESTS_JARFILE);
|
|
112 |
String classPath = String.join(File.pathSeparator, System.getProperty("java.class.path"),
|
|
113 |
String.join(File.separator, libsDir, MXTOOL_JARFILE));
|
|
114 |
|
|
115 |
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false,
|
|
116 |
"-cp", classPath,
|
|
117 |
"com.oracle.mxtool.junit.FindClassesByAnnotatedMethods", graalUnitTestFilePath, testAnnotationName);
|
|
118 |
|
|
119 |
System.out.println("INFO: run command " + String.join(" ", pb.command()));
|
|
120 |
|
|
121 |
OutputAnalyzer out = new OutputAnalyzer(pb.start());
|
|
122 |
int exitCode = out.getExitValue();
|
|
123 |
if (exitCode != 0) {
|
|
124 |
throw new Exception("Failed to find tests, VM crashed with exit code " + exitCode);
|
|
125 |
}
|
|
126 |
|
|
127 |
String[] lines = out.getStdout().split(" ");
|
|
128 |
if (lines.length > 1) { // first line contains jar file name
|
|
129 |
for (int i = 1; i < lines.length; i++) {
|
|
130 |
String className = lines[i];
|
|
131 |
|
|
132 |
if (testPrefix.equals(".*") || className.matches(testPrefix)) {
|
|
133 |
// add the test only in case it is not in exclude list
|
|
134 |
if (excludeTests!= null && excludeTests.contains(className)) {
|
|
135 |
System.out.println("INFO: excluded test: " + className);
|
|
136 |
} else {
|
|
137 |
classes.add(className);
|
|
138 |
}
|
|
139 |
}
|
|
140 |
}
|
|
141 |
}
|
|
142 |
|
|
143 |
return classes;
|
|
144 |
}
|
|
145 |
|
|
146 |
/*
|
|
147 |
* Return set of excluded tests
|
|
148 |
*
|
|
149 |
* @param excludeFileName
|
|
150 |
* Name of the file to read excluded test list
|
|
151 |
*/
|
|
152 |
static Set loadExcludeList(String excludeFileName) {
|
|
153 |
Set<String> excludeTests;
|
|
154 |
|
|
155 |
Path excludeFilePath = Paths.get(excludeFileName);
|
|
156 |
try {
|
|
157 |
excludeTests = Files.readAllLines(excludeFilePath).stream()
|
|
158 |
.filter(l -> !l.trim().isEmpty())
|
|
159 |
.filter(l -> !l.trim().startsWith("#"))
|
|
160 |
.map(l -> l.split(" ")[0])
|
|
161 |
.collect(Collectors.toSet());
|
|
162 |
|
|
163 |
} catch (IOException ioe) {
|
|
164 |
throw new Error("TESTBUG: failed to read " + excludeFilePath);
|
|
165 |
}
|
|
166 |
|
|
167 |
return excludeTests;
|
|
168 |
}
|
|
169 |
|
|
170 |
static String getUsageString() {
|
|
171 |
return "Usage: " + GraalUnitTestLauncher.class.getName() + " " +
|
|
172 |
"-prefix (org.graalvm.compiler.api.test) " +
|
|
173 |
"-exclude <ExcludedTestsFileName>" + System.lineSeparator();
|
|
174 |
}
|
|
175 |
|
|
176 |
public static void main(String... args) throws Exception {
|
|
177 |
|
|
178 |
String testPrefix = null;
|
|
179 |
String excludeFileName = null;
|
|
180 |
|
|
181 |
int i=0;
|
|
182 |
String arg, val;
|
|
183 |
while (i+1 < args.length) {
|
|
184 |
arg = args[i++];
|
|
185 |
val = args[i++];
|
|
186 |
|
|
187 |
switch (arg) {
|
|
188 |
case "-prefix":
|
|
189 |
testPrefix = val;
|
|
190 |
break;
|
|
191 |
|
|
192 |
case "-exclude":
|
|
193 |
excludeFileName = val;
|
|
194 |
break;
|
|
195 |
|
|
196 |
default:
|
|
197 |
System.out.println("WARN: illegal option " + arg);
|
|
198 |
break;
|
|
199 |
}
|
|
200 |
}
|
|
201 |
|
|
202 |
if (testPrefix == null)
|
|
203 |
throw new Error("TESTBUG: no tests to run specified." + System.lineSeparator() + getUsageString());
|
|
204 |
|
|
205 |
|
|
206 |
Set<String> excludeTests = null;
|
|
207 |
if (excludeFileName != null) {
|
|
208 |
excludeTests = loadExcludeList(excludeFileName);
|
|
209 |
}
|
|
210 |
|
|
211 |
// Find list of tests which match provided predicate and write into GENERATED_TESTCLASSES_FILENAME file
|
|
212 |
ArrayList<String> tests = getListOfTestsByPrefix(testPrefix, excludeTests);
|
|
213 |
if (tests.size() > 0) {
|
|
214 |
Files.write(Paths.get(GENERATED_TESTCLASSES_FILENAME), String.join(System.lineSeparator(), tests).getBytes());
|
|
215 |
} else {
|
|
216 |
throw new Error("TESTBUG: no tests found for prefix " + testPrefix);
|
|
217 |
}
|
|
218 |
|
|
219 |
ArrayList<String> javaFlags = new ArrayList<String>();
|
|
220 |
|
|
221 |
// add modules and exports
|
|
222 |
javaFlags.add("--add-modules");
|
|
223 |
javaFlags.add("jdk.internal.vm.compiler,jdk.internal.vm.ci");
|
|
224 |
javaFlags.add("--add-exports");
|
|
225 |
javaFlags.add("java.base/jdk.internal.module=ALL-UNNAMED");
|
|
226 |
javaFlags.addAll(getModuleExports("jdk.internal.vm.compiler", "ALL-UNNAMED"));
|
|
227 |
javaFlags.addAll(getModuleExports("jdk.internal.vm.ci", "ALL-UNNAMED,jdk.internal.vm.compiler"));
|
|
228 |
|
|
229 |
|
|
230 |
// add VM flags
|
|
231 |
javaFlags.add("-XX:+UnlockExperimentalVMOptions");
|
|
232 |
javaFlags.add("-XX:+EnableJVMCI");
|
|
233 |
javaFlags.add("-Djava.awt.headless=true");
|
|
234 |
javaFlags.add("-esa");
|
|
235 |
javaFlags.add("-ea");
|
|
236 |
|
|
237 |
|
|
238 |
// generate class path
|
|
239 |
ArrayList<String> graalJars = new ArrayList<String>(Arrays.asList(GRAAL_EXTRA_JARS));
|
|
240 |
graalJars.add(MXTOOL_JARFILE);
|
|
241 |
graalJars.add(GRAAL_UNITTESTS_JARFILE);
|
|
242 |
|
|
243 |
String graalJarsCP = graalJars.stream()
|
|
244 |
.map(s -> String.join(File.separator, libsDir, s))
|
|
245 |
.collect(Collectors.joining(File.pathSeparator));
|
|
246 |
|
|
247 |
javaFlags.add("-cp");
|
|
248 |
javaFlags.add(String.join(File.pathSeparator, System.getProperty("java.class.path"), graalJarsCP));
|
|
249 |
|
|
250 |
//
|
|
251 |
javaFlags.add("com.oracle.mxtool.junit.MxJUnitWrapper");
|
|
252 |
javaFlags.add("-JUnitVerbose");
|
|
253 |
javaFlags.add("-JUnitEagerStackTrace");
|
|
254 |
javaFlags.add("-JUnitEnableTiming");
|
|
255 |
|
|
256 |
javaFlags.add("@"+GENERATED_TESTCLASSES_FILENAME);
|
|
257 |
|
|
258 |
ProcessBuilder javaPB = ProcessTools.createJavaProcessBuilder(true,
|
|
259 |
javaFlags.toArray(new String[javaFlags.size()]));
|
|
260 |
System.out.println("INFO: run command: " + String.join(" ", javaPB.command()));
|
|
261 |
|
|
262 |
OutputAnalyzer outputAnalyzer = new OutputAnalyzer(javaPB.start());
|
|
263 |
System.out.println("INFO: execution result: " + outputAnalyzer.getOutput());
|
|
264 |
outputAnalyzer.shouldHaveExitValue(0);
|
|
265 |
}
|
|
266 |
}
|