#![cfg(feature = "var-collections")]
use armdb::{Config, MigrateAction, NoHook, VarMap, VarTree};
use tempfile::tempdir;
fn big(fill: u8) -> Vec<u8> {
vec![fill; 16 * 1024]
}
fn truncate_shard_data_files(dir: &std::path::Path) {
fn walk(dir: &std::path::Path, found: &mut bool) {
for entry in std::fs::read_dir(dir).unwrap() {
let path = entry.unwrap().path();
if path.is_dir() {
walk(&path, found);
} else if path.extension().is_some_and(|e| e == "data") {
let f = std::fs::OpenOptions::new().write(true).open(&path).unwrap();
f.set_len(8).unwrap();
*found = true;
}
}
}
let mut found = false;
walk(dir, &mut found);
assert!(found, "no data files found to truncate");
}
#[test]
fn var_tree_migrate_errors_on_unreadable_value() {
let dir = tempdir().unwrap();
let tree: VarTree<[u8; 8], NoHook> = VarTree::open(dir.path(), Config::test()).unwrap();
tree.put(&1u64.to_be_bytes(), &big(0xAA)).unwrap();
tree.flush_buffers().unwrap();
truncate_shard_data_files(dir.path());
assert_eq!(tree.len(), 1, "entry must remain in index after truncate");
let res = tree.migrate(|_, _| MigrateAction::Keep);
assert!(
res.is_err(),
"migrate must fail loudly on unreadable value, got {res:?}"
);
}
#[test]
fn var_map_migrate_errors_on_unreadable_value() {
let dir = tempdir().unwrap();
let map: VarMap<[u8; 8], NoHook> = VarMap::open(dir.path(), Config::test()).unwrap();
map.put(&1u64.to_be_bytes(), &big(0xBB)).unwrap();
map.flush_buffers().unwrap();
truncate_shard_data_files(dir.path());
assert_eq!(map.len(), 1, "entry must remain in index after truncate");
let res = map.migrate(|_, _| MigrateAction::Keep);
assert!(
res.is_err(),
"migrate must fail loudly on unreadable value, got {res:?}"
);
}