Skip to content

test(turn): add Coturn relay-path load test - #83

Open
Harxhit wants to merge 1 commit into
mainfrom
test/turn-relay-load
Open

test(turn): add Coturn relay-path load test#83
Harxhit wants to merge 1 commit into
mainfrom
test/turn-relay-load

Conversation

@Harxhit

@Harxhit Harxhit commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Puppeteer test that forces iceTransportPolicy:"relay" so all viewer media flows through Coturn, verifies relay use via getStats candidateType, and ramps viewers to find the TURN relay ceiling — untested until now.

  • load-test/turn-relay-load.js — forces + verifies relay; per-batch CSV
  • load-test/results/TURN-RELAY-LOAD.md — how relay is forced/verified, Coturn sampling

Authored by Claude (Anthropic) via Claude Code. Not executed against a live backend — results are placeholders, not fabricated.


Summary by cubic

Adds a relay-path load test that forces every viewer's media through Coturn and verifies the relay is actually used, closing the gap where the existing SFU capacity test never exercised Coturn on a LAN.

Test mechanics

  • Subclasses RTCPeerConnection to merge iceTransportPolicy: "relay" into the app's config — no frontend or backend changes.
  • Confirms relay use per viewer by checking the succeeded candidate-pair's local candidate has candidateType === 'relay'.
  • Ramps viewers in batches and writes a per-batch CSV with relay-confirmed count, bitrate, loss, fps, join latency percentiles, and failures.
  • load-test/results/TURN-RELAY-LOAD.md documents how relay is forced and verified, plus Coturn-side sampling commands.

Not yet run against a live backend — results in the markdown are placeholders, not fabricated. Credentials are passed via flags or environment variables, never hardcoded.

Written for commit f7ec67f. Summary will update on new commits.

Review in cubic

Puppeteer test that forces iceTransportPolicy:"relay" so all viewer media flows
through Coturn, verifies relay use via getStats candidateType, and ramps viewers
to find the TURN relay ceiling — untested until now.

- load-test/turn-relay-load.js — forces + verifies relay; per-batch CSV
- load-test/results/TURN-RELAY-LOAD.md — how relay is forced/verified, Coturn sampling

Authored by Claude (Anthropic) via Claude Code. Not executed against a live
backend — results are placeholders, not fabricated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ee95f9b-3aa6-4862-9f2d-df4c7a634c8d


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="load-test/turn-relay-load.js">

<violation number="1" location="load-test/turn-relay-load.js:304">
P0: After sign-in, `window.__csSocket` is never populated, so `login()` always times out before launching the broadcaster or any viewer. Wait on the app's actual readiness signal or add an explicit test hook.</violation>

<violation number="2" location="load-test/turn-relay-load.js:358">
P0: After the Go live click, the application never sets `window.__csRoomId`, so `launchBroadcaster()` times out before creating viewers. Read the returned/rendered room ID or add an explicit test hook.</violation>

<violation number="3" location="load-test/turn-relay-load.js:425">
P1: The viewer page never sets either timing global, so every successful join is reported as a failure after up to 40 seconds of unnecessary waiting. Add timing hooks in the app or wait for observable socket/video readiness and record timestamps from those events.</violation>

<violation number="4" location="load-test/turn-relay-load.js:527">
P2: When `maxViewers` is not a multiple of `batchSize`, the test under-loads the requested ceiling or runs zero viewers. Size the final batch from the remaining `MAX_VIEWERS - viewers.length` capacity.</violation>
</file>

<file name="load-test/results/TURN-RELAY-LOAD.md">

<violation number="1" location="load-test/results/TURN-RELAY-LOAD.md:7">
P3: This doc points readers at `load-test/sfu-capacity.js` (roadmap claim on line 7 and prerequisite on line 76), but no such file exists in the repository — `git ls-files load-test/` contains only `signaling-latency.js` and `turn-relay-load.js`. A reader cannot find the referenced test, and the claim that the media plane is already exercised by it is misleading. Reference the actual existing load test (`signaling-latency.js`) or remove the claim that a media-plane test exists.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

console.log('Clicked "Go live".');

await page.waitForFunction(
() => Boolean(window.__csRoomId),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0: After the Go live click, the application never sets window.__csRoomId, so launchBroadcaster() times out before creating viewers. Read the returned/rendered room ID or add an explicit test hook.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/turn-relay-load.js, line 358:

<comment>After the Go live click, the application never sets `window.__csRoomId`, so `launchBroadcaster()` times out before creating viewers. Read the returned/rendered room ID or add an explicit test hook.</comment>

<file context>
@@ -0,0 +1,666 @@
+  console.log('Clicked "Go live".');
+
+  await page.waitForFunction(
+    () => Boolean(window.__csRoomId),
+    { timeout: WAIT_TIMEOUT_MS }
+  );
</file context>


await page.waitForFunction(
() =>
window.__csSocket &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0: After sign-in, window.__csSocket is never populated, so login() always times out before launching the broadcaster or any viewer. Wait on the app's actual readiness signal or add an explicit test hook.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/turn-relay-load.js, line 304:

<comment>After sign-in, `window.__csSocket` is never populated, so `login()` always times out before launching the broadcaster or any viewer. Wait on the app's actual readiness signal or add an explicit test hook.</comment>

<file context>
@@ -0,0 +1,666 @@
+
+  await page.waitForFunction(
+    () =>
+      window.__csSocket &&
+      window.__csSocket.connected === true,
+    { timeout: WAIT_TIMEOUT_MS }
</file context>

let joinedAt = null;
try {
await page.waitForFunction(
() => Boolean(window.__csJoinedAt),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The viewer page never sets either timing global, so every successful join is reported as a failure after up to 40 seconds of unnecessary waiting. Add timing hooks in the app or wait for observable socket/video readiness and record timestamps from those events.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/turn-relay-load.js, line 425:

<comment>The viewer page never sets either timing global, so every successful join is reported as a failure after up to 40 seconds of unnecessary waiting. Add timing hooks in the app or wait for observable socket/video readiness and record timestamps from those events.</comment>

<file context>
@@ -0,0 +1,666 @@
+    let joinedAt = null;
+    try {
+      await page.waitForFunction(
+        () => Boolean(window.__csJoinedAt),
+        { timeout: WAIT_TIMEOUT_MS }
+      );
</file context>

console.log("========================================");

const batch = await Promise.all(
Array.from({ length: BATCH_SIZE }, (_, i) =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When maxViewers is not a multiple of batchSize, the test under-loads the requested ceiling or runs zero viewers. Size the final batch from the remaining MAX_VIEWERS - viewers.length capacity.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/turn-relay-load.js, line 527:

<comment>When `maxViewers` is not a multiple of `batchSize`, the test under-loads the requested ceiling or runs zero viewers. Size the final batch from the remaining `MAX_VIEWERS - viewers.length` capacity.</comment>

<file context>
@@ -0,0 +1,666 @@
+      console.log("========================================");
+
+      const batch = await Promise.all(
+        Array.from({ length: BATCH_SIZE }, (_, i) =>
+          launchViewer(browser, roomId, viewers.length + i)
+        )
</file context>


## Roadmap gap this closes

CrowdStream's media plane is exercised end-to-end by `load-test/sfu-capacity.js`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This doc points readers at load-test/sfu-capacity.js (roadmap claim on line 7 and prerequisite on line 76), but no such file exists in the repository — git ls-files load-test/ contains only signaling-latency.js and turn-relay-load.js. A reader cannot find the referenced test, and the claim that the media plane is already exercised by it is misleading. Reference the actual existing load test (signaling-latency.js) or remove the claim that a media-plane test exists.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/results/TURN-RELAY-LOAD.md, line 7:

<comment>This doc points readers at `load-test/sfu-capacity.js` (roadmap claim on line 7 and prerequisite on line 76), but no such file exists in the repository — `git ls-files load-test/` contains only `signaling-latency.js` and `turn-relay-load.js`. A reader cannot find the referenced test, and the claim that the media plane is already exercised by it is misleading. Reference the actual existing load test (`signaling-latency.js`) or remove the claim that a media-plane test exists.</comment>

<file context>
@@ -0,0 +1,219 @@
+
+## Roadmap gap this closes
+
+CrowdStream's media plane is exercised end-to-end by `load-test/sfu-capacity.js`,
+but that test lets each client pick its cheapest ICE path — on a LAN that is
+almost always a **host** or **server-reflexive** candidate, so the SFU talks to
</file context>
Suggested change
CrowdStream's media plane is exercised end-to-end by `load-test/sfu-capacity.js`,
CrowdStream's media plane is not currently exercised end-to-end by any load test; the only existing load test is `load-test/signaling-latency.js`,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant