diff --git a/benchmark-runner/src/test/java/io/netty/loom/benchmark/runner/BenchmarkIntegrationTest.java b/benchmark-runner/src/test/java/io/netty/loom/benchmark/runner/BenchmarkIntegrationTest.java
index 4dcad60..f2d3ebc 100644
--- a/benchmark-runner/src/test/java/io/netty/loom/benchmark/runner/BenchmarkIntegrationTest.java
+++ b/benchmark-runner/src/test/java/io/netty/loom/benchmark/runner/BenchmarkIntegrationTest.java
@@ -36,8 +36,15 @@
*
* Tests cover:
*
- * - NIO I/O with virtual Netty mode
+ * - NIO I/O with virtual Netty mode (mock server)
+ * - NIO I/O with non-virtual Netty mode (mock server)
+ * - NIO I/O with virtual Netty mode (mockless)
+ * - NIO I/O with non-virtual Netty mode (mockless)
*
+ *
+ * Note: NETTY_SCHEDULER mode requires
+ * {@code -Djdk.virtualThreadScheduler.implClass=io.netty.loom.NettyScheduler}
+ * and is therefore not covered here.
*/
class BenchmarkIntegrationTest {
@@ -50,11 +57,18 @@ class BenchmarkIntegrationTest {
static Stream serverConfigurations() {
return Stream.of(
- // IO type, mode, description
- Arguments.of(HandoffHttpServer.IO.NIO, HandoffHttpServer.Mode.VIRTUAL_NETTY, "NIO with Netty on FJ"));
+ // IO type, mode, mockless, description
+ Arguments.of(HandoffHttpServer.IO.NIO, HandoffHttpServer.Mode.VIRTUAL_NETTY, false,
+ "NIO with Netty on FJ"),
+ Arguments.of(HandoffHttpServer.IO.NIO, HandoffHttpServer.Mode.NON_VIRTUAL_NETTY, false,
+ "NIO with platform IO + VT blocking"),
+ Arguments.of(HandoffHttpServer.IO.NIO, HandoffHttpServer.Mode.VIRTUAL_NETTY, true,
+ "NIO with Netty on FJ (mockless)"),
+ Arguments.of(HandoffHttpServer.IO.NIO, HandoffHttpServer.Mode.NON_VIRTUAL_NETTY, true,
+ "NIO with platform IO + VT blocking (mockless)"));
}
- void startServers(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode) throws Exception {
+ void startServers(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, boolean mockless) throws Exception {
// Use unique ports for each test to avoid conflicts
mockPort = PORT_COUNTER.getAndIncrement();
handoffPort = PORT_COUNTER.getAndIncrement();
@@ -74,7 +88,7 @@ void startServers(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode) thro
// Start handoff server with specified configuration
handoffServer = new HandoffHttpServer(handoffPort, "http://localhost:" + mockPort + "/fruits", 1, ioType, true,
- false, mode);
+ mockless, mode);
handoffServer.start();
// Wait for handoff server to be ready
@@ -99,64 +113,64 @@ void stopServers() {
}
}
- @ParameterizedTest(name = "{2}")
+ @ParameterizedTest(name = "{3}")
@MethodSource("serverConfigurations")
- void mockServerHealthEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, String description)
- throws Exception {
- startServers(ioType, mode);
+ void mockServerHealthEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, boolean mockless,
+ String description) throws Exception {
+ startServers(ioType, mode, mockless);
given().port(mockPort).when().get("/health").then().statusCode(200).body(equalTo("OK"));
}
- @ParameterizedTest(name = "{2}")
+ @ParameterizedTest(name = "{3}")
@MethodSource("serverConfigurations")
- void mockServerFruitsEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, String description)
- throws Exception {
- startServers(ioType, mode);
+ void mockServerFruitsEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, boolean mockless,
+ String description) throws Exception {
+ startServers(ioType, mode, mockless);
given().port(mockPort).when().get("/fruits").then().statusCode(200).contentType(ContentType.JSON)
.body("fruits", hasSize(10)).body("fruits[0].name", equalTo("Apple"))
.body("fruits[0].color", equalTo("Red")).body("fruits[0].price", equalTo(1.20f));
}
- @ParameterizedTest(name = "{2}")
+ @ParameterizedTest(name = "{3}")
@MethodSource("serverConfigurations")
- void handoffServerHealthEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, String description)
- throws Exception {
- startServers(ioType, mode);
+ void handoffServerHealthEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, boolean mockless,
+ String description) throws Exception {
+ startServers(ioType, mode, mockless);
given().port(handoffPort).when().get("/health").then().statusCode(200).body(equalTo("OK"));
}
- @ParameterizedTest(name = "{2}")
+ @ParameterizedTest(name = "{3}")
@MethodSource("serverConfigurations")
- void handoffServerFruitsEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, String description)
- throws Exception {
- startServers(ioType, mode);
+ void handoffServerFruitsEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, boolean mockless,
+ String description) throws Exception {
+ startServers(ioType, mode, mockless);
given().port(handoffPort).when().get("/fruits").then().statusCode(200).contentType(ContentType.JSON)
.body("fruits", hasSize(10)).body("fruits[0].name", equalTo("Apple"))
.body("fruits[0].color", equalTo("Red"));
}
- @ParameterizedTest(name = "{2}")
+ @ParameterizedTest(name = "{3}")
@MethodSource("serverConfigurations")
- void handoffServerRootEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, String description)
- throws Exception {
- startServers(ioType, mode);
+ void handoffServerRootEndpoint(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, boolean mockless,
+ String description) throws Exception {
+ startServers(ioType, mode, mockless);
given().port(handoffPort).when().get("/").then().statusCode(200).contentType(ContentType.JSON).body("fruits",
hasSize(10));
}
- @ParameterizedTest(name = "{2}")
+ @ParameterizedTest(name = "{3}")
@MethodSource("serverConfigurations")
- void handoffServer404ForUnknownPath(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, String description)
- throws Exception {
- startServers(ioType, mode);
+ void handoffServer404ForUnknownPath(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, boolean mockless,
+ String description) throws Exception {
+ startServers(ioType, mode, mockless);
given().port(handoffPort).when().get("/unknown").then().statusCode(404);
}
- @ParameterizedTest(name = "{2}")
+ @ParameterizedTest(name = "{3}")
@MethodSource("serverConfigurations")
- void handoffServerReturnsAllFruits(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, String description)
- throws Exception {
- startServers(ioType, mode);
+ void handoffServerReturnsAllFruits(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, boolean mockless,
+ String description) throws Exception {
+ startServers(ioType, mode, mockless);
List fruitNames = given().port(handoffPort).when().get("/fruits").then().statusCode(200).extract()
.jsonPath().getList("fruits.name", String.class);
@@ -167,11 +181,11 @@ void handoffServerReturnsAllFruits(HandoffHttpServer.IO ioType, HandoffHttpServe
assertTrue(fruitNames.contains("Kiwi"));
}
- @ParameterizedTest(name = "{2}")
+ @ParameterizedTest(name = "{3}")
@MethodSource("serverConfigurations")
void handoffServerHandlesMultipleRequests(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode,
- String description) throws Exception {
- startServers(ioType, mode);
+ boolean mockless, String description) throws Exception {
+ startServers(ioType, mode, mockless);
// Send multiple requests to verify server handles concurrent load
for (int i = 0; i < 10; i++) {
@@ -179,15 +193,16 @@ void handoffServerHandlesMultipleRequests(HandoffHttpServer.IO ioType, HandoffHt
}
}
- @ParameterizedTest(name = "{2}")
+ @ParameterizedTest(name = "{3}")
@MethodSource("serverConfigurations")
- void verifyEndToEndJsonParsing(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, String description)
- throws Exception {
- startServers(ioType, mode);
+ void verifyEndToEndJsonParsing(HandoffHttpServer.IO ioType, HandoffHttpServer.Mode mode, boolean mockless,
+ String description) throws Exception {
+ startServers(ioType, mode, mockless);
// This test verifies the complete flow:
// 1. HandoffHttpServer receives request
- // 2. Makes blocking call to MockHttpServer
+ // 2. In non-mockless mode: makes blocking call to MockHttpServer
+ // In mockless mode: uses cached JSON bytes directly
// 3. Parses JSON with Jackson into Fruit objects
// 4. Re-encodes and returns