testing: expand layout and camera contracts
This commit is contained in:
parent
31d4ee47b4
commit
659a77ff5f
@ -3,9 +3,12 @@
|
||||
"files": [
|
||||
"client/src/app_support.rs",
|
||||
"client/src/input/keymap.rs",
|
||||
"client/src/layout.rs",
|
||||
"client/src/output/layout.rs",
|
||||
"client/src/paste.rs",
|
||||
"common/src/cli.rs",
|
||||
"common/src/hid.rs",
|
||||
"common/src/lib.rs",
|
||||
"common/src/paste.rs",
|
||||
"server/src/handshake.rs",
|
||||
"server/src/paste.rs",
|
||||
|
||||
@ -20,9 +20,10 @@ fn install_sway_stub(dir: &std::path::Path) -> std::path::PathBuf {
|
||||
set -euo pipefail
|
||||
if [[ "${1:-}" == "-t" && "${2:-}" == "get_outputs" && "${3:-}" == "-r" ]]; then
|
||||
printf '%s\n' "${LESAVKA_TEST_SWAY_OUTPUTS:-[]}"
|
||||
exit 0
|
||||
exit "${LESAVKA_TEST_SWAY_GET_OUTPUTS_EXIT:-0}"
|
||||
fi
|
||||
echo "$*" >> "${LESAVKA_TEST_SWAY_LOG}"
|
||||
exit "${LESAVKA_TEST_SWAY_PLACE_EXIT:-0}"
|
||||
"#,
|
||||
)
|
||||
.expect("write swaymsg stub");
|
||||
@ -53,6 +54,16 @@ fn run_apply_with_outputs(layout: Layout, outputs_json: &str) -> Option<String>
|
||||
fs::read_to_string(log_path).ok()
|
||||
}
|
||||
|
||||
fn run_apply_without_swaymsg(layout: Layout) {
|
||||
with_var(
|
||||
"PATH",
|
||||
Some("/definitely-missing-lesavka-test-path"),
|
||||
|| {
|
||||
apply(layout);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn side_by_side_places_each_eye_on_half_of_focused_output() {
|
||||
@ -97,3 +108,45 @@ fn apply_skips_window_commands_when_no_output_is_focused() {
|
||||
"expected no placement calls, got: {log}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn apply_skips_window_commands_when_outputs_shape_is_not_an_array() {
|
||||
let log = run_apply_with_outputs(Layout::SideBySide, r#"{"focused":true}"#).unwrap_or_default();
|
||||
assert!(
|
||||
log.trim().is_empty(),
|
||||
"expected no placement calls, got: {log}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn apply_tolerates_nonzero_window_placement_exit_status() {
|
||||
let dir = tempdir().expect("create temp dir");
|
||||
install_sway_stub(dir.path());
|
||||
let log_path = dir.path().join("sway.log");
|
||||
let old_path = std::env::var("PATH").unwrap_or_default();
|
||||
let new_path = format!("{}:{old_path}", dir.path().display());
|
||||
let outputs = r#"[{"focused":true,"rect":{"x":0,"y":0,"width":640,"height":360}}]"#;
|
||||
let log_value = log_path.to_string_lossy().to_string();
|
||||
|
||||
with_var("PATH", Some(new_path.as_str()), || {
|
||||
with_var("LESAVKA_TEST_SWAY_LOG", Some(log_value.as_str()), || {
|
||||
with_var("LESAVKA_TEST_SWAY_OUTPUTS", Some(outputs), || {
|
||||
with_var("LESAVKA_TEST_SWAY_PLACE_EXIT", Some("2"), || {
|
||||
apply(Layout::SideBySide);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let log = fs::read_to_string(log_path).expect("read command log");
|
||||
assert!(log.contains(r#"[title="^Lesavka-eye-0$"]"#));
|
||||
assert!(log.contains(r#"[title="^Lesavka-eye-1$"]"#));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn apply_handles_missing_sway_binary_without_panicking() {
|
||||
run_apply_without_swaymsg(Layout::SideBySide);
|
||||
}
|
||||
|
||||
113
testing/tests/server_camera_contract.rs
Normal file
113
testing/tests/server_camera_contract.rs
Normal file
@ -0,0 +1,113 @@
|
||||
//! 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_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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user