#[cfg(feature = "var-collections")]
use armdb::{ByteView, VarTree};
use armdb::{Config, ConstTree, MigrateAction};
use tempfile::tempdir;
#[test]
fn test_migrate_large_const_tree() {
let dir = tempdir().unwrap();
let tree = ConstTree::<[u8; 8], 8>::open(dir.path(), Config::test()).unwrap();
for i in 0..10_000u64 {
let key = i.to_be_bytes();
let val = i.to_be_bytes();
tree.put(&key, &val).unwrap();
}
assert_eq!(tree.len(), 10_000);
let mutations = tree
.migrate(|key, _val| {
let i = u64::from_be_bytes(*key);
if i < 5_000 {
MigrateAction::Update((i + 100_000).to_be_bytes())
} else {
MigrateAction::Keep
}
})
.unwrap();
assert_eq!(mutations, 5_000);
assert_eq!(tree.len(), 10_000);
for i in 0..5_000u64 {
let key = i.to_be_bytes();
let expected = (i + 100_000).to_be_bytes();
assert_eq!(
tree.get(&key).unwrap(),
expected,
"updated value mismatch at key {}",
i
);
}
for i in 5_000..10_000u64 {
let key = i.to_be_bytes();
let expected = i.to_be_bytes();
assert_eq!(
tree.get(&key).unwrap(),
expected,
"kept value mismatch at key {}",
i
);
}
}
#[test]
fn test_migrate_large_delete() {
let dir = tempdir().unwrap();
let tree = ConstTree::<[u8; 8], 8>::open(dir.path(), Config::test()).unwrap();
for i in 0..10_000u64 {
let key = i.to_be_bytes();
let val = i.to_be_bytes();
tree.put(&key, &val).unwrap();
}
let mutations = tree
.migrate(|key, _val| {
let i = u64::from_be_bytes(*key);
if i % 2 == 0 {
MigrateAction::Delete
} else {
MigrateAction::Keep
}
})
.unwrap();
assert_eq!(mutations, 5_000);
assert_eq!(tree.len(), 5_000);
for i in 0..10_000u64 {
let key = i.to_be_bytes();
if i % 2 == 0 {
assert!(tree.get(&key).is_none(), "key {} should be deleted", i);
} else {
assert_eq!(tree.get(&key).unwrap(), i.to_be_bytes());
}
}
}
#[test]
fn test_migrate_then_recovery() {
let dir = tempdir().unwrap();
{
let tree = ConstTree::<[u8; 8], 8>::open(dir.path(), Config::test()).unwrap();
for i in 0..5_000u64 {
let key = i.to_be_bytes();
let val = i.to_be_bytes();
tree.put(&key, &val).unwrap();
}
let mutations = tree
.migrate(|_key, val| {
let v = u64::from_be_bytes(*val);
MigrateAction::Update((v * 10).to_be_bytes())
})
.unwrap();
assert_eq!(mutations, 5_000);
tree.close().unwrap();
}
{
let tree = ConstTree::<[u8; 8], 8>::open(dir.path(), Config::test()).unwrap();
assert_eq!(tree.len(), 5_000);
for i in 0..5_000u64 {
let key = i.to_be_bytes();
let expected = (i * 10).to_be_bytes();
assert_eq!(
tree.get(&key).unwrap(),
expected,
"recovered value mismatch at key {}",
i
);
}
}
}
#[cfg(feature = "var-collections")]
#[test]
fn test_migrate_large_var_tree() {
let dir = tempdir().unwrap();
let tree = VarTree::<[u8; 8]>::open(dir.path(), Config::test()).unwrap();
for i in 0..10_000u64 {
let key = i.to_be_bytes();
let val = format!("val_{i}");
tree.put(&key, val.as_bytes()).unwrap();
}
assert_eq!(tree.len(), 10_000);
let mutations = tree
.migrate(|key, _val| {
let i = u64::from_be_bytes(*key);
if i < 5_000 {
let new_val = format!("updated_{i}");
MigrateAction::Update(ByteView::new(new_val.as_bytes()))
} else {
MigrateAction::Keep
}
})
.unwrap();
assert_eq!(mutations, 5_000);
assert_eq!(tree.len(), 10_000);
for i in 0..5_000u64 {
let key = i.to_be_bytes();
let expected = format!("updated_{i}");
assert_eq!(tree.get(&key).unwrap().as_ref(), expected.as_bytes());
}
for i in 5_000..10_000u64 {
let key = i.to_be_bytes();
let expected = format!("val_{i}");
assert_eq!(tree.get(&key).unwrap().as_ref(), expected.as_bytes());
}
}
#[test]
fn test_migrate_all_delete() {
let dir = tempdir().unwrap();
let tree = ConstTree::<[u8; 8], 8>::open(dir.path(), Config::test()).unwrap();
for i in 0..1_000u64 {
let key = i.to_be_bytes();
let val = i.to_be_bytes();
tree.put(&key, &val).unwrap();
}
let mutations = tree.migrate(|_, _| MigrateAction::Delete).unwrap();
assert_eq!(mutations, 1_000);
assert_eq!(tree.len(), 0);
for i in 0..1_000u64 {
let key = i.to_be_bytes();
assert!(tree.get(&key).is_none());
}
}