use rustdupe::duplicates::DuplicateFinder;
use std::fs::{self, File};
use std::io::Write;
use tempfile::tempdir;
use unicode_normalization::UnicodeNormalization;
#[test]
fn test_paths_with_quotes() {
let dir = tempdir().unwrap();
if cfg!(not(windows)) {
let quote_name = "file_with_\"quote\".txt";
let file_path = dir.path().join(quote_name);
File::create(&file_path)
.expect("Failed to create file with quotes")
.write_all(b"content")
.unwrap();
let dup_path = dir.path().join("duplicate.txt");
File::create(&dup_path)
.unwrap()
.write_all(b"content")
.unwrap();
let finder = DuplicateFinder::with_defaults();
let (groups, _) = finder.find_duplicates(dir.path()).unwrap();
assert_eq!(groups.len(), 1);
assert!(groups[0]
.files
.iter()
.any(|f| f.path.to_string_lossy().contains("\"")));
}
}
#[test]
fn test_paths_with_newlines() {
let dir = tempdir().unwrap();
if cfg!(not(windows)) {
let newline_name = "file_with\nnewline.txt";
let file_path = dir.path().join(newline_name);
File::create(&file_path)
.expect("Failed to create file with newline")
.write_all(b"content")
.unwrap();
let dup_path = dir.path().join("duplicate.txt");
File::create(&dup_path)
.unwrap()
.write_all(b"content")
.unwrap();
let finder = DuplicateFinder::with_defaults();
let (groups, _) = finder.find_duplicates(dir.path()).unwrap();
assert_eq!(groups.len(), 1);
assert!(groups[0]
.files
.iter()
.any(|f| f.path.to_string_lossy().contains('\n')));
}
}
#[test]
fn test_extremely_long_paths() {
let dir = tempdir().unwrap();
let mut current_path = dir.path().to_path_buf();
let folder_name = "a".repeat(50);
for i in 0..6 {
current_path = current_path.join(format!("{}_{}", i, folder_name));
if let Err(e) = fs::create_dir(¤t_path) {
eprintln!(
"Skipping extremely long path test: failed to create dir: {}",
e
);
return;
}
}
let file_path = current_path.join("file.txt");
if let Err(e) = File::create(&file_path).and_then(|mut f| f.write_all(b"content")) {
eprintln!(
"Skipping extremely long path test: failed to create file: {}",
e
);
return;
}
let dup_path = dir.path().join("duplicate.txt");
File::create(&dup_path)
.unwrap()
.write_all(b"content")
.unwrap();
let finder = DuplicateFinder::with_defaults();
let (groups, _) = finder.find_duplicates(dir.path()).unwrap();
assert_eq!(groups.len(), 1);
}
#[test]
fn test_unicode_nfd_normalization_integration() {
let dir = tempdir().unwrap();
let name_nfc = "café_test.txt";
let name_nfd = "cafe\u{0301}_test.txt";
assert_ne!(name_nfc, name_nfd);
assert_eq!(name_nfc, name_nfd.nfc().collect::<String>());
let path_nfc = dir.path().join(name_nfc);
File::create(&path_nfc)
.unwrap()
.write_all(b"content")
.unwrap();
let path_nfd = dir.path().join(name_nfd);
let nfd_write_result = File::create(&path_nfd).and_then(|mut f| f.write_all(b"content"));
if let Err(e) = nfd_write_result {
log::debug!(
"Could not create second file (likely filesystem normalization): {}",
e
);
}
let file_count = fs::read_dir(dir.path())
.unwrap()
.filter_map(|e| e.ok())
.filter(|e| e.file_type().map(|ft| ft.is_file()).unwrap_or(false))
.count();
let finder = DuplicateFinder::with_defaults();
let (groups, _) = finder.find_duplicates(dir.path()).unwrap();
if file_count == 2 {
assert_eq!(groups.len(), 1);
assert_eq!(groups[0].files.len(), 2);
} else {
let path_other = dir.path().join("other_file.txt");
File::create(&path_other)
.unwrap()
.write_all(b"content")
.unwrap();
let (groups, _) = finder.find_duplicates(dir.path()).unwrap();
assert_eq!(groups.len(), 1);
assert_eq!(groups[0].files.len(), 2);
}
}