use super::*;
#[test]
fn extract_file_returns_none_for_missing_path() {
let dir = TempDir::new("vfs_newmethods_extract_none");
let vfs = VFS::from_directories(vec![dir.path()], None);
let dest = TempDir::new("vfs_newmethods_extract_none_dest");
let result = vfs
.extract_file(Path::new("nonexistent.txt"), dest.path())
.unwrap();
assert!(result.is_none());
}
#[test]
fn extract_file_copies_content_to_dest() {
let src = TempDir::new("vfs_newmethods_extract_src");
src.write("data.bin", b"hello extract");
let vfs = VFS::from_directories(vec![src.path()], None);
let dest = TempDir::new("vfs_newmethods_extract_dest");
let extracted = vfs
.extract_file(Path::new("data.bin"), dest.path())
.unwrap()
.expect("file should be found and extracted");
assert!(extracted.exists());
assert_eq!(fs::read(&extracted).unwrap(), b"hello extract");
}
#[test]
fn extract_file_uses_normalized_key_for_destination_filename() {
let src = TempDir::new("vfs_newmethods_extract_normalized_dest_src");
src.write("textures/foo.dds", b"texture");
let vfs = VFS::from_directories(vec![src.path()], None);
let dest = TempDir::new("vfs_newmethods_extract_normalized_dest");
let extracted = vfs
.extract_file(Path::new("textures\\foo.dds"), dest.path())
.unwrap()
.expect("file should be found and extracted");
assert_eq!(extracted, dest.path().join("foo.dds"));
assert_eq!(fs::read(&extracted).unwrap(), b"texture");
}
#[test]
#[cfg(unix)]
fn extract_file_does_not_follow_existing_destination_symlink() {
let src = TempDir::new("vfs_newmethods_extract_symlink_src");
src.write("data.bin", b"safe");
let vfs = VFS::from_directories(vec![src.path()], None);
let dest = TempDir::new("vfs_newmethods_extract_symlink_dest");
let outside = dest.write("outside.bin", b"outside");
std::os::unix::fs::symlink(&outside, dest.path().join("data.bin")).unwrap();
let extracted = vfs
.extract_file(Path::new("data.bin"), dest.path())
.unwrap()
.expect("file should be extracted");
assert_eq!(fs::read(&outside).unwrap(), b"outside");
assert_eq!(fs::read(&extracted).unwrap(), b"safe");
assert!(
!fs::symlink_metadata(&extracted)
.unwrap()
.file_type()
.is_symlink()
);
}
#[test]
fn extract_file_creates_dest_dir_if_missing() {
let src = TempDir::new("vfs_newmethods_extract_mkdest");
src.write("note.txt", b"content");
let vfs = VFS::from_directories(vec![src.path()], None);
let base = TempDir::new("vfs_newmethods_extract_mkdest_base");
let dest = base.path().join("new_subdir");
assert!(!dest.exists(), "dest should not exist yet");
let extracted = vfs
.extract_file(Path::new("note.txt"), &dest)
.unwrap()
.expect("file should be extracted");
assert!(extracted.exists());
}
#[test]
fn remaining_replacements_false_includes_files_from_filter_path() {
let dir1 = TempDir::new("vfs_newmethods_rem_d1");
let dir2 = TempDir::new("vfs_newmethods_rem_d2");
dir1.write("unique.txt", b"from dir1");
dir1.write("shared.txt", b"dir1 version");
dir2.write("shared.txt", b"dir2 version");
dir2.write("only_dir2.txt", b"dir2 only");
let all_dirs = vec![dir1.path().to_path_buf(), dir2.path().to_path_buf()];
let vfs = VFS::from_directories(all_dirs.iter().map(std::path::PathBuf::as_path), None);
let tree = vfs.remaining(dir1.path(), false, &all_dirs, true);
let count = count_files_in_tree(&tree);
assert_eq!(count, 1, "only unique.txt should still be served from dir1");
}
#[test]
fn remaining_replacements_true_includes_overridden_files() {
let dir1 = TempDir::new("vfs_newmethods_rem2_d1");
let dir2 = TempDir::new("vfs_newmethods_rem2_d2");
dir1.write("unique.txt", b"from dir1");
dir1.write("shared.txt", b"dir1 version");
dir2.write("shared.txt", b"dir2 version");
let all_dirs = vec![dir1.path().to_path_buf(), dir2.path().to_path_buf()];
let vfs = VFS::from_directories(all_dirs.iter().map(std::path::PathBuf::as_path), None);
let tree = vfs.remaining(dir1.path(), true, &all_dirs, true);
let count = count_files_in_tree(&tree);
assert_eq!(count, 1, "only the overridden shared.txt should appear");
}
#[test]
fn remaining_uses_source_path_component_boundaries() {
let root = TempDir::new("vfs_newmethods_remaining_boundaries_root");
let dir = root.path().join("foo");
let dir_sibling = root.path().join("foobar");
fs::create_dir_all(&dir).unwrap();
fs::create_dir_all(&dir_sibling).unwrap();
fs::write(dir.join("from_foo.txt"), b"foo").unwrap();
fs::write(dir_sibling.join("from_foobar.txt"), b"foobar").unwrap();
let all_dirs = vec![dir.clone(), dir_sibling.clone()];
let vfs = VFS::from_directories(all_dirs.iter().map(std::path::PathBuf::as_path), None);
let tree = vfs.remaining(&dir, false, &all_dirs, true);
assert_eq!(count_files_in_tree(&tree), 1);
}