1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
|
/*
* Copyright (c) 2014, 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 compiler.testlibrary.rtm;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.Utils;
import jdk.test.lib.cli.CommandLineOptionTest;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Auxiliary methods used for RTM testing.
*/
public class RTMTestBase {
private static final String RTM_STATE_CHANGE_REASON = "rtm_state_change";
/**
* We don't parse compilation log as XML-document and use regular
* expressions instead, because in some cases it could be
* malformed.
*/
private static final String FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE
= "<uncommon_trap thread='[0-9]+' reason='%s'";
private static final String INSTALLED_UNCOMMON_TRAP_PATTERN_TEMPLATE
= "<uncommon_trap bci='[0-9]+' reason='%s'";
/**
* Executes RTM test in a new JVM started with {@code options} cli options.
*
* @param test test case to execute.
* @param options additional options for VM
* @throws Exception when something went wrong.
*/
public static OutputAnalyzer executeRTMTest(CompilableTest test,
String... options) throws Exception {
ProcessBuilder processBuilder
= ProcessTools.createJavaProcessBuilder(
RTMTestBase.prepareTestOptions(test, options));
OutputAnalyzer outputAnalyzer
= new OutputAnalyzer(processBuilder.start());
System.out.println(outputAnalyzer.getOutput());
return outputAnalyzer;
}
/**
* Executes test case and save compilation log to {@code logFileName}.
*
* @param logFileName a name of compilation log file
* @param test a test case to execute case to execute
* @param options additional options to VM
* @return OutputAnalyzer for started test case
* @throws Exception when something went wrong
*/
public static OutputAnalyzer executeRTMTest(String logFileName,
CompilableTest test, String... options) throws Exception {
ProcessBuilder processBuilder
= ProcessTools.createJavaProcessBuilder(
RTMTestBase.prepareTestOptions(logFileName, test, options));
OutputAnalyzer outputAnalyzer
= new OutputAnalyzer(processBuilder.start());
System.out.println(outputAnalyzer.getOutput());
return outputAnalyzer;
}
/**
* Finds count of uncommon traps with reason {@code reason} installed
* during compilation.
*
* @param compilationLogFile a path to file with LogCompilation output.
* @param reason reason of installed uncommon traps.
* @return count of installed uncommon traps with reason {@code reason}.
* @throws IOException
*/
public static int installedUncommonTraps(String compilationLogFile,
String reason)throws IOException {
String pattern = String.format(
RTMTestBase.INSTALLED_UNCOMMON_TRAP_PATTERN_TEMPLATE,
reason);
return RTMTestBase.findTraps(compilationLogFile, pattern);
}
/**
* Finds count of uncommon traps with reason <i>rtm_state_change</i>
* installed during compilation.
*
* @param compilationLogFile a path to file with LogCompilation output.
* @return count of installed uncommon traps with reason
* <i>rtm_state_change</i>.
* @throws IOException
*/
public static int installedRTMStateChangeTraps(String compilationLogFile)
throws IOException {
return RTMTestBase.installedUncommonTraps(compilationLogFile,
RTMTestBase.RTM_STATE_CHANGE_REASON);
}
/**
* Finds count of fired uncommon traps with reason {@code reason}.
*
* @param compilationLogFile a path to file with LogCompilation output.
* @param reason a reason of fired uncommon traps.
* @return count of fired uncommon traps with reason {@code reason}.
* @throws IOException
*/
public static int firedUncommonTraps(String compilationLogFile,
String reason) throws IOException {
String pattern = String.format(
RTMTestBase.FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE,
reason);
return RTMTestBase.findTraps(compilationLogFile, pattern);
}
/**
* Finds count of fired uncommon traps with reason <i>rtm_state_change</i>.
*
* @param compilationLogFile a path to file with LogCompilation output.
* @return count of fired uncommon traps with reason
* <i>rtm_state_change</i>.
* @throws IOException
*/
public static int firedRTMStateChangeTraps(String compilationLogFile)
throws IOException {
return RTMTestBase.firedUncommonTraps(compilationLogFile,
RTMTestBase.RTM_STATE_CHANGE_REASON);
}
/**
* Finds count of uncommon traps that matches regular
* expression in {@code re}.
*
* @param compilationLogFile a path to file with LogCompilation output.
* @param re regular expression to match uncommon traps.
* @throws IOException
*/
private static int findTraps(String compilationLogFile, String re)
throws IOException {
String compilationLog = RTMTestBase.fileAsString(compilationLogFile);
Pattern pattern = Pattern.compile(re);
Matcher matcher = pattern.matcher(compilationLog);
int traps = 0;
while (matcher.find()) {
traps++;
}
return traps;
}
/**
* Returns file's content as a string.
*
* @param path a path to file to operate on.
* @return string with content of file.
* @throws IOException
*/
private static String fileAsString(String path) throws IOException {
byte[] fileAsBytes = Files.readAllBytes(Paths.get(path));
return new String(fileAsBytes);
}
/**
* Prepares VM options for test execution.
* This method get test java options, filter out all RTM-related options,
* adds CompileCommand=compileonly,method_name options for each method
* from {@code methodToCompile} and finally appends all {@code vmOpts}.
*
* @param test test case whose methods that should be compiled.
* If {@code null} then no additional <i>compileonly</i>
* commands will be added to VM options.
* @param vmOpts additional options to pass to VM.
* @return Array with VM options.
*/
private static String[] prepareTestOptions(CompilableTest test,
String... vmOpts) {
return RTMTestBase.prepareFilteredTestOptions(test, null, vmOpts);
}
/**
* Prepares VM options for test execution.
* This method get test java options, filter out all RTM-related options
* and all options that matches regexps in {@code additionalFilters},
* adds CompileCommand=compileonly,method_name options for each method
* from {@code methodToCompile} and finally appends all {@code vmOpts}.
*
* @param test test case whose methods that should be compiled.
* If {@code null} then no additional <i>compileonly</i>
* commands will be added to VM options.
* @param additionalFilters array with regular expression that will be
* used to filter out test java options.
* If {@code null} then no additional filters
* will be used.
* @param vmOpts additional options to pass to VM.
* @return array with VM options.
*/
private static String[] prepareFilteredTestOptions(CompilableTest test,
String[] additionalFilters, String... vmOpts) {
List<String> finalVMOpts = new LinkedList<>();
String[] filters;
if (additionalFilters != null) {
filters = Arrays.copyOf(additionalFilters,
additionalFilters.length + 1);
} else {
filters = new String[1];
}
filters[filters.length - 1] = "RTM";
String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters);
Collections.addAll(finalVMOpts, filteredVMOpts);
Collections.addAll(finalVMOpts, "-Xcomp", "-server",
"-XX:-TieredCompilation", "-XX:+UseRTMLocking",
CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS,
CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
"-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI",
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED");
if (test != null) {
for (String method : test.getMethodsToCompileNames()) {
finalVMOpts.add("-XX:CompileCommand=compileonly," + method);
}
}
Collections.addAll(finalVMOpts, vmOpts);
return finalVMOpts.toArray(new String[finalVMOpts.size()]);
}
/**
* Adds additional options for VM required for successful execution of test.
*
* @param logFileName a name of compilation log file
* @param test a test case to execute
* @param options additional options to VM
* @return an array with VM options
*/
private static String[] prepareTestOptions(String logFileName,
CompilableTest test, String... options) {
String[] preparedOptions = RTMTestBase.prepareFilteredTestOptions(
test,
new String[] {
"LogCompilation",
"LogFile"
});
List<String> updatedOptions = new LinkedList<>();
Collections.addAll(updatedOptions, preparedOptions);
Collections.addAll(updatedOptions,
"-XX:+LogCompilation",
"-XX:LogFile=" + logFileName);
Collections.addAll(updatedOptions, options);
return updatedOptions.toArray(new String[updatedOptions.size()]);
}
}
|