Stop using io_thread pool in test_universal

Just use ordinary threads.

Also allow universal variable tests to run in parallel, by using real
temporary paths.
This commit is contained in:
Peter Ammon
2025-10-19 12:56:00 -07:00
parent d6f0e1fdf2
commit e299b71560
2 changed files with 43 additions and 41 deletions

View File

@@ -3,19 +3,28 @@
use crate::common::wcs2osstring;
use crate::env::{EnvVar, EnvVarFlags, VarTable};
use crate::env_universal_common::{EnvUniversal, UvarFormat};
use crate::reader::fake_scoped_reader;
use crate::tests::prelude::*;
use crate::threads::{iothread_drain_all, iothread_perform};
use crate::wchar::prelude::*;
use crate::wutil::{INVALID_FILE_ID, file_id_for_path};
const UVARS_PER_THREAD: usize = 8;
const UVARS_TEST_PATH: &wstr = L!("test/fish_uvars_test/varsfile.txt");
fn test_universal_helper(x: usize) {
/// Creates a unique temporary directory and file path for universal variable tests.
/// Returns (directory_path, file_path).
fn make_test_uvar_path(test_name: &str) -> (std::path::PathBuf, WString) {
let test_dir = std::env::temp_dir().join(format!(
"fish_test_{}_{:?}",
test_name,
std::thread::current().id()
));
let test_path = sprintf!("%s/varsfile.txt", test_dir.to_string_lossy());
(test_dir, test_path)
}
fn test_universal_helper(x: usize, path: &wstr) {
let _cleanup = test_init();
let mut uvars = EnvUniversal::new();
uvars.initialize_at_path(UVARS_TEST_PATH.to_owned());
uvars.initialize_at_path(path.to_owned());
for j in 0..UVARS_PER_THREAD {
let key = sprintf!("key_%d_%d", x, j);
@@ -35,23 +44,28 @@ fn test_universal_helper(x: usize) {
}
#[test]
#[serial]
fn test_universal() {
let _cleanup = test_init();
let _ = std::fs::remove_dir_all("test/fish_uvars_test/");
std::fs::create_dir_all("test/fish_uvars_test/").unwrap();
let parser = TestParser::new();
let mut reader = fake_scoped_reader(&parser);
let (test_dir, test_path) = make_test_uvar_path("universal");
let _ = std::fs::remove_dir_all(&test_dir);
std::fs::create_dir_all(&test_dir).unwrap();
let threads = 1;
let mut handles = Vec::new();
for i in 0..threads {
iothread_perform(move || test_universal_helper(i));
let path = test_path.to_owned();
handles.push(std::thread::spawn(move || {
test_universal_helper(i, &path);
}));
}
for h in handles {
h.join().unwrap();
}
iothread_drain_all(&mut reader);
let mut uvars = EnvUniversal::new();
uvars.initialize_at_path(UVARS_TEST_PATH.to_owned());
uvars.initialize_at_path(test_path.to_owned());
for i in 0..threads {
for j in 0..UVARS_PER_THREAD {
@@ -69,7 +83,7 @@ fn test_universal() {
}
}
std::fs::remove_dir_all("test/fish_uvars_test/").unwrap();
std::fs::remove_dir_all(&test_dir).unwrap();
}
#[test]
@@ -211,18 +225,18 @@ fn test_universal_parsing_legacy() {
}
#[test]
#[serial]
fn test_universal_callbacks() {
let _cleanup = test_init();
std::fs::create_dir_all("test/fish_uvars_test/").unwrap();
let (test_dir, test_path) = make_test_uvar_path("callbacks");
std::fs::create_dir_all(&test_dir).unwrap();
let mut uvars1 = EnvUniversal::new();
let mut uvars2 = EnvUniversal::new();
let mut callbacks = uvars1
.initialize_at_path(UVARS_TEST_PATH.to_owned())
.initialize_at_path(test_path.to_owned())
.unwrap_or_default();
callbacks.append(
&mut uvars2
.initialize_at_path(UVARS_TEST_PATH.to_owned())
.initialize_at_path(test_path.to_owned())
.unwrap_or_default(),
);
@@ -278,7 +292,7 @@ macro_rules! sync {
assert_eq!(callbacks[1].val.as_ref().unwrap().as_string(), L!("1"));
assert_eq!(callbacks[2].key, L!("delta"));
assert_eq!(callbacks[2].val, None);
std::fs::remove_dir_all("test/fish_uvars_test/").unwrap();
std::fs::remove_dir_all(&test_dir).unwrap();
}
#[test]
@@ -304,23 +318,20 @@ macro_rules! validate {
}
#[test]
#[serial]
fn test_universal_ok_to_save() {
let _cleanup = test_init();
// Ensure we don't try to save after reading from a newer fish.
std::fs::create_dir_all("test/fish_uvars_test/").unwrap();
let (test_dir, test_path) = make_test_uvar_path("ok_to_save");
std::fs::create_dir_all(&test_dir).unwrap();
let contents = b"# VERSION: 99999.99\n";
std::fs::write(wcs2osstring(UVARS_TEST_PATH), contents).unwrap();
std::fs::write(wcs2osstring(&test_path), contents).unwrap();
let before_id = file_id_for_path(UVARS_TEST_PATH);
assert_ne!(
before_id, INVALID_FILE_ID,
"UVARS_TEST_PATH should be readable"
);
let before_id = file_id_for_path(&test_path);
assert_ne!(before_id, INVALID_FILE_ID, "test_path should be readable");
let mut uvars = EnvUniversal::new();
uvars
.initialize_at_path(UVARS_TEST_PATH.to_owned())
.initialize_at_path(test_path.to_owned())
.unwrap_or_default();
assert!(!uvars.is_ok_to_save(), "Should not be OK to save");
uvars.sync();
@@ -331,10 +342,7 @@ fn test_universal_ok_to_save() {
);
// Ensure file is same.
let after_id = file_id_for_path(UVARS_TEST_PATH);
assert_eq!(
before_id, after_id,
"UVARS_TEST_PATH should not have changed",
);
std::fs::remove_dir_all("test/fish_uvars_test/").unwrap();
let after_id = file_id_for_path(&test_path);
assert_eq!(before_id, after_id, "test_path should not have changed",);
std::fs::remove_dir_all(&test_dir).unwrap();
}

View File

@@ -507,12 +507,6 @@ pub fn iothread_service_main(ctx: &mut Reader) {
io_thread_pool().invoke_completions(ctx);
}
/// Does nasty polling via select(), only used for testing.
#[cfg(test)]
pub(crate) fn iothread_drain_all(ctx: &mut Reader) {
io_thread_pool().drain_all(ctx);
}
/// `Debounce` is a simple class which executes one function on a background thread while enqueuing
/// at most one more. Subsequent execution requests overwrite the enqueued one. It takes an optional
/// timeout; if a handler does not finish within the timeout then a new thread is spawned to service