mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8376174: [IR Framework] Refactor Test VM socket communication
This commit is contained in:
parent
bbae38e510
commit
828124da4e
@ -881,8 +881,7 @@ public class TestFramework {
|
||||
if (shouldVerifyIR) {
|
||||
try {
|
||||
TestClassParser testClassParser = new TestClassParser(testClass, allowNotCompilable);
|
||||
Matchable testClassMatchable = testClassParser.parse(testVMProcess.getHotspotPidFileName(),
|
||||
testVMProcess.getApplicableIRRules());
|
||||
Matchable testClassMatchable = testClassParser.parse(testVMProcess.testVmData());
|
||||
IRMatcher matcher = new IRMatcher(testClassMatchable);
|
||||
matcher.match();
|
||||
} catch (IRViolationException e) {
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
package compiler.lib.ir_framework.driver;
|
||||
|
||||
import compiler.lib.ir_framework.TestFramework;
|
||||
import compiler.lib.ir_framework.driver.network.TestVMData;
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkException;
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
|
||||
import compiler.lib.ir_framework.shared.NoTestsRunException;
|
||||
@ -58,10 +59,9 @@ public class TestVMProcess {
|
||||
private static String lastTestVMOutput = "";
|
||||
|
||||
private final ArrayList<String> cmds;
|
||||
private String hotspotPidFileName;
|
||||
private String commandLine;
|
||||
private OutputAnalyzer oa;
|
||||
private String applicableIRRules;
|
||||
private final TestVMData testVmData;
|
||||
|
||||
public TestVMProcess(List<String> additionalFlags, Class<?> testClass, Set<Class<?>> helperClasses, int defaultWarmup,
|
||||
boolean allowNotCompilable, boolean testClassesOnBootClassPath) {
|
||||
@ -72,20 +72,17 @@ public class TestVMProcess {
|
||||
allowNotCompilable, testClassesOnBootClassPath);
|
||||
start();
|
||||
}
|
||||
processSocketOutput(socket);
|
||||
checkTestVMExitCode();
|
||||
String hotspotPidFileName = String.format("hotspot_pid%d.log", oa.pid());
|
||||
testVmData = socket.testVmData(hotspotPidFileName, allowNotCompilable);
|
||||
}
|
||||
|
||||
public String getCommandLine() {
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
public String getApplicableIRRules() {
|
||||
return applicableIRRules;
|
||||
}
|
||||
|
||||
public String getHotspotPidFileName() {
|
||||
return hotspotPidFileName;
|
||||
public TestVMData testVmData() {
|
||||
return testVmData;
|
||||
}
|
||||
|
||||
public static String getLastTestVMOutput() {
|
||||
@ -172,55 +169,9 @@ public class TestVMProcess {
|
||||
process.command().add(1, "-DReproduce=true"); // Add after "/path/to/bin/java" in order to rerun the Test VM directly
|
||||
commandLine = "Command Line:" + System.lineSeparator() + String.join(" ", process.command())
|
||||
+ System.lineSeparator();
|
||||
hotspotPidFileName = String.format("hotspot_pid%d.log", oa.pid());
|
||||
lastTestVMOutput = oa.getOutput();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void processSocketOutput(TestFrameworkSocket socket) {
|
||||
String output = socket.getOutput();
|
||||
if (socket.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(TestFrameworkSocket.STDOUT_PREFIX)) {
|
||||
// Exclude [STDOUT] from message.
|
||||
line = line.substring(TestFrameworkSocket.STDOUT_PREFIX.length());
|
||||
if (line.startsWith(TestFrameworkSocket.TESTLIST_TAG)) {
|
||||
// Exclude [TESTLIST] from message for better formatting.
|
||||
line = "> " + line.substring(TestFrameworkSocket.TESTLIST_TAG.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);
|
||||
}
|
||||
applicableIRRules = nonStdOutBuilder.toString();
|
||||
} else {
|
||||
applicableIRRules = output;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkTestVMExitCode() {
|
||||
final int exitCode = oa.getExitValue();
|
||||
if (EXCLUDE_RANDOM || REPORT_STDOUT || (VERBOSE && exitCode == 0)) {
|
||||
|
||||
@ -30,6 +30,7 @@ import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethod;
|
||||
import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethodMatchable;
|
||||
import compiler.lib.ir_framework.driver.irmatching.parser.hotspot.HotSpotPidFileParser;
|
||||
import compiler.lib.ir_framework.driver.irmatching.parser.hotspot.LoggedMethods;
|
||||
import compiler.lib.ir_framework.driver.network.TestVMData;
|
||||
import compiler.lib.ir_framework.shared.TestFormat;
|
||||
|
||||
import java.util.SortedSet;
|
||||
@ -53,13 +54,13 @@ public class TestClassParser {
|
||||
* Parse the Applicable IR Rules and hotspot_pid* file to create a collection of {@link IRMethod} objects.
|
||||
* Return a default/empty TestClass object if there are no applicable @IR rules in any method of the test class.
|
||||
*/
|
||||
public Matchable parse(String hotspotPidFileName, String applicableIRRules) {
|
||||
public Matchable parse(TestVMData testVmData) {
|
||||
ApplicableIRRulesParser applicableIRRulesParser = new ApplicableIRRulesParser(testClass);
|
||||
TestMethods testMethods = applicableIRRulesParser.parse(applicableIRRules);
|
||||
VMInfo vmInfo = VMInfoParser.parseVMInfo(applicableIRRules);
|
||||
TestMethods testMethods = applicableIRRulesParser.parse(testVmData.applicableIRRules());
|
||||
VMInfo vmInfo = VMInfoParser.parseVMInfo(testVmData.applicableIRRules());
|
||||
if (testMethods.hasTestMethods()) {
|
||||
HotSpotPidFileParser hotSpotPidFileParser = new HotSpotPidFileParser(testClass.getName(), testMethods);
|
||||
LoggedMethods loggedMethods = hotSpotPidFileParser.parse(hotspotPidFileName);
|
||||
LoggedMethods loggedMethods = hotSpotPidFileParser.parse(testVmData.hotspotPidFileName());
|
||||
return createTestClass(testMethods, loggedMethods, vmInfo);
|
||||
}
|
||||
return new NonIRTestClass();
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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 boolean allowNotCompilable;
|
||||
private final String hotspotPidFileName;
|
||||
private final String applicableIRRules;
|
||||
|
||||
public TestVMData(JavaMessages javaMessages, String hotspotPidFileName, boolean allowNotCompilable) {
|
||||
this.applicableIRRules = processOutput(javaMessages);
|
||||
this.hotspotPidFileName = hotspotPidFileName;
|
||||
this.allowNotCompilable = allowNotCompilable;
|
||||
}
|
||||
|
||||
public String hotspotPidFileName() {
|
||||
return hotspotPidFileName;
|
||||
}
|
||||
|
||||
public boolean allowNotCompilable() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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;
|
||||
import java.util.concurrent.Callable;
|
||||
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()}.
|
||||
*/
|
||||
public class TestVmMessageReader implements Callable<JavaMessages> {
|
||||
private final Socket socket;
|
||||
private final BufferedReader reader;
|
||||
private boolean receivedStdOut;
|
||||
|
||||
public TestVmMessageReader(Socket socket, BufferedReader reader) {
|
||||
this.socket = socket;
|
||||
this.reader = reader;
|
||||
this.receivedStdOut = false;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
return new JavaMessages(builder.toString(), receivedStdOut);
|
||||
} catch (Exception e) {
|
||||
throw new TestFrameworkException("Error while reading Test VM socket messages", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
public JavaMessages(String output, boolean receivedStdOut) {
|
||||
this.output = output;
|
||||
this.receivedStdOut = receivedStdOut;
|
||||
}
|
||||
|
||||
public String output() {
|
||||
return output;
|
||||
}
|
||||
|
||||
public boolean hasStdOut() {
|
||||
return receivedStdOut;
|
||||
}
|
||||
}
|
||||
@ -24,40 +24,27 @@
|
||||
package compiler.lib.ir_framework.shared;
|
||||
|
||||
import compiler.lib.ir_framework.TestFramework;
|
||||
import compiler.lib.ir_framework.driver.network.*;
|
||||
import compiler.lib.ir_framework.driver.network.testvm.TestVmMessageReader;
|
||||
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessages;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.net.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Dedicated socket to send data from the flag and Test VM back to the Driver VM.
|
||||
* Dedicated Driver VM socket to receive data from the Test VM. Could either be received from Java and C2 code.
|
||||
*/
|
||||
public class TestFrameworkSocket implements AutoCloseable {
|
||||
public static final String STDOUT_PREFIX = "[STDOUT]";
|
||||
public static final String TESTLIST_TAG = "[TESTLIST]";
|
||||
public static final String DEFAULT_REGEX_TAG = "[DEFAULT_REGEX]";
|
||||
public static final String PRINT_TIMES_TAG = "[PRINT_TIMES]";
|
||||
public static final String NOT_COMPILABLE_TAG = "[NOT_COMPILABLE]";
|
||||
|
||||
// Static fields used for Test VM only.
|
||||
private static final String SERVER_PORT_PROPERTY = "ir.framework.server.port";
|
||||
private static final int SERVER_PORT = Integer.getInteger(SERVER_PORT_PROPERTY, -1);
|
||||
|
||||
private static final boolean REPRODUCE = Boolean.getBoolean("Reproduce");
|
||||
private static Socket clientSocket = null;
|
||||
private static PrintWriter clientWriter = null;
|
||||
|
||||
private final String serverPortPropertyFlag;
|
||||
private FutureTask<String> socketTask;
|
||||
private final int serverSocketPort;
|
||||
private final ServerSocket serverSocket;
|
||||
private boolean receivedStdOut = false;
|
||||
private boolean running;
|
||||
private final ExecutorService executor;
|
||||
private Future<JavaMessages> javaFuture;
|
||||
|
||||
public TestFrameworkSocket() {
|
||||
try {
|
||||
@ -66,140 +53,80 @@ public class TestFrameworkSocket implements AutoCloseable {
|
||||
} catch (IOException e) {
|
||||
throw new TestFrameworkException("Failed to create TestFramework server socket", e);
|
||||
}
|
||||
int port = serverSocket.getLocalPort();
|
||||
serverSocketPort = serverSocket.getLocalPort();
|
||||
executor = Executors.newCachedThreadPool();
|
||||
if (TestFramework.VERBOSE) {
|
||||
System.out.println("TestFramework server socket uses port " + port);
|
||||
System.out.println("TestFramework server socket uses port " + serverSocketPort);
|
||||
}
|
||||
serverPortPropertyFlag = "-D" + SERVER_PORT_PROPERTY + "=" + port;
|
||||
start();
|
||||
}
|
||||
|
||||
public String getPortPropertyFlag() {
|
||||
return serverPortPropertyFlag;
|
||||
return "-D" + SERVER_PORT_PROPERTY + "=" + serverSocketPort;
|
||||
}
|
||||
|
||||
private void start() {
|
||||
socketTask = initSocketTask();
|
||||
Thread socketThread = new Thread(socketTask);
|
||||
socketThread.start();
|
||||
running = true;
|
||||
executor.submit(this::acceptLoop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a client (created by flag or Test VM) to connect. Return the messages received from the client.
|
||||
* Main loop to wait for new client connections and handling them upon connection request.
|
||||
*/
|
||||
private FutureTask<String> initSocketTask() {
|
||||
return new FutureTask<>(() -> {
|
||||
try (Socket clientSocket = serverSocket.accept();
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))
|
||||
) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String next;
|
||||
while ((next = in.readLine()) != null) {
|
||||
builder.append(next).append(System.lineSeparator());
|
||||
if (next.startsWith(STDOUT_PREFIX)) {
|
||||
receivedStdOut = true;
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
} catch (IOException e) {
|
||||
private void acceptLoop() {
|
||||
while (running) {
|
||||
try {
|
||||
acceptNewClientConnection();
|
||||
} catch (TestFrameworkException e) {
|
||||
running = false;
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
running = false;
|
||||
throw new TestFrameworkException("Server socket error", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept new client connection and then submit a task accordingly to manage incoming message on that connection/socket.
|
||||
*/
|
||||
private void acceptNewClientConnection() throws IOException {
|
||||
Socket client = serverSocket.accept();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
|
||||
submitTask(client, reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit dedicated tasks which are wrapped into {@link Future} objects. The tasks will read all messages sent
|
||||
* over that connection.
|
||||
*/
|
||||
private void submitTask(Socket client, BufferedReader reader) {
|
||||
javaFuture = executor.submit(new TestVmMessageReader(client, reader));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
running = false;
|
||||
serverSocket.close();
|
||||
} catch (IOException e) {
|
||||
throw new TestFrameworkException("Could not close socket", e);
|
||||
}
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Only called by Test VM to write to server socket.
|
||||
*/
|
||||
public static void write(String msg, String tag) {
|
||||
write(msg, tag, false);
|
||||
public TestVMData testVmData(String hotspotPidFileName, boolean allowNotCompilable) {
|
||||
JavaMessages javaMessages = testVmMessages();
|
||||
return new TestVMData(javaMessages, hotspotPidFileName, allowNotCompilable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only called by Test VM to write to server socket.
|
||||
* <p>
|
||||
* The Test VM is spawned by the main jtreg VM. The stdout of the Test VM is hidden
|
||||
* unless the Verbose or ReportStdout flag is used. TestFrameworkSocket is used by the parent jtreg
|
||||
* VM and the Test VM to communicate. By sending the prints through the TestFrameworkSocket with the
|
||||
* parameter stdout set to true, the parent VM will print the received messages to its stdout, making it
|
||||
* visible to the user.
|
||||
*/
|
||||
public static void write(String msg, String tag, boolean stdout) {
|
||||
if (REPRODUCE) {
|
||||
System.out.println("Debugging Test VM: Skip writing due to -DReproduce");
|
||||
return;
|
||||
}
|
||||
TestFramework.check(SERVER_PORT != -1, "Server port was not set correctly for flag and/or Test VM "
|
||||
+ "or method not called from flag or Test VM");
|
||||
private JavaMessages testVmMessages() {
|
||||
try {
|
||||
// Keep the client socket open until the Test VM terminates (calls closeClientSocket before exiting main()).
|
||||
if (clientSocket == null) {
|
||||
clientSocket = new Socket(InetAddress.getLoopbackAddress(), SERVER_PORT);
|
||||
clientWriter = new PrintWriter(clientSocket.getOutputStream(), true);
|
||||
}
|
||||
if (stdout) {
|
||||
msg = STDOUT_PREFIX + tag + " " + msg;
|
||||
}
|
||||
clientWriter.println(msg);
|
||||
} catch (Exception e) {
|
||||
// When the Test VM is directly run, we should ignore all messages that would normally be sent to the
|
||||
// Driver VM.
|
||||
String failMsg = System.lineSeparator() + System.lineSeparator() + """
|
||||
###########################################################
|
||||
Did you directly run the Test VM (TestVM class)
|
||||
to reproduce a bug?
|
||||
=> Append the flag -DReproduce=true and try again!
|
||||
###########################################################
|
||||
""";
|
||||
throw new TestRunException(failMsg, e);
|
||||
}
|
||||
if (TestFramework.VERBOSE) {
|
||||
System.out.println("Written " + tag + " to socket:");
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes (and flushes) the printer to the socket and the socket itself. Is called as last thing before exiting
|
||||
* the main() method of the flag and the Test VM.
|
||||
*/
|
||||
public static void closeClientSocket() {
|
||||
if (clientSocket != null) {
|
||||
try {
|
||||
clientWriter.close();
|
||||
clientSocket.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not close TestVM socket", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the socket output of the Flag VM.
|
||||
*/
|
||||
public String getOutput() {
|
||||
try {
|
||||
return socketTask.get();
|
||||
return javaFuture.get();
|
||||
} catch (ExecutionException e) {
|
||||
// Thrown when socket task was not finished, yet (i.e. no client sent data) but socket was already closed.
|
||||
return "";
|
||||
throw new TestFrameworkException("No test VM messages were received", e);
|
||||
} catch (Exception e) {
|
||||
throw new TestFrameworkException("Could not read from socket task", e);
|
||||
throw new TestFrameworkException("Error while fetching Test VM Future", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether Test VM sent messages to be put on stdout (starting with {@link ::STDOUT_PREFIX}).
|
||||
*/
|
||||
public boolean hasStdOut() {
|
||||
return receivedStdOut;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 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
|
||||
@ -26,14 +26,13 @@ package compiler.lib.ir_framework.test;
|
||||
import compiler.lib.ir_framework.*;
|
||||
import compiler.lib.ir_framework.shared.TestRun;
|
||||
import compiler.lib.ir_framework.shared.TestRunException;
|
||||
import compiler.lib.ir_framework.test.network.TestVmSocket;
|
||||
import jdk.test.whitebox.WhiteBox;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
|
||||
|
||||
/**
|
||||
* Abstract super class for base, checked and custom run tests.
|
||||
*/
|
||||
@ -118,7 +117,7 @@ abstract class AbstractTest {
|
||||
tryCompileMethod(test);
|
||||
} catch (MethodNotCompilableException e) {
|
||||
final Method testMethod = test.getTestMethod();
|
||||
TestFrameworkSocket.write("Method not compilable: " + testMethod, TestFrameworkSocket.NOT_COMPILABLE_TAG, true);
|
||||
TestVmSocket.send("Method not compilable: " + testMethod);
|
||||
TestRun.check(test.isAllowNotCompilable(),
|
||||
"Method " + testMethod + " not compilable (anymore) at level " + test.getCompLevel() +
|
||||
". Most likely, this is not expected, but if it is, you can use 'allowNotCompilable'.");
|
||||
|
||||
@ -27,6 +27,8 @@ import compiler.lib.ir_framework.IR;
|
||||
import compiler.lib.ir_framework.IRNode;
|
||||
import compiler.lib.ir_framework.TestFramework;
|
||||
import compiler.lib.ir_framework.shared.*;
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
import compiler.lib.ir_framework.test.network.TestVmSocket;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.whitebox.WhiteBox;
|
||||
|
||||
@ -169,9 +171,8 @@ public class ApplicableIRRulesPrinter {
|
||||
}
|
||||
|
||||
private void printDisableReason(String method, String reason, String[] apply, int ruleIndex, int ruleMax) {
|
||||
TestFrameworkSocket.write("Disabling IR matching for rule " + ruleIndex + " of " + ruleMax + " in " +
|
||||
method + ": " + reason + ": " + String.join(", ", apply),
|
||||
"[ApplicableIRRules]", true);
|
||||
TestVmSocket.send("Disabling IR matching for rule " + ruleIndex + " of " + ruleMax + " in " + method + ": " +
|
||||
reason + ": " + String.join(", ", apply));
|
||||
}
|
||||
|
||||
private boolean shouldApplyIrRule(IR irAnno, String m, int ruleIndex, int ruleMax) {
|
||||
@ -284,7 +285,7 @@ public class ApplicableIRRulesPrinter {
|
||||
IRNode.checkIRNodeSupported(s);
|
||||
}
|
||||
} catch (CheckedTestFrameworkException e) {
|
||||
TestFrameworkSocket.write("Skip Rule " + ruleIndex + ": " + e.getMessage(), TestFrameworkSocket.DEFAULT_REGEX_TAG, true);
|
||||
TestVmSocket.send("Skip Rule " + ruleIndex + ": " + e.getMessage());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -522,7 +523,7 @@ public class ApplicableIRRulesPrinter {
|
||||
|
||||
public void emit() {
|
||||
output.append(END);
|
||||
TestFrameworkSocket.write(output.toString(), "ApplicableIRRules");
|
||||
TestVmSocket.sendWithTag(MessageTag.APPLICABLE_IR_RULES, output.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,6 +26,8 @@ package compiler.lib.ir_framework.test;
|
||||
import compiler.lib.ir_framework.*;
|
||||
import compiler.lib.ir_framework.Compiler;
|
||||
import compiler.lib.ir_framework.shared.*;
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
import compiler.lib.ir_framework.test.network.TestVmSocket;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.whitebox.WhiteBox;
|
||||
@ -38,8 +40,6 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static compiler.lib.ir_framework.shared.TestFrameworkSocket.PRINT_TIMES_TAG;
|
||||
|
||||
/**
|
||||
* This class' main method is called from {@link TestFramework} and represents the so-called "Test VM". The class is
|
||||
* the heart of the framework and is responsible for executing all the specified tests in the test class. It uses the
|
||||
@ -159,6 +159,7 @@ public class TestVM {
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
TestVmSocket.connect();
|
||||
String testClassName = args[0];
|
||||
System.out.println("TestVM main() called - about to run tests in class " + testClassName);
|
||||
Class<?> testClass = getClassObject(testClassName, "test");
|
||||
@ -167,7 +168,7 @@ public class TestVM {
|
||||
framework.addHelperClasses(args);
|
||||
framework.start();
|
||||
} finally {
|
||||
TestFrameworkSocket.closeClientSocket();
|
||||
TestVmSocket.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -859,7 +860,7 @@ public class TestVM {
|
||||
System.out.println("Run " + test.toString());
|
||||
}
|
||||
if (testFilterPresent) {
|
||||
TestFrameworkSocket.write("Run " + test.toString(), TestFrameworkSocket.TESTLIST_TAG, true);
|
||||
TestVmSocket.send(MessageTag.TEST_LIST + "Run " + test.toString());
|
||||
}
|
||||
try {
|
||||
test.run();
|
||||
@ -887,10 +888,9 @@ public class TestVM {
|
||||
|
||||
// Print execution times
|
||||
if (PRINT_TIMES) {
|
||||
TestFrameworkSocket.write("Test execution times:", PRINT_TIMES_TAG, true);
|
||||
TestVmSocket.send(MessageTag.PRINT_TIMES + " Test execution times:");
|
||||
for (Map.Entry<Long, String> entry : durations.entrySet()) {
|
||||
TestFrameworkSocket.write(String.format("%-25s%15d ns%n", entry.getValue() + ":", entry.getKey()),
|
||||
PRINT_TIMES_TAG, true);
|
||||
TestVmSocket.send(MessageTag.PRINT_TIMES + String.format("%-25s%15d ns%n", entry.getValue() + ":", entry.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,8 @@
|
||||
|
||||
package compiler.lib.ir_framework.test;
|
||||
|
||||
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
|
||||
import compiler.lib.ir_framework.test.network.MessageTag;
|
||||
import compiler.lib.ir_framework.test.network.TestVmSocket;
|
||||
import jdk.test.whitebox.WhiteBox;
|
||||
|
||||
/**
|
||||
@ -65,6 +66,6 @@ public class VMInfoPrinter {
|
||||
.append(System.lineSeparator());
|
||||
|
||||
vmInfo.append(END_VM_INFO);
|
||||
TestFrameworkSocket.write(vmInfo.toString(), "VMInfo");
|
||||
TestVmSocket.sendWithTag(MessageTag.VM_INFO, vmInfo.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.test.network;
|
||||
|
||||
public class MessageTag {
|
||||
public static final String STDOUT = "[STDOUT]";
|
||||
public static final String TEST_LIST = "[TEST_LIST]";
|
||||
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]";
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.test.network;
|
||||
|
||||
import compiler.lib.ir_framework.TestFramework;
|
||||
import compiler.lib.ir_framework.shared.TestRunException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
public class TestVmSocket {
|
||||
private static final boolean REPRODUCE = Boolean.getBoolean("Reproduce");
|
||||
private static final String SERVER_PORT_PROPERTY = "ir.framework.server.port";
|
||||
private static final int SERVER_PORT = Integer.getInteger(SERVER_PORT_PROPERTY, -1);
|
||||
|
||||
private static Socket socket = null;
|
||||
private static PrintWriter writer = null;
|
||||
|
||||
/**
|
||||
* Send a message to the Driver VM which is unconditionally shown in the Driver VM output.
|
||||
*/
|
||||
public static void send(String message) {
|
||||
sendWithTag(MessageTag.STDOUT, 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}.
|
||||
*/
|
||||
public static void sendWithTag(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 + " " + message);
|
||||
}
|
||||
|
||||
public static void connect() {
|
||||
if (REPRODUCE) {
|
||||
// Debugging Test VM: Skip writing due to -DReproduce;
|
||||
return;
|
||||
}
|
||||
|
||||
TestFramework.check(SERVER_PORT != -1, "Server port was not set correctly for flag and/or test VM "
|
||||
+ "or method not called from flag or test VM");
|
||||
|
||||
try {
|
||||
// Keep the client socket open until the test VM terminates (calls closeClientSocket before exiting main()).
|
||||
socket = new Socket(InetAddress.getLoopbackAddress(), SERVER_PORT);
|
||||
writer = new PrintWriter(socket.getOutputStream(), true);
|
||||
} catch (Exception e) {
|
||||
// When the test VM is directly run, we should ignore all messages that would normally be sent to the
|
||||
// driver VM.
|
||||
String failMsg = System.lineSeparator() + System.lineSeparator() + """
|
||||
###########################################################
|
||||
Did you directly run the test VM (TestVM class)
|
||||
to reproduce a bug?
|
||||
=> Append the flag -DReproduce=true and try again!
|
||||
###########################################################
|
||||
""";
|
||||
throw new TestRunException(failMsg, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes (and flushes) the printer to the socket and the socket itself. Is called as last thing before exiting
|
||||
* the main() method of the flag and the test VM.
|
||||
*/
|
||||
public static void close() {
|
||||
if (socket != null) {
|
||||
writer.close();
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not close TestVM socket", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,8 +69,7 @@ public class TestPhaseIRMatching {
|
||||
List<String> testVMFlags = flagVMProcess.getTestVMFlags();
|
||||
TestVMProcess testVMProcess = new TestVMProcess(testVMFlags, testClass, null, -1, false, false);
|
||||
TestClassParser testClassParser = new TestClassParser(testClass, false);
|
||||
Matchable testClassMatchable = testClassParser.parse(testVMProcess.getHotspotPidFileName(),
|
||||
testVMProcess.getApplicableIRRules());
|
||||
Matchable testClassMatchable = testClassParser.parse(testVMProcess.testVmData());
|
||||
MatchResult result = testClassMatchable.match();
|
||||
List<Failure> expectedFails = new ExpectedFailsBuilder().build(testClass);
|
||||
List<Failure> foundFailures = new FailureBuilder().build(result);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user