Testing Guide#

Running Tests#

All Tests#

go test ./...

All Tests with Race Detector#

go test -race ./...

The race detector is mandatory for CI. It catches data races that would otherwise be invisible.

Package-Level Tests#

Run tests for a specific protocol layer:

go test ./internal/rtmp/handshake/    # Handshake FSM
go test ./internal/rtmp/chunk/        # Chunk reader/writer
go test ./internal/rtmp/amf/          # AMF0 codec
go test ./internal/rtmp/control/      # Control messages
go test ./internal/rtmp/rpc/          # Command dispatch
go test ./internal/rtmp/conn/         # Connection lifecycle
go test ./internal/rtmp/server/       # Server integration
go test ./internal/rtmp/server/auth/  # Authentication
go test ./internal/rtmp/server/hooks/ # Event hooks
go test ./internal/rtmp/media/        # Media handling + recording
go test ./internal/rtmp/relay/        # Multi-destination relay
go test ./internal/rtmp/metrics/      # Expvar counters
go test ./internal/errors/            # Error types

Integration Tests#

go test ./tests/integration/ -count=1

The -count=1 flag disables test caching, ensuring tests always run fresh.

Golden Binary Vectors#

Golden vectors live in tests/golden/ as .bin files. Each file contains exact wire-format bytes for a specific protocol element:

  • Handshake packets — C0, C1, S0, S1, C2, S2
  • Chunk headers — FMT 0-3, various CSIDs, extended timestamps
  • AMF0 values — Number, Boolean, String, Object, Null, Array
  • Control messages — Set Chunk Size, Window Ack Size, Abort, etc.

Tests read these files and verify that:

  1. Decoding the bytes produces the expected Go values
  2. Encoding the Go values produces the exact same bytes

This catches endianness bugs, off-by-one errors, missing fields, and encoding mistakes.

Regenerating Golden Vectors#

If you change a wire format (rare), regenerate the golden files:

go run tests/golden/gen_*.go

Warning: Only regenerate vectors if you intentionally changed the wire format. Accidentally regenerating them will mask bugs.

Static Analysis#

go vet ./...     # Static analysis
gofmt -l .       # Check formatting (should print nothing)

Manual Interop Testing#

For end-to-end validation with real RTMP clients:

Basic Publish/Subscribe#

Start the server:

go run ./cmd/rtmp-server -listen localhost:1935 -log-level debug

Publish a stream:

ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost:1935/live/test

Subscribe in another terminal:

ffplay rtmp://localhost:1935/live/test

Late-Join Test#

This verifies that sequence header caching works:

  1. Start the server
  2. Start publishing: ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost:1935/live/test
  3. Wait 10 seconds for several keyframe cycles to pass
  4. Start subscribing: ffplay rtmp://localhost:1935/live/test
  5. Expected: Video should appear immediately (within 1-2 seconds), not after a long black screen

If the subscriber sees a black screen for more than a few seconds, sequence header caching may be broken.

Enhanced RTMP (H.265) Test#

# Requires FFmpeg 6.1+ with libx265
./scripts/test-enhanced-rtmp.sh

This verifies H.265/HEVC publishing via Enhanced RTMP, recording, and codec detection.

Relay Test#

Test multi-destination relay between two servers:

Terminal 1 — origin server:

go run ./cmd/rtmp-server -listen localhost:1935 -relay-to rtmp://localhost:1936/live

Terminal 2 — edge server:

go run ./cmd/rtmp-server -listen localhost:1936

Terminal 3 — publish to origin:

ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost:1935/live/test

Terminal 4 — subscribe from edge:

ffplay rtmp://localhost:1936/live/test

E2E Testing Scripts#

The scripts/ directory contains cross-platform E2E test scripts that validate the full streaming pipeline using FFmpeg, ffplay, and the go-rtmp server.

Running the Full Suite#

Linux/macOS:

./scripts/run-all-tests.sh

Windows (PowerShell):

.\scripts\run-all-tests.ps1

Test Cases#

TestValidates
RTMP Publish + CaptureBasic publish → capture → ffprobe verify
RTMPS Publish + CaptureTLS connection with dual listener
RTMP + HLS via HookPublish hook triggers FFmpeg → HLS conversion
RTMPS + HLS via HookTLS transport with hook-based HLS
RTMP + Auth (allowed)Token auth with valid credentials
RTMP + Auth (rejected)Token auth rejects invalid/missing credentials
RTMPS + AuthTLS + authentication combined

Each test starts its own server instance on a unique port, runs the scenario, and cleans up on exit.

Prerequisites#

Run scripts/check-deps.sh (or .ps1 on Windows) to verify that FFmpeg, ffplay, ffprobe, and the go-rtmp binary are available.

For full documentation on the scripts, see the E2E Testing Guide.

Test Coverage Map#

AreaTest FilesWhat’s Verified
Handshakehandshake/*_test.goState machine transitions, C0/C1/C2 byte format, timeout handling
Chunkschunk/*_test.goFMT 0-3 encoding/decoding, extended timestamps, message reassembly
AMF0amf/*_test.goAll type markers, object end sentinel, round-trip encoding
Controlcontrol/*_test.goSet Chunk Size, Window Ack, Abort, Set Peer Bandwidth
RPCrpc/*_test.goconnect, createStream, publish, play command parsing
Connectionconn/*_test.goFull handshake + command flow over net.Pipe
Serverserver/*_test.goRegistry, pub/sub fan-out, disconnect cleanup
Authserver/auth/*_test.goToken validation, file-based auth, callback auth
Hooksserver/hooks/*_test.goWebhook delivery, shell execution, stdio format
Mediamedia/*_test.goAudio/video parsing, codec detection (incl. Enhanced RTMP), FLV writing
Relayrelay/*_test.goDestination management, reconnection, late-join
Integrationtests/integration/*_test.goEnd-to-end publish/subscribe through full stack
E2E Scriptsscripts/test-e2e.*Full pipeline: publish, capture, HLS hooks, auth, TLS