193 lines
7.0 KiB
Rust
193 lines
7.0 KiB
Rust
//! Integration coverage for the server camera-selection contract.
|
|
//!
|
|
//! Scope: exercise environment-driven camera mode selection and stable enum
|
|
//! string mappings via the public camera module API.
|
|
//! Targets: `server/src/camera.rs`.
|
|
//! Why: camera policy decides the entire stream transport path, so these
|
|
//! behavior contracts belong in centralized testing.
|
|
|
|
use lesavka_server::camera::{
|
|
CameraCodec, CameraOutput, current_camera_config, update_camera_config,
|
|
};
|
|
use serial_test::serial;
|
|
use temp_env::with_var;
|
|
|
|
#[test]
|
|
fn camera_enum_strings_are_stable() {
|
|
assert_eq!(CameraOutput::Uvc.as_str(), "uvc");
|
|
assert_eq!(CameraOutput::Hdmi.as_str(), "hdmi");
|
|
assert_eq!(CameraCodec::Mjpeg.as_str(), "mjpeg");
|
|
assert_eq!(CameraCodec::H264.as_str(), "h264");
|
|
}
|
|
|
|
#[test]
|
|
#[serial]
|
|
fn camera_config_uses_interval_when_fps_is_unset_or_invalid() {
|
|
with_var("LESAVKA_CAM_OUTPUT", Some("uvc"), || {
|
|
with_var("LESAVKA_UVC_WIDTH", Some("640"), || {
|
|
with_var("LESAVKA_UVC_HEIGHT", Some("360"), || {
|
|
with_var("LESAVKA_UVC_FPS", None::<&str>, || {
|
|
with_var("LESAVKA_UVC_INTERVAL", Some("250000"), || {
|
|
let cfg = update_camera_config();
|
|
assert_eq!(cfg.output, CameraOutput::Uvc);
|
|
assert_eq!(cfg.codec, CameraCodec::Mjpeg);
|
|
assert_eq!(cfg.width, 640);
|
|
assert_eq!(cfg.height, 360);
|
|
assert_eq!(cfg.fps, 40);
|
|
});
|
|
});
|
|
|
|
with_var("LESAVKA_UVC_FPS", Some("not-a-number"), || {
|
|
with_var("LESAVKA_UVC_INTERVAL", Some("250000"), || {
|
|
let cfg = update_camera_config();
|
|
assert_eq!(cfg.output, CameraOutput::Uvc);
|
|
assert_eq!(cfg.codec, CameraCodec::Mjpeg);
|
|
assert_eq!(cfg.width, 640);
|
|
assert_eq!(cfg.height, 360);
|
|
assert_eq!(cfg.fps, 40);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[serial]
|
|
fn camera_config_zero_interval_falls_back_to_default_fps() {
|
|
with_var("LESAVKA_CAM_OUTPUT", Some("uvc"), || {
|
|
with_var("LESAVKA_UVC_WIDTH", Some("800"), || {
|
|
with_var("LESAVKA_UVC_HEIGHT", Some("600"), || {
|
|
with_var("LESAVKA_UVC_FPS", None::<&str>, || {
|
|
with_var("LESAVKA_UVC_INTERVAL", Some("0"), || {
|
|
let cfg = update_camera_config();
|
|
assert_eq!(cfg.output, CameraOutput::Uvc);
|
|
assert_eq!(cfg.codec, CameraCodec::Mjpeg);
|
|
assert_eq!(cfg.width, 800);
|
|
assert_eq!(cfg.height, 600);
|
|
assert_eq!(cfg.fps, 25);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[serial]
|
|
fn camera_config_forced_hdmi_tracks_cached_state() {
|
|
with_var("LESAVKA_CAM_OUTPUT", Some("hdmi"), || {
|
|
let cfg = update_camera_config();
|
|
assert_eq!(cfg.output, CameraOutput::Hdmi);
|
|
assert_eq!(cfg.codec, CameraCodec::H264);
|
|
assert_eq!(cfg.fps, 30);
|
|
assert!(matches!(
|
|
(cfg.width, cfg.height),
|
|
(1920, 1080) | (1280, 720)
|
|
));
|
|
|
|
let cached = current_camera_config();
|
|
assert_eq!(cached.output, CameraOutput::Hdmi);
|
|
assert_eq!(cached.codec, CameraCodec::H264);
|
|
assert_eq!(cached.fps, 30);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[serial]
|
|
fn camera_config_forced_hdmi_honors_1080p_uplink_override() {
|
|
with_var("LESAVKA_CAM_OUTPUT", Some("hdmi"), || {
|
|
with_var("LESAVKA_CAM_WIDTH", Some("1920"), || {
|
|
with_var("LESAVKA_CAM_HEIGHT", Some("1080"), || {
|
|
with_var("LESAVKA_CAM_FPS", Some("30"), || {
|
|
let cfg = update_camera_config();
|
|
assert_eq!(cfg.output, CameraOutput::Hdmi);
|
|
assert_eq!(cfg.codec, CameraCodec::H264);
|
|
assert_eq!(cfg.width, 1920);
|
|
assert_eq!(cfg.height, 1080);
|
|
assert_eq!(cfg.fps, 30);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[serial]
|
|
fn camera_config_output_override_is_case_insensitive() {
|
|
with_var("LESAVKA_CAM_OUTPUT", Some(" UVC "), || {
|
|
with_var("LESAVKA_UVC_WIDTH", Some("1024"), || {
|
|
with_var("LESAVKA_UVC_HEIGHT", Some("576"), || {
|
|
with_var("LESAVKA_UVC_FPS", Some("12"), || {
|
|
let cfg = update_camera_config();
|
|
assert_eq!(cfg.output, CameraOutput::Uvc);
|
|
assert_eq!(cfg.codec, CameraCodec::Mjpeg);
|
|
assert_eq!(cfg.width, 1024);
|
|
assert_eq!(cfg.height, 576);
|
|
assert_eq!(cfg.fps, 12);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[serial]
|
|
fn camera_config_defaults_when_uvc_dimensions_and_rate_are_missing() {
|
|
with_var("LESAVKA_CAM_OUTPUT", Some("uvc"), || {
|
|
with_var("LESAVKA_UVC_WIDTH", None::<&str>, || {
|
|
with_var("LESAVKA_UVC_HEIGHT", None::<&str>, || {
|
|
with_var("LESAVKA_UVC_FPS", None::<&str>, || {
|
|
with_var("LESAVKA_UVC_INTERVAL", None::<&str>, || {
|
|
let cfg = update_camera_config();
|
|
assert_eq!(cfg.output, CameraOutput::Uvc);
|
|
assert_eq!(cfg.codec, CameraCodec::Mjpeg);
|
|
assert_eq!(cfg.width, 1280);
|
|
assert_eq!(cfg.height, 720);
|
|
assert_eq!(cfg.fps, 25);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[serial]
|
|
fn camera_config_prefers_explicit_fps_over_interval() {
|
|
with_var("LESAVKA_CAM_OUTPUT", Some("uvc"), || {
|
|
with_var("LESAVKA_UVC_WIDTH", Some("800"), || {
|
|
with_var("LESAVKA_UVC_HEIGHT", Some("600"), || {
|
|
with_var("LESAVKA_UVC_FPS", Some("48"), || {
|
|
with_var("LESAVKA_UVC_INTERVAL", Some("250000"), || {
|
|
let cfg = update_camera_config();
|
|
assert_eq!(cfg.output, CameraOutput::Uvc);
|
|
assert_eq!(cfg.codec, CameraCodec::Mjpeg);
|
|
assert_eq!(cfg.width, 800);
|
|
assert_eq!(cfg.height, 600);
|
|
assert_eq!(cfg.fps, 48);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[serial]
|
|
fn camera_config_invalid_output_falls_back_to_detected_policy() {
|
|
with_var("LESAVKA_CAM_OUTPUT", Some("not-a-real-mode"), || {
|
|
let cfg = update_camera_config();
|
|
match cfg.output {
|
|
CameraOutput::Uvc => {
|
|
assert_eq!(cfg.codec, CameraCodec::Mjpeg);
|
|
assert!(cfg.fps > 0);
|
|
}
|
|
CameraOutput::Hdmi => {
|
|
assert_eq!(cfg.codec, CameraCodec::H264);
|
|
assert_eq!(cfg.fps, 30);
|
|
}
|
|
}
|
|
});
|
|
}
|