lesavka/testing/tests/server_video_sink_smoke_contract.rs

132 lines
3.8 KiB
Rust
Raw Normal View History

//! Integration smoke coverage for server camera sink constructors.
//!
//! Scope: exercise public sink and relay constructors with resilient
//! assertions that tolerate host-specific media capabilities.
//! Targets: `server/src/video_sinks.rs`.
//! Why: sink setup contains substantial branch logic that should be executed
//! in CI even when real HDMI/UVC hardware is unavailable.
use lesavka_common::lesavka::VideoPacket;
use lesavka_server::camera::{CameraCodec, CameraConfig, CameraOutput};
use lesavka_server::video::{CameraRelay, HdmiSink, WebcamSink};
use serial_test::serial;
use temp_env::with_var;
fn hdmi_config(codec: CameraCodec) -> CameraConfig {
CameraConfig {
output: CameraOutput::Hdmi,
codec,
width: 640,
height: 360,
fps: 30,
hdmi: None,
}
}
#[test]
#[serial]
fn webcam_sink_constructor_is_stable_for_missing_uvc_device() {
let cfg = hdmi_config(CameraCodec::Mjpeg);
match WebcamSink::new("/dev/video-definitely-missing", &cfg) {
Ok(sink) => sink.push(VideoPacket {
id: 2,
pts: 0,
data: vec![0xFF, 0xD8, 0xFF, 0xD9],
}),
Err(err) => assert!(!err.to_string().trim().is_empty()),
}
}
#[test]
#[serial]
fn hdmi_sink_constructor_and_push_are_stable_with_override() {
with_var("LESAVKA_HDMI_SINK", Some("autovideosink"), || {
let cfg = hdmi_config(CameraCodec::H264);
match HdmiSink::new(&cfg) {
Ok(sink) => sink.push(VideoPacket {
id: 2,
pts: 0,
data: vec![0, 0, 0, 1, 0x65],
}),
Err(err) => assert!(!err.to_string().trim().is_empty()),
}
});
}
#[test]
#[serial]
fn camera_relay_hdmi_constructor_and_feed_are_stable() {
with_var("LESAVKA_HDMI_SINK", Some("autovideosink"), || {
let cfg = hdmi_config(CameraCodec::Mjpeg);
match CameraRelay::new_hdmi(7, &cfg) {
Ok(relay) => relay.feed(VideoPacket {
id: 2,
pts: 123,
data: vec![0xFF, 0xD8, 0xFF, 0xD9],
}),
Err(err) => assert!(!err.to_string().trim().is_empty()),
}
});
}
#[test]
#[serial]
fn camera_relay_uvc_constructor_is_stable_for_missing_device() {
let cfg = hdmi_config(CameraCodec::Mjpeg);
match CameraRelay::new_uvc(9, "/dev/video-definitely-missing", &cfg) {
Ok(relay) => relay.feed(VideoPacket {
id: 2,
pts: 321,
data: vec![0xFF, 0xD8, 0xFF, 0xD9],
}),
Err(err) => assert!(!err.to_string().trim().is_empty()),
}
}
#[test]
#[serial]
fn webcam_sink_h264_constructor_path_is_stable() {
let cfg = hdmi_config(CameraCodec::H264);
match WebcamSink::new("/dev/video-definitely-missing", &cfg) {
Ok(sink) => sink.push(VideoPacket {
id: 3,
pts: 55,
data: vec![0, 0, 0, 1, 0x65],
}),
Err(err) => assert!(!err.to_string().trim().is_empty()),
}
}
#[test]
#[serial]
fn hdmi_sink_mjpeg_constructor_path_is_stable() {
with_var("LESAVKA_HDMI_SINK", Some("autovideosink"), || {
let cfg = hdmi_config(CameraCodec::Mjpeg);
match HdmiSink::new(&cfg) {
Ok(sink) => sink.push(VideoPacket {
id: 4,
pts: 99,
data: vec![0xFF, 0xD8, 0xFF, 0xD9],
}),
Err(err) => assert!(!err.to_string().trim().is_empty()),
}
});
}
#[test]
#[serial]
fn hdmi_sink_override_with_invalid_element_returns_error() {
with_var(
"LESAVKA_HDMI_SINK",
Some("definitely-not-a-real-gst-element"),
|| {
let cfg = hdmi_config(CameraCodec::H264);
let result = HdmiSink::new(&cfg);
assert!(
result.is_err(),
"invalid sink override should fail construction"
);
},
);
}