This commit is contained in:
Julien Cretin
2021-09-26 19:02:32 +02:00
committed by Julien Cretin
parent 0f88d6502f
commit fbca34b1d1
2 changed files with 54 additions and 3 deletions

View File

@@ -0,0 +1,51 @@
use persistent_store::{BufferOptions, StoreDriverOff, StoreInterruption, StoreOperation};
#[test]
fn interrupted_overflowing_compaction() {
let options = BufferOptions {
word_size: 4,
page_size: 32,
max_word_writes: 2,
max_page_erases: 3,
strict_mode: true,
};
let num_pages = 7;
let mut driver = StoreDriverOff::new(options, num_pages).power_on().unwrap();
let v = driver.model().format().virt_size() as usize;
let c = driver.model().format().total_capacity() as usize;
let q = driver.model().format().virt_page_size() as usize;
// We setup the storage such that the next 2 compactions are overflowing. This means they copy 1
// more word than the size of a page.
let mut k = 0;
// Fill the first 2 pages with non-deleted entries.
while k < 2 * q {
driver.insert(k, &[]).unwrap();
k += 1;
}
// Write enough deleted entries to be able to continue writing without compaction.
for _ in c..v {
driver.insert(k, &[]).unwrap();
}
// Fill until the end of the window with deleted entries.
while k < c {
driver.insert(k, &[]).unwrap();
driver.remove(k).unwrap();
k += 1;
}
// Make sure we did not compact and we actually filled until the end of the window.
assert_eq!(driver.store().lifetime().unwrap().used(), v);
// We trigger 2 interrupted overflowing compactions, which would move the last non-deleted entry
// out of the window unless additional compactions are done to restore the overflow.
for _ in 0..2 {
let interruption = StoreInterruption {
delay: 0,
corrupt: Box::new(|old, new| old.copy_from_slice(new)),
};
match driver.partial_apply(StoreOperation::Prepare { length: 1 }, interruption) {
Ok((None, d)) => driver = d.power_on().unwrap(),
_ => unreachable!(),
}
}
}