Skip to content

Commit 54f588a

Browse files
committed
loadtest-controller: add HTML output
1 parent 2742e71 commit 54f588a

21 files changed

Lines changed: 1484 additions & 55 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,5 @@ browser-emulator/qoe_scripts/__pycache__/
6262
browser-emulator/.awsconfig/
6363

6464
docker/browser-emulator/browser-emulator/
65+
66+
report.html

AGENTS.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ When implementing changes in this repository, agents MUST follow these rules:
150150

151151
- **Browser-emulator changes**: Run `pnpm run test:unit` and `pnpm run test:integration` after modifications
152152
- **Loadtest-controller changes**: Run `mvn test` after Java modifications
153-
- **E2E affecting changes**: Run the smoke test via `./e2e-tests/scripts/run-smoke-test.sh`
154153

155154
### 2. Lint Requirements (Browser-emulator only)
156155

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ The docker compose file will start two services:
7777
- **Browser-emulator**: The worker that launches Chrome browsers to connect to rooms
7878
- **Loadtest-controller**: Orchestrates the test by coordinating the browser-emulator
7979

80-
OpenVidu loadtest will execute the test cases and output results at `results/results.txt`.
80+
OpenVidu loadtest will execute the test cases and output results at `results/results.html`, you can open this file in a browser to see the results. You can also check the console output for real-time logs.
8181

