use std::fs; use std::io::Write; use std::sync::{Arc, Mutex}; use fuser::INodeNo; use musicfs::item::FileType; use musicfs::origins::local::snapshot::{build_snapshot, fill_fileset}; #[test] fn build_snapshot_empty_dir() { let source = tempfile::tempdir().unwrap(); let dest = tempfile::tempdir().unwrap(); let snapshot = build_snapshot(source.path(), dest.path()).unwrap(); assert_eq!(snapshot.len(), 1); assert!(snapshot.contains_key(&INodeNo::ROOT)); let root = &snapshot[&INodeNo::ROOT]; assert_eq!(root.inode, INodeNo::ROOT); assert_eq!(root.parent_inode, INodeNo::ROOT); assert_eq!(root.file_type, FileType::Directory); } #[test] fn build_snapshot_flat_files() { let source = tempfile::tempdir().unwrap(); let dest = tempfile::tempdir().unwrap(); let mut f = fs::File::create(source.path().join("a.txt")).unwrap(); f.write_all(b"content a").unwrap(); let mut f = fs::File::create(source.path().join("b.txt")).unwrap(); f.write_all(b"content b").unwrap(); let mut f = fs::File::create(source.path().join("c.txt")).unwrap(); f.write_all(b"content c").unwrap(); let snapshot = build_snapshot(source.path(), dest.path()).unwrap(); assert_eq!(snapshot.len(), 4); assert!(snapshot.contains_key(&INodeNo::ROOT)); let file_entries: Vec<_> = snapshot .values() .filter(|item| item.file_type == FileType::File) .collect(); assert_eq!(file_entries.len(), 3); for file_entry in file_entries { assert_eq!(file_entry.parent_inode, INodeNo::ROOT); } } #[test] fn build_snapshot_nested_dirs() { let source = tempfile::tempdir().unwrap(); let dest = tempfile::tempdir().unwrap(); fs::create_dir(source.path().join("subdir")).unwrap(); let nested_path = source.path().join("subdir").join("file.txt"); let mut f = fs::File::create(&nested_path).unwrap(); f.write_all(b"nested content").unwrap(); let snapshot = build_snapshot(source.path(), dest.path()).unwrap(); assert!(snapshot.contains_key(&INodeNo::ROOT)); let file_entry = snapshot .values() .find(|item| item.name == "file.txt" && item.file_type == FileType::File) .expect("file.txt not found"); assert_eq!(file_entry.parent_inode, INodeNo::ROOT); assert_eq!(file_entry.original_path, nested_path); } #[test] fn fill_fileset_removes_deleted() { let source = tempfile::tempdir().unwrap(); let dest = tempfile::tempdir().unwrap(); let mut f = fs::File::create(source.path().join("file1.txt")).unwrap(); f.write_all(b"content 1").unwrap(); let mut f = fs::File::create(source.path().join("file2.txt")).unwrap(); f.write_all(b"content 2").unwrap(); let initial_snapshot = build_snapshot(source.path(), dest.path()).unwrap(); let map = Arc::new(Mutex::new(initial_snapshot)); assert_eq!(map.lock().unwrap().len(), 3); fs::remove_file(source.path().join("file1.txt")).unwrap(); fill_fileset(&map, source.path(), dest.path()); let final_map = map.lock().unwrap(); assert_eq!(final_map.len(), 2); assert!(final_map.contains_key(&INodeNo::ROOT)); let remaining_files: Vec<_> = final_map .values() .filter(|item| item.file_type == FileType::File) .collect(); assert_eq!(remaining_files.len(), 1); assert_eq!(remaining_files[0].name, "file2.txt"); }