//! Include-based coverage for server camera sink internals. //! //! Scope: include `server/src/video_sinks.rs` and directly exercise private sink //! selection/dispatch helpers through stable constructor paths. //! Targets: `server/src/video_sinks.rs`. //! Why: sink internals carry substantial branch logic beyond public smoke tests. mod camera { pub use lesavka_server::camera::*; } mod video_support { pub use lesavka_server::video_support::*; } #[allow(warnings)] mod video_sinks_include_contract { include!(env!("LESAVKA_SERVER_VIDEO_SINKS_SRC")); use crate::camera::CameraOutput; use serial_test::serial; use temp_env::with_var; fn cfg(codec: CameraCodec) -> CameraConfig { CameraConfig { output: CameraOutput::Hdmi, codec, width: 640, height: 360, fps: 24, hdmi: None, } } fn init_gst() { let _ = gst::init(); } #[test] #[serial] fn build_hdmi_sink_respects_env_override_success_path() { init_gst(); with_var("LESAVKA_HDMI_SINK", Some("autovideosink"), || { let sink = build_hdmi_sink(&cfg(CameraCodec::H264)); assert!(sink.is_ok(), "known override sink should build"); }); } #[test] #[serial] fn build_hdmi_sink_invalid_override_surfaces_error() { init_gst(); with_var( "LESAVKA_HDMI_SINK", Some("definitely-not-a-real-gst-element"), || { let sink = build_hdmi_sink(&cfg(CameraCodec::H264)); assert!(sink.is_err(), "invalid override must fail"); }, ); } #[test] #[serial] fn build_hdmi_sink_falls_back_when_override_is_unset() { init_gst(); with_var("LESAVKA_HDMI_SINK", None::<&str>, || { let sink = build_hdmi_sink(&cfg(CameraCodec::H264)); assert!(sink.is_ok(), "fallback sink should build"); }); } #[test] #[serial] fn camera_sink_dispatch_is_stable_for_hdmi_variant() { with_var("LESAVKA_HDMI_SINK", Some("autovideosink"), || { if let Ok(sink) = HdmiSink::new(&cfg(CameraCodec::Mjpeg)) { let cam_sink = CameraSink::Hdmi(sink); cam_sink.push(VideoPacket { id: 8, pts: 1, data: vec![0xFF, 0xD8, 0xFF, 0xD9], }); } }); } #[test] #[serial] fn camera_sink_dispatch_is_stable_for_uvc_variant() { if let Ok(sink) = WebcamSink::new("/dev/video-definitely-missing", &cfg(CameraCodec::Mjpeg)) { let cam_sink = CameraSink::Uvc(sink); cam_sink.push(VideoPacket { id: 9, pts: 2, data: vec![0xFF, 0xD8, 0xFF, 0xD9], }); } } #[test] #[serial] fn camera_relay_feed_covers_dev_mode_dump_branch_without_panicking() { with_var("LESAVKA_DEV_MODE", Some("1"), || { with_var("LESAVKA_HDMI_SINK", Some("autovideosink"), || { if let Ok(relay) = CameraRelay::new_hdmi(3, &cfg(CameraCodec::H264)) { relay.feed(VideoPacket { id: 3, pts: 3, data: vec![0, 0, 0, 1, 0x65, 0x88, 0x84], }); } }); }); } }