Skip to content

Commit 8a40150

Browse files
authored
fix test_backup_mode_suffix_without_backup_option test on mac (#9891)
* fix test_backup_mode_suffix_without_backup_option test on mac
1 parent d946dce commit 8a40150

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

src/uu/date/src/locale.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,23 @@ cfg_langinfo! {
2929
use std::ffi::CStr;
3030
use std::sync::OnceLock;
3131
use nix::libc;
32+
33+
#[cfg(test)]
34+
use std::sync::Mutex;
3235
}
3336

3437
cfg_langinfo! {
3538
/// Cached locale date/time format string
3639
static DEFAULT_FORMAT_CACHE: OnceLock<&'static str> = OnceLock::new();
3740

41+
/// Mutex to serialize setlocale() calls during tests.
42+
///
43+
/// setlocale() is process-global, so parallel tests that call it can
44+
/// interfere with each other. This mutex ensures only one test accesses
45+
/// locale functions at a time.
46+
#[cfg(test)]
47+
static LOCALE_MUTEX: Mutex<()> = Mutex::new(());
48+
3849
/// Returns the default date format string for the current locale.
3950
///
4051
/// The format respects locale preferences for time display (12-hour vs 24-hour),
@@ -55,6 +66,11 @@ cfg_langinfo! {
5566

5667
/// Retrieves the date/time format string from the system locale
5768
fn get_locale_format_string() -> Option<String> {
69+
// In tests, acquire mutex to prevent race conditions with setlocale()
70+
// which is process-global and not thread-safe
71+
#[cfg(test)]
72+
let _lock = LOCALE_MUTEX.lock().unwrap();
73+
5874
unsafe {
5975
// Set locale from environment variables
6076
libc::setlocale(libc::LC_TIME, c"".as_ptr());
@@ -158,11 +174,24 @@ mod tests {
158174

159175
#[test]
160176
fn test_c_locale_format() {
161-
// Save original locale
177+
// Acquire mutex to prevent interference with other tests
178+
let _lock = LOCALE_MUTEX.lock().unwrap();
179+
180+
// Save original locale (both environment and process locale)
162181
let original_lc_all = std::env::var("LC_ALL").ok();
163182
let original_lc_time = std::env::var("LC_TIME").ok();
164183
let original_lang = std::env::var("LANG").ok();
165184

185+
// Save current process locale
186+
let original_process_locale = unsafe {
187+
let ptr = libc::setlocale(libc::LC_TIME, std::ptr::null());
188+
if ptr.is_null() {
189+
None
190+
} else {
191+
CStr::from_ptr(ptr).to_str().ok().map(|s| s.to_string())
192+
}
193+
};
194+
166195
unsafe {
167196
// Set C locale
168197
std::env::set_var("LC_ALL", "C");
@@ -177,7 +206,7 @@ mod tests {
177206
if d_t_fmt_ptr.is_null() {
178207
None
179208
} else {
180-
std::ffi::CStr::from_ptr(d_t_fmt_ptr).to_str().ok()
209+
CStr::from_ptr(d_t_fmt_ptr).to_str().ok()
181210
}
182211
};
183212

@@ -190,7 +219,7 @@ mod tests {
190219
assert!(uses_24_hour, "C locale should use 24-hour format, got: {locale_format}");
191220
}
192221

193-
// Restore original locale
222+
// Restore original environment variables
194223
unsafe {
195224
if let Some(val) = original_lc_all {
196225
std::env::set_var("LC_ALL", val);
@@ -208,6 +237,17 @@ mod tests {
208237
std::env::remove_var("LANG");
209238
}
210239
}
240+
241+
// Restore original process locale
242+
unsafe {
243+
if let Some(locale) = original_process_locale {
244+
let c_locale = std::ffi::CString::new(locale).unwrap();
245+
libc::setlocale(libc::LC_TIME, c_locale.as_ptr());
246+
} else {
247+
// Restore from environment
248+
libc::setlocale(libc::LC_TIME, c"".as_ptr());
249+
}
250+
}
211251
}
212252

213253
#[test]

src/uucore/src/lib/features/backup_control.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ mod tests {
683683
let result = determine_backup_mode(&matches).unwrap();
684684

685685
assert_eq!(result, BackupMode::Numbered);
686+
unsafe { env::remove_var(ENV_VERSION_CONTROL) };
686687
}
687688

688689
#[test]

0 commit comments

Comments
 (0)