mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-25 01:30:10 +00:00
8376291: [IR Framework] Create classes for separate Test VM messages
Reviewed-by: mchevalier, dfenacci, epeter
This commit is contained in:
parent
f0da04a40a
commit
14cb5ddfc5
@ -75,6 +75,7 @@ public class TestVMProcess {
|
||||
checkTestVMExitCode();
|
||||
String hotspotPidFileName = String.format("hotspot_pid%d.log", oa.pid());
|
||||
testVmData = socket.testVmData(hotspotPidFileName, allowNotCompilable);
|
||||
testVmData.printJavaMessages();
|
||||
}
|
||||
|
||||
public String getCommandLine() {
|
||||
|
||||
@ -98,7 +98,7 @@ public class IRMethod implements IRMethodMatchable {
|
||||
List<MatchResult> match = matcher.match();
|
||||
long endTime = System.nanoTime();
|
||||
long duration = (endTime - startTime);
|
||||
System.out.println("Verifying IR rules for " + name() + ": " + duration + " ns = " + (duration / 1000000) + " ms");
|
||||
System.out.println("Verifying IR rules for " + name() + ": " + duration + " ns = " + (duration / 1_000_000) + " ms");
|
||||
return new IRMethodMatchResult(method, match);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,8 +36,6 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Class to parse the Applicable IR Rules emitted by the Test VM and creating {@link TestMethod} objects for each entry.
|
||||
@ -45,11 +43,6 @@ import java.util.regex.Pattern;
|
||||
* @see TestMethod
|
||||
*/
|
||||
public class ApplicableIRRulesParser {
|
||||
|
||||
private static final boolean PRINT_APPLICABLE_IR_RULES = Boolean.parseBoolean(System.getProperty("PrintApplicableIRRules", "false"));
|
||||
private static final Pattern APPLICABLE_IR_RULES_PATTERN =
|
||||
Pattern.compile("(?<=" + ApplicableIRRulesPrinter.START + "\r?\n).*\\R([\\s\\S]*)(?=" + ApplicableIRRulesPrinter.END + ")");
|
||||
|
||||
private final Map<String, TestMethod> testMethods;
|
||||
private final Class<?> testClass;
|
||||
|
||||
@ -63,10 +56,6 @@ public class ApplicableIRRulesParser {
|
||||
* entry for each method that needs to be IR matched on.
|
||||
*/
|
||||
public TestMethods parse(String applicableIRRules) {
|
||||
if (TestFramework.VERBOSE || PRINT_APPLICABLE_IR_RULES) {
|
||||
System.out.println("Read Applicable IR Rules from Test VM:");
|
||||
System.out.println(applicableIRRules);
|
||||
}
|
||||
createTestMethodMap(applicableIRRules, testClass);
|
||||
// We could have found format errors in @IR annotations. Report them now with an exception.
|
||||
TestFormat.throwIfAnyFailures();
|
||||
@ -105,15 +94,11 @@ public class ApplicableIRRulesParser {
|
||||
* Parse the Applicable IR Rules lines without header, explanation line and footer and return them in an array.
|
||||
*/
|
||||
private String[] getApplicableIRRulesLines(String applicableIRRules) {
|
||||
Matcher matcher = APPLICABLE_IR_RULES_PATTERN.matcher(applicableIRRules);
|
||||
TestFramework.check(matcher.find(), "Did not find Applicable IR Rules in:" +
|
||||
System.lineSeparator() + applicableIRRules);
|
||||
String lines = matcher.group(1).trim();
|
||||
if (lines.isEmpty()) {
|
||||
if (applicableIRRules.isEmpty()) {
|
||||
// Nothing to IR match.
|
||||
return new String[0];
|
||||
}
|
||||
return lines.split("\\R");
|
||||
return applicableIRRules.split("\\R");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,7 +133,7 @@ public class ApplicableIRRulesParser {
|
||||
private void validateIRRuleIds(Method m, IR[] irAnnos, IRRuleIds irRuleIds) {
|
||||
TestFramework.check(irRuleIds != null, "Should find method name in validIrRulesMap for " + m);
|
||||
TestFramework.check(!irRuleIds.isEmpty(), "Did not find any rule indices for " + m);
|
||||
TestFramework.check((irRuleIds.first() >= 1 || irRuleIds.first() == ApplicableIRRulesPrinter.NO_RULE_APPLIED)
|
||||
TestFramework.check((irRuleIds.first() >= 1 || irRuleIds.first() == ApplicableIRRulesPrinter.NO_RULES)
|
||||
&& irRuleIds.last() <= irAnnos.length,
|
||||
"Invalid IR rule index found in validIrRulesMap for " + m);
|
||||
}
|
||||
@ -157,6 +142,6 @@ public class ApplicableIRRulesParser {
|
||||
* Does the list of IR rules contain any applicable IR rules for the given conditions?
|
||||
*/
|
||||
private boolean hasAnyApplicableIRRules(IRRuleIds irRuleIds) {
|
||||
return irRuleIds.first() != ApplicableIRRulesPrinter.NO_RULE_APPLIED;
|
||||
return irRuleIds.first() != ApplicableIRRulesPrinter.NO_RULES;
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ public class TestClassParser {
|
||||
public Matchable parse(TestVMData testVmData) {
|
||||
ApplicableIRRulesParser applicableIRRulesParser = new ApplicableIRRulesParser(testClass);
|
||||
TestMethods testMethods = applicableIRRulesParser.parse(testVmData.applicableIRRules());
|
||||
VMInfo vmInfo = VMInfoParser.parseVMInfo(testVmData.applicableIRRules());
|
||||
VMInfo vmInfo = VMInfoParser.parseVMInfo(testVmData.vmInfo());
|
||||
if (testMethods.hasTestMethods()) {
|
||||
HotSpotPidFileParser hotSpotPidFileParser = new HotSpotPidFileParser(testClass.getName(), testMethods);
|
||||
LoggedMethods loggedMethods = hotSpotPidFileParser.parse(testVmData.hotspotPidFileName());
|
||||
|
||||
@ -23,14 +23,10 @@
|
||||
|
||||
package compiler.lib.ir_framework.driver.irmatching.parser;
|
||||
|
||||
import compiler.lib.ir_framework.TestFramework;
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkException;
|
||||
import compiler.lib.ir_framework.test.VMInfoPrinter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Class to parse the VMInfo emitted by the Test VM and creating {@link VMInfo} objects for each entry.
|
||||
@ -39,15 +35,12 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class VMInfoParser {
|
||||
|
||||
private static final Pattern VM_INFO_PATTERN =
|
||||
Pattern.compile("(?<=" + VMInfoPrinter.START_VM_INFO + "\r?\n).*\\R([\\s\\S]*)(?=" + VMInfoPrinter.END_VM_INFO + ")");
|
||||
|
||||
/**
|
||||
* Extract VMInfo from the applicableIRRules.
|
||||
* Create a new VMInfo object from the vmInfo string.
|
||||
*/
|
||||
public static VMInfo parseVMInfo(String applicableIRRules) {
|
||||
public static VMInfo parseVMInfo(String vmInfo) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
String[] lines = getVMInfoLines(applicableIRRules);
|
||||
String[] lines = getVMInfoLines(vmInfo);
|
||||
for (String s : lines) {
|
||||
String line = s.trim();
|
||||
String[] splitLine = line.split(":", 2);
|
||||
@ -64,14 +57,11 @@ public class VMInfoParser {
|
||||
/**
|
||||
* Extract the VMInfo from the applicableIRRules string, strip away the header and return the individual key-value lines.
|
||||
*/
|
||||
private static String[] getVMInfoLines(String applicableIRRules) {
|
||||
Matcher matcher = VM_INFO_PATTERN.matcher(applicableIRRules);
|
||||
TestFramework.check(matcher.find(), "Did not find VMInfo in:" + System.lineSeparator() + applicableIRRules);
|
||||
String lines = matcher.group(1).trim();
|
||||
if (lines.isEmpty()) {
|
||||
private static String[] getVMInfoLines(String vmInfo) {
|
||||
if (vmInfo.isEmpty()) {
|
||||
// Nothing to IR match.
|
||||
return new String[0];
|
||||
}
|
||||
return lines.split("\\R");
|
||||
return vmInfo.split("\\R");
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,25 +26,30 @@ package compiler.lib.ir_framework.driver.network;
|
||||
import compiler.lib.ir_framework.driver.irmatching.IRMatcher;
|
||||
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessages;
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* This class collects all the parsed data received over the {@link TestFrameworkSocket}. This data is required later
|
||||
* in the {@link IRMatcher}.
|
||||
*/
|
||||
public class TestVMData {
|
||||
private final JavaMessages javaMessages;
|
||||
private final boolean allowNotCompilable;
|
||||
private final String hotspotPidFileName;
|
||||
private final String applicableIRRules;
|
||||
|
||||
public TestVMData(JavaMessages javaMessages, String hotspotPidFileName, boolean allowNotCompilable) {
|
||||
this.applicableIRRules = processOutput(javaMessages);
|
||||
this.javaMessages = javaMessages;
|
||||
this.hotspotPidFileName = hotspotPidFileName;
|
||||
this.allowNotCompilable = allowNotCompilable;
|
||||
}
|
||||
|
||||
public String applicableIRRules() {
|
||||
return javaMessages.applicableIRRules();
|
||||
}
|
||||
|
||||
public String vmInfo() {
|
||||
return javaMessages.vmInfo();
|
||||
}
|
||||
|
||||
public String hotspotPidFileName() {
|
||||
return hotspotPidFileName;
|
||||
}
|
||||
@ -53,52 +58,7 @@ public class TestVMData {
|
||||
return allowNotCompilable;
|
||||
}
|
||||
|
||||
public String applicableIRRules() {
|
||||
return applicableIRRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the socket output: All prefixed lines are dumped to the standard output while the remaining lines
|
||||
* represent the Applicable IR Rules used for IR matching later.
|
||||
*/
|
||||
private String processOutput(JavaMessages javaMessages) {
|
||||
String output = javaMessages.output();
|
||||
if (javaMessages.hasStdOut()) {
|
||||
StringBuilder testListBuilder = new StringBuilder();
|
||||
StringBuilder messagesBuilder = new StringBuilder();
|
||||
StringBuilder nonStdOutBuilder = new StringBuilder();
|
||||
Scanner scanner = new Scanner(output);
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
if (line.startsWith(MessageTag.STDOUT)) {
|
||||
// Exclude [STDOUT] from message.
|
||||
line = line.substring(MessageTag.STDOUT.length());
|
||||
if (line.startsWith(MessageTag.TEST_LIST)) {
|
||||
// Exclude [TEST_LIST] from message for better formatting.
|
||||
line = "> " + line.substring(MessageTag.TEST_LIST.length() + 1);
|
||||
testListBuilder.append(line).append(System.lineSeparator());
|
||||
} else {
|
||||
messagesBuilder.append(line).append(System.lineSeparator());
|
||||
}
|
||||
} else {
|
||||
nonStdOutBuilder.append(line).append(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
if (!testListBuilder.isEmpty()) {
|
||||
System.out.println("Run flag defined test list");
|
||||
System.out.println("--------------------------");
|
||||
System.out.println(testListBuilder);
|
||||
System.out.println();
|
||||
}
|
||||
if (!messagesBuilder.isEmpty()) {
|
||||
System.out.println("Messages from Test VM");
|
||||
System.out.println("---------------------");
|
||||
System.out.println(messagesBuilder);
|
||||
}
|
||||
return nonStdOutBuilder.toString();
|
||||
} else {
|
||||
return output;
|
||||
}
|
||||
public void printJavaMessages() {
|
||||
javaMessages.print();
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,10 +23,10 @@
|
||||
|
||||
package compiler.lib.ir_framework.driver.network.testvm;
|
||||
|
||||
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessageParser;
|
||||
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessages;
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkException;
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.net.Socket;
|
||||
@ -35,33 +35,29 @@ import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Dedicated reader for Test VM messages received by the {@link TestFrameworkSocket}. The reader is used as a task
|
||||
* wrapped in a {@link Future}. The received messages are returned in a new {@link JavaMessages} wrapper. Once the
|
||||
* Test VM is terminated, the client connection is closed and the parsed messages can be fetched with
|
||||
* {@link Future#get()} which calls {@link #call()}.
|
||||
* wrapped in a {@link Future}. The received messages are parsed with the {@link JavaMessageParser}. Once the Test VM
|
||||
* is terminated, client connection is closed and the parsed messages can be fetched with {@link Future#get()} which
|
||||
* calls {@link #call()}.
|
||||
*/
|
||||
public class TestVmMessageReader implements Callable<JavaMessages> {
|
||||
private final Socket socket;
|
||||
private final BufferedReader reader;
|
||||
private boolean receivedStdOut;
|
||||
private final JavaMessageParser messageParser;
|
||||
|
||||
public TestVmMessageReader(Socket socket, BufferedReader reader) {
|
||||
this.socket = socket;
|
||||
this.reader = reader;
|
||||
this.receivedStdOut = false;
|
||||
this.messageParser = new JavaMessageParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaMessages call() {
|
||||
try (socket; reader) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
builder.append(line).append(System.lineSeparator());
|
||||
if (line.startsWith(MessageTag.STDOUT)) {
|
||||
receivedStdOut = true;
|
||||
}
|
||||
messageParser.parseLine(line);
|
||||
}
|
||||
return new JavaMessages(builder.toString(), receivedStdOut);
|
||||
return messageParser.output();
|
||||
} catch (Exception e) {
|
||||
throw new TestFrameworkException("Error while reading Test VM socket messages", e);
|
||||
}
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
|
||||
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class to collect all Java Messages sent with tag {@link MessageTag#TEST_LIST}. These are only generated when the
|
||||
* user runs with {@code -DTest=myTest} and represent the executed tests.
|
||||
*/
|
||||
class ExecutedTests implements JavaMessage {
|
||||
private final List<String> tests;
|
||||
|
||||
public ExecutedTests(List<String> tests) {
|
||||
this.tests = tests;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print() {
|
||||
if (tests.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Executed Subset of Tests");
|
||||
System.out.println("------------------------");
|
||||
for (String test : tests) {
|
||||
System.out.println("- " + test);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
|
||||
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
|
||||
/**
|
||||
* Interface for a message sent from Java code to the Driver VM via the {@link TestFrameworkSocket}. We differentiate
|
||||
* between different messages depending on the leading {@link MessageTag} of a received message.
|
||||
*/
|
||||
public interface JavaMessage {
|
||||
void print();
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
|
||||
|
||||
import compiler.lib.ir_framework.TestFramework;
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkException;
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static compiler.lib.ir_framework.test.network.MessageTag.*;
|
||||
|
||||
/**
|
||||
* Dedicated parser for {@link JavaMessages} received from the Test VM. Depending on the parsed {@link MessageTag}, the
|
||||
* message is parsed differently.
|
||||
*/
|
||||
public class JavaMessageParser {
|
||||
private static final Pattern TAG_PATTERN = Pattern.compile("^(\\[[^]]+])\\s*(.*)$");
|
||||
|
||||
private final List<String> stdoutMessages;
|
||||
private final List<String> executedTests;
|
||||
private final Map<String, Long> methodTimes;
|
||||
private final StringBuilder vmInfoBuilder;
|
||||
private final StringBuilder applicableIrRules;
|
||||
|
||||
private StringBuilder currentBuilder;
|
||||
|
||||
public JavaMessageParser() {
|
||||
this.stdoutMessages = new ArrayList<>();
|
||||
this.methodTimes = new HashMap<>();
|
||||
this.executedTests = new ArrayList<>();
|
||||
this.vmInfoBuilder = new StringBuilder();
|
||||
this.applicableIrRules = new StringBuilder();
|
||||
this.currentBuilder = null;
|
||||
}
|
||||
|
||||
public void parseLine(String line) {
|
||||
line = line.trim();
|
||||
Matcher tagLineMatcher = TAG_PATTERN.matcher(line);
|
||||
if (tagLineMatcher.matches()) {
|
||||
// New tag
|
||||
assertNoActiveParser();
|
||||
parseTagLine(tagLineMatcher);
|
||||
return;
|
||||
}
|
||||
|
||||
assertActiveParser();
|
||||
if (line.equals(END_MARKER)) {
|
||||
// End tag
|
||||
parseEndTag();
|
||||
return;
|
||||
}
|
||||
|
||||
// Multi-line message for single tag.
|
||||
currentBuilder.append(line).append(System.lineSeparator());
|
||||
}
|
||||
|
||||
private void assertNoActiveParser() {
|
||||
TestFramework.check(currentBuilder == null, "Unexpected new tag while parsing block");
|
||||
}
|
||||
|
||||
private void parseTagLine(Matcher tagLineMatcher) {
|
||||
String tag = tagLineMatcher.group(1);
|
||||
String message = tagLineMatcher.group(2);
|
||||
switch (tag) {
|
||||
case STDOUT -> stdoutMessages.add(message);
|
||||
case TEST_LIST -> executedTests.add(message);
|
||||
case PRINT_TIMES -> parsePrintTimes(message);
|
||||
case VM_INFO -> currentBuilder = vmInfoBuilder;
|
||||
case APPLICABLE_IR_RULES -> currentBuilder = applicableIrRules;
|
||||
default -> throw new TestFrameworkException("unknown tag");
|
||||
}
|
||||
}
|
||||
|
||||
private void parsePrintTimes(String message) {
|
||||
String[] split = message.split(",");
|
||||
TestFramework.check(split.length == 2, "unexpected format");
|
||||
String methodName = split[0];
|
||||
try {
|
||||
long duration = Long.parseLong(split[1]);
|
||||
methodTimes.put(methodName, duration);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new TestFrameworkException("invalid duration", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertActiveParser() {
|
||||
TestFramework.check(currentBuilder != null, "Received non-tag line outside of any tag block");
|
||||
}
|
||||
|
||||
private void parseEndTag() {
|
||||
currentBuilder = null;
|
||||
}
|
||||
|
||||
public JavaMessages output() {
|
||||
return new JavaMessages(new StdoutMessages(stdoutMessages),
|
||||
new ExecutedTests(executedTests),
|
||||
new MethodTimes(methodTimes),
|
||||
applicableIrRules.toString(),
|
||||
vmInfoBuilder.toString());
|
||||
}
|
||||
}
|
||||
@ -23,28 +23,44 @@
|
||||
|
||||
package compiler.lib.ir_framework.driver.network.testvm.java;
|
||||
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
import compiler.lib.ir_framework.TestFramework;
|
||||
|
||||
/**
|
||||
* Class to collect all Java messages sent from the Test VM to the Driver VM.
|
||||
*/
|
||||
public class JavaMessages {
|
||||
private final String output;
|
||||
private final boolean receivedStdOut;
|
||||
private static final boolean PRINT_APPLICABLE_IR_RULES = Boolean.parseBoolean(System.getProperty("PrintApplicableIRRules", "false"));
|
||||
|
||||
public JavaMessages(String output, boolean receivedStdOut) {
|
||||
this.output = output;
|
||||
this.receivedStdOut = receivedStdOut;
|
||||
private final StdoutMessages stdoutMessages;
|
||||
private final ExecutedTests executedTests;
|
||||
private final MethodTimes methodTimes;
|
||||
private final String applicableIrRules;
|
||||
private final String vmInfo;
|
||||
|
||||
JavaMessages(StdoutMessages stdoutMessages, ExecutedTests executedTests, MethodTimes methodTimes,
|
||||
String applicableIrRules, String vmInfo) {
|
||||
this.stdoutMessages = stdoutMessages;
|
||||
this.executedTests = executedTests;
|
||||
this.methodTimes = methodTimes;
|
||||
this.applicableIrRules = applicableIrRules;
|
||||
this.vmInfo = vmInfo;
|
||||
}
|
||||
|
||||
public String output() {
|
||||
return output;
|
||||
public String applicableIRRules() {
|
||||
return applicableIrRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether Test VM sent messages to be put on stdout (starting with {@link MessageTag#STDOUT}).
|
||||
*/
|
||||
public boolean hasStdOut() {
|
||||
return receivedStdOut;
|
||||
public String vmInfo() {
|
||||
return vmInfo;
|
||||
}
|
||||
|
||||
public void print() {
|
||||
stdoutMessages.print();
|
||||
methodTimes.print();
|
||||
executedTests.print();
|
||||
if (TestFramework.VERBOSE || PRINT_APPLICABLE_IR_RULES) {
|
||||
System.out.println("Read Applicable IR Rules from Test VM:");
|
||||
System.out.println(applicableIrRules);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
|
||||
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Class to collect all Java Messages sent with tag {@link MessageTag#PRINT_TIMES}. These are only generated when the
|
||||
* user runs with {@code -DPrintTimes=true} and represent the execution times for methods.
|
||||
*/
|
||||
class MethodTimes implements JavaMessage {
|
||||
private final Map<String, Long> methodTimes;
|
||||
|
||||
public MethodTimes(Map<String, Long> methodTimes) {
|
||||
this.methodTimes = methodTimes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print() {
|
||||
if (methodTimes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Test Execution Times");
|
||||
System.out.println("--------------------");
|
||||
|
||||
int maxWidthNames = maxMethodNameWidth();
|
||||
int maxDurationsWidth = maxDurationsWidth();
|
||||
List<Map.Entry<String, Long>> sortedMethodTimes = sortByDurationAsc();
|
||||
|
||||
for (Map.Entry<String, Long> entry : sortedMethodTimes) {
|
||||
System.out.printf("- %-" + (maxWidthNames + 3) + "s %" + maxDurationsWidth + "d ns%n",
|
||||
entry.getKey() + ":", entry.getValue());
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private int maxMethodNameWidth() {
|
||||
return methodTimes.keySet().stream()
|
||||
.mapToInt(String::length)
|
||||
.max()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
private int maxDurationsWidth() {
|
||||
return methodTimes.values().stream()
|
||||
.mapToInt(v -> Long.toString(v).length())
|
||||
.max()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
private List<Map.Entry<String, Long>> sortByDurationAsc() {
|
||||
return methodTimes.entrySet().stream()
|
||||
.sorted(Map.Entry.comparingByValue())
|
||||
.toList();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
|
||||
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Class to collect all Java Messages sent with tag {@link MessageTag#STDOUT}. These messages are generated at various
|
||||
* places in the Test VM and are unconditionally shown in the Driver VM output.
|
||||
*/
|
||||
class StdoutMessages implements JavaMessage {
|
||||
private final List<String> messages;
|
||||
|
||||
public StdoutMessages(List<String> messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print() {
|
||||
if (messages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println("Test VM Messages");
|
||||
System.out.println("----------------");
|
||||
for (String message : messages) {
|
||||
System.out.println("- " + message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -47,9 +47,7 @@ import java.util.function.Function;
|
||||
* termination of the Test VM. IR rule indices start at 1.
|
||||
*/
|
||||
public class ApplicableIRRulesPrinter {
|
||||
public static final String START = "##### ApplicableIRRules - used by TestFramework #####";
|
||||
public static final String END = "----- END -----";
|
||||
public static final int NO_RULE_APPLIED = -1;
|
||||
public static final int NO_RULES = -1;
|
||||
|
||||
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||
private static final List<Function<String, Object>> LONG_GETTERS = Arrays.asList(
|
||||
@ -131,11 +129,6 @@ public class ApplicableIRRulesPrinter {
|
||||
"zvkn"
|
||||
));
|
||||
|
||||
public ApplicableIRRulesPrinter() {
|
||||
output.append(START).append(System.lineSeparator());
|
||||
output.append("<method>,{comma separated applied @IR rule ids}").append(System.lineSeparator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits "<method>,{ids}" where {ids} is either:
|
||||
* - indices of all @IR rules that should be applied, separated by a comma
|
||||
@ -162,7 +155,7 @@ public class ApplicableIRRulesPrinter {
|
||||
if (irAnnos.length != 0) {
|
||||
output.append(m.getName());
|
||||
if (validRules.isEmpty()) {
|
||||
output.append("," + NO_RULE_APPLIED);
|
||||
output.append("," + NO_RULES);
|
||||
} else {
|
||||
for (i = 0; i < validRules.size(); i++) {
|
||||
output.append(",").append(validRules.get(i));
|
||||
@ -524,8 +517,8 @@ public class ApplicableIRRulesPrinter {
|
||||
}
|
||||
|
||||
public void emit() {
|
||||
output.append(END);
|
||||
TestVmSocket.sendWithTag(MessageTag.APPLICABLE_IR_RULES, output.toString());
|
||||
output.append(MessageTag.END_MARKER);
|
||||
TestVmSocket.sendMultiLine(MessageTag.APPLICABLE_IR_RULES, output.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -594,8 +594,8 @@ public class TestVM {
|
||||
"Cannot overload @Test methods, but method " + m + " has " + overloads.size() + " overload" + (overloads.size() == 1 ? "" : "s") + ":" +
|
||||
overloads.stream().map(String::valueOf).collect(Collectors.joining("\n - ", "\n - ", ""))
|
||||
);
|
||||
TestFormat.check(!testMethodMap.containsKey(m.getName()),
|
||||
"Cannot overload two @Test methods: " + m + ", " + testMethodMap.get(m.getName()));
|
||||
TestFramework.check(!testMethodMap.containsKey(m.getName()),
|
||||
"Cannot overload two @Test methods: " + m + ", " + testMethodMap.get(m.getName()));
|
||||
TestFormat.check(testAnno != null, m + " must be a method with a @Test annotation");
|
||||
|
||||
Check checkAnno = getAnnotation(m, Check.class);
|
||||
@ -836,7 +836,6 @@ public class TestVM {
|
||||
* Once all framework tests are collected, they are run in this method.
|
||||
*/
|
||||
private void runTests() {
|
||||
TreeMap<Long, String> durations = PRINT_TIMES ? new TreeMap<>() : null;
|
||||
long startTime = System.nanoTime();
|
||||
List<AbstractTest> testList;
|
||||
boolean testFilterPresent = testFilterPresent();
|
||||
@ -865,7 +864,7 @@ public class TestVM {
|
||||
System.out.println("Run " + test.toString());
|
||||
}
|
||||
if (testFilterPresent) {
|
||||
TestVmSocket.send(MessageTag.TEST_LIST + "Run " + test.toString());
|
||||
TestVmSocket.sendWithTag(MessageTag.TEST_LIST, "Run " + test.toString());
|
||||
}
|
||||
try {
|
||||
test.run();
|
||||
@ -880,10 +879,11 @@ public class TestVM {
|
||||
if (PRINT_TIMES) {
|
||||
long endTime = System.nanoTime();
|
||||
long duration = (endTime - startTime);
|
||||
durations.put(duration, test.getName());
|
||||
if (VERBOSE) {
|
||||
System.out.println("Done " + test.getName() + ": " + duration + " ns = " + (duration / 1000000) + " ms");
|
||||
System.out.println("Done " + test.getName() + ": " + duration + " ns = " + (duration / 1_000_000) + " ms");
|
||||
}
|
||||
// Will be correctly formatted later.
|
||||
TestVmSocket.sendWithTag(MessageTag.PRINT_TIMES, test.getName() + "," + duration);
|
||||
}
|
||||
if (GC_AFTER) {
|
||||
System.out.println("doing GC");
|
||||
@ -891,14 +891,6 @@ public class TestVM {
|
||||
}
|
||||
}
|
||||
|
||||
// Print execution times
|
||||
if (PRINT_TIMES) {
|
||||
TestVmSocket.send(MessageTag.PRINT_TIMES + " Test execution times:");
|
||||
for (Map.Entry<Long, String> entry : durations.entrySet()) {
|
||||
TestVmSocket.send(MessageTag.PRINT_TIMES + String.format("%-25s%15d ns%n", entry.getValue() + ":", entry.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
if (failures > 0) {
|
||||
// Finally, report all occurred exceptions in a nice format.
|
||||
String msg = System.lineSeparator() + System.lineSeparator() + "Test Failures (" + failures + ")"
|
||||
|
||||
@ -31,15 +31,10 @@ import jdk.test.whitebox.WhiteBox;
|
||||
* Prints some Test VM info to the socket.
|
||||
*/
|
||||
public class VMInfoPrinter {
|
||||
public static final String START_VM_INFO = "##### IRMatchingVMInfo - used by TestFramework #####";
|
||||
public static final String END_VM_INFO = "----- END VMInfo -----";
|
||||
|
||||
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||
|
||||
public static void emit() {
|
||||
StringBuilder vmInfo = new StringBuilder();
|
||||
vmInfo.append(START_VM_INFO).append(System.lineSeparator());
|
||||
vmInfo.append("<key>:<value>").append(System.lineSeparator());
|
||||
|
||||
// CPU feature independent info
|
||||
String cpuFeatures = WHITE_BOX.getCPUFeatures();
|
||||
@ -65,7 +60,7 @@ public class VMInfoPrinter {
|
||||
.append(useAVXIsDefault ? 1 : 0)
|
||||
.append(System.lineSeparator());
|
||||
|
||||
vmInfo.append(END_VM_INFO);
|
||||
TestVmSocket.sendWithTag(MessageTag.VM_INFO, vmInfo.toString());
|
||||
vmInfo.append(MessageTag.END_MARKER);
|
||||
TestVmSocket.sendMultiLine(MessageTag.VM_INFO, vmInfo.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,4 +29,5 @@ public class MessageTag {
|
||||
public static final String PRINT_TIMES = "[PRINT_TIMES]";
|
||||
public static final String VM_INFO = "[VM_INFO]";
|
||||
public static final String APPLICABLE_IR_RULES = "[APPLICABLE_IR_RULES]";
|
||||
public static final String END_MARKER = "#END#";
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ package compiler.lib.ir_framework.test.network;
|
||||
|
||||
import compiler.lib.ir_framework.TestFramework;
|
||||
import compiler.lib.ir_framework.shared.TestRunException;
|
||||
import compiler.lib.ir_framework.test.TestVM;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
@ -46,6 +47,20 @@ public class TestVmSocket {
|
||||
sendWithTag(MessageTag.STDOUT, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message with multiple lines to the Driver VM with a {@link MessageTag}. Not all messages are shown by
|
||||
* default in the Driver VM output and require setting some property flags first like {@code -DPrintTimes=true}.
|
||||
*/
|
||||
public static void sendMultiLine(String tag, String message) {
|
||||
if (REPRODUCE) {
|
||||
// Debugging Test VM: Skip writing due to -DReproduce;
|
||||
return;
|
||||
}
|
||||
|
||||
TestFramework.check(socket != null, "must be connected");
|
||||
writer.println(tag + System.lineSeparator() + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the Driver VM with a {@link MessageTag}. Not all messages are shown by default in the
|
||||
* Driver VM output and require setting some property flags first like {@code -DPrintTimes=true}.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user