From d2c8d46a7ba841558f76993e53bf1db63e716e0a Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 24 Oct 2026 08:03:17 -0700 Subject: [PATCH] Tests: the launch-list read-only test compares a held lock file without reading it On Windows, tests_launch_library::listing_the_libraries_leaves_every_folder_byte_identical failed every time with os error 33. Its snapshot read every file in the folder, including the lock file of the library the test holds with LibraryLock::acquire. On Windows that lock is LockFileEx, and reading the locked bytes through another handle fails with ERROR_LOCK_VIOLATION. The snapshot now records each file's length as well as its contents and modification time. When the read of a catalog.lock fails with os error 33 on Windows, its contents are left out and the file is compared by its length and modification time. Every other file is still compared byte for byte, and on other platforms the held lock file is too. The app does not read a held lock file anywhere, so only the test changes. --- crates/ui-egui/src/tests_launch_library.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/crates/ui-egui/src/tests_launch_library.rs b/crates/ui-egui/src/tests_launch_library.rs index b0b3bec6b..61c894750 100644 --- a/crates/ui-egui/src/tests_launch_library.rs +++ b/crates/ui-egui/src/tests_launch_library.rs @@ -129,8 +129,8 @@ fn the_list_checks_each_library_and_selects_the_last_one() { let _ = std::fs::remove_dir_all(&dir); } -/// Every file under `dir`: relative path → (contents, modification time). -fn snapshot(dir: &Path) -> std::collections::BTreeMap, std::time::SystemTime)> { +/// Every file under `dir`: relative path → (contents, length, modification time). +fn snapshot(dir: &Path) -> std::collections::BTreeMap>, u64, std::time::SystemTime)> { let mut out = std::collections::BTreeMap::new(); let mut todo = vec![dir.to_path_buf()]; while let Some(d) = todo.pop() { @@ -140,13 +140,25 @@ fn snapshot(dir: &Path) -> std::collections::BTreeMap, std::ti if m.is_dir() { todo.push(p.clone()); } - let bytes = if m.is_file() { std::fs::read(&p).unwrap() } else { Vec::new() }; - out.insert(p.strip_prefix(dir).unwrap().to_path_buf(), (bytes, m.modified().unwrap())); + let (bytes, len) = if m.is_file() { (contents(&p), m.len()) } else { (Some(Vec::new()), 0) }; + out.insert(p.strip_prefix(dir).unwrap().to_path_buf(), (bytes, len, m.modified().unwrap())); } } out } +/// The bytes of the file `p`, or `None` for a lock file that a [`lightcraft_catalog::LibraryLock`] +/// holds on Windows: there `LockFileEx` locks the file's bytes, and reading them through another +/// handle fails with os error 33 (`ERROR_LOCK_VIOLATION`). Such a file is compared by its length +/// and modification time only. +fn contents(p: &Path) -> Option> { + match std::fs::read(p) { + Ok(bytes) => Some(bytes), + Err(e) if cfg!(windows) && e.raw_os_error() == Some(33) && p.file_name().is_some_and(|n| n == lightcraft_catalog::lock::LOCK) => None, + Err(e) => panic!("{}: {e}", p.display()), + } +} + /// Listing the recent libraries (and drawing the window) writes nothing into any of them: no /// lock file, no owner file, nothing modified — free, held by another program or not a library. #[test]