From 14351f121f6fc8c84b7c6c6eda78ad210e93cfcb Mon Sep 17 00:00:00 2001 From: JJ Liebig Date: Thu, 17 Sep 2026 22:43:35 +0200 Subject: test: skip windows symlink tests without symlink privilege (#4311) Windows refuses file symlinks with ERROR_PRIVILEGE_NOT_HELD (1314) unless the test process is elevated or Developer Mode is enabled, which broke non-admin local runs. Share a helper that reports the missing privilege so the two symlink tests skip only the symlink-dependent assertions. --- src/integration/test_support.rs | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/integration/test_support.rs (limited to 'src/integration/test_support.rs') diff --git a/src/integration/test_support.rs b/src/integration/test_support.rs new file mode 100644 index 00000000..638beb00 --- /dev/null +++ b/src/integration/test_support.rs @@ -0,0 +1,49 @@ +//! Shared helpers for integration tests. + +use std::path::Path; + +/// Windows refuses file symlinks with `ERROR_PRIVILEGE_NOT_HELD` when the +/// process is neither elevated nor running with Developer Mode enabled. +#[cfg(windows)] +const ERROR_PRIVILEGE_NOT_HELD: i32 = 1314; + +#[cfg(windows)] +fn symlink_privilege_denied(error: &std::io::Error) -> bool { + error.raw_os_error() == Some(ERROR_PRIVILEGE_NOT_HELD) +} + +/// Create a file symlink, returning `false` when Windows denied the symlink +/// privilege. Callers skip symlink-only assertions on `false` instead of +/// failing an ordinary non-elevated local test run. +#[cfg(unix)] +pub(super) fn symlink_file(target: &Path, link: &Path) -> bool { + std::os::unix::fs::symlink(target, link).expect("create symlink"); + true +} + +#[cfg(windows)] +pub(super) fn symlink_file(target: &Path, link: &Path) -> bool { + match std::os::windows::fs::symlink_file(target, link) { + Ok(()) => true, + Err(error) if symlink_privilege_denied(&error) => { + eprintln!("skipping symlink test: Windows denied SeCreateSymbolicLinkPrivilege"); + false + } + Err(error) => panic!("create symlink {}: {error}", link.display()), + } +} + +#[cfg(all(test, windows))] +mod tests { + use super::*; + + #[test] + fn symlink_privilege_error_is_detected() { + assert!(symlink_privilege_denied( + &std::io::Error::from_raw_os_error(ERROR_PRIVILEGE_NOT_HELD) + )); + assert!(!symlink_privilege_denied( + &std::io::Error::from_raw_os_error(/* ERROR_ACCESS_DENIED */ 5) + )); + } +} -- cgit v1.2.3