diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afb158553..b3a38c51e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -340,6 +340,10 @@ jobs: "FFMPEG_DIR=$prefix" >> $env:GITHUB_ENV "PKG_CONFIG_PATH=$prefix\lib\pkgconfig" >> $env:GITHUB_ENV "$prefix\tools\pkgconf" >> $env:GITHUB_PATH + # The test binaries link vcpkg's dynamic DLLs (ffmpeg and its + # codecs): without this the runner reports STATUS_DLL_NOT_FOUND + # when the first test executable starts. + "$prefix\bin" >> $env:GITHUB_PATH # Bundled OCIO: ocio-sys' vendored sources build with the MSVC # toolchain (what they need — the MSYS2 package was the # workaround, not the preference), so no OCIO_INSTALL_DIR and diff --git a/crates/oak-storage/tests/database_test.rs b/crates/oak-storage/tests/database_test.rs index 1a6e8a31c..a80ef23b7 100644 --- a/crates/oak-storage/tests/database_test.rs +++ b/crates/oak-storage/tests/database_test.rs @@ -1090,6 +1090,28 @@ fn invalid_uri_matrix() { ); } +/// Linux CI containers run as root, which bypasses the file permission bits +/// (`CAP_DAC_OVERRIDE`), so the read-only failure paths cannot be exercised +/// there. +#[cfg(target_os = "linux")] +fn running_as_root() -> bool { + std::fs::read_to_string("/proc/self/status") + .ok() + .and_then(|status| { + status + .lines() + .find(|line| line.starts_with("Uid:")) + .and_then(|line| line.split_whitespace().nth(1).map(str::to_string)) + }) + .map(|uid| uid == "0") + .unwrap_or(false) +} + +#[cfg(not(target_os = "linux"))] +fn running_as_root() -> bool { + false +} + /// Write failures surface as errors, not panics or silent corruption: /// (a) read-only database files, (b) an out-of-range undo target, and /// (c) concurrent writers on one file. @@ -1120,8 +1142,15 @@ fn failure_paths_report_cleanly() { std::fs::set_permissions(f, p).unwrap(); } let fresh = DatabaseBackend::new(); - let err = save_project(&fresh, &project, &uri).err().unwrap(); - assert_eq!(err.code(), OAKSTORAGE_E_IO, "read-only library write must fail"); + let result = save_project(&fresh, &project, &uri); + if running_as_root() { + // The openKylin CI container runs as root: the read-only bits do not + // stop the write, so the failure cannot be asserted here. + println!("SKIP: read-only library write check needs an unprivileged user"); + } else { + let err = result.err().expect("read-only library write must fail"); + assert_eq!(err.code(), OAKSTORAGE_E_IO, "read-only library write must fail"); + } for (f, p) in targets.iter().zip(saved) { std::fs::set_permissions(f, p).unwrap(); }