lesavka/tests/reliability/downstream/video/downstream_blackout_recovery_contract.rs

74 lines
2.4 KiB
Rust

// Downstream blackout recovery contracts.
//
// Scope: keep the eye-video stream observable when frames stop arriving or
// queues overflow.
// Targets: `server/src/video/eye_capture.rs` and `server/src/video/stream_core.rs`.
// Why: black-screen episodes should become measurable recovery events, not
// silent UI mysteries.
const SERVER_EYE_CAPTURE: &str = include_str!("../../../../server/src/video/eye_capture.rs");
const SERVER_STREAM_CORE: &str = include_str!("../../../../server/src/video/stream_core.rs");
#[test]
fn first_frame_and_midstream_blackouts_have_separate_watchdogs() {
let first_frame = SERVER_EYE_CAPTURE
.find("LESAVKA_EYE_FIRST_FRAME_TIMEOUT_MS")
.expect("first-frame timeout marker");
let midstream = SERVER_EYE_CAPTURE
.find("eye_stall_warn_timeout()")
.expect("midstream stall timeout marker");
assert!(
first_frame < midstream,
"initial no-video failures should be reported before midstream stall monitoring starts"
);
for marker in [
"capture produced no frames within",
"downstream eye stream has produced no samples since the last frame",
"last_sample_wall_ms",
"first_sample_seen",
"stall_watchdog_alive",
] {
assert!(
SERVER_EYE_CAPTURE.contains(marker),
"blackout recovery should preserve marker {marker}"
);
}
}
#[test]
fn blackout_warning_defaults_are_bounded_below_ten_seconds() {
for marker in [
"unwrap_or(5_000)",
"Duration::from_millis(millis.max(500))",
"(millis > 0).then_some",
] {
assert!(
SERVER_STREAM_CORE.contains(marker),
"stall warning timeout should preserve bounded marker {marker}"
);
}
}
#[test]
fn overflow_recovery_waits_for_idr_before_resuming_after_drops() {
let full_branch = SERVER_EYE_CAPTURE
.find("TrySendError::Full")
.expect("overflow branch");
let wait_for_idr = SERVER_EYE_CAPTURE
.find("wait_for_idr.store(true")
.expect("IDR recovery marker");
let clear_idr = SERVER_EYE_CAPTURE
.find("wait_for_idr.store(false")
.expect("IDR clear marker");
assert!(
full_branch < wait_for_idr,
"queue overflow should arm IDR recovery"
);
assert!(
clear_idr < full_branch,
"successful IDR sends should clear recovery before later overflow can re-arm it"
);
}