2026-05-06 05:50:59 -03:00
use super ::{
CalibrationAction , CapturePowerCommand , CommandKind , Config , ParseOutcome ,
calibration_request_for , capture_power_request , parse_args_from , parse_args_outcome_from ,
} ;
2026-05-09 11:34:13 -03:00
use lesavka_common ::lesavka ::{ CapturePowerState , UpstreamSyncState } ;
2026-05-06 05:50:59 -03:00
#[ test ]
/// Verifies safe recovery commands stay separate from explicit hard reset.
fn command_aliases_parse_to_stable_actions ( ) {
assert_eq! ( CommandKind ::parse ( " status " ) , Some ( CommandKind ::Status ) ) ;
assert_eq! ( CommandKind ::parse ( " get " ) , Some ( CommandKind ::Status ) ) ;
assert_eq! ( CommandKind ::parse ( " version " ) , Some ( CommandKind ::Version ) ) ;
assert_eq! ( CommandKind ::parse ( " versions " ) , Some ( CommandKind ::Version ) ) ;
assert_eq! (
CommandKind ::parse ( " calibration " ) ,
Some ( CommandKind ::CalibrationStatus )
) ;
assert_eq! (
CommandKind ::parse ( " calibrate " ) ,
Some ( CommandKind ::CalibrationAdjust )
) ;
assert_eq! (
CommandKind ::parse ( " calibration-restore-default " ) ,
Some ( CommandKind ::CalibrationRestoreDefault )
) ;
assert_eq! (
CommandKind ::parse ( " calibration-restore-factory " ) ,
Some ( CommandKind ::CalibrationRestoreFactory )
) ;
assert_eq! (
CommandKind ::parse ( " calibration-save-default " ) ,
Some ( CommandKind ::CalibrationSaveDefault )
) ;
assert_eq! (
CommandKind ::parse ( " upstream-sync " ) ,
Some ( CommandKind ::UpstreamSync )
) ;
assert_eq! ( CommandKind ::parse ( " sync " ) , Some ( CommandKind ::UpstreamSync ) ) ;
assert_eq! (
CommandKind ::parse ( " output-delay-probe " ) ,
Some ( CommandKind ::OutputDelayProbe )
) ;
assert_eq! (
CommandKind ::parse ( " probe-output-delay " ) ,
Some ( CommandKind ::OutputDelayProbe )
) ;
assert_eq! ( CommandKind ::parse ( " force-on " ) , Some ( CommandKind ::On ) ) ;
assert_eq! ( CommandKind ::parse ( " force-off " ) , Some ( CommandKind ::Off ) ) ;
assert_eq! (
CommandKind ::parse ( " recover-usb " ) ,
Some ( CommandKind ::RecoverUsb )
) ;
assert_eq! (
CommandKind ::parse ( " recover-uac " ) ,
Some ( CommandKind ::RecoverUac )
) ;
assert_eq! (
CommandKind ::parse ( " recover-uvc " ) ,
Some ( CommandKind ::RecoverUvc )
) ;
assert_eq! (
CommandKind ::parse ( " hard-reset-usb " ) ,
Some ( CommandKind ::ResetUsb )
) ;
assert_eq! ( CommandKind ::parse ( " wat " ) , None ) ;
}
#[ test ]
fn parse_args_defaults_to_local_status ( ) {
let config = parse_args_from ( std ::iter ::empty ::< & str > ( ) ) . expect ( " default config " ) ;
assert_eq! ( config . server , " http://127.0.0.1:50051 " ) ;
assert_eq! ( config . command , CommandKind ::Status ) ;
assert_eq! ( config . audio_delta_us , 0 ) ;
assert_eq! ( config . video_delta_us , 0 ) ;
assert! ( config . note . is_empty ( ) ) ;
}
#[ test ]
fn parse_args_accepts_server_and_command ( ) {
let config =
parse_args_from ( [ " --server " , " http://lab:50051 " , " upstream-sync " ] ) . expect ( " config " ) ;
assert_eq! ( config . server , " http://lab:50051 " ) ;
assert_eq! ( config . command , CommandKind ::UpstreamSync ) ;
}
#[ test ]
/// Keeps `parse_args_accepts_output_delay_probe_config` explicit because it sits on CLI orchestration, where operators need deterministic exits and artifact paths.
/// Inputs are the typed parameters; output is the return value or side effect.
fn parse_args_accepts_output_delay_probe_config ( ) {
let config = parse_args_from ( [
" --server " ,
" http://lab:50051 " ,
" output-delay-probe " ,
" 20 " ,
" 4 " ,
" 1000 " ,
" 120 " ,
" 1,2,3,4 " ,
" 0 " ,
" 157712 " ,
] )
. expect ( " probe config " ) ;
assert_eq! ( config . command , CommandKind ::OutputDelayProbe ) ;
assert_eq! ( config . probe_duration_seconds , 20 ) ;
assert_eq! ( config . probe_warmup_seconds , 4 ) ;
assert_eq! ( config . probe_pulse_period_ms , 1000 ) ;
assert_eq! ( config . probe_pulse_width_ms , 120 ) ;
assert_eq! ( config . probe_event_width_codes , " 1,2,3,4 " ) ;
assert_eq! ( config . probe_audio_delay_us , 0 ) ;
assert_eq! ( config . probe_video_delay_us , 157_712 ) ;
}
#[ test ]
/// Keeps `parse_args_accepts_calibration_adjustment` explicit because it sits on CLI orchestration, where operators need deterministic exits and artifact paths.
/// Inputs are the typed parameters; output is the return value or side effect.
fn parse_args_accepts_calibration_adjustment ( ) {
let config = parse_args_from ( [
" --server " ,
" http://lab:50051 " ,
" calibrate " ,
" 0 " ,
" 71600 " ,
" probe " ,
" median " ,
] )
. expect ( " calibration config " ) ;
assert_eq! ( config . command , CommandKind ::CalibrationAdjust ) ;
assert_eq! ( config . audio_delta_us , 0 ) ;
assert_eq! ( config . video_delta_us , 71_600 ) ;
assert_eq! ( config . note , " probe median " ) ;
}
#[ test ]
/// Keeps `parse_args_rejects_bad_inputs` explicit because it sits on CLI orchestration, where operators need deterministic exits and artifact paths.
/// Inputs are the typed parameters; output is the return value or side effect.
fn parse_args_rejects_bad_inputs ( ) {
assert! ( parse_args_from ( [ " --server " ] ) . is_err ( ) ) ;
assert! ( parse_args_from ( [ " nope " ] ) . is_err ( ) ) ;
assert! ( parse_args_from ( [ " status " , " extra " ] ) . is_err ( ) ) ;
assert! ( parse_args_from ( [ " calibrate " ] ) . is_err ( ) ) ;
assert! ( parse_args_from ( [ " calibrate " , " 0 " , " not-int " ] ) . is_err ( ) ) ;
assert! (
parse_args_from ( [
" output-delay-probe " ,
" 1 " ,
" 2 " ,
" 3 " ,
" 4 " ,
" 1 " ,
" 0 " ,
" 0 " ,
" extra "
] )
. is_err ( )
) ;
}
#[ test ]
fn parse_args_reports_help_without_exiting_test_process ( ) {
assert_eq! (
parse_args_outcome_from ( [ " --help " ] ) . unwrap ( ) ,
ParseOutcome ::Help
) ;
assert_eq! ( parse_args_outcome_from ( [ " -h " ] ) . unwrap ( ) , ParseOutcome ::Help ) ;
assert! ( parse_args_from ( [ " --help " ] ) . is_err ( ) ) ;
}
#[ test ]
fn parse_args_runtime_wrapper_is_non_panicking_under_tests ( ) {
let _ = super ::parse_args ( ) ;
}
#[ cfg(coverage) ]
#[ test ]
fn coverage_main_references_runtime_parser ( ) {
super ::main ( ) ;
}
#[ cfg(coverage) ]
#[ tokio::test(flavor = " current_thread " ) ]
async fn coverage_connect_uses_lazy_channel_after_endpoint_validation ( ) {
let client = super ::connect ( " http://127.0.0.1:1 " )
. await
. expect ( " coverage lazy channel " ) ;
drop ( client ) ;
}
#[ test ]
/// Keeps status/read commands from accidentally mutating capture power.
fn mutating_commands_map_to_capture_power_requests ( ) {
let auto = capture_power_request ( CommandKind ::Auto ) . expect ( " auto request " ) ;
assert! ( ! auto . enabled ) ;
assert_eq! ( auto . command , CapturePowerCommand ::Auto as i32 ) ;
let on = capture_power_request ( CommandKind ::On ) . expect ( " on request " ) ;
assert! ( on . enabled ) ;
assert_eq! ( on . command , CapturePowerCommand ::ForceOn as i32 ) ;
let off = capture_power_request ( CommandKind ::Off ) . expect ( " off request " ) ;
assert! ( ! off . enabled ) ;
assert_eq! ( off . command , CapturePowerCommand ::ForceOff as i32 ) ;
assert! ( capture_power_request ( CommandKind ::Status ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::Version ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::CalibrationStatus ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::CalibrationAdjust ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::CalibrationRestoreDefault ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::CalibrationRestoreFactory ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::CalibrationSaveDefault ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::RecoverUsb ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::RecoverUac ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::RecoverUvc ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::ResetUsb ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::UpstreamSync ) . is_none ( ) ) ;
assert! ( capture_power_request ( CommandKind ::OutputDelayProbe ) . is_none ( ) ) ;
}
#[ test ]
fn print_state_accepts_full_capture_power_payload ( ) {
super ::print_state ( CapturePowerState {
available : true ,
enabled : false ,
mode : " auto " . to_string ( ) ,
detected_devices : 2 ,
active_leases : 1 ,
unit : " lesavka-capture-power.service " . to_string ( ) ,
detail : " ready " . to_string ( ) ,
} ) ;
}
2026-05-09 11:34:13 -03:00
#[ test ]
fn print_versions_accepts_unknown_and_reported_server_identity ( ) {
super ::print_versions (
" https://lab:50051 " ,
& lesavka_common ::lesavka ::HandshakeSet {
camera_output : " uvc " . to_string ( ) ,
camera_codec : " mjpeg " . to_string ( ) ,
camera_width : 1280 ,
camera_height : 720 ,
camera_fps : 30 ,
bundled_webcam_media : true ,
.. Default ::default ( )
} ,
) ;
super ::print_versions (
" https://lab:50051 " ,
& lesavka_common ::lesavka ::HandshakeSet {
server_version : " 0.21.1 " . to_string ( ) ,
server_revision : " abc1234 " . to_string ( ) ,
camera_output : " uvc " . to_string ( ) ,
camera_codec : " hevc " . to_string ( ) ,
camera_width : 1920 ,
camera_height : 1080 ,
camera_fps : 30 ,
bundled_webcam_media : true ,
.. Default ::default ( )
} ,
) ;
}
2026-05-06 05:50:59 -03:00
#[ test ]
/// Keeps `print_calibration_accepts_full_payload` explicit because it sits on CLI orchestration, where operators need deterministic exits and artifact paths.
/// Inputs are the typed parameters; output is the return value or side effect.
fn print_calibration_accepts_full_payload ( ) {
super ::print_calibration_state ( lesavka_common ::lesavka ::CalibrationState {
profile : " mjpeg " . to_string ( ) ,
factory_audio_offset_us : 0 ,
factory_video_offset_us : 1_090_000 ,
default_audio_offset_us : 0 ,
default_video_offset_us : 1_090_000 ,
active_audio_offset_us : 0 ,
active_video_offset_us : 1_161_600 ,
source : " manual " . to_string ( ) ,
confidence : " manual " . to_string ( ) ,
updated_at : " 2026-05-02T00:00:00Z " . to_string ( ) ,
detail : " probe nudge " . to_string ( ) ,
} ) ;
}
2026-05-09 11:34:13 -03:00
#[ test ]
fn print_upstream_sync_accepts_complete_and_pending_payloads ( ) {
super ::print_upstream_sync ( UpstreamSyncState {
session_id : 7 ,
phase : " locked " . to_string ( ) ,
latest_camera_remote_pts_us : Some ( 1_000 ) ,
latest_microphone_remote_pts_us : Some ( 1_010 ) ,
last_video_presented_pts_us : Some ( 2_000 ) ,
last_audio_presented_pts_us : Some ( 2_010 ) ,
live_lag_ms : Some ( 44.5 ) ,
planner_skew_ms : Some ( - 3.25 ) ,
stale_audio_drops : 1 ,
stale_video_drops : 2 ,
skew_video_drops : 3 ,
freshness_reanchors : 4 ,
startup_timeouts : 5 ,
video_freezes : 6 ,
last_reason : " healthy " . to_string ( ) ,
client_capture_skew_ms : Some ( 1.5 ) ,
client_send_skew_ms : Some ( - 2.5 ) ,
server_receive_skew_ms : Some ( 3.5 ) ,
camera_client_queue_age_ms : Some ( 4.5 ) ,
microphone_client_queue_age_ms : Some ( 5.5 ) ,
camera_server_receive_age_ms : Some ( 6.5 ) ,
microphone_server_receive_age_ms : Some ( 7.5 ) ,
client_capture_abs_skew_p95_ms : Some ( 8.5 ) ,
client_send_abs_skew_p95_ms : Some ( 9.5 ) ,
server_receive_abs_skew_p95_ms : Some ( 10.5 ) ,
camera_client_queue_age_p95_ms : Some ( 11.5 ) ,
microphone_client_queue_age_p95_ms : Some ( 12.5 ) ,
sink_handoff_skew_ms : Some ( - 13.5 ) ,
sink_handoff_abs_skew_p95_ms : Some ( 14.5 ) ,
camera_sink_late_ms : Some ( 15.5 ) ,
microphone_sink_late_ms : Some ( - 16.5 ) ,
camera_sink_late_p95_ms : Some ( 17.5 ) ,
microphone_sink_late_p95_ms : Some ( 18.5 ) ,
client_timing_window_samples : 19 ,
sink_handoff_window_samples : 20 ,
} ) ;
super ::print_upstream_sync ( UpstreamSyncState {
session_id : 0 ,
phase : " acquiring " . to_string ( ) ,
last_reason : " waiting " . to_string ( ) ,
.. UpstreamSyncState ::default ( )
} ) ;
}
2026-05-06 05:50:59 -03:00
#[ test ]
/// Keeps `calibration_requests_are_only_built_for_calibration_mutations` explicit because it sits on CLI orchestration, where operators need deterministic exits and artifact paths.
/// Inputs are the typed parameters; output is the return value or side effect.
fn calibration_requests_are_only_built_for_calibration_mutations ( ) {
let config = Config {
server : " http://127.0.0.1:50051 " . to_string ( ) ,
command : CommandKind ::CalibrationAdjust ,
audio_delta_us : 0 ,
video_delta_us : 71_600 ,
note : " probe " . to_string ( ) ,
probe_duration_seconds : 0 ,
probe_warmup_seconds : 0 ,
probe_pulse_period_ms : 0 ,
probe_pulse_width_ms : 0 ,
probe_event_width_codes : String ::new ( ) ,
probe_audio_delay_us : 0 ,
probe_video_delay_us : 0 ,
} ;
let request = calibration_request_for ( & config ) . expect ( " request " ) ;
assert_eq! ( request . action , CalibrationAction ::AdjustActive as i32 ) ;
assert_eq! ( request . audio_delta_us , 0 ) ;
assert_eq! ( request . video_delta_us , 71_600 ) ;
assert_eq! ( request . note , " probe " ) ;
2026-05-09 11:34:13 -03:00
for ( command , action ) in [
(
CommandKind ::CalibrationRestoreDefault ,
CalibrationAction ::RestoreDefault ,
) ,
(
CommandKind ::CalibrationRestoreFactory ,
CalibrationAction ::RestoreFactory ,
) ,
(
CommandKind ::CalibrationSaveDefault ,
CalibrationAction ::SaveActiveAsDefault ,
) ,
] {
let mutation = Config {
server : config . server . clone ( ) ,
command ,
audio_delta_us : config . audio_delta_us ,
video_delta_us : config . video_delta_us ,
note : config . note . clone ( ) ,
probe_duration_seconds : config . probe_duration_seconds ,
probe_warmup_seconds : config . probe_warmup_seconds ,
probe_pulse_period_ms : config . probe_pulse_period_ms ,
probe_pulse_width_ms : config . probe_pulse_width_ms ,
probe_event_width_codes : config . probe_event_width_codes . clone ( ) ,
probe_audio_delay_us : config . probe_audio_delay_us ,
probe_video_delay_us : config . probe_video_delay_us ,
} ;
let request = calibration_request_for ( & mutation ) . expect ( " calibration mutation " ) ;
assert_eq! ( request . action , action as i32 ) ;
}
2026-05-06 05:50:59 -03:00
let status = Config {
command : CommandKind ::CalibrationStatus ,
.. config
} ;
assert! ( calibration_request_for ( & status ) . is_none ( ) ) ;
}