diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index ca06aa2b0..c70abd284 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -101,6 +101,7 @@ jobs: uses: Swatinem/rust-cache@v2 with: shared-key: oak-${{ matrix.distro }} + cache-on-failure: true - name: Cache project FFmpeg uses: actions/cache@v4 @@ -175,6 +176,7 @@ jobs: uses: Swatinem/rust-cache@v2 with: shared-key: oak-appimage + cache-on-failure: true - name: Cache project FFmpeg uses: actions/cache@v4 @@ -241,6 +243,7 @@ jobs: uses: Swatinem/rust-cache@v2 with: shared-key: oak-workspace + cache-on-failure: true - name: Cache project FFmpeg uses: actions/cache@v4 @@ -368,6 +371,7 @@ jobs: uses: Swatinem/rust-cache@v2 with: shared-key: oak-workspace + cache-on-failure: true - name: Cache project FFmpeg uses: actions/cache@v4 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4d41e16d..23bf4372b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,6 +152,7 @@ jobs: uses: Swatinem/rust-cache@v2 with: shared-key: oak-workspace + cache-on-failure: true # The project FFmpeg (release/8.0, static, all free codecs + hwaccel) # is built by tooling/ffmpeg/build-ffmpeg.sh — 10-20 min on a cold @@ -208,9 +209,30 @@ jobs: # xvfb + 24-bit screen: the gpui #[gpui::test] tests open real windows # and render through wgpu on Mesa's software Vulkan (lavapipe). + # The watchdog bounds the step: a deadlocked test produces no output + # and no failure, so after 1500 s (a green run needs ~4 min) it dumps + # every hung process's thread stacks and kills the suite. - name: Test (Linux) if: runner.os == 'Linux' - run: xvfb-run -a -s "-screen 0 1920x1080x24" cargo test --workspace --locked + run: | + sudo apt-get install -y gdb + xvfb-run -a -s "-screen 0 1920x1080x24" cargo test --workspace --locked & + TEST_PID=$! + ( + sleep 1500 + echo "::warning::test suite exceeded 1500s; dumping hung-process stacks" + for p in $(pgrep -f 'target/debug/deps/|target/debug/oak-worker'); do + echo "===== thread stacks of pid $p ($(readlink /proc/$p/exe 2>/dev/null)) =====" + sudo gdb -batch -ex 'thread apply all bt' -p "$p" || true + done + pkill -9 -f 'target/debug/deps/' || true + pkill -9 -f 'target/debug/oak-worker' || true + ) & + WATCHDOG_PID=$! + wait $TEST_PID + rc=$? + kill $WATCHDOG_PID 2>/dev/null || true + exit $rc # A crashing (SIGSEGV) test gives no Rust backtrace; rerun the # crashing test binaries under gdb to capture the native stack. diff --git a/crates/oakstorage/src/backends/database/mod.rs b/crates/oakstorage/src/backends/database/mod.rs index da1940e03..fdf28f7ad 100644 --- a/crates/oakstorage/src/backends/database/mod.rs +++ b/crates/oakstorage/src/backends/database/mod.rs @@ -1484,13 +1484,21 @@ mod tests { StorageUri::parse(s).unwrap() } + /// An absolute database path for the platform: `/tmp/...` is not + /// absolute on Windows (no drive prefix), and parse_target rejects + /// relative paths. + #[cfg(unix)] + const ABS_DB: &str = "/tmp/lib.db"; + #[cfg(windows)] + const ABS_DB: &str = "C:/tmp/lib.db"; + #[test] fn parse_target_sqlite_absolute() { - let t = parse_target(&uri("oakdb+sqlite:///tmp/lib.db")).unwrap(); + let t = parse_target(&uri(&format!("oakdb+sqlite://{ABS_DB}"))).unwrap(); assert_eq!( t, DbTarget::Sqlite { - path: "/tmp/lib.db".to_string(), + path: ABS_DB.to_string(), project: None } ); @@ -1498,11 +1506,14 @@ mod tests { #[test] fn parse_target_sqlite_project_query() { - let t = parse_target(&uri("oakdb+sqlite:///tmp/lib.db?project={abc-123}")).unwrap(); + let t = parse_target(&uri(&format!( + "oakdb+sqlite://{ABS_DB}?project={{abc-123}}" + ))) + .unwrap(); assert_eq!( t, DbTarget::Sqlite { - path: "/tmp/lib.db".to_string(), + path: ABS_DB.to_string(), project: Some("{abc-123}".to_string()) } );