From 35e603717d1f2c73af1d5e3f5c4e8215d7b7abe6 Mon Sep 17 00:00:00 2001 From: fdelpoggio Date: Thu, 18 Jun 2026 10:08:53 -0300 Subject: [PATCH 1/2] fix: Websocket URL parser --- .../javadsl/websocket/WebsocketJMeterDsl.java | 72 ++++++++++--------- .../test/java/DslWebsocketSamplerTest.java | 8 +-- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/jmeter-java-dsl-websocket/src/main/java/us/abstracta/jmeter/javadsl/websocket/WebsocketJMeterDsl.java b/jmeter-java-dsl-websocket/src/main/java/us/abstracta/jmeter/javadsl/websocket/WebsocketJMeterDsl.java index 1a82411e..eb147b50 100644 --- a/jmeter-java-dsl-websocket/src/main/java/us/abstracta/jmeter/javadsl/websocket/WebsocketJMeterDsl.java +++ b/jmeter-java-dsl-websocket/src/main/java/us/abstracta/jmeter/javadsl/websocket/WebsocketJMeterDsl.java @@ -11,8 +11,6 @@ import eu.luminis.jmeter.wssampler.SingleWriteWebSocketSampler; import eu.luminis.jmeter.wssampler.SingleWriteWebSocketSamplerGui; import java.lang.reflect.Method; -import java.net.URI; -import java.net.URISyntaxException; import java.util.Arrays; import java.util.List; import org.apache.jmeter.testelement.TestElement; @@ -25,6 +23,7 @@ import us.abstracta.jmeter.javadsl.codegeneration.params.EnumParam; import us.abstracta.jmeter.javadsl.codegeneration.params.StringParam; import us.abstracta.jmeter.javadsl.core.samplers.BaseSampler; +import us.abstracta.jmeter.javadsl.http.JmeterUrl; /** * Provides factory methods to create WebSocket samplers for performance @@ -150,43 +149,40 @@ public static class DslConnectSampler extends BaseSampler { private DslConnectSampler(String url) { super("WebSocket Open Connection", OpenWebSocketSamplerGui.class); - try { - URI uri = new URI(url); + parseUrl(url); + } + + private static boolean containsJmeterExpression(String value) { + return value != null && value.contains("${"); + } - String scheme = uri.getScheme(); - if (scheme == null || (!"ws".equals(scheme) && !"wss".equals(scheme))) { + private void parseUrl(String url) { + JmeterUrl parsed = JmeterUrl.valueOf(url); + String scheme = parsed.protocol(); + if (scheme != null && !containsJmeterExpression(scheme)) { + if (!"ws".equals(scheme) && !"wss".equals(scheme)) { throw new IllegalArgumentException( "Invalid WebSocket URL. Must start with 'ws://' or 'wss://'"); } - - this.tls = "wss".equals(scheme); - this.server = uri.getHost(); - if (this.server == null) { - throw new IllegalArgumentException("Invalid WebSocket URL. Host is required"); - } - - int port = uri.getPort(); - if (port == -1) { - this.port = this.tls ? "443" : "80"; - } else { - this.port = String.valueOf(port); - } - - String path = uri.getPath(); - if (path == null || path.isEmpty()) { - this.path = "/"; + tls = "wss".equals(scheme); + } + server = parsed.host(); + if ((server == null || server.isEmpty()) && scheme != null + && !containsJmeterExpression(scheme)) { + throw new IllegalArgumentException("Invalid WebSocket URL. Host is required"); + } + String parsedPort = parsed.port(); + if (parsedPort == null || parsedPort.isEmpty()) { + if (scheme != null && !containsJmeterExpression(scheme)) { + port = tls ? "443" : "80"; } else { - this.path = path; - } - - String query = uri.getQuery(); - if (query != null && !query.isEmpty()) { - this.path = this.path + "?" + query; + port = ""; } - - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Invalid WebSocket URL: " + url, e); + } else { + port = parsedPort; } + String parsedPath = parsed.path(); + path = (parsedPath == null || parsedPath.isEmpty()) ? "/" : parsedPath; } @Override @@ -199,9 +195,15 @@ protected TestElement buildTestElement() { ret.setReadTimeout(responseTimeoutMillis); } ret.setTLS(tls); - ret.setServer(server); - ret.setPort(port); - ret.setPath(path); + if (server != null) { + ret.setServer(server); + } + if (port != null) { + ret.setPort(port); + } + if (path != null) { + ret.setPath(path); + } return ret; } diff --git a/jmeter-java-dsl-websocket/src/test/java/DslWebsocketSamplerTest.java b/jmeter-java-dsl-websocket/src/test/java/DslWebsocketSamplerTest.java index a1122587..8312e5df 100644 --- a/jmeter-java-dsl-websocket/src/test/java/DslWebsocketSamplerTest.java +++ b/jmeter-java-dsl-websocket/src/test/java/DslWebsocketSamplerTest.java @@ -1,13 +1,12 @@ import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -import static us.abstracta.jmeter.javadsl.JmeterDsl.responseAssertion; -import static us.abstracta.jmeter.javadsl.JmeterDsl.testPlan; -import static us.abstracta.jmeter.javadsl.JmeterDsl.threadGroup; +import static us.abstracta.jmeter.javadsl.JmeterDsl.*; import static us.abstracta.jmeter.javadsl.websocket.WebsocketJMeterDsl.*; import org.junit.jupiter.api.Test; import us.abstracta.jmeter.javadsl.core.TestPlanStats; +import us.abstracta.jmeter.javadsl.core.samplers.DslSampler; public class DslWebsocketSamplerTest { @@ -19,7 +18,8 @@ public void shouldConnectAndEchoMessageWhenWebSocketTestPlanWithEchoServer() thr String wsUri = echoServer.getUri(); TestPlanStats stats = testPlan( threadGroup(1, 1, - websocketConnect(wsUri), + vars().set("stream_key", "1234567890"), + websocketConnect(wsUri + "/test?stream_key=${stream_key}"), websocketWrite("Hello WebSocket Test!"), websocketRead() .children( From 5cebd1092589c726d99be56db3f6767b7645c297 Mon Sep 17 00:00:00 2001 From: fdelpoggio Date: Thu, 18 Jun 2026 11:42:42 -0300 Subject: [PATCH 2/2] Fix: Add text/binary data type to WebSocket read and write sampler --- .../javadsl/websocket/WebsocketJMeterDsl.java | 27 +++++++++++++------ .../test/java/DslWebsocketSamplerTest.java | 8 +++--- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/jmeter-java-dsl-websocket/src/main/java/us/abstracta/jmeter/javadsl/websocket/WebsocketJMeterDsl.java b/jmeter-java-dsl-websocket/src/main/java/us/abstracta/jmeter/javadsl/websocket/WebsocketJMeterDsl.java index eb147b50..a5b02dac 100644 --- a/jmeter-java-dsl-websocket/src/main/java/us/abstracta/jmeter/javadsl/websocket/WebsocketJMeterDsl.java +++ b/jmeter-java-dsl-websocket/src/main/java/us/abstracta/jmeter/javadsl/websocket/WebsocketJMeterDsl.java @@ -118,8 +118,8 @@ public static DslDisconnectSampler websocketDisconnect() { * @return the write sampler for further configuration or usage * @since 2.2 */ - public static DslWriteSampler websocketWrite(String requestData) { - return new DslWriteSampler(requestData); + public static DslWriteSampler websocketWrite(String requestData, String dataType) { + return new DslWriteSampler(requestData, dataType); } /** @@ -132,11 +132,12 @@ public static DslWriteSampler websocketWrite(String requestData) { * Requires an active WebSocket connection established via * {@link #websocketConnect(String)}. * + * @param type the data type to read from the server. Must be 'text' or 'binary' * @return the read sampler for further configuration or usage * @since 2.2 */ - public static DslReadSampler websocketRead() { - return new DslReadSampler(); + public static DslReadSampler websocketRead(String type) { + return new DslReadSampler(type); } public static class DslConnectSampler extends BaseSampler { @@ -426,16 +427,21 @@ protected MethodCall buildMethodCall(CloseWebSocketSampler testElement, public static class DslWriteSampler extends BaseSampler { private String requestData; + private String dataType; - private DslWriteSampler(String requestData) { + private DslWriteSampler(String requestData, String dataType) { super("WebSocket Single Write", SingleWriteWebSocketSamplerGui.class); this.requestData = requestData; + this.dataType = dataType; + if (dataType != null && !"text".equals(dataType) && !"binary".equals(dataType)) { + throw new IllegalArgumentException("Invalid data type. Must be 'text' or 'binary'"); + } } @Override protected TestElement buildTestElement() { SingleWriteWebSocketSampler write = new SingleWriteWebSocketSampler(); - write.setType(DataPayloadType.Text); + write.setType("text".equals(dataType) ? DataPayloadType.Text : DataPayloadType.Binary); write.setRequestData(requestData); write.setCreateNewConnection(false); return write; @@ -462,9 +468,14 @@ protected MethodCall buildMethodCall(SingleWriteWebSocketSampler testElement, public static class DslReadSampler extends BaseSampler { private String responseTimeoutMillis; private boolean waitForResponse = true; + private String type; - private DslReadSampler() { + private DslReadSampler(String type) { super("WebSocket Single Read", SingleReadWebSocketSamplerGui.class); + this.type = type; + if (type != null && !"text".equals(type) && !"binary".equals(type)) { + throw new IllegalArgumentException("Invalid data type. Must be 'text' or 'binary'"); + } } @Override @@ -473,7 +484,7 @@ protected TestElement buildTestElement() { if (responseTimeoutMillis != null) { read.setReadTimeout(responseTimeoutMillis); } - read.setDataType(DataType.Text); + read.setDataType("text".equals(type) ? DataType.Text : DataType.Binary); read.setOptional(!waitForResponse); read.setCreateNewConnection(false); return read; diff --git a/jmeter-java-dsl-websocket/src/test/java/DslWebsocketSamplerTest.java b/jmeter-java-dsl-websocket/src/test/java/DslWebsocketSamplerTest.java index 8312e5df..32623567 100644 --- a/jmeter-java-dsl-websocket/src/test/java/DslWebsocketSamplerTest.java +++ b/jmeter-java-dsl-websocket/src/test/java/DslWebsocketSamplerTest.java @@ -20,8 +20,8 @@ public void shouldConnectAndEchoMessageWhenWebSocketTestPlanWithEchoServer() thr threadGroup(1, 1, vars().set("stream_key", "1234567890"), websocketConnect(wsUri + "/test?stream_key=${stream_key}"), - websocketWrite("Hello WebSocket Test!"), - websocketRead() + websocketWrite("Hello WebSocket Test!", "text"), + websocketRead("text") .children( responseAssertion() .containsSubstrings("Hello WebSocket Test!")), @@ -61,7 +61,7 @@ public void shouldErrorSamplerWhenConnectWithVeryShortTimeout() throws Exception public void shouldErrorSamplerWhenWriteOperationWhenNoPreviousConnection() throws Exception { TestPlanStats stats = testPlan( threadGroup(1, 1, - websocketWrite("Test message"))) + websocketWrite("Test message", "text"))) .run(); assertThat(stats.overall().errorsCount()).isEqualTo(1); } @@ -70,7 +70,7 @@ public void shouldErrorSamplerWhenWriteOperationWhenNoPreviousConnection() throw public void shouldErrorSamplerWhenReadOperationWhenNoPreviousConnection() throws Exception { TestPlanStats stats = testPlan( threadGroup(1, 1, - websocketRead())) + websocketRead("text"))) .run(); assertThat(stats.overall().errorsCount()).isEqualTo(1); }