//! Contract tests for the manual upstream A/V sync harness. //! //! Scope: statically guard the workstation-side tunnel/bootstrap behavior. //! Targets: `scripts/manual/run_upstream_av_sync.sh`. //! Why: the manual probe should reach Theia through SSH even when the gRPC //! port is not exposed on the public SSH endpoint. const SYNC_SCRIPT: &str = include_str!("../../scripts/manual/run_upstream_av_sync.sh"); const BROWSER_SYNC_SCRIPT: &str = include_str!("../../scripts/manual/run_upstream_browser_av_sync.sh"); const MIRRORED_SYNC_SCRIPT: &str = include_str!("../../scripts/manual/run_upstream_mirrored_av_sync.sh"); const LOCAL_STIMULUS: &str = include_str!("../../scripts/manual/local_av_stimulus.py"); #[test] fn upstream_sync_script_tunnels_auto_server_addr_through_ssh() { for expected in [ "cleanup_server_tunnel", "pick_local_server_tunnel_port", "wait_for_server_tunnel", "start_server_tunnel", "ExitOnForwardFailure=yes", "127.0.0.1:${local_port}:127.0.0.1:${remote_port}", "LESAVKA_SERVER_SCHEME=${LESAVKA_SERVER_SCHEME:-https}", "LESAVKA_TLS_DOMAIN=${LESAVKA_TLS_DOMAIN:-lesavka-server}", "RESOLVED_LESAVKA_SERVER_ADDR=\"${LESAVKA_SERVER_SCHEME}://127.0.0.1:${SERVER_TUNNEL_LOCAL_PORT}\"", "LESAVKA_TLS_DOMAIN=\"${LESAVKA_TLS_DOMAIN}\"", "tunneled to ${LESAVKA_SERVER_HOST}:127.0.0.1:${SERVER_TUNNEL_REMOTE_PORT}", "CAPTURE_READY_MARKER=\"__LESAVKA_CAPTURE_READY__\"", "LOCAL_OUTPUT_DIR=${LOCAL_OUTPUT_DIR:-/tmp}", "LOCAL_REPORT_DIR=\"${LOCAL_OUTPUT_DIR%/}/lesavka-sync-probe-${STAMP}\"", "LOCAL_ANALYSIS_JSON=\"${LOCAL_REPORT_DIR}/report.json\"", "LOCAL_EVENTS_CSV=\"${LOCAL_REPORT_DIR}/events.csv\"", "LEAD_IN_SECONDS=${LEAD_IN_SECONDS:-0}", "PROBE_TIMEOUT_SECONDS=${PROBE_TIMEOUT_SECONDS:-$((PROBE_DURATION_SECONDS + PROBE_WARMUP_SECONDS + 20))}", "timeout --signal=INT \"${PROBE_TIMEOUT_SECONDS}\" \"${PROBE_BIN}\"", "sync probe timed out after ${PROBE_TIMEOUT_SECONDS}s", "VIDIOC_STREAMON.*Connection timed out", "the UVC host opened before MJPEG frames reached the gadget", "Tethys capture failed before the sync probe could start", "wait_for_capture_ready", "Timed out waiting for Tethys capture to become ready", "grep -q \"${CAPTURE_READY_MARKER}\"", "Lesavka UVC video device not found on Tethys; refusing to fall back to an unrelated webcam/capture card.", "resolve_alsa_audio_device", "PipeWire Lesavka source not found; falling back to ALSA device", "Lesavka audio source not found in PipeWire or ALSA; capture host does not currently expose the gadget microphone.", "artifact_dir: ${LOCAL_REPORT_DIR}", "events_csv: ${LOCAL_EVENTS_CSV}", "==> Lesavka versions under test", "lesavka-relayctl", "--bin lesavka-relayctl", "client_revision=", "server_version=", "server_revision=", "combined version+revision", ] { assert!( SYNC_SCRIPT.contains(expected), "manual sync script should contain {expected}" ); } assert!( !SYNC_SCRIPT.contains( "RESOLVED_LESAVKA_SERVER_ADDR=\"http://${LESAVKA_SERVER_CONNECT_HOST}:${port}\"" ), "auto server resolution should not guess a public gRPC host when SSH is already required" ); } #[test] fn browser_sync_script_can_delegate_to_a_real_path_driver() { for expected in [ "BROWSER_RECORD_SECONDS=${BROWSER_RECORD_SECONDS:-${PROBE_DURATION_SECONDS}}", "BROWSER_SYNC_DRIVER_COMMAND=${BROWSER_SYNC_DRIVER_COMMAND:-}", "SYNC_ANALYZE_EVENT_WIDTH_CODES=${SYNC_ANALYZE_EVENT_WIDTH_CODES:-}", "==> running custom browser sync driver", "bash -lc \"${BROWSER_SYNC_DRIVER_COMMAND}\"", "--event-width-codes", "--report-dir \"${LOCAL_REPORT_DIR}\"", "for attempt in 1 2 3 4 5", "capture fetch attempt ${attempt} failed; retrying", "failed to fetch browser capture from ${TETHYS_HOST}:${REMOTE_CAPTURE}", ] { assert!( BROWSER_SYNC_SCRIPT.contains(expected), "browser sync script should contain {expected}" ); } } #[test] fn mirrored_sync_script_uses_real_client_capture_path() { for expected in [ "local_av_stimulus.py", "lesavka-client", "LESAVKA_HEADLESS=1", "LESAVKA_MEDIA_CONTROL=\"${MEDIA_CONTROL}\"", "--no-launcher --server \"${RESOLVED_LESAVKA_SERVER_ADDR}\"", "BROWSER_SYNC_DRIVER_COMMAND=\"${driver_command}\"", "SYNC_ANALYZE_EVENT_WIDTH_CODES=\"${PROBE_EVENT_WIDTH_CODES}\"", "run_upstream_browser_av_sync.sh", "wait_for_stimulus_page_ready 15", "Point the real webcam at the stimulus window", "==> Lesavka versions under test", "lesavka-relayctl", "--bin lesavka-relayctl", "client_revision=", "server_version=", "server_revision=", "combined version+revision", "run_status=0", "run_mirrored_segments || run_status=$?", "LESAVKA_SYNC_APPLY_CALIBRATION=${LESAVKA_SYNC_APPLY_CALIBRATION:-0}", "LESAVKA_SYNC_SAVE_CALIBRATION=${LESAVKA_SYNC_SAVE_CALIBRATION:-0}", "LESAVKA_SYNC_CALIBRATION_TARGET=${LESAVKA_SYNC_CALIBRATION_TARGET:-video}", "LESAVKA_SYNC_CALIBRATION_SEGMENTS=${LESAVKA_SYNC_CALIBRATION_SEGMENTS:-1}", "LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS=${LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS:-3}", "LESAVKA_SYNC_CALIBRATION_SEGMENTS must be a positive integer", "run_mirrored_segments", "for segment in $(seq 1 \"${LESAVKA_SYNC_CALIBRATION_SEGMENTS}\")", "segment-${segment}", "calibration-before.env", "planner-before.env", "calibration-decision.env", "settling ${LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS}s before next calibration segment", "print_upstream_calibration_state \"before mirrored run\"", "maybe_apply_probe_calibration", "calibration_ready=${calibration_ready}", "calibration apply refused: analyzer did not mark this report calibration-ready", "calibrate \"${calibration_apply_audio_delta_us}\" \"${calibration_apply_video_delta_us}\"", "calibration-save-default", "print_upstream_sync_state \"after mirrored run\"", "print_upstream_calibration_state \"after mirrored run\"", "==> mirrored probe failed", ] { assert!( MIRRORED_SYNC_SCRIPT.contains(expected), "mirrored sync script should contain {expected}" ); } assert!( !MIRRORED_SYNC_SCRIPT.contains("lesavka-sync-probe"), "mirrored sync must not use the synthetic direct sender" ); } #[test] fn local_stimulus_matches_sync_analyzer_pulse_contract() { for expected in [ "--warmup-seconds", "--pulse-period-ms", "--pulse-width-ms", "--marker-tick-period", "--event-width-codes", "event_width_codes", "widthCode", "oscillator.frequency.value = 880", "setStatus(`ready", "Point the real webcam at this window", ] { assert!( LOCAL_STIMULUS.contains(expected), "local stimulus should contain {expected}" ); } } #[test] fn manual_probe_python_servers_use_reentrant_state_locks() { const BROWSER_CONSUMER: &str = include_str!("../../scripts/manual/browser_consumer_probe.py"); for (name, script) in [ ("local stimulus", LOCAL_STIMULUS), ("browser consumer", BROWSER_CONSUMER), ] { assert!( script.contains("threading.RLock()"), "{name} server request handlers call snapshot while holding state lock; use RLock to avoid /start deadlocks" ); } }