use rustdupe::duplicates::DuplicateFinder;
use std::fs::{self, File};
use std::io::Write;
use tempfile::tempdir;
#[test]
fn test_empty_files_skipped() {
let dir = tempdir().unwrap();
File::create(dir.path().join("empty1.txt")).unwrap();
File::create(dir.path().join("empty2.txt")).unwrap();
let finder = DuplicateFinder::with_defaults();
let (groups, _summary) = finder.find_duplicates(dir.path()).unwrap();
assert!(groups.is_empty());
}
#[test]
fn test_very_small_files() {
let dir = tempdir().unwrap();
File::create(dir.path().join("small1.txt"))
.unwrap()
.write_all(b"a")
.unwrap();
File::create(dir.path().join("small2.txt"))
.unwrap()
.write_all(b"a")
.unwrap();
File::create(dir.path().join("small3.txt"))
.unwrap()
.write_all(b"b")
.unwrap();
let finder = DuplicateFinder::with_defaults();
let (groups, summary) = finder.find_duplicates(dir.path()).unwrap();
assert_eq!(groups.len(), 1);
assert_eq!(groups[0].size, 1);
assert_eq!(groups[0].files.len(), 2);
assert_eq!(summary.total_files, 3);
}
#[test]
fn test_file_at_prehash_boundary() {
let dir = tempdir().unwrap();
const PREHASH_SIZE: usize = 4096;
let mut content1 = vec![b'x'; PREHASH_SIZE];
let content2 = content1.clone();
File::create(dir.path().join("boundary1.txt"))
.unwrap()
.write_all(&content1)
.unwrap();
File::create(dir.path().join("boundary2.txt"))
.unwrap()
.write_all(&content2)
.unwrap();
content1[PREHASH_SIZE - 1] = b'y';
File::create(dir.path().join("boundary3.txt"))
.unwrap()
.write_all(&content1)
.unwrap();
let finder = DuplicateFinder::with_defaults();
let (groups, summary) = finder.find_duplicates(dir.path()).unwrap();
assert_eq!(groups.len(), 1);
assert_eq!(groups[0].size, PREHASH_SIZE as u64);
assert_eq!(groups[0].files.len(), 2);
assert_eq!(summary.total_files, 3);
}
#[test]
fn test_special_characters_in_filenames() {
let dir = tempdir().unwrap();
let space_name = "file with spaces.txt";
File::create(dir.path().join(space_name))
.unwrap()
.write_all(b"content")
.unwrap();
File::create(dir.path().join("duplicate1.txt"))
.unwrap()
.write_all(b"content")
.unwrap();
let unicode_name = "café_🦀.txt";
File::create(dir.path().join(unicode_name))
.unwrap()
.write_all(b"unicode content")
.unwrap();
File::create(dir.path().join("duplicate2.txt"))
.unwrap()
.write_all(b"unicode content")
.unwrap();
let special_name = "special_!@#$%^&()_+.txt";
File::create(dir.path().join(special_name))
.unwrap()
.write_all(b"special content")
.unwrap();
File::create(dir.path().join("duplicate3.txt"))
.unwrap()
.write_all(b"special content")
.unwrap();
let finder = DuplicateFinder::with_defaults();
let (groups, _summary) = finder.find_duplicates(dir.path()).unwrap();
assert_eq!(groups.len(), 3);
}
#[test]
fn test_deeply_nested_paths() {
let dir = tempdir().unwrap();
let mut current_path = dir.path().to_path_buf();
for i in 0..15 {
current_path = current_path.join(format!("level_{}", i));
fs::create_dir(¤t_path).unwrap();
}
let file1 = current_path.join("deep.txt");
File::create(&file1)
.unwrap()
.write_all(b"deep content")
.unwrap();
let file2 = dir.path().join("shallow.txt");
File::create(&file2)
.unwrap()
.write_all(b"deep content")
.unwrap();
let finder = DuplicateFinder::with_defaults();
let (groups, summary) = finder.find_duplicates(dir.path()).unwrap();
assert_eq!(groups.len(), 1);
assert_eq!(summary.total_files, 2);
}
#[test]
fn test_long_path_near_limit() {
let dir = tempdir().unwrap();
let long_name = "a".repeat(50);
let mut current_path = dir.path().to_path_buf();
for i in 0..4 {
current_path = current_path.join(format!("{}_{}", i, long_name));
if let Err(e) = fs::create_dir(¤t_path) {
eprintln!(
"Failed to create dir at level {}: {}. Skipping long path test.",
i, e
);
return;
}
}
let file_path = current_path.join("file.txt");
if let Err(e) = File::create(&file_path).map(|mut f| f.write_all(b"content")) {
eprintln!(
"Failed to create file in long path: {}. Skipping long path test.",
e
);
return;
}
let file_path2 = dir.path().join("duplicate.txt");
File::create(&file_path2)
.unwrap()
.write_all(b"content")
.unwrap();
let finder = DuplicateFinder::with_defaults();
let (groups, summary) = finder.find_duplicates(dir.path()).unwrap();
assert_eq!(groups.len(), 1);
assert_eq!(summary.total_files, 2);
}