diff --git a/tests/compatibility/server/uvc/server_uvc_runtime_contract.rs b/tests/compatibility/server/uvc/server_uvc_runtime_contract.rs index 52315bb..4104215 100644 --- a/tests/compatibility/server/uvc/server_uvc_runtime_contract.rs +++ b/tests/compatibility/server/uvc/server_uvc_runtime_contract.rs @@ -10,11 +10,28 @@ use lesavka_server::uvc_runtime::{pick_uvc_device, supervise_uvc_control}; use serial_test::serial; use std::fs; use std::os::unix::fs::PermissionsExt; +use std::path::Path; use std::time::Duration; use temp_env::{with_var, with_vars}; use tempfile::tempdir; use tokio::runtime::Runtime; +async fn wait_for_marker(marker: &Path, is_ready: impl Fn(&str) -> bool) -> String { + let deadline = tokio::time::Instant::now() + Duration::from_secs(2); + loop { + if let Ok(contents) = fs::read_to_string(marker) { + if is_ready(&contents) { + return contents; + } + } + assert!( + tokio::time::Instant::now() < deadline, + "helper marker was not written in time" + ); + tokio::time::sleep(Duration::from_millis(20)).await; + } +} + #[test] #[serial] fn supervise_uvc_control_starts_helper_when_device_is_set() { @@ -24,7 +41,7 @@ fn supervise_uvc_control_starts_helper_when_device_is_set() { fs::write( &helper, format!( - "#!/usr/bin/env bash\nset -euo pipefail\necho \"$*\" >> '{}'\n", + "#!/usr/bin/env bash\nset -euo pipefail\necho \"$*\" >> '{}'\nsleep 0.05\n", marker.display() ), ) @@ -36,19 +53,21 @@ fn supervise_uvc_control_starts_helper_when_device_is_set() { fs::set_permissions(&helper, perms).expect("chmod helper script"); let helper_path = helper.to_string_lossy().to_string(); - with_var("LESAVKA_UVC_DEV", Some("/dev/video-loop"), || { + let calls = with_var("LESAVKA_UVC_DEV", Some("/dev/video-loop"), || { let rt = Runtime::new().expect("runtime"); - let result = rt.block_on(async { - tokio::time::timeout( - Duration::from_millis(350), - supervise_uvc_control(helper_path), - ) - .await - }); - assert!(result.is_err(), "supervisor should still be running"); + rt.block_on(async { + let supervisor = tokio::spawn(supervise_uvc_control(helper_path)); + let calls = wait_for_marker(&marker, |contents| { + contents.contains("--device /dev/video-loop") + }) + .await; + supervisor.abort(); + let _ = supervisor.await; + tokio::time::sleep(Duration::from_millis(100)).await; + calls + }) }); - let calls = fs::read_to_string(marker).expect("read helper marker"); assert!( calls.contains("--device /dev/video-loop"), "expected helper to receive device args, got: {calls}" @@ -64,7 +83,7 @@ fn supervise_uvc_control_restarts_helper_after_exit() { fs::write( &helper, format!( - "#!/usr/bin/env bash\nset -euo pipefail\necho \"$*\" >> '{}'\nexit 0\n", + "#!/usr/bin/env bash\nset -euo pipefail\necho \"$*\" >> '{}'\nsleep 0.05\nexit 0\n", marker.display() ), ) @@ -76,25 +95,31 @@ fn supervise_uvc_control_restarts_helper_after_exit() { fs::set_permissions(&helper, perms).expect("chmod helper script"); let helper_path = helper.to_string_lossy().to_string(); - with_vars( + let calls = with_vars( [ ("LESAVKA_UVC_DEV", Some("/dev/video-loop")), ("LESAVKA_UVC_RESTART_DELAY_MS", Some("25")), ], || { let rt = Runtime::new().expect("runtime"); - let result = rt.block_on(async { - tokio::time::timeout( - Duration::from_millis(450), - supervise_uvc_control(helper_path), - ) - .await - }); - assert!(result.is_err(), "supervisor should still be running"); + rt.block_on(async { + let supervisor = tokio::spawn(supervise_uvc_control(helper_path)); + let calls = wait_for_marker(&marker, |contents| { + contents + .lines() + .filter(|line| line.contains("--device /dev/video-loop")) + .count() + >= 2 + }) + .await; + supervisor.abort(); + let _ = supervisor.await; + tokio::time::sleep(Duration::from_millis(100)).await; + calls + }) }, ); - let calls = fs::read_to_string(marker).expect("read helper marker"); let restart_count = calls .lines() .filter(|line| line.contains("--device /dev/video-loop")) diff --git a/tests/contract/client/input/camera/client_camera_include_contract.rs b/tests/contract/client/input/camera/client_camera_include_contract.rs index 24c6c87..be9e290 100644 --- a/tests/contract/client/input/camera/client_camera_include_contract.rs +++ b/tests/contract/client/input/camera/client_camera_include_contract.rs @@ -102,6 +102,7 @@ mod camera_include_contract { | "vulkanh264enc" | "vaapih264enc" | "v4l2h264enc" + | "x264enc" | "missing-hardware-h264enc" ), "unexpected encoder: {enc}" @@ -111,7 +112,7 @@ mod camera_include_contract { assert!( matches!( enc, - "nvh264enc" | "vulkanh264enc" | "vaapih264enc" | "v4l2h264enc" + "nvh264enc" | "vulkanh264enc" | "vaapih264enc" | "v4l2h264enc" | "x264enc" ), "unexpected encoder: {enc}" );