Add a scenario
A scenario is one JSON file. You write the conversation once, capture the C server's answers, commit the normalised trace, and from then on CI checks the Rust server gives the same answers.
1. Write the file
parity/scenarios/my-videoroom.json:
{
"scenario": "my-videoroom",
"description": "VideoRoom exists and list on the demo room, and the error for a room that is not there",
"steps": [
{"step": "create", "request": {"janus": "create", "transaction": "x"},
"expect": "success", "save": {"session": "data.id"}},
{"step": "attach", "path": "/janus/{session}",
"request": {"janus": "attach", "plugin": "janus.plugin.videoroom", "transaction": "y"},
"expect": "success", "save": {"handle": "data.id"}},
{"step": "exists", "path": "/janus/{session}/{handle}",
"request": {"janus": "message", "transaction": "z", "body": {"request": "exists", "room": 1234}},
"expect": "success"},
{"step": "missing", "path": "/janus/{session}/{handle}",
"request": {"janus": "message", "transaction": "w", "body": {"request": "exists", "room": 9999}},
"expect": "success"}
]
}scenarioequals the file name without.json.- A step is a request (
pathdefaults to/janus;apican beadminorws) orpoll: N, which collects N events with long polls and records them as<step>-1to<step>-N. expectis thejanusvalue of the reply (or a list). Plugin errors come back assuccess, so the proof of those is in the trace, not inexpect.savekeeps a value from a reply ({"var": "dotted.path"}), and{var}in a laterpathor in a string that is exactly{var}is replaced by it.setupedits a sample config before the server starts:{"file": "janus.jcfg", "find": "#broadcast = true", "replace": "broadcast = true"}. The text must be in the file, or the run stops with a message.@file:sdp/offer-audio-video.sdpin a request string is replaced with that SDP file, with CRLF line ends. Reuse the Chrome, Firefox and Safari offers inparity/scenarios/sdp/.- Also available:
wait_ms,backgroundandawaitfor overlapping requests,raw_body,headers,record_headers,any_path,allow_dropfor HTTP edge cases. The full format is inparity/scenarios/README.md.
Use ids you choose ("id" of a publisher, a fixed room) instead of letting the server draw them, so that normalisation does not have to guess.
2. Capture the C answers
Needs Docker and the janus-c:bc0de3b3 image (build it):
cargo run -p xtask -- capture --scenario my-videoroomIt starts a container janus-cap-my-videoroom, runs the steps, and writes parity/traces/my-videoroom/raw.json (every exchange as it came, git-ignored) and normalised.json (committed). Capture the same scenario twice: the two normalised.json files must be byte-identical. If they are not, something the normaliser does not know changes between runs. Fix the scenario to avoid it, or teach xtask/src/capture/normalise.rs and its copy parity/src/numbered.rs about it.
3. Replay on the Rust server
cargo run -p xtask -- parity-run --scenario my-videoroomA pass prints PASS my-videoroom (N exchanges). A failure prints the first differing exchange as a diff: that diff is your to-do list.
4. Record that it is verified
Add the scenario to the harness.planned list of parity/status.json with "state": "verified" once it passes, update the notes of the component it covers, then run:
cargo run -p xtask -- progress
cargo run -p xtask -- progress --checkThe README bar for parity verified counts those entries.
Before you capture
Run the scenario's requests by hand against the C container first (docker run --rm -p 8088:8088 janus-c:bc0de3b3), so you know the replies you are about to pin make sense.