use aeternusdb::{Db, DbConfig, DbError};
use tempfile::TempDir;
fn tiny_config() -> DbConfig {
DbConfig {
write_buffer_size: 1024,
min_compaction_threshold: 2,
max_compaction_threshold: 4,
tombstone_compaction_ratio: 0.1,
thread_pool_size: 2,
..DbConfig::default()
}
}
#[test]
fn db_debug_impl() {
let tmp = TempDir::new().unwrap();
let db = Db::open(tmp.path(), DbConfig::default()).unwrap();
let debug_str = format!("{db:?}");
assert!(debug_str.contains("Db"), "should contain struct name");
assert!(debug_str.contains("closed"), "should contain closed field");
assert!(debug_str.contains("false"), "should show closed = false");
db.close().unwrap();
}
#[test]
fn drop_without_close_is_safe() {
let tmp = TempDir::new().unwrap();
{
let db = Db::open(tmp.path(), DbConfig::default()).unwrap();
db.put(b"key1", b"val1").unwrap();
db.put(b"key2", b"val2").unwrap();
}
{
let db = Db::open(tmp.path(), DbConfig::default()).unwrap();
assert_eq!(db.get(b"key1").unwrap(), Some(b"val1".to_vec()));
assert_eq!(db.get(b"key2").unwrap(), Some(b"val2".to_vec()));
db.close().unwrap();
}
}
#[test]
fn background_flush_cycle() {
let tmp = TempDir::new().unwrap();
let db = Db::open(tmp.path(), tiny_config()).unwrap();
for i in 0..200u32 {
let key = format!("k{i:04}");
let val = format!("v{i:04}");
db.put(key.as_bytes(), val.as_bytes()).unwrap();
}
for i in 0..100u32 {
let key = format!("k{i:04}");
db.delete(key.as_bytes()).unwrap();
}
for i in 200..300u32 {
let key = format!("k{i:04}");
let val = format!("v{i:04}");
db.put(key.as_bytes(), val.as_bytes()).unwrap();
}
std::thread::sleep(std::time::Duration::from_millis(200));
for i in 100..300u32 {
let key = format!("k{i:04}");
let val = format!("v{i:04}");
assert_eq!(
db.get(key.as_bytes()).unwrap(),
Some(val.into_bytes()),
"key {key} should exist"
);
}
db.close().unwrap();
}
#[test]
fn delete_range_triggers_flush() {
let tmp = TempDir::new().unwrap();
let db = Db::open(tmp.path(), tiny_config()).unwrap();
for i in 0..50u32 {
let key = format!("r{i:04}");
let val = format!("v{i:04}");
db.put(key.as_bytes(), val.as_bytes()).unwrap();
}
db.delete_range(b"r0000", b"r0050").unwrap();
std::thread::sleep(std::time::Duration::from_millis(200));
for i in 0..50u32 {
let key = format!("r{i:04}");
assert_eq!(
db.get(key.as_bytes()).unwrap(),
None,
"{key} should be deleted"
);
}
db.close().unwrap();
}
#[test]
fn config_tombstone_interval_at_max() {
let tmp = TempDir::new().unwrap();
let config = DbConfig {
tombstone_compaction_interval: 604_800,
..DbConfig::default()
};
let db = Db::open(tmp.path(), config).unwrap();
db.close().unwrap();
}
#[test]
fn config_tombstone_interval_over_max() {
let tmp = TempDir::new().unwrap();
let config = DbConfig {
tombstone_compaction_interval: 604_801,
..DbConfig::default()
};
let err = Db::open(tmp.path(), config).unwrap_err();
assert!(matches!(err, DbError::InvalidConfig(_)));
}
#[test]
fn config_tombstone_ratio_at_one() {
let tmp = TempDir::new().unwrap();
let config = DbConfig {
tombstone_compaction_ratio: 1.0,
..DbConfig::default()
};
let db = Db::open(tmp.path(), config).unwrap();
db.close().unwrap();
}
#[test]
fn config_tombstone_ratio_at_zero() {
let tmp = TempDir::new().unwrap();
let config = DbConfig {
tombstone_compaction_ratio: 0.0,
..DbConfig::default()
};
let err = Db::open(tmp.path(), config).unwrap_err();
assert!(matches!(err, DbError::InvalidConfig(_)));
}
#[test]
fn config_thread_pool_max() {
let tmp = TempDir::new().unwrap();
let config = DbConfig {
thread_pool_size: 32,
..DbConfig::default()
};
let db = Db::open(tmp.path(), config).unwrap();
db.close().unwrap();
}
#[test]
fn config_thread_pool_over_max() {
let tmp = TempDir::new().unwrap();
let config = DbConfig {
thread_pool_size: 33,
..DbConfig::default()
};
let err = Db::open(tmp.path(), config).unwrap_err();
assert!(matches!(err, DbError::InvalidConfig(_)));
}
#[test]
fn config_write_buffer_at_min() {
let tmp = TempDir::new().unwrap();
let config = DbConfig {
write_buffer_size: 1024,
..DbConfig::default()
};
let db = Db::open(tmp.path(), config).unwrap();
db.close().unwrap();
}
#[test]
fn config_write_buffer_below_min() {
let tmp = TempDir::new().unwrap();
let config = DbConfig {
write_buffer_size: 1023,
..DbConfig::default()
};
let err = Db::open(tmp.path(), config).unwrap_err();
assert!(matches!(err, DbError::InvalidConfig(_)));
}