A fault is a deterministic modification made by FaultCam. Each activation is recorded with logical time, connection, track, packet/frame coordinate, trigger, action, and detail. The log proves what the server did; the regression probe or external client proves what crossed the observable boundary.
| Family | Actions | Effect |
|---|---|---|
| RTSP response | delay, response_delay |
Delay a matching request response by duration_ms (100 ms default). Use request_method and/or client_behavior to scope request faults. |
| RTSP status | status_code, response_status |
Return the numeric status in value for a matching request, then stop normal handling of that request. |
| Connection/media control | disconnect, disconnect_reconnect, media_stall, stop_media |
Close a session, close the first session and permit a new one, suppress media for a bounded interval, or stop media. |
| RTCP | stop_rtcp, rtcp_silence, bye |
Persistently stop reports, suppress reports during an active window, or send RTCP BYE and stop media. |
| Codec startup | missing_parameter_sets, delayed_parameter_sets, start_before_idr |
Remove VPS/SPS/PPS, release them after a logical time, or suppress startup until the intended non-IDR ordering is exposed. |
| Packet delivery | drop_packet, isolated_loss, burst_loss, reorder, duplicate, delay |
Drop selected RTP packets, create isolated/burst gaps, exchange arrival order, repeat a packet, or delay media. |
| Sequence state | sequence_reset, sequence_wrap |
Change the emitted sequence and retain the new progression, or exercise 16-bit wrap. |
| Timestamp state | timestamp_jump, timestamp_backward, timestamp_backward_jump, timestamp_freeze, timestamp_drift, timestamp_wrap |
Change, freeze, drift, or wrap the persistent 32-bit RTP timeline. |
| RTP identity | ssrc_switch, payload_type_switch |
Change the persistent emitted SSRC or payload type. |
| Multi-track | audio_disappear, audio_start_skew |
Suppress audio or offset its starting RTP timestamp relative to video. |
| UDP negotiation | udp_no_media |
Complete UDP SETUP/PLAY while suppressing RTP payload delivery. |
The aliases in the table are accepted because existing scenarios may use them, but new scenarios should prefer delay, status_code, and timestamp_backward.
Authentication behavior is configured under the camera's auth block rather than as a fault action. rotate_nonce, stale_on_rotation, and boundary_realm change the actual challenge path.
For media/timeline faults, at_ms, duration_ms, every_ms, packet, frame, track, and connection_count narrow activation. All supplied selectors must match. A packet or frame value of zero means no exact-index restriction; use logical time zero for startup behavior. connection_count scopes the domain already selected; by itself it does not turn a media/timeline fault into an RTSP request fault.
Supplying a non-empty request_method and/or client_behavior selects the RTSP request domain. These strings must not have leading or trailing whitespace. Only delay, response_delay, status_code, response_status, disconnect, and disconnect_reconnect accept request selectors. response_delay, status_code, and response_status require at least one request selector. In this domain:
- non-empty
track, non-zeropacket,frame,at_ms, orevery_ms, non-defaultprobability, and non-defaultseedare rejected because request handling does not consume them; duration_msis consumed only bydelayandresponse_delay;valueis consumed only bystatus_codeandresponse_status, and must be an RTSP status from 100 through 599;connection_countmay further scope the selected request, and request-scopeddisconnect_reconnectrequires an explicit positive value.
Probability actions are repeatable for the same scenario seed and logical coordinates. They are not a promise that two operating systems deliver packets at the same wall-clock instant.
Packet actions are evaluated per generated RTP packet. Stateful timestamp, sequence, SSRC, and payload changes continue after their trigger where the action semantics require it. media_stall suppresses units while logical time advances; it does not sleep once per frame and accidentally extend the scenario without bound. An unscoped delay is a media-pacing fault; adding a request selector moves it exclusively into response handling so that RTP is not delayed a second time. Media-domain disconnect_reconnect defaults to the first connection so that the replacement session is not immediately disconnected again; its request-scoped form requires the explicit connection noted above.
The 37 files in scenarios/regressions/ are registered as individual regression_* CTest cases. Five cover normal/authentication/SDP behavior; the remaining 32 provide one scenario-level oracle for every accepted fault action name or compatibility alias. Their comments state the primary variable, client, expected reaction, pass condition, and automatic assertions. The test harness requires:
- runner exit
0, a started non-timeout probe, and a live server; - non-empty JSON, JSONL, and JUnit outputs with no failed assertion;
- an explicit
FAULTCAM_PROBE_PASS action=...observation; - the action-specific request/RTP/RTCP evidence implemented by the strict probe.
Examples:
25-media-stall-control-alive.ymlrequires a threshold-sized RTP gap, a successful keepalive within that gap, and resumed media.27-disconnect-reconnect.ymlrequires two accepted connections, bounded reconnect delay, and RTP on connection two.30-udp-negotiated-no-media.ymlrequires successful UDP negotiation and then absence of media during the bounded observation.31-request-delay.ymlproves request-scoped canonicaldelayraises OPTIONS latency without adding a second RTP pacing delay.32-response-delay.ymlrequires a delayed but otherwise valid OPTIONS 200 response.33-status-code.ymland34-response-status.ymlrequire the configured RTSP 503 and alias-driven 454 responses on the wire.35-stop-media.ymlrequires a permanent terminal RTP gap while keepalive remains responsive.36-drop-packet.ymlrequires continued UDP media with an observed RTP sequence-number hole.37-timestamp-backward-jump.ymlrequires the compatibility alias to produce a negative RTP timestamp transition.
Merely finding an action string in JSONL is insufficient. Likewise, a decoder error is not automatically a successful negative test: the scenario must declare the expected client outcome, and the report must show why the assertion passed.