Add test
This commit is contained in:
committed by
Julien Cretin
parent
0f88d6502f
commit
fbca34b1d1
@@ -17,7 +17,7 @@
|
|||||||
//! [`StoreDriver`] wraps a [`Store`] and compares its behavior with its associated [`StoreModel`].
|
//! [`StoreDriver`] wraps a [`Store`] and compares its behavior with its associated [`StoreModel`].
|
||||||
|
|
||||||
use crate::format::{Format, Position};
|
use crate::format::{Format, Position};
|
||||||
#[cfg(test)]
|
#[cfg(feature = "std")]
|
||||||
use crate::StoreUpdate;
|
use crate::StoreUpdate;
|
||||||
use crate::{
|
use crate::{
|
||||||
BufferCorruptFunction, BufferOptions, BufferStorage, Nat, Store, StoreError, StoreHandle,
|
BufferCorruptFunction, BufferOptions, BufferStorage, Nat, Store, StoreError, StoreHandle,
|
||||||
@@ -431,7 +431,7 @@ impl StoreDriverOn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Applies an insertion to the store and model without interruption.
|
/// Applies an insertion to the store and model without interruption.
|
||||||
#[cfg(test)]
|
#[cfg(feature = "std")]
|
||||||
pub fn insert(&mut self, key: usize, value: &[u8]) -> Result<(), StoreInvariant> {
|
pub fn insert(&mut self, key: usize, value: &[u8]) -> Result<(), StoreInvariant> {
|
||||||
let value = value.to_vec();
|
let value = value.to_vec();
|
||||||
let updates = vec![StoreUpdate::Insert { key, value }];
|
let updates = vec![StoreUpdate::Insert { key, value }];
|
||||||
@@ -439,7 +439,7 @@ impl StoreDriverOn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Applies a deletion to the store and model without interruption.
|
/// Applies a deletion to the store and model without interruption.
|
||||||
#[cfg(test)]
|
#[cfg(feature = "std")]
|
||||||
pub fn remove(&mut self, key: usize) -> Result<(), StoreInvariant> {
|
pub fn remove(&mut self, key: usize) -> Result<(), StoreInvariant> {
|
||||||
let updates = vec![StoreUpdate::Remove { key }];
|
let updates = vec![StoreUpdate::Remove { key }];
|
||||||
self.apply(StoreOperation::Transaction { updates })
|
self.apply(StoreOperation::Transaction { updates })
|
||||||
|
|||||||
51
libraries/persistent_store/tests/store.rs
Normal file
51
libraries/persistent_store/tests/store.rs
Normal 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!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user