Skip to content

The differential harness ​

The port has one rule for behaviour: ask the C server. The harness turns that rule into tests. It records what the C server says to a scripted conversation, then replays the same conversation against the Rust binary and compares.

text
 scenario (JSON)                     C oracle in Docker                       parity/traces/<name>/
 parity/scenarios/*.json  ──────▶   janus-c:bc0de3b3 on a random port  ──▶   raw.json         (git-ignored)
   steps: requests, polls            every request and reply, byte for byte   normalised.json  (committed)
        │
        │  cargo run -p xtask -- parity-run
        ▼
 Rust binary on a free loopback port, with the same sample configs
 requests replayed ─▶ replies normalised the same way ─▶ diffed with normalised.json ─▶ PASS or FAIL + diff

The pieces ​

PieceWhereDoes
Scenariosparity/scenarios/*.jsonA conversation: requests, polls for events, config edits before start.
Oracle imageparity/oracle/Dockerfile.oracleBuilds the C server at the pinned commit with every sample config enabled. Tag janus-c:bc0de3b3.
Capturecargo run -p xtask -- capture --scenario <name>Runs a scenario against the oracle in a container named janus-cap-<name> (removed afterwards) and writes the trace.
Normaliserxtask/src/capture/normalise.rs, copied in parity/src/numbered.rsReplaces what differs between runs (ids, transactions, times, addresses, SSRCs) with placeholders such as $SESSION_1. A test keeps the two copies equal.
Runnercargo run -p xtask -- parity-runStarts the Rust binary per scenario, replays, normalises and diffs. Exits non-zero on any difference.
Media probecargo run -p xtask -- parity-mediaA loopback WebRTC client (ICE, DTLS-SRTP, RTP, RTCP) runs against both servers; the two normalised reports are diffed. --golden compares with the recorded one, no Docker.
SIP and Lua probesparity-sip, parity-luaThe same idea for SIP calls against a UDP peer and for Lua number handling. Need Docker and python3.

Running it ​

sh
cargo run -p xtask -- parity-run                        # every scenario, builds janus first
cargo run -p xtask -- parity-run --scenario echotest    # one scenario
cargo run -p xtask -- parity-run --bin target/debug/janus --no-build

A passing scenario prints its name and the number of exchanges. A failing one prints which exchanges differ and a unified diff of the first, like this (a real failure caused by another process holding the NoSIP port range):

text
FAIL  nosip-requests (trace has 440 exchanges, server gave 440, 22 differ)
      first difference: exchange 48 of 440, request GET /janus/2409443595219312?maxev=1
      --- expected (trace)
      +++ actual (janus)
      -            "m=audio 20000 RTP/AVP 111",
      +            "m=audio 20020 RTP/AVP 111",

Scenarios bind real ports

NoSIP gets RTP ports 20000 and up, Streaming uses 25810 and up. Run the harness while no other janus is using those ranges, or scenarios that print ports will differ.

What a pass means, and what it does not ​

A pass means the Rust server gave the same normalised replies as the C server to every request in the scenario. It does not cover:

  • Timing-dependent events: webrtcup, media, slowlink, ICE failures. No peer connects in a scenario. The media probe and Janus Bench cover these.
  • Hash-table order of list replies. The C server's order depends on GLib; the normaliser sorts the one array known to differ (VideoCall's list), and a port that lists in another order must decide whether to sort elsewhere.
  • A VideoRoom subscriber's offer, the SDP of Lua and Duktape, and live SIP: nothing there is captured.

The full list is in parity/scenarios/README.md. When the oracle moves past the pin, drift is logged in PARITY_LOG.md and PARITY.md is regenerated with cargo run -p xtask -- parity-matrix.

Rules ​

  • Every wave that touches a component updates parity/status.json, then runs cargo run -p xtask -- progress. The README bars come from it.
  • PARITY.md is generated. Do not edit it.
  • Never modify the C checkout. It is read-only evidence.

GPL-3.0-or-later, like the Janus gateway it ports.