8282
For more detailed instructions on how to configure tests, see [Configuration](#configuration).
8383

@@ -265,6 +265,14 @@ Performance and retry settings.
265265
| `advanced.batches.maxConcurrentRequests` | No | `CPU cores + 1` | Max concurrent requests when in batch mode |
266266
| `advanced.waitForCompletion` | No | `true` | Wait for all participants in the batch to confirm insertion into the platform before inserting the next batch. Will wait for individual participants if `batches: false` |
267267

268+
### Report Output Configuration
269+
270+
Control which output formats are generated after test completion.
271+
272+
| Property | Required | Default | Description |
273+
| ----------------------- | -------- | ------- | ----------------------------------------- |
274+
| `advanced.reportOutput` | No | `html` | Comma-separated list: `html` and/or `txt` |
275+
268276
### Environment Variables
269277

270278
All configuration values can be set via environment variables. Environment variables take precedence over config file values. Any configuration value can be overridden by an environment variable. Some examples are:

e2e-tests/README.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ Where:
3333
- `PLATFORM_APIKEY`: Optional. API key for authentication (defaults to "devkey")
3434
- `PLATFORM_APISECRET`: Optional. API secret for authentication (defaults to "secret")
3535

36+
### Configuration File
37+
38+
The smoke test uses the configuration file `config/smoke-test-config.yaml` which specifies `advanced.reportOutput: html,txt` to generate both text and HTML reports.
39+
3640
### Running the Smoke Test
3741

3842
```bash
@@ -59,12 +63,16 @@ The test should:
5963
- Start both loadtest-controller and browser-emulator services
6064
- Launch 2 Chrome browsers that connect to the OpenVidu instance
6165
- Create a single session with 2 participants in N:N topology
62-
- Generate results in the `results/` directory
66+
- Generate results in the `results/` directory:
67+
- `results.txt` (text summary)
68+
- `report.html` (HTML report, with user retry details if retries occurred)
6369
- Complete successfully and shut down cleanly
6470

6571
### Validation Checks
6672

67-
The smoke test validates that the results.txt file contains:
73+
The smoke test validates that both `results.txt` and `report.html` files are generated and contain expected content.
74+
75+
**results.txt validation:**
6876

6977
- "Test Case Report"
7078
- "Number of sessions created: 1"
@@ -73,6 +81,17 @@ The smoke test validates that the results.txt file contains:
7381
- "User start times:"
7482
- User start time lines in the format: "Day Mon DD HH:MM:SS TZ YYYY | LoadTestSessionX | UserY"
7583

84+
**report.html validation:**
85+
86+
- "OpenVidu Load Test Report"
87+
- "Sessions Created"
88+
- "Total Participants"
89+
- "User Connections" (mandatory)
90+
- Table columns: User, Session, Join date (from successful connection), Disconnect Date (captured from ParticipantDisconnected websocket event), Retry Number (count of retries per user)
91+
- Two user rows (User1 and User2) present
92+
93+
The smoke test configuration uses `advanced.reportOutput: html,txt` to generate both output formats. If validation fails, the result files are kept in the `results/` directory for debugging.
94+
7695
## Extending the Test Suite
7796

7897
Additional test scenarios can be added by:

e2e-tests/config/smoke-test-config.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ workers:
1010
urls: browser-emulator
1111

1212
distribution:
13-
usersPerWorker: 2
13+
usersPerWorker: 2
14+
15+
advanced:
16+
reportOutput: html,txt

e2e-tests/docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ services:
3131
restart: unless-stopped
3232
environment:
3333
RUNNING_IN_DOCKER: true
34-
DOCKER_NETWORK_NAME: browseremulator
34+
DOCKER_NETWORK_NAME: browseremulator-e2e
3535
DOCKER_BROWSER_EMULATOR_HOST: browser-emulator
3636
MEDIAFILES_HOST_DIR: ${MEDIAFILES_HOST_DIR:-${PWD}/../../browser-emulator/mediafiles}
3737
SCRIPTS_LOGS_HOST_DIR: ${SCRIPTS_LOGS_HOST_DIR:-${PWD}/../../browser-emulator/logs}
@@ -47,4 +47,4 @@ services:
4747

4848
networks:
4949
browseremulator:
50-
name: browseremulator
50+
name: browseremulator-e2e

e2e-tests/scripts/run-smoke-test.sh

Lines changed: 94 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
set -e # Exit on any error
99

1010
echo "Starting OpenVidu Load Test Smoke Test..."
11+
EXIT_CODE=0
1112

12-
# Check if docker-compose is available
13-
if ! command -v docker-compose &> /dev/null; then
14-
echo "docker-compose not found. Please install docker-compose."
13+
# Check if docker compose is available
14+
if ! command -v docker compose &> /dev/null; then
15+
echo "docker compose not found. Please install docker compose."
1516
exit 1
1617
fi
1718

@@ -33,25 +34,24 @@ E2E_TEST_DIR="$(dirname "$(realpath "$0")")/.."
3334
export LOCAL_CONFIG_DIR="$E2E_TEST_DIR/config"
3435
export LOCAL_RESULTS_DIR="$E2E_TEST_DIR/results"
3536
export LOADTEST_CONFIG="/config/smoke-test-config.yaml"
36-
3737
# Start services
38-
echo "Starting services with docker-compose..."
39-
docker-compose up --build -d
38+
echo "Starting services with docker compose..."
39+
docker compose up --build -d
4040

4141
MAX_WAIT=120
4242
ELAPSED=0
4343
while [ $ELAPSED -lt $MAX_WAIT ]; do
44-
# Check if loadtest-controller has finished (results file exists)
45-
if [ -f "$LOCAL_RESULTS_DIR/results.txt" ]; then
46-
echo "Results file found. Test appears to be complete."
44+
# Check if loadtest-controller has finished (results and HTML report exist)
45+
if [ -f "$LOCAL_RESULTS_DIR/results.txt" ] && [ -f "$LOCAL_RESULTS_DIR/report.html" ]; then
46+
echo "Results and HTML report found. Test appears to be complete."
4747
break
4848
fi
4949

5050
# Check if containers are still running
51-
RUNNING_CONTAINERS=$(docker-compose ps -q)
51+
RUNNING_CONTAINERS=$(docker compose ps -q)
5252
if [ -z "$RUNNING_CONTAINERS" ]; then
5353
echo "No running containers found. Something went wrong."
54-
docker-compose logs
54+
docker compose logs
5555
exit 1
5656
fi
5757

@@ -62,13 +62,14 @@ done
6262

6363
if [ $ELAPSED -ge $MAX_WAIT ]; then
6464
echo "Timeout waiting for test to complete after $MAX_WAIT seconds."
65-
docker-compose ps
66-
docker-compose logs
65+
docker compose ps
66+
docker compose logs
6767
fi
6868

6969
# Stop services
70+
docker compose logs > $LOCAL_RESULTS_DIR/docker-compose.log 2>&1
7071
echo "Stopping services..."
71-
docker-compose down
72+
docker compose down
7273

7374
# Check results
7475
echo "Checking test results..."
@@ -120,29 +121,96 @@ docker-compose down
120121
VALIDATION_PASSED=false
121122
fi
122123

123-
# Check for user start time lines (pattern: Day Mon DD HH:MM:SS TZ YYYY | LoadTestSession | UserX)
124-
# Using a more flexible pattern that matches the expected format
125-
if grep -E "[A-Za-z]{3} [A-Za-z]{3} [0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} [A-Z]+ [0-9]{4} \| LoadTestSession[0-9]+ \| User[0-9]+" "$LOCAL_RESULTS_DIR/results.txt"; then
124+
# Check for user start time lines (pattern: Day Mon DD HH:MM:SS TZ YYYY | session | user)
125+
# Using a flexible pattern that matches any session/user values (including empty)
126+
if grep -E "[A-Za-z]{3} [A-Za-z]{3} [0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} [A-Z]+ [0-9]{4} \\| [^|]* \\| [^|]*" "$LOCAL_RESULTS_DIR/results.txt"; then
126127
echo "✓ Found user start time lines matching expected pattern"
127128
else
128129
echo "✗ Missing user start time lines matching expected pattern (e.g., 'Fri Mar 20 12:53:18 GMT 2026 | LoadTestSession1 | User1')"
129130
VALIDATION_PASSED=false
130131
fi
131132

132-
if [ "$VALIDATION_PASSED" = true ]; then
133+
# HTML report validation
134+
HTML_VALIDATION_PASSED=true
135+
HTML_FILE="$LOCAL_RESULTS_DIR/report.html"
136+
if [ -f "$HTML_FILE" ]; then
137+
echo "✓ HTML report found"
138+
139+
# Check for basic HTML structure
140+
if grep -q "OpenVidu Load Test Report" "$HTML_FILE"; then
141+
echo "✓ HTML contains 'OpenVidu Load Test Report'"
142+
else
143+
echo "✗ HTML missing 'OpenVidu Load Test Report'"
144+
HTML_VALIDATION_PASSED=false
145+
fi
146+
147+
# Check for sessions created
148+
if grep -q "Sessions Created" "$HTML_FILE"; then
149+
echo "✓ HTML contains 'Sessions Created'"
150+
else
151+
echo "✗ HTML missing 'Sessions Created'"
152+
HTML_VALIDATION_PASSED=false
153+
fi
154+
155+
# Check for total participants
156+
if grep -q "Total Participants" "$HTML_FILE"; then
157+
echo "✓ HTML contains 'Total Participants'"
158+
else
159+
echo "✗ HTML missing 'Total Participants'"
160+
HTML_VALIDATION_PASSED=false
161+
fi
162+
163+
# Check for User Connections section (mandatory)
164+
if grep -q "User Connections" "$HTML_FILE"; then
165+
echo "✓ HTML contains 'User Connections'"
166+
# Check for new column headers
167+
if grep -q "Join date" "$HTML_FILE" && grep -q "Disconnect Date" "$HTML_FILE" && grep -q "Retry Number" "$HTML_FILE"; then
168+
echo "✓ HTML contains new table columns"
169+
# Check for two user rows (User1 and User2)
170+
if grep -q "User1" "$HTML_FILE" && grep -q "User2" "$HTML_FILE"; then
171+
echo "✓ HTML contains two user rows"
172+
else
173+
echo "✗ HTML missing user rows (expected User1 and User2)"
174+
HTML_VALIDATION_PASSED=false
175+
fi
176+
else
177+
echo "✗ HTML missing new table columns"
178+
HTML_VALIDATION_PASSED=false
179+
fi
180+
else
181+
echo "✗ HTML missing 'User Connections'"
182+
HTML_VALIDATION_PASSED=false
183+
fi
184+
185+
# HTML file will be deleted later if validation passes
186+
else
187+
echo "✗ HTML report not found at $HTML_FILE"
188+
HTML_VALIDATION_PASSED=false
189+
fi
190+
191+
# Combine validation results
192+
if [ "$VALIDATION_PASSED" = true ] && [ "$HTML_VALIDATION_PASSED" = true ]; then
133193
echo "SUCCESS: All validation checks passed."
134194
else
135195
echo "FAILURE: One or more validation checks failed."
196+
EXIT_CODE=1
136197
fi
137198

138-
# Delete results file after reading
139-
echo "Deleting results file..."
140-
rm -f "$LOCAL_RESULTS_DIR/results.txt"
199+
# Delete result files only if validation passed
200+
if [ $EXIT_CODE -eq 0 ]; then
201+
echo "Deleting result files..."
202+
rm -f "$LOCAL_RESULTS_DIR/results.txt"
203+
rm -f "$HTML_FILE"
204+
rm -f "$LOCAL_RESULTS_DIR/docker-compose.log"
205+
else
206+
echo "Keeping result files for debugging. Remember to remove them manually before re-running the test."
207+
fi
141208
else
142-
echo "ERROR: Results file not found at $LOCAL_RESULTS_DIR/results.txt"
143-
exit 1
209+
echo "ERROR: Results file or HTML report not found at $LOCAL_RESULTS_DIR/results.txt or report.html"
210+
EXIT_CODE=1
144211
fi
145212

146-
echo "Smoke test completed successfully!"
147-
148-
exit 0
213+
if [ $EXIT_CODE -eq 0 ]; then
214+
echo "Smoke test completed successfully!"
215+
fi
216+
exit $EXIT_CODE

loadtest-controller/src/main/java/io/openvidu/loadtest/config/LoadTestConfig.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ protected LoadTestConfig(Environment env) {
9292

9393
private int retryTimes;
9494

95+
private List<String> reportOutput = new ArrayList<>(Arrays.asList("html"));
96+
9597
private boolean qoeAnalysisRecordings;
9698

9799
private boolean qoeAnalysisInSitu;
@@ -263,6 +265,16 @@ public int getRetryTimes() {
263265
return retryTimes;
264266
}
265267

268+
269+
270+
public List<String> getReportOutput() {
271+
return reportOutput;
272+
}
273+
274+
public void setReportOutput(List<String> reportOutput) {
275+
this.reportOutput = reportOutput;
276+
}
277+
266278
public boolean isQoeAnalysisRecordings() {
267279
return qoeAnalysisRecordings;
268280
}
@@ -436,6 +448,12 @@ private void initBatchAndMiscConfig() {
436448
batches = !Boolean.FALSE.equals(batchesEnabled);
437449
Boolean waitCompleteEnabled = yamlConfig.getBooleanOrNull("advanced.waitForCompletion");
438450
waitCompletion = !Boolean.FALSE.equals(waitCompleteEnabled);
451+
// Parse report output list
452+
List<String> reportOutputList = asOptionalStringList("advanced.reportOutput");
453+
if (!reportOutputList.isEmpty()) {
454+
reportOutput = reportOutputList;
455+
}
456+
// default reportOutput already initialized to ["html"]
439457
}
440458

441459
private String defaultIfEmpty(String value, String defaultValue) {

0 commit comments

Comments
 (0)