Commit graph

7 commits

Author SHA1 Message Date
917225c994 chore: create test/load/results/ directory for load test reports
Some checks failed
ci / vet + build (push) Failing after 4m50s
ci / race tests (push) Has been skipped
ci / WebRTC smoke (5-viewer fanout) (push) Has been skipped
ci / WebRTC latency p95 gate (push) Has been skipped
2026-05-06 16:04:13 -04:00
561a93e044 feat(test): add 5-peer sustained WHEP load test (closes #14)
Some checks failed
ci / race tests (push) Blocked by required conditions
ci / WebRTC smoke (5-viewer fanout) (push) Blocked by required conditions
ci / WebRTC latency p95 gate (push) Blocked by required conditions
ci / vet + build (push) Has been cancelled
2026-05-06 16:01:22 -04:00
b7afd0f08a ci(webrtc): server-hop latency p95 gate
Some checks failed
ci / vet + build (push) Successful in 9m54s
ci / vet + build (pull_request) Successful in 9m49s
ci / race tests (push) Failing after 8m1s
ci / WebRTC smoke (5-viewer fanout) (push) Successful in 9m45s
ci / WebRTC latency p95 gate (push) Successful in 10m3s
ci / race tests (pull_request) Failing after 7m59s
ci / WebRTC smoke (5-viewer fanout) (pull_request) Successful in 9m45s
ci / WebRTC latency p95 gate (pull_request) Successful in 10m4s
Adds an end-to-end RTP-arrival latency probe that runs as a dedicated
CI job and asserts p95 < 50ms.

Implementation
--------------
A build-tagged test (-tags latency, off by default) sends 1000
synthetic RTP packets at 60Hz into corewebrtc.Source and reads them
back via a Pion subscriber's track.ReadRTP(). Each packet's payload
starts with the publisher's UnixNano send time; the subscriber diffs
against time.Now() at arrival and accumulates p50/p95/p99.

This exercises every link of the egress hop: Source UDP read,
subscriber fan-out, forwardRTPSplit, Pion's TrackLocalStaticRTP
write, DTLS-SRTP encrypt, ICE socket write, decrypt at the
subscriber, RTP unmarshal at ReadRTP. Pure server-side; no FFmpeg
or codecs involved.

Why not glass-to-glass
----------------------
The design's §7 calls for FFmpeg drawtext frame counters + decode-
side pixel sampling, p95<300ms RTMP / <200ms SRT. Implementing that
in pure Go needs a cgo H.264 decoder or an FFmpeg sidecar pipe — a
significantly bigger lift for a marginal regression-detection win
(encode/decode latency is roughly fixed by the codec stack and
isn't moved by Core code changes). The server-hop measurement
captures everything Core code can actually regress.

Threshold
---------
50ms p95. Locally observed on a quiet host:
  p50=110µs, p95=237µs, p99=318µs.
The 50ms gate is ~200x headroom — generous enough to absorb CI
runner noise without false alarms, tight enough to catch a real
slowdown.

Race-clean: latencySamples uses a sync.Mutex around the slice append
(initial draft had a slice racing with the receive goroutine; vet
caught it).

Documented in test/TESTING.md and wired to .forgejo/workflows/test.yml
as the latency-gate job (depends on lint-and-vet, parallel with test
and webrtc-smoke).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 12:18:57 +00:00
927ccc6ced ci+test: forgejo workflow, browser WHEP player, TESTING.md (M4 part 1)
Some checks failed
ci / vet + build (push) Successful in 9m50s
ci / vet + build (pull_request) Successful in 9m49s
ci / race tests (push) Failing after 8m4s
ci / WebRTC smoke (5-viewer fanout) (push) Successful in 9m48s
ci / race tests (pull_request) Failing after 6m28s
ci / WebRTC smoke (5-viewer fanout) (pull_request) Successful in 9m46s
Three artifacts that close out the easier half of the M4 milestone:

1. .forgejo/workflows/test.yml — CI on every push and PR. Three jobs:
     - lint-and-vet: go vet + go build (~30s)
     - test:        go test -race -short ./... + a no-race coverage
                    pass that uploads coverage.out as an artifact
     - webrtc-smoke: TestIntegration_FiveViewerFanout and the rest of
                     the WebRTC subsystem tests in isolation, so a
                     failure on the egress path stays readable in the
                     log.
   Pinned to Go 1.24 to match go.mod. The forge has a
   forgejo-runner sibling container; this YAML uses GitHub Actions
   syntax which Forgejo Actions accepts unchanged.

2. test/whep-player.html — self-contained browser WHEP subscriber for
   manual smoke testing. RTCPeerConnection (recvonly V+A) + fetch()
   POST/DELETE/PATCH against /api/v3/whep/:id, ICE/PC state pills,
   inbound-bitrate sampling at 1 Hz, codec hint pulled from the answer
   SDP, JWT token field, ?url=&token= shareable query string. No
   external deps; works from file:// or any static host.

3. test/TESTING.md — short doc that ties together the in-process race
   tests, the browser player, and the existing Pion CLI helper at
   test/whep-client/. Notes the latency p95 gate as a follow-up.

Latency gate (FFmpeg drawtext frame counter + decode-side pixel
sampling, p95 < 300ms RTMP / < 200ms SRT) is queued for a separate
PR — it's a several-hundred-line addition in its own right and
shouldn't block CI from landing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 12:14:43 +00:00
0417aff3b1 test(whep-client): add -token flag for JWT-gated /api/v3/whep endpoints
Some checks failed
tests / build (push) Failing after 2s
CodeQL / Analyze (pull_request) Failing after 2s
tests / build (pull_request) Failing after 1s
The M2 WHEP route lives under /api/v3 and inherits Core's JWT auth.
The M1 test client was written for the unauth'd PoC port; without
this flag it's useless against the real Core build.

- Subscribe() and postOffer() take a token string; empty means no
  Authorization header (M1 behavior preserved).
- main.go gains a -token flag.
- main_test.go pass empty token (existing tests run against an
  in-process unauth'd handler).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 04:59:08 +00:00
413d0f24b6 test(webrtc): add Pion WHEP subscriber client + e2e test
Some checks failed
tests / build (push) Failing after 13s
CodeQL / Analyze (pull_request) Failing after 2s
tests / build (pull_request) Failing after 2s
whep-client/main.go: minimal Pion subscriber that POSTs a recvonly
offer, applies the answer, and waits for one RTP packet on each of
the video and audio tracks. Used as M1's end-to-end verifier.

whep-client/main_test.go: in-process e2e wiring — stands up Source,
Registry, PeerFactory and WHEPHandler behind an httptest server,
injects synthetic PT=102/111 RTP on the Source's UDP port and calls
Subscribe. Validates the full egress pipeline without requiring
FFmpeg or external network. Skipped under -short.
2026-04-17 08:52:40 -04:00
e471bd02b2 test(webrtc): add FFmpeg publisher script for M1 PoC
Generates a synthetic testsrc2 video + sine audio and pushes H.264/Opus
RTP to the webrtc-poc's UDP port, using the hard-coded payload types
(102 video, 111 audio) the M1 forwarder dispatches on. Intended to be
run alongside test/whep-client (M1 Task 11) for end-to-end verification.
2026-04-17 08:51:22 -04:00