Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
1 change: 1 addition & 0 deletions docs/guide/protocols/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
<!-- @include: jdbc.md -->
<!-- @include: java.md -->
<!-- @include: selenium.md -->
<!-- @include: websocket.md -->
68 changes: 68 additions & 0 deletions docs/guide/protocols/websocket.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
### WebSocket

The `DslWebsocketSampler` class provides a Java DSL for creating WebSocket performance tests using JMeter. It supports the full WebSocket lifecycle including connection, data transmission, and disconnection operations. It is based on [WebSocket Samplers by Peter Doornbosch](https://bitbucket.org/pjtr/jmeter-websocket-samplers/src/master/) plugin.

To use it, add the following dependency to your project:

:::: code-group
::: code-group-item Maven
```xml
<dependency>
<groupId>us.abstracta.jmeter</groupId>
<artifactId>jmeter-java-dsl-websocket</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
```
:::
::: code-group-item Gradle
```groovy
testImplementation 'us.abstracta.jmeter:jmeter-java-dsl-websocket:2.2'
```
:::
::::



Below you can see a basic usage example of WebSocket protocol.

```java
import static us.abstracta.jmeter.javadsl.JmeterDsl.*;
import static us.abstracta.jmeter.javadsl.websocket.WebsocketJMeterDsl.*;
import us.abstracta.jmeter.javadsl.core.TestPlanStats;

public class Test {
public static void main(String[] args) throws Exception {
TestPlanStats stats = testPlan(
threadGroup(1, 1,
websocketConnect("wss://ws.postman-echo.com/raw"),
websocketWrite("Hello WebSocket!"),
websocketRead()
.children(
responseAssertion()
.equalsToStrings("Hello WebSocket!")
),
websocketDisconnect()
)
).run();
}
}
```

::: warning
Only `ws://` and `wss://` protocols are supported. Using any other scheme will throw an `IllegalArgumentException`.
:::

::: tip
You can use a non-blocking read if necessary in the following way:

```java
websocketRead().waitForResponse(false)
```

In this case, it is not recommended to add an assertion because the response could be empty.
:::

::: warning
The WebSocket plugin only supports one connection per thread at a time. If you want to change the WebSocket server during execution, you should add a disconnect sampler and then establish a new connection.
:::
6 changes: 6 additions & 0 deletions jmeter-java-dsl-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
<artifactId>jmeter-java-dsl-recorder</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>us.abstracta.jmeter</groupId>
<artifactId>jmeter-java-dsl-websocket</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
Expand Down Expand Up @@ -165,6 +170,7 @@
<include>com.blazemeter:jmeter-plugins-random-csv-data-set</include>
<include>com.blazemeter:jmeter-plugins-wsc</include>
<include>com.blazemeter:jmeter-parallel</include>
<include>net.luminis.jmeter:jmeter-websocket-samplers</include>
<include>info.picocli:*</include>
<include>com.fifesoft:rsyntaxtextarea</include>
<include>com.github.weisj:darklaf-extensions-rsyntaxarea</include>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import us.abstracta.jmeter.javadsl.graphql.DslGraphqlSampler;
import us.abstracta.jmeter.javadsl.jdbc.JdbcJmeterDsl;
import us.abstracta.jmeter.javadsl.parallel.ParallelController;
import us.abstracta.jmeter.javadsl.websocket.WebsocketJMeterDsl;
import us.abstracta.jmeter.javadsl.wrapper.WrapperJmeterDsl;

@Command(name = "jmx2dsl", header = "Converts a JMX file to DSL code",
Expand Down Expand Up @@ -48,6 +49,7 @@ public Integer call() throws Exception {
addBuildersFrom(ElasticsearchBackendListener.class, "jmeter-java-dsl-elasticsearch-listener",
codeGenerator);
addBuildersFrom(DatadogBackendListener.class, "jmeter-java-dsl-datadog", codeGenerator);
addBuildersFrom(WebsocketJMeterDsl.class, "jmeter-java-dsl-websocket", codeGenerator);
System.out.println(codeGenerator.generateCodeFromJmx(jmxFile));
return 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
import us.abstracta.jmeter.javadsl.octoperf.api.Scenario;
import us.abstracta.jmeter.javadsl.octoperf.api.TableEntry;
import us.abstracta.jmeter.javadsl.octoperf.api.User;
import us.abstracta.jmeter.javadsl.octoperf.api.UserLoad;
import us.abstracta.jmeter.javadsl.octoperf.api.UserLoad.UserLoadRampUp;
import us.abstracta.jmeter.javadsl.octoperf.api.UserProfile;
import us.abstracta.jmeter.javadsl.octoperf.api.UserProfile.UserLoadRampUp;
import us.abstracta.jmeter.javadsl.octoperf.api.VirtualUser;
import us.abstracta.jmeter.javadsl.octoperf.api.Workspace;

Expand Down Expand Up @@ -264,8 +264,8 @@ private Scenario buildScenario(User user, Project project, List<VirtualUser> vus
HashTree tree) throws IOException {
Provider provider = apiClient.findProviderByWorkspace(project.getWorkspace());
String defaultRegion = provider.getRegions().keySet().iterator().next();
List<UserLoad> userLoads = vus.stream()
.map(vu -> new UserLoad(vu.getId(), provider.getId(), defaultRegion,
List<UserProfile> userLoads = vus.stream()
.map(vu -> new UserProfile(vu.getId(), provider.getId(), defaultRegion,
buildUserLoadConfig(tree)))
.collect(Collectors.toList());
Scenario ret = apiClient.createScenario(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Set;

Expand All @@ -16,12 +15,11 @@ public class Scenario {
private final String projectId;
private final String name;
private final String description = "";
private final List<UserLoad> userLoads;
private final List<UserProfile> userProfiles;
private final String mode = "STANDARD";
private final Instant created = Instant.now();
private final Instant lastModified = Instant.now();
private final Set<String> tags;
private final BackendListenerSettings backendListeners = new BackendListenerSettings();
private Project project;

@JsonCreator
Expand All @@ -30,18 +28,18 @@ public Scenario(@JsonProperty("id") String id, @JsonProperty("tags") Set<String>
this.userId = null;
this.projectId = null;
this.name = null;
this.userLoads = null;
this.userProfiles = null;
this.tags = tags;
}

public Scenario(User user, Project project, String name, List<UserLoad> userLoads,
public Scenario(User user, Project project, String name, List<UserProfile> userProfiles,
Set<String> tags) {
this.id = "";
this.userId = user.getId();
this.project = project;
this.projectId = project.getId();
this.name = name;
this.userLoads = userLoads;
this.userProfiles = userProfiles;
this.tags = tags;
}

Expand All @@ -67,15 +65,4 @@ public String getUrl() {
return project.getBaseUrl() + "/runtime/scenario/" + id;
}

public static class BackendListenerSettings {

private final int queueSize = 5000;
private final List<BackendListener> listeners = Collections.emptyList();

}

public static class BackendListener {

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,30 @@
import org.apache.jmeter.threads.ThreadGroup;
import us.abstracta.jmeter.javadsl.core.threadgroups.BaseThreadGroup.SampleErrorAction;

public class UserLoad {
public class UserProfile {

// we don't need getters since Jackson gets the values from fields
private final String name = "";
private final String virtualUserId;
private final String providerId;
private final String region;
private final UserLoadStrategy strategy;
private final BandwidthSettings bandwidth = new BandwidthSettings();
private final BrowserSettings browser = new BrowserSettings();
private final DnsSettings dns = new DnsSettings();
private final ThinkTimeSettings thinktime = new ThinkTimeSettings();
private final String location;
private final UserLoadStrategy load;
private final MemorySettings memory = new MemorySettings();
private final JtlSettings jtl = new JtlSettings();
private final PropertiesSettings properties = new PropertiesSettings();
private final SetUpTearDownSettings setUp = null;
private final SetUpTearDownSettings tearDown = null;
private final Engine engine = new Engine();

public UserLoad() {
public UserProfile() {
virtualUserId = null;
providerId = null;
region = null;
strategy = null;
location = null;
load = null;
}

public UserLoad(String virtualUserId, String providerId, String region,
public UserProfile(String virtualUserId, String providerId, String location,
UserLoadStrategy strategy) {
this.virtualUserId = virtualUserId;
this.providerId = providerId;
this.region = region;
this.strategy = strategy;
this.location = location;
this.load = strategy;
}

@JsonTypeInfo(use = NAME, include = PROPERTY)
Expand All @@ -53,25 +46,24 @@ public abstract static class UserLoadStrategy {

}

@JsonTypeName("UserLoadRampup")
@JsonTypeName("UserProfileLoadRampUp")
public static class UserLoadRampUp extends UserLoadStrategy {

private final int userload;
private final long rampup;
private final long peak;
private final long delay = 0;
private final SampleErrorAction onSampleError = SampleErrorAction.CONTINUE;
private final int plateauVus;
private final long rampUpMs;
private final long plateauMs;
private final long delayMs = 0;

public UserLoadRampUp() {
userload = 0;
rampup = 0;
peak = 0;
plateauVus = 0;
rampUpMs = 0;
plateauMs = 0;
}

public UserLoadRampUp(int userLoad, long rampUpMillis, long peakMillis) {
this.userload = userLoad;
this.rampup = rampUpMillis;
this.peak = peakMillis;
this.plateauVus = userLoad;
this.rampUpMs = rampUpMillis;
this.plateauMs = peakMillis;
}

public static UserLoadRampUp fromThreadGroup(ThreadGroup threadGroup) {
Expand All @@ -85,6 +77,39 @@ public static UserLoadRampUp fromThreadGroup(ThreadGroup threadGroup) {

}

@JsonTypeInfo(use = NAME, include = PROPERTY)
@JsonTypeName("JmeterUserProfileEngine")
public static class Engine {

private final EngineSettings settings = new EngineSettings();
private final BrowserSettings browser = new BrowserSettings();
private final BandwidthSettings bandwidth = new BandwidthSettings();
private final DnsSettings dns = new DnsSettings();
private final JtlSettings jtl = new JtlSettings();
private final PropertiesSettings properties = new PropertiesSettings();

}

public static class EngineSettings {

private final ExternalLiveReportingSettings externalLiveReporting =
new ExternalLiveReportingSettings();
private final SampleErrorAction errorHandling = SampleErrorAction.CONTINUE;
private final ThinkTimeSettings thinkTime = new ThinkTimeSettings();
private final SetUpTearDownSettings setUp = null;
private final SetUpTearDownSettings tearDown = null;

}

@JsonTypeInfo(use = NAME, include = PROPERTY)
@JsonTypeName("JmeterExternalLiveReportingSettings")
public static class ExternalLiveReportingSettings {

private final List<String> listeners = Collections.emptyList();
private final int queueSize = 5000;

}

public static class SetUpTearDownSettings {

}
Expand All @@ -102,6 +127,8 @@ public static class BrowserSettings {
private final String userAgent = "";
private final CacheManager cache = new CacheManager();
private final CookiesManager cookies = new CookiesManager();
private final Boolean downloadResources = null;
private final Boolean keepAlive = null;

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import static us.abstracta.jmeter.javadsl.JmeterDsl.threadGroup;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import us.abstracta.jmeter.javadsl.core.TestPlanStats;

Expand Down
44 changes: 44 additions & 0 deletions jmeter-java-dsl-websocket/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>us.abstracta.jmeter</groupId>
<artifactId>jmeter-java-dsl-parent</artifactId>
<version>2.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>jmeter-java-dsl-websocket</artifactId>

<dependencies>
<dependency>
<groupId>us.abstracta.jmeter</groupId>
<artifactId>jmeter-java-dsl</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>net.luminis.jmeter</groupId>
<artifactId>jmeter-websocket-samplers</artifactId>
<version>1.3.1</version>
<exclusions>
<exclusion>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.jmeter</groupId>
<artifactId>jorphan</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.6.0</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Loading