use crate::fs::{Fault, FaultFs, FaultOp, FaultRule, StdFs};
use crate::io::ErrorKind;
use crate::{AbstractTree, SequenceNumberCounter};
use std::sync::Arc;
use test_log::test;
#[test]
fn level_manifest_atomicity() -> crate::Result<()> {
let folder = tempfile::tempdir()?;
let fault_fs = FaultFs::new(StdFs);
let injector = fault_fs.injector();
let tree = crate::Config::new(
folder,
SequenceNumberCounter::default(),
SequenceNumberCounter::default(),
)
.with_shared_fs(Arc::new(fault_fs))
.open()?;
tree.insert("a", "a", 0);
tree.flush_active_memtable(0)?;
tree.insert("a", "a", 1);
tree.flush_active_memtable(0)?;
tree.insert("a", "a", 2);
tree.flush_active_memtable(0)?;
assert_eq!(3, tree.approximate_len());
tree.major_compact(u64::MAX, 3)?;
assert_eq!(1, tree.table_count());
tree.insert("a", "a", 3);
tree.flush_active_memtable(0)?;
let table_count_before_major_compact = tree.table_count();
let crate::AnyTree::Standard(tree) = tree else {
unreachable!();
};
injector.arm(
FaultRule::new(FaultOp::SyncAll, Fault::Error(ErrorKind::Other))
.on_path("edits")
.once(),
);
match tree.major_compact(u64::MAX, 4) {
Ok(_) => panic!("the injected manifest-commit fault must fail the compaction"),
Err(e) => assert!(
format!("{e}").contains("injected fault"),
"compaction must fail on the armed edit-log fsync, not an earlier error: {e}"
),
}
assert!(tree.compaction_state.lock().hidden_set().is_empty());
assert_eq!(table_count_before_major_compact, tree.table_count());
assert!(tree.contains_key("a", u64::MAX)?);
Ok(())
}