126 lines
3.2 KiB
Rust
126 lines
3.2 KiB
Rust
use super::*;
|
|
use serial_test::serial;
|
|
use std::fs;
|
|
use temp_env::{with_var, with_vars};
|
|
use tempfile::NamedTempFile;
|
|
|
|
fn sample_cfg() -> UvcConfig {
|
|
UvcConfig {
|
|
width: 1280,
|
|
height: 720,
|
|
fps: 25,
|
|
interval: 400_000,
|
|
max_packet: 1024,
|
|
frame_size: 1_843_200,
|
|
}
|
|
}
|
|
|
|
fn sample_interfaces() -> UvcInterfaces {
|
|
UvcInterfaces {
|
|
control: UVC_STRING_CONTROL_IDX,
|
|
streaming: UVC_STRING_STREAMING_IDX,
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn branch_smoke_covers_low_hit_paths() {
|
|
let interfaces = sample_interfaces();
|
|
let mut state = UvcState::new(sample_cfg());
|
|
let mut pending = Some(PendingRequest {
|
|
interface: interfaces.control,
|
|
selector: UVC_VS_PROBE_CONTROL,
|
|
expected_len: STREAM_CTRL_SIZE_11,
|
|
});
|
|
handle_data(
|
|
-1,
|
|
0,
|
|
&mut state,
|
|
&mut pending,
|
|
interfaces,
|
|
UvcRequestData {
|
|
length: STREAM_CTRL_SIZE_11 as i32,
|
|
data: [0u8; UVC_DATA_SIZE],
|
|
},
|
|
true,
|
|
);
|
|
assert!(pending.is_none());
|
|
assert!(
|
|
build_in_response(
|
|
&state,
|
|
interfaces,
|
|
interfaces.streaming,
|
|
0xFE,
|
|
UVC_GET_CUR,
|
|
8
|
|
)
|
|
.is_none()
|
|
);
|
|
let short = [0u8; 8];
|
|
let _ = sanitize_streaming_control(&short, &state);
|
|
}
|
|
|
|
#[test]
|
|
fn io_helpers_cover_empty_and_missing_sources() {
|
|
let empty = NamedTempFile::new().expect("tmp");
|
|
fs::write(empty.path(), "\n").expect("write empty");
|
|
assert_eq!(read_u32_first(empty.path().to_str().expect("path")), None);
|
|
|
|
let missing = format!("/tmp/lesavka-uvc-missing-{}", std::process::id());
|
|
assert_eq!(read_fifo_min(&missing), None);
|
|
}
|
|
|
|
#[test]
|
|
fn uvc_frame_max_bytes_defaults_to_freshness_budget_and_allows_override() {
|
|
with_vars(
|
|
[
|
|
("LESAVKA_UVC_FRAME_SIZE_GUARD", None::<&str>),
|
|
("LESAVKA_UVC_FRAME_MAX_BYTES", None::<&str>),
|
|
("LESAVKA_UVC_MJPEG_BUDGET_BYTES_PER_SEC", None::<&str>),
|
|
],
|
|
|| {
|
|
let cfg = sample_cfg();
|
|
assert_eq!(uvc_frame_max_bytes(cfg), 400_000);
|
|
},
|
|
);
|
|
|
|
with_vars(
|
|
[
|
|
("LESAVKA_UVC_FRAME_SIZE_GUARD", Some("1")),
|
|
("LESAVKA_UVC_FRAME_MAX_BYTES", Some("123456")),
|
|
("LESAVKA_UVC_MJPEG_BUDGET_BYTES_PER_SEC", Some("1")),
|
|
],
|
|
|| {
|
|
assert_eq!(uvc_frame_max_bytes(sample_cfg()), 123_456);
|
|
},
|
|
);
|
|
|
|
with_var("LESAVKA_UVC_FRAME_MAX_BYTES", Some("0"), || {
|
|
assert_eq!(uvc_frame_max_bytes(sample_cfg()), 400_000);
|
|
});
|
|
|
|
with_vars(
|
|
[
|
|
("LESAVKA_UVC_FRAME_SIZE_GUARD", Some("0")),
|
|
("LESAVKA_UVC_FRAME_MAX_BYTES", Some("123456")),
|
|
],
|
|
|| {
|
|
assert_eq!(uvc_frame_max_bytes(sample_cfg()), MAX_MJPEG_FRAME_BYTES);
|
|
},
|
|
);
|
|
|
|
with_var("LESAVKA_UVC_STATS_INTERVAL_MS", Some("0"), || {
|
|
assert_eq!(uvc_stats_interval(), None);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[serial]
|
|
fn main_coverage_mode_returns_error_for_non_uvc_node() {
|
|
with_var("LESAVKA_UVC_DEV", Some("/dev/null"), || {
|
|
with_var("LESAVKA_UVC_BLOCKING", Some("1"), || {
|
|
let result = main();
|
|
assert!(result.is_err());
|
|
});
|
|
});
|
|
}
|