280 lines
11 KiB
Java
280 lines
11 KiB
Java
|
/*
|
||
|
* Copyright (c) 2014, 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 rtm;
|
||
|
|
||
|
import java.io.IOException;
|
||
|
import java.nio.file.Files;
|
||
|
import java.nio.file.Paths;
|
||
|
import java.util.List;
|
||
|
import java.util.LinkedList;
|
||
|
import java.util.Arrays;
|
||
|
import java.util.Collections;
|
||
|
import java.util.regex.Matcher;
|
||
|
import java.util.regex.Pattern;
|
||
|
|
||
|
import com.oracle.java.testlibrary.OutputAnalyzer;
|
||
|
import com.oracle.java.testlibrary.ProcessTools;
|
||
|
import com.oracle.java.testlibrary.Utils;
|
||
|
import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
|
||
|
|
||
|
/**
|
||
|
* 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);
|
||
|
|
||
|
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()]);
|
||
|
}
|
||
|
}
|