From 2d3b660503eb1b80f2ff1e8200f6498ba478d421 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:27:00 +0900 Subject: [PATCH 1/2] test(verify): opt-in 30-minute Studio and Instant soak recordings --- .github/workflows/verify-recording.yml | 6 ++- crates/verify/tests/recording.rs | 51 +++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/.github/workflows/verify-recording.yml b/.github/workflows/verify-recording.yml index 28a0af88722..58159a2e7c6 100644 --- a/.github/workflows/verify-recording.yml +++ b/.github/workflows/verify-recording.yml @@ -51,6 +51,9 @@ on: type: choice options: [blacksmith, hosted, both] default: blacksmith + soak_secs: + description: "Adds the recording/soak/* cases at this length (seconds, at most 1800); set case_filter to recording/soak/* to run only them" + default: "" schedule: - cron: "41 3 * * *" pull_request: @@ -149,13 +152,14 @@ jobs: matrix: runner: ${{ fromJSON(needs.scope.outputs.runners) }} runs-on: ${{ matrix.runner }} - timeout-minutes: 45 + timeout-minutes: ${{ inputs.soak_secs != '' && 180 || 45 }} env: CAP_VERIFY_CAPTURE: display CAP_VERIFY_REQUIRE_CAPTURE: "1" CAP_VERIFY_TIER: ${{ needs.scope.outputs.tier }} CAP_VERIFY_REPEAT: ${{ inputs.repeat || (github.event_name == 'schedule' && '3') || '1' }} CAP_VERIFY_CASE: ${{ inputs.case_filter || '' }} + CAP_VERIFY_SOAK_SECS: ${{ inputs.soak_secs || '' }} CAP_VERIFY_KEEP: ${{ inputs.keep_artifacts && '1' || '' }} CAP_VERIFY_SCRATCH: ${{ github.workspace }}/verify-scratch CAP_VERIFY_REPORT_DIR: ${{ github.workspace }}/verify-report diff --git a/crates/verify/tests/recording.rs b/crates/verify/tests/recording.rs index 33c4a3a163b..639c99c84a3 100644 --- a/crates/verify/tests/recording.rs +++ b/crates/verify/tests/recording.rs @@ -114,7 +114,7 @@ struct Spec { } fn specs() -> Vec { - vec![ + let mut specs = vec![ Spec { id: "recording/studio-screen/fragmented", tier: Tier::Fast, @@ -289,6 +289,55 @@ fn specs() -> Vec { mic: true, system_audio: true, }, + ]; + specs.extend(soak_specs()); + specs +} + +/// `CAP_VERIFY_SOAK_SECS=` adds a long Studio recording with a +/// camera and a long Instant recording, for drift, frame loss and memory over +/// a real session length (up to 30 minutes: past that the microphone's +/// marker indices run out). Run them with `CAP_VERIFY_TIER=full` and +/// `CAP_VERIFY_CASE='recording/soak/*'`. +fn soak_specs() -> Vec { + let Some(seconds) = std::env::var("CAP_VERIFY_SOAK_SECS") + .ok() + .and_then(|v| v.parse::().ok()) + .filter(|&s| s > 0.0) + else { + return vec![]; + }; + let seconds = seconds.min(1800.0); + vec![ + Spec { + id: "recording/soak/studio-camera", + tier: Tier::Full, + mode: Mode::Studio { + fragmented: true, + camera: true, + }, + seconds, + stimulus_fps: STIMULUS_FPS_30, + holds: vec![(seconds / 3.0, 3.0), (2.0 * seconds / 3.0, 10.0)], + camera_drops_at: vec![], + gated: true, + mic_delay: 0.0, + mic: true, + system_audio: true, + }, + Spec { + id: "recording/soak/instant", + tier: Tier::Full, + mode: Mode::Instant, + seconds, + stimulus_fps: STIMULUS_FPS_30, + holds: vec![(seconds / 2.0, 5.0)], + camera_drops_at: vec![], + gated: true, + mic_delay: 0.0, + mic: true, + system_audio: true, + }, ] } From dead545d55f0c8654721113f3d43dfa99dd7e4ed Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Sat, 17 Oct 2026 14:26:29 +0900 Subject: [PATCH 2/2] test(verify): reject an invalid CAP_VERIFY_SOAK_SECS instead of running no soak --- crates/verify/tests/recording.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/verify/tests/recording.rs b/crates/verify/tests/recording.rs index 639c99c84a3..5ad4ff5d698 100644 --- a/crates/verify/tests/recording.rs +++ b/crates/verify/tests/recording.rs @@ -294,19 +294,23 @@ fn specs() -> Vec { specs } -/// `CAP_VERIFY_SOAK_SECS=` adds a long Studio recording with a -/// camera and a long Instant recording, for drift, frame loss and memory over -/// a real session length (up to 30 minutes: past that the microphone's -/// marker indices run out). Run them with `CAP_VERIFY_TIER=full` and -/// `CAP_VERIFY_CASE='recording/soak/*'`. +/// `CAP_VERIFY_SOAK_SECS`: at most 1800 s, because the microphone's 12-bit +/// marker index (one marker every 0.5 s) runs out past 34 minutes. fn soak_specs() -> Vec { - let Some(seconds) = std::env::var("CAP_VERIFY_SOAK_SECS") + let Some(value) = std::env::var("CAP_VERIFY_SOAK_SECS") .ok() - .and_then(|v| v.parse::().ok()) - .filter(|&s| s > 0.0) + .filter(|v| !v.trim().is_empty()) else { return vec![]; }; + let seconds = value + .trim() + .parse::() + .ok() + .filter(|s| s.is_finite() && *s > 0.0) + .unwrap_or_else(|| { + panic!("CAP_VERIFY_SOAK_SECS={value:?} is not a positive number of seconds") + }); let seconds = seconds.min(1800.0); vec![ Spec {