fix test_backup_mode_suffix_without_backup_option test on mac (#9891)

* fix test_backup_mode_suffix_without_backup_option test on mac
This commit is contained in:
Sylvestre Ledru
2025-12-28 22:37:02 +01:00
committed by GitHub
parent d946dce1a9
commit 8a40150b89
2 changed files with 44 additions and 3 deletions
+43 -3
View File
@@ -29,12 +29,23 @@ cfg_langinfo! {
use std::ffi::CStr;
use std::sync::OnceLock;
use nix::libc;
#[cfg(test)]
use std::sync::Mutex;
}
cfg_langinfo! {
/// Cached locale date/time format string
static DEFAULT_FORMAT_CACHE: OnceLock<&'static str> = OnceLock::new();
/// Mutex to serialize setlocale() calls during tests.
///
/// setlocale() is process-global, so parallel tests that call it can
/// interfere with each other. This mutex ensures only one test accesses
/// locale functions at a time.
#[cfg(test)]
static LOCALE_MUTEX: Mutex<()> = Mutex::new(());
/// Returns the default date format string for the current locale.
///
/// The format respects locale preferences for time display (12-hour vs 24-hour),
@@ -55,6 +66,11 @@ cfg_langinfo! {
/// Retrieves the date/time format string from the system locale
fn get_locale_format_string() -> Option<String> {
// In tests, acquire mutex to prevent race conditions with setlocale()
// which is process-global and not thread-safe
#[cfg(test)]
let _lock = LOCALE_MUTEX.lock().unwrap();
unsafe {
// Set locale from environment variables
libc::setlocale(libc::LC_TIME, c"".as_ptr());
@@ -158,11 +174,24 @@ mod tests {
#[test]
fn test_c_locale_format() {
// Save original locale
// Acquire mutex to prevent interference with other tests
let _lock = LOCALE_MUTEX.lock().unwrap();
// Save original locale (both environment and process locale)
let original_lc_all = std::env::var("LC_ALL").ok();
let original_lc_time = std::env::var("LC_TIME").ok();
let original_lang = std::env::var("LANG").ok();
// Save current process locale
let original_process_locale = unsafe {
let ptr = libc::setlocale(libc::LC_TIME, std::ptr::null());
if ptr.is_null() {
None
} else {
CStr::from_ptr(ptr).to_str().ok().map(|s| s.to_string())
}
};
unsafe {
// Set C locale
std::env::set_var("LC_ALL", "C");
@@ -177,7 +206,7 @@ mod tests {
if d_t_fmt_ptr.is_null() {
None
} else {
std::ffi::CStr::from_ptr(d_t_fmt_ptr).to_str().ok()
CStr::from_ptr(d_t_fmt_ptr).to_str().ok()
}
};
@@ -190,7 +219,7 @@ mod tests {
assert!(uses_24_hour, "C locale should use 24-hour format, got: {locale_format}");
}
// Restore original locale
// Restore original environment variables
unsafe {
if let Some(val) = original_lc_all {
std::env::set_var("LC_ALL", val);
@@ -208,6 +237,17 @@ mod tests {
std::env::remove_var("LANG");
}
}
// Restore original process locale
unsafe {
if let Some(locale) = original_process_locale {
let c_locale = std::ffi::CString::new(locale).unwrap();
libc::setlocale(libc::LC_TIME, c_locale.as_ptr());
} else {
// Restore from environment
libc::setlocale(libc::LC_TIME, c"".as_ptr());
}
}
}
#[test]
@@ -683,6 +683,7 @@ mod tests {
let result = determine_backup_mode(&matches).unwrap();
assert_eq!(result, BackupMode::Numbered);
unsafe { env::remove_var(ENV_VERSION_CONTROL) };
}
#[test]