use rustdupe::cache::{CacheEntry, HashCache};
use std::fs;
use std::io::Write;
use std::path::PathBuf;
use std::time::SystemTime;
use tempfile::NamedTempFile;
#[test]
fn test_open_corrupted_database() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
{
let mut f = fs::File::create(path).unwrap();
f.write_all(b"not a sqlite database").unwrap();
}
let res = HashCache::new(path);
assert!(res.is_err());
}
#[test]
fn test_recovery_on_corruption() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
{
let mut f = fs::File::create(path).unwrap();
f.write_all(b"corrupted garbage").unwrap();
}
let res = HashCache::new(path);
assert!(res.is_err());
if res.is_err() {
fs::remove_file(path).unwrap();
let cache = HashCache::new(path).expect("Should succeed after deleting corrupted file");
assert!(cache.clear().is_ok());
}
}
#[test]
fn test_cache_on_readonly_filesystem() {
let temp_file = NamedTempFile::new().unwrap();
let path = temp_file.path();
{
let cache = HashCache::new(path).unwrap();
let entry = CacheEntry {
path: PathBuf::from("test"),
size: 0,
mtime: SystemTime::now(),
inode: None,
prehash: [0u8; 32],
fullhash: None,
};
cache.insert_prehash(&entry, [0u8; 32]).unwrap();
cache.close().unwrap();
}
let mut perms = fs::metadata(path).unwrap().permissions();
perms.set_readonly(true);
fs::set_permissions(path, perms.clone()).unwrap();
let cache_res = HashCache::new(path);
if let Ok(cache) = cache_res {
let entry = CacheEntry {
path: PathBuf::from("test2"),
size: 0,
mtime: SystemTime::now(),
inode: None,
prehash: [0u8; 32],
fullhash: None,
};
let res = cache.insert_prehash(&entry, [0u8; 32]);
assert!(res.is_err(), "Insert should fail on read-only database");
}
#[allow(clippy::permissions_set_readonly_false)]
perms.set_readonly(false);
let _ = fs::set_permissions(path, perms);
}