8378257: [IR Framework] Add identity for socket connection and prepare for parsing C2 dumps

Reviewed-by: dfenacci, thartmann, mhaessig
This commit is contained in:
Christian Hagedorn 2026-04-27 12:47:06 +00:00
parent 102302ba87
commit 455707c3dc
5 changed files with 98 additions and 16 deletions

View File

@ -0,0 +1,49 @@
/*
* 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.JavaMessage;
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
/**
* We currently have only one type of Test VM message sent to the {@link TestFrameworkSocket}:
* - {@link JavaMessage}: A message sent from Java code.
*
* <p>
* Later, we will add C2 messages as well as second type with JDK-8375270.
* Both kinds of messages are parsed differently by classes implementing this interface.
*/
public interface TestVmMessageParser<Output> {
/**
* Parse a single line of a received Test VM message.
*
* @param line A single message line forwarded by {@link TestVmMessageReader}.
*/
void parseLine(String line);
/**
* Once parsing is done, this method returns the final output.
*/
Output output();
}

View File

@ -23,8 +23,6 @@
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;
@ -35,23 +33,23 @@ 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 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()}.
* wrapped in a {@link Future}. The received messages are parsed with the provided {@link TestVmMessageParser}. 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> {
public class TestVmMessageReader<Output> implements Callable<Output> {
private final Socket socket;
private final BufferedReader reader;
private final JavaMessageParser messageParser;
private final BufferedReader reader; // identity already consumed
private final TestVmMessageParser<Output> messageParser;
public TestVmMessageReader(Socket socket, BufferedReader reader) {
public TestVmMessageReader(Socket socket, BufferedReader reader, TestVmMessageParser<Output> messageParser) {
this.socket = socket;
this.reader = reader;
this.messageParser = new JavaMessageParser();
this.messageParser = messageParser;
}
@Override
public JavaMessages call() {
public Output call() {
try (socket; reader) {
String line;
while ((line = reader.readLine()) != null) {
@ -63,3 +61,4 @@ public class TestVmMessageReader implements Callable<JavaMessages> {
}
}
}

View File

@ -24,6 +24,7 @@
package compiler.lib.ir_framework.driver.network.testvm.java;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.driver.network.testvm.TestVmMessageParser;
import compiler.lib.ir_framework.driver.network.testvm.java.multiline.ApplicableIRRulesStrategy;
import compiler.lib.ir_framework.driver.network.testvm.java.multiline.MultiLineParser;
import compiler.lib.ir_framework.driver.network.testvm.java.multiline.VMInfoStrategy;
@ -40,7 +41,7 @@ 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 {
public class JavaMessageParser implements TestVmMessageParser<JavaMessages> {
private static final Pattern TAG_PATTERN = Pattern.compile("^(\\[[^]]+])\\s*(.*)$");
private final List<String> stdoutMessages;
@ -60,6 +61,7 @@ public class JavaMessageParser {
this.currentMultiLineParser = null;
}
@Override
public void parseLine(String line) {
line = line.trim();
Matcher tagLineMatcher = TAG_PATTERN.matcher(line);
@ -118,6 +120,7 @@ public class JavaMessageParser {
currentMultiLineParser = null;
}
@Override
public JavaMessages output() {
return new JavaMessages(new StdoutMessages(stdoutMessages),
new ExecutedTests(executedTests),

View File

@ -26,7 +26,9 @@ 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.JavaMessageParser;
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessages;
import compiler.lib.ir_framework.test.network.TestVmSocket;
import java.io.BufferedReader;
import java.io.IOException;
@ -116,20 +118,46 @@ public class TestFrameworkSocket implements AutoCloseable {
}
/**
* Accept new client connection and then submit a task accordingly to manage incoming message on that connection/socket.
* Accept new client connection by first reading the identity of the connection (either coming from Java or C2)
* and then submitting a task accordingly to manage incoming messages on that connection/socket.
*/
private void acceptNewClientConnection() throws IOException {
Socket client = serverSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
submitTask(client, reader);
try {
String identity = readIdentity(client, reader).trim();
submitTask(identity, client, reader);
} catch (Exception e) {
client.close();
reader.close();
throw e;
}
}
private String readIdentity(Socket client, BufferedReader reader) throws IOException {
String identity;
try {
client.setSoTimeout(10000);
identity = reader.readLine();
TestFramework.check(identity != null, "end of stream has been reached without reading the identity");
} catch (SocketTimeoutException e) {
throw new TestFrameworkException("Did not receive initial identity message after 10s", e);
} finally {
client.setSoTimeout(0);
}
return identity;
}
/**
* 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 = clientExecutor.submit(new TestVmMessageReader(client, reader));
private void submitTask(String identity, Socket client, BufferedReader reader) {
if (identity.equals(TestVmSocket.IDENTITY)) {
javaFuture = clientExecutor.submit(new TestVmMessageReader<>(client, reader, new JavaMessageParser()));
} else {
throw new TestFrameworkException("Unrecognized identity: " + identity);
}
}
@Override

View File

@ -33,6 +33,8 @@ import java.net.InetAddress;
import java.net.Socket;
public class TestVmSocket {
public static final String IDENTITY = "#TestVM-Java#";
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);
@ -88,6 +90,7 @@ public class TestVmSocket {
// 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);
writer.println(IDENTITY);
} catch (Exception e) {
// When the test VM is directly run, we should ignore all messages that would normally be sent to the
// driver VM.