use rawdb::Database;
use std::ops::DerefMut;
use tempfile::TempDir;
use vecdb::{
AnyStoredVec, ImportOptions, ImportableVec, ReadableVec, Result, Stamp, StoredVec, Version,
WritableVec,
};
fn setup_db() -> Result<(Database, TempDir)> {
let temp = TempDir::new()?;
let db = Database::open(temp.path())?;
Ok((db, temp))
}
mod generic_rollback {
use super::*;
fn import_with_changes<V>(db: &Database, name: &str, changes: u16) -> Result<V>
where
V: StoredVec<I = usize, T = u32>,
{
let mut options: ImportOptions = (db, name, Version::TWO).into();
options = options.with_saved_stamped_changes(changes);
V::forced_import_with(options)
}
fn run_basic_rollback<V>() -> Result<()>
where
V: StoredVec<I = usize, T = u32>,
{
let (db, _temp) = setup_db()?;
let mut vec = import_with_changes::<V>(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.stamp(), Stamp::new(1));
vec.push(5);
vec.push(6);
vec.stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4, 5, 6]);
assert_eq!(vec.stamp(), Stamp::new(2));
vec.rollback()?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.stamp(), Stamp::new(1));
Ok(())
}
fn run_rollback_with_truncation<V>() -> Result<()>
where
V: StoredVec<I = usize, T = u32>,
{
let (db, _temp) = setup_db()?;
let mut vec = import_with_changes::<V>(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.stamped_write_with_changes(Stamp::new(1))?;
vec.push(5);
vec.push(6);
vec.push(7);
vec.stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4, 5, 6, 7]);
vec.rollback()?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.stamp(), Stamp::new(1));
Ok(())
}
fn run_multiple_sequential_rollbacks<V>() -> Result<()>
where
V: StoredVec<I = usize, T = u32>,
{
let (db, _temp) = setup_db()?;
let mut vec = import_with_changes::<V>(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.stamped_write_with_changes(Stamp::new(1))?;
vec.push(5);
vec.stamped_write_with_changes(Stamp::new(2))?;
vec.push(6);
vec.stamped_write_with_changes(Stamp::new(3))?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4, 5, 6]);
vec.rollback()?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4, 5]);
assert_eq!(vec.stamp(), Stamp::new(2));
vec.rollback()?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.stamp(), Stamp::new(1));
Ok(())
}
fn run_rollback_then_save_new_state<V>() -> Result<()>
where
V: StoredVec<I = usize, T = u32>,
{
let (db, _temp) = setup_db()?;
let mut vec = import_with_changes::<V>(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.stamped_write_with_changes(Stamp::new(1))?;
vec.push(5);
vec.stamped_write_with_changes(Stamp::new(2))?;
vec.rollback()?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4]);
vec.push(99);
vec.stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4, 99]);
assert_eq!(vec.stamp(), Stamp::new(2));
Ok(())
}
fn run_rollback_to_empty<V>() -> Result<()>
where
V: StoredVec<I = usize, T = u32>,
{
let (db, _temp) = setup_db()?;
let mut vec = import_with_changes::<V>(&db, "test", 10)?;
vec.stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.collect(), Vec::<u32>::new());
vec.push(0);
vec.push(1);
vec.push(2);
vec.stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.collect(), vec![0, 1, 2]);
vec.rollback()?;
assert_eq!(vec.collect(), Vec::<u32>::new());
Ok(())
}
fn run_rollback_before<V>() -> Result<()>
where
V: StoredVec<I = usize, T = u32>,
{
let (db, _temp) = setup_db()?;
let mut vec = import_with_changes::<V>(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.stamped_write_with_changes(Stamp::new(1))?;
vec.push(5);
vec.stamped_write_with_changes(Stamp::new(2))?;
vec.push(6);
vec.stamped_write_with_changes(Stamp::new(3))?;
vec.push(7);
vec.stamped_write_with_changes(Stamp::new(4))?;
vec.push(8);
vec.stamped_write_with_changes(Stamp::new(5))?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4, 5, 6, 7, 8]);
let _ = vec.rollback_before(Stamp::new(4))?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4, 5, 6]);
assert_eq!(vec.stamp(), Stamp::new(3));
Ok(())
}
fn run_deep_rollback_chain<V>() -> Result<()>
where
V: StoredVec<I = usize, T = u32>,
{
let (db, _temp) = setup_db()?;
let mut vec = import_with_changes::<V>(&db, "test", 10)?;
vec.stamped_write_with_changes(Stamp::new(1))?;
vec.push(0);
vec.stamped_write_with_changes(Stamp::new(2))?;
vec.push(1);
vec.stamped_write_with_changes(Stamp::new(3))?;
vec.push(2);
vec.stamped_write_with_changes(Stamp::new(4))?;
vec.push(3);
vec.push(4);
vec.stamped_write_with_changes(Stamp::new(5))?; assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4]);
vec.rollback()?; assert_eq!(vec.collect(), vec![0, 1, 2]);
vec.rollback()?; assert_eq!(vec.collect(), vec![0, 1]);
vec.rollback()?; assert_eq!(vec.collect(), vec![0]);
vec.rollback()?; assert_eq!(vec.collect(), Vec::<u32>::new());
Ok(())
}
fn run_rollback_persistence<V>() -> Result<()>
where
V: StoredVec<I = usize, T = u32>,
{
let (db, _temp) = setup_db()?;
{
let mut vec = import_with_changes::<V>(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.stamped_write_with_changes(Stamp::new(1))?;
vec.push(5);
vec.push(6);
vec.stamped_write_with_changes(Stamp::new(2))?;
vec.rollback()?;
vec.stamped_write_with_changes(Stamp::new(1))?;
}
{
let vec = import_with_changes::<V>(&db, "test", 10)?;
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.stamp(), Stamp::new(1));
}
Ok(())
}
fn run_reset<V>() -> Result<()>
where
V: StoredVec<I = usize, T = u32>,
{
let (db, _temp) = setup_db()?;
let mut vec = import_with_changes::<V>(&db, "test", 10)?;
for i in 0..10 {
vec.push(i);
}
vec.stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.len(), 10);
assert_eq!(vec.stored_len(), 10);
assert_eq!(vec.pushed_len(), 0);
assert_eq!(vec.collect(), vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
vec.push(10);
vec.push(11);
assert_eq!(vec.len(), 12);
assert_eq!(vec.stored_len(), 10);
assert_eq!(vec.pushed_len(), 2);
vec.reset()?;
assert_eq!(vec.len(), 0);
assert_eq!(vec.stored_len(), 0);
assert_eq!(vec.pushed_len(), 0);
assert_eq!(vec.collect(), Vec::<u32>::new());
vec.push(100);
vec.push(101);
vec.push(102);
assert_eq!(vec.len(), 3);
assert_eq!(vec.stored_len(), 0);
assert_eq!(vec.pushed_len(), 3);
assert_eq!(vec.collect(), vec![100, 101, 102]);
vec.stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.len(), 3);
assert_eq!(vec.stored_len(), 3);
assert_eq!(vec.pushed_len(), 0);
assert_eq!(vec.collect(), vec![100, 101, 102]);
Ok(())
}
mod bytes {
use super::*;
use vecdb::BytesVec;
type V = BytesVec<usize, u32>;
#[test]
fn basic_rollback() -> Result<()> {
run_basic_rollback::<V>()
}
#[test]
fn rollback_with_truncation() -> Result<()> {
run_rollback_with_truncation::<V>()
}
#[test]
fn multiple_sequential_rollbacks() -> Result<()> {
run_multiple_sequential_rollbacks::<V>()
}
#[test]
fn rollback_then_save_new_state() -> Result<()> {
run_rollback_then_save_new_state::<V>()
}
#[test]
fn rollback_to_empty() -> Result<()> {
run_rollback_to_empty::<V>()
}
#[test]
fn rollback_before() -> Result<()> {
run_rollback_before::<V>()
}
#[test]
fn deep_rollback_chain() -> Result<()> {
run_deep_rollback_chain::<V>()
}
#[test]
fn rollback_persistence() -> Result<()> {
run_rollback_persistence::<V>()
}
#[test]
fn reset() -> Result<()> {
run_reset::<V>()
}
}
#[cfg(feature = "zerocopy")]
mod zerocopy {
use super::*;
use vecdb::ZeroCopyVec;
type V = ZeroCopyVec<usize, u32>;
#[test]
fn basic_rollback() -> Result<()> {
run_basic_rollback::<V>()
}
#[test]
fn rollback_with_truncation() -> Result<()> {
run_rollback_with_truncation::<V>()
}
#[test]
fn multiple_sequential_rollbacks() -> Result<()> {
run_multiple_sequential_rollbacks::<V>()
}
#[test]
fn rollback_then_save_new_state() -> Result<()> {
run_rollback_then_save_new_state::<V>()
}
#[test]
fn rollback_to_empty() -> Result<()> {
run_rollback_to_empty::<V>()
}
#[test]
fn rollback_before() -> Result<()> {
run_rollback_before::<V>()
}
#[test]
fn deep_rollback_chain() -> Result<()> {
run_deep_rollback_chain::<V>()
}
#[test]
fn rollback_persistence() -> Result<()> {
run_rollback_persistence::<V>()
}
#[test]
fn reset() -> Result<()> {
run_reset::<V>()
}
}
#[cfg(feature = "pco")]
mod pco {
use super::*;
use vecdb::PcoVec;
type V = PcoVec<usize, u32>;
#[test]
fn basic_rollback() -> Result<()> {
run_basic_rollback::<V>()
}
#[test]
fn rollback_with_truncation() -> Result<()> {
run_rollback_with_truncation::<V>()
}
#[test]
fn multiple_sequential_rollbacks() -> Result<()> {
run_multiple_sequential_rollbacks::<V>()
}
#[test]
fn rollback_then_save_new_state() -> Result<()> {
run_rollback_then_save_new_state::<V>()
}
#[test]
fn rollback_to_empty() -> Result<()> {
run_rollback_to_empty::<V>()
}
#[test]
fn rollback_before() -> Result<()> {
run_rollback_before::<V>()
}
#[test]
fn deep_rollback_chain() -> Result<()> {
run_deep_rollback_chain::<V>()
}
#[test]
fn rollback_persistence() -> Result<()> {
run_rollback_persistence::<V>()
}
#[test]
fn reset() -> Result<()> {
run_reset::<V>()
}
}
#[cfg(feature = "lz4")]
mod lz4 {
use super::*;
use vecdb::LZ4Vec;
type V = LZ4Vec<usize, u32>;
#[test]
fn basic_rollback() -> Result<()> {
run_basic_rollback::<V>()
}
#[test]
fn rollback_with_truncation() -> Result<()> {
run_rollback_with_truncation::<V>()
}
#[test]
fn multiple_sequential_rollbacks() -> Result<()> {
run_multiple_sequential_rollbacks::<V>()
}
#[test]
fn rollback_then_save_new_state() -> Result<()> {
run_rollback_then_save_new_state::<V>()
}
#[test]
fn rollback_to_empty() -> Result<()> {
run_rollback_to_empty::<V>()
}
#[test]
fn rollback_before() -> Result<()> {
run_rollback_before::<V>()
}
#[test]
fn deep_rollback_chain() -> Result<()> {
run_deep_rollback_chain::<V>()
}
#[test]
fn rollback_persistence() -> Result<()> {
run_rollback_persistence::<V>()
}
#[test]
fn reset() -> Result<()> {
run_reset::<V>()
}
}
#[cfg(feature = "zstd")]
mod zstd {
use super::*;
use vecdb::ZstdVec;
type V = ZstdVec<usize, u32>;
#[test]
fn basic_rollback() -> Result<()> {
run_basic_rollback::<V>()
}
#[test]
fn rollback_with_truncation() -> Result<()> {
run_rollback_with_truncation::<V>()
}
#[test]
fn multiple_sequential_rollbacks() -> Result<()> {
run_multiple_sequential_rollbacks::<V>()
}
#[test]
fn rollback_then_save_new_state() -> Result<()> {
run_rollback_then_save_new_state::<V>()
}
#[test]
fn rollback_to_empty() -> Result<()> {
run_rollback_to_empty::<V>()
}
#[test]
fn rollback_before() -> Result<()> {
run_rollback_before::<V>()
}
#[test]
fn deep_rollback_chain() -> Result<()> {
run_deep_rollback_chain::<V>()
}
#[test]
fn rollback_persistence() -> Result<()> {
run_rollback_persistence::<V>()
}
#[test]
fn reset() -> Result<()> {
run_reset::<V>()
}
}
#[cfg(feature = "zerocopy")]
mod eager_zerocopy {
use super::*;
use vecdb::{EagerVec, ZeroCopyVec};
type V = EagerVec<ZeroCopyVec<usize, u32>>;
#[test]
fn basic_rollback() -> Result<()> {
run_basic_rollback::<V>()
}
#[test]
fn rollback_with_truncation() -> Result<()> {
run_rollback_with_truncation::<V>()
}
#[test]
fn multiple_sequential_rollbacks() -> Result<()> {
run_multiple_sequential_rollbacks::<V>()
}
#[test]
fn rollback_then_save_new_state() -> Result<()> {
run_rollback_then_save_new_state::<V>()
}
#[test]
fn rollback_to_empty() -> Result<()> {
run_rollback_to_empty::<V>()
}
#[test]
fn rollback_before() -> Result<()> {
run_rollback_before::<V>()
}
#[test]
fn deep_rollback_chain() -> Result<()> {
run_deep_rollback_chain::<V>()
}
#[test]
fn rollback_persistence() -> Result<()> {
run_rollback_persistence::<V>()
}
#[test]
fn reset() -> Result<()> {
run_reset::<V>()
}
}
#[cfg(feature = "pco")]
mod eager_pco {
use super::*;
use vecdb::{EagerVec, PcoVec};
type V = EagerVec<PcoVec<usize, u32>>;
#[test]
fn basic_rollback() -> Result<()> {
run_basic_rollback::<V>()
}
#[test]
fn rollback_with_truncation() -> Result<()> {
run_rollback_with_truncation::<V>()
}
#[test]
fn multiple_sequential_rollbacks() -> Result<()> {
run_multiple_sequential_rollbacks::<V>()
}
#[test]
fn rollback_then_save_new_state() -> Result<()> {
run_rollback_then_save_new_state::<V>()
}
#[test]
fn rollback_to_empty() -> Result<()> {
run_rollback_to_empty::<V>()
}
#[test]
fn rollback_before() -> Result<()> {
run_rollback_before::<V>()
}
#[test]
fn deep_rollback_chain() -> Result<()> {
run_deep_rollback_chain::<V>()
}
#[test]
fn rollback_persistence() -> Result<()> {
run_rollback_persistence::<V>()
}
#[test]
fn reset() -> Result<()> {
run_reset::<V>()
}
}
}
mod raw_rollback {
use super::*;
pub trait RollbackVec: StoredVec<I = usize, T = u32> + DerefMut
where
Self::Target: RollbackOps,
{
fn import_with_changes<'a>(
db: &'a Database,
name: &'a str,
changes: u16,
) -> Result<(Self, ImportOptions<'a>)>;
}
pub trait RollbackOps {
fn update(&mut self, index: usize, value: u32) -> Result<()>;
fn take(&mut self, index: usize) -> Result<Option<u32>>;
fn stamped_write_with_changes(&mut self, stamp: Stamp) -> Result<()>;
fn rollback(&mut self) -> Result<()>;
fn rollback_before(&mut self, stamp: Stamp) -> Result<Stamp>;
fn stamp(&self) -> Stamp;
fn stored_len(&self) -> usize;
fn collect(&self) -> Vec<u32>;
fn collect_holed(&self) -> Result<Vec<Option<u32>>>;
fn get_any_or_read(&self, index: usize, reader: &vecdb::Reader) -> Result<Option<u32>>;
fn create_reader(&self) -> vecdb::Reader;
}
#[cfg(feature = "zerocopy")]
use vecdb::{ReadWriteRawVec, ZeroCopyStrategy, ZeroCopyVec};
#[cfg(feature = "zerocopy")]
impl RollbackVec for ZeroCopyVec<usize, u32> {
fn import_with_changes<'a>(
db: &'a Database,
name: &'a str,
changes: u16,
) -> Result<(Self, ImportOptions<'a>)> {
let mut options: ImportOptions = (db, name, Version::TWO).into();
options = options.with_saved_stamped_changes(changes);
let vec = Self::forced_import_with(options)?;
Ok((vec, options))
}
}
#[cfg(feature = "zerocopy")]
impl RollbackOps for ReadWriteRawVec<usize, u32, ZeroCopyStrategy<u32>> {
fn update(&mut self, index: usize, value: u32) -> Result<()> {
ReadWriteRawVec::update(self, index, value)
}
fn take(&mut self, index: usize) -> Result<Option<u32>> {
let reader = self.create_reader();
let result = ReadWriteRawVec::take(self, index, &reader);
drop(reader);
result
}
fn stamped_write_with_changes(&mut self, stamp: Stamp) -> Result<()> {
WritableVec::stamped_write_with_changes(self, stamp)
}
fn rollback(&mut self) -> Result<()> {
WritableVec::rollback(self)
}
fn rollback_before(&mut self, stamp: Stamp) -> Result<Stamp> {
WritableVec::rollback_before(self, stamp)
}
fn stamp(&self) -> Stamp {
AnyStoredVec::stamp(self)
}
fn stored_len(&self) -> usize {
AnyStoredVec::stored_len(self)
}
fn collect(&self) -> Vec<u32> {
ReadableVec::collect(self)
}
fn collect_holed(&self) -> Result<Vec<Option<u32>>> {
ReadWriteRawVec::collect_holed(self)
}
fn get_any_or_read(&self, index: usize, reader: &vecdb::Reader) -> Result<Option<u32>> {
ReadWriteRawVec::get_any_or_read(self, index, reader)
}
fn create_reader(&self) -> vecdb::Reader {
ReadWriteRawVec::create_reader(self)
}
}
#[cfg(not(feature = "zerocopy"))]
use vecdb::ReadWriteRawVec;
use vecdb::{BytesStrategy, BytesVec};
impl RollbackVec for BytesVec<usize, u32> {
fn import_with_changes<'a>(
db: &'a Database,
name: &'a str,
changes: u16,
) -> Result<(Self, ImportOptions<'a>)> {
let mut options: ImportOptions = (db, name, Version::TWO).into();
options = options.with_saved_stamped_changes(changes);
let vec = Self::forced_import_with(options)?;
Ok((vec, options))
}
}
impl RollbackOps for ReadWriteRawVec<usize, u32, BytesStrategy<u32>> {
fn update(&mut self, index: usize, value: u32) -> Result<()> {
ReadWriteRawVec::update(self, index, value)
}
fn take(&mut self, index: usize) -> Result<Option<u32>> {
let reader = self.create_reader();
let result = ReadWriteRawVec::take(self, index, &reader);
drop(reader);
result
}
fn stamped_write_with_changes(&mut self, stamp: Stamp) -> Result<()> {
WritableVec::stamped_write_with_changes(self, stamp)
}
fn rollback(&mut self) -> Result<()> {
WritableVec::rollback(self)
}
fn rollback_before(&mut self, stamp: Stamp) -> Result<Stamp> {
WritableVec::rollback_before(self, stamp)
}
fn stamp(&self) -> Stamp {
AnyStoredVec::stamp(self)
}
fn stored_len(&self) -> usize {
AnyStoredVec::stored_len(self)
}
fn collect(&self) -> Vec<u32> {
ReadableVec::collect(self)
}
fn collect_holed(&self) -> Result<Vec<Option<u32>>> {
ReadWriteRawVec::collect_holed(self)
}
fn get_any_or_read(&self, index: usize, reader: &vecdb::Reader) -> Result<Option<u32>> {
ReadWriteRawVec::get_any_or_read(self, index, reader)
}
fn create_reader(&self) -> vecdb::Reader {
ReadWriteRawVec::create_reader(self)
}
}
fn run_basic_single_rollback<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
vec.deref_mut().update(2, 99)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 99, 3, 4]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(2));
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
Ok(())
}
fn run_rollback_with_truncation<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
vec.push(5);
vec.push(6);
vec.push(7);
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4, 5, 6, 7]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
Ok(())
}
fn run_multiple_sequential_rollbacks<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.push(5);
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
vec.push(6);
vec.deref_mut().stamped_write_with_changes(Stamp::new(3))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4, 5, 6]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4, 5]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(2));
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
Ok(())
}
fn run_rollback_then_save_new_state<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.push(5);
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
vec.push(99);
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4, 99]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(2));
Ok(())
}
fn run_rollback_with_updates<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.deref_mut().update(1, 99)?;
vec.deref_mut().update(3, 88)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 99, 2, 88, 4]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
Ok(())
}
fn run_rollback_with_holes<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.deref_mut().take(1)?;
vec.deref_mut().take(3)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 2, 4]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
Ok(())
}
fn run_rollback_with_truncation_and_updates<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.deref_mut().update(1, 99)?;
vec.push(5);
vec.push(6);
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 99, 2, 3, 4, 5, 6]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
Ok(())
}
fn run_rollback_with_holes_and_updates<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.deref_mut().take(1)?;
vec.deref_mut().update(2, 99)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 99, 3, 4]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
Ok(())
}
fn run_multiple_updates_to_same_index<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.deref_mut().update(0, 100)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
vec.deref_mut().update(0, 200)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(3))?;
vec.deref_mut().update(0, 300)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(4))?;
assert_eq!(vec.deref_mut().collect(), vec![300, 1, 2, 3, 4]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![200, 1, 2, 3, 4]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![100, 1, 2, 3, 4]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
Ok(())
}
fn run_complex_mixed_operations<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..10 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.deref_mut().take(1)?;
vec.deref_mut().take(3)?;
vec.deref_mut().take(5)?;
vec.deref_mut().update(2, 222)?;
vec.deref_mut().update(6, 666)?;
vec.deref_mut().update(8, 888)?;
vec.push(100);
vec.push(101);
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(
vec.deref_mut().collect(),
vec![0, 222, 4, 666, 7, 888, 9, 100, 101]
);
vec.deref_mut().rollback()?;
assert_eq!(
vec.deref_mut().collect(),
vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
);
Ok(())
}
fn run_rollback_to_empty<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.deref_mut().collect(), Vec::<u32>::new());
vec.push(0);
vec.push(1);
vec.push(2);
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), Vec::<u32>::new());
Ok(())
}
fn run_reset<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..10 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.len(), 10);
assert_eq!(vec.deref_mut().stored_len(), 10);
assert_eq!(vec.pushed_len(), 0);
assert_eq!(
vec.deref_mut().collect(),
vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
);
vec.push(10);
vec.push(11);
assert_eq!(vec.len(), 12);
assert_eq!(vec.deref_mut().stored_len(), 10);
assert_eq!(vec.pushed_len(), 2);
vec.reset()?;
assert_eq!(vec.len(), 0);
assert_eq!(vec.deref_mut().stored_len(), 0);
assert_eq!(vec.pushed_len(), 0);
assert_eq!(vec.deref_mut().collect(), Vec::<u32>::new());
vec.push(100);
vec.push(101);
vec.push(102);
assert_eq!(vec.len(), 3);
assert_eq!(vec.deref_mut().stored_len(), 0);
assert_eq!(vec.pushed_len(), 3);
assert_eq!(vec.deref_mut().collect(), vec![100, 101, 102]);
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.len(), 3);
assert_eq!(vec.deref_mut().stored_len(), 3);
assert_eq!(vec.pushed_len(), 0);
assert_eq!(vec.deref_mut().collect(), vec![100, 101, 102]);
Ok(())
}
fn run_deep_rollback_chain<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.push(0);
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
vec.push(1);
vec.deref_mut().stamped_write_with_changes(Stamp::new(3))?;
vec.deref_mut().update(0, 10)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(4))?;
vec.push(2);
vec.deref_mut().stamped_write_with_changes(Stamp::new(5))?;
vec.deref_mut().take(1)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(6))?;
vec.push(3);
vec.deref_mut().stamped_write_with_changes(Stamp::new(7))?;
vec.deref_mut().update(0, 20)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(8))?;
vec.push(4);
vec.push(5);
vec.deref_mut().stamped_write_with_changes(Stamp::new(9))?;
vec.deref_mut().update(2, 33)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(10))?; assert_eq!(vec.deref_mut().collect(), vec![20, 33, 3, 4, 5]);
vec.deref_mut().rollback()?; assert_eq!(vec.deref_mut().collect(), vec![20, 2, 3, 4, 5]);
vec.deref_mut().rollback()?; assert_eq!(vec.deref_mut().collect(), vec![20, 2, 3]);
vec.deref_mut().rollback()?; assert_eq!(vec.deref_mut().collect(), vec![10, 2, 3]);
vec.deref_mut().rollback()?; assert_eq!(vec.deref_mut().collect(), vec![10, 2]);
vec.deref_mut().rollback()?; assert_eq!(vec.deref_mut().collect(), vec![10, 1, 2]);
vec.deref_mut().rollback()?; assert_eq!(vec.deref_mut().collect(), vec![10, 1]);
vec.deref_mut().rollback()?; assert_eq!(vec.deref_mut().collect(), vec![0, 1]);
vec.deref_mut().rollback()?; assert_eq!(vec.deref_mut().collect(), vec![0]);
vec.deref_mut().rollback()?; assert_eq!(vec.deref_mut().collect(), Vec::<u32>::new());
Ok(())
}
fn run_rollback_all_elements_updated<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
for i in 0..5 {
vec.deref_mut().update(i, (i * 100) as u32)?;
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 100, 200, 300, 400]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4]);
Ok(())
}
fn run_multiple_holes_then_rollback<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..10 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
for i in (0..10).step_by(2) {
vec.deref_mut().take(i)?;
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![1, 3, 5, 7, 9]);
vec.deref_mut().rollback()?;
assert_eq!(
vec.deref_mut().collect(),
vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
);
Ok(())
}
fn run_rollback_before<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
vec.push(5);
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
vec.push(6);
vec.deref_mut().stamped_write_with_changes(Stamp::new(3))?;
vec.push(7);
vec.deref_mut().stamped_write_with_changes(Stamp::new(4))?;
vec.push(8);
vec.deref_mut().stamped_write_with_changes(Stamp::new(5))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4, 5, 6, 7, 8]);
let _ = vec.deref_mut().rollback_before(Stamp::new(4))?;
assert_eq!(vec.deref_mut().collect(), vec![0, 1, 2, 3, 4, 5, 6]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(3));
Ok(())
}
fn run_rollback_after_rollback_with_delete<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (db, _temp) = setup_db()?;
let (mut vec, _) = V::import_with_changes(&db, "test", 10)?;
for &v in &[10, 20, 30, 40, 50] {
vec.push(v);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
assert_eq!(vec.deref_mut().collect(), vec![10, 20, 30, 40, 50]);
vec.deref_mut().update(2, 99)?;
vec.deref_mut().take(1)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
assert_eq!(vec.deref_mut().collect(), vec![10, 99, 40, 50]);
vec.deref_mut().rollback()?;
assert_eq!(vec.deref_mut().collect(), vec![10, 20, 30, 40, 50]);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
vec.deref_mut().take(2)?; vec.deref_mut().update(3, 88)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(3))?;
assert_eq!(vec.deref_mut().collect(), vec![10, 20, 88, 50]);
vec.deref_mut().rollback()?;
let result = vec.deref_mut().collect();
assert_eq!(
result,
vec![10, 20, 30, 40, 50],
"Second rollback must restore all original values. \
Slot 2 was deleted during reprocessing but its prev value (30) \
must still be tracked in the change file."
);
assert_eq!(vec.deref_mut().stamp(), Stamp::new(1));
Ok(())
}
#[cfg(feature = "zerocopy")]
mod zerocopy {
use super::*;
use vecdb::ZeroCopyVec;
type V = ZeroCopyVec<usize, u32>;
#[test]
fn basic_single_rollback() -> Result<()> {
run_basic_single_rollback::<V>()
}
#[test]
fn rollback_with_truncation() -> Result<()> {
run_rollback_with_truncation::<V>()
}
#[test]
fn multiple_sequential_rollbacks() -> Result<()> {
run_multiple_sequential_rollbacks::<V>()
}
#[test]
fn rollback_then_save_new_state() -> Result<()> {
run_rollback_then_save_new_state::<V>()
}
#[test]
fn rollback_with_updates() -> Result<()> {
run_rollback_with_updates::<V>()
}
#[test]
fn rollback_with_holes() -> Result<()> {
run_rollback_with_holes::<V>()
}
#[test]
fn rollback_with_truncation_and_updates() -> Result<()> {
run_rollback_with_truncation_and_updates::<V>()
}
#[test]
fn rollback_with_holes_and_updates() -> Result<()> {
run_rollback_with_holes_and_updates::<V>()
}
#[test]
fn multiple_updates_to_same_index() -> Result<()> {
run_multiple_updates_to_same_index::<V>()
}
#[test]
fn complex_mixed_operations() -> Result<()> {
run_complex_mixed_operations::<V>()
}
#[test]
fn rollback_to_empty() -> Result<()> {
run_rollback_to_empty::<V>()
}
#[test]
fn deep_rollback_chain() -> Result<()> {
run_deep_rollback_chain::<V>()
}
#[test]
fn rollback_all_elements_updated() -> Result<()> {
run_rollback_all_elements_updated::<V>()
}
#[test]
fn multiple_holes_then_rollback() -> Result<()> {
run_multiple_holes_then_rollback::<V>()
}
#[test]
fn rollback_before() -> Result<()> {
run_rollback_before::<V>()
}
#[test]
fn reset() -> Result<()> {
run_reset::<V>()
}
#[test]
fn rollback_after_rollback_with_delete() -> Result<()> {
run_rollback_after_rollback_with_delete::<V>()
}
}
mod bytes {
use super::*;
use vecdb::BytesVec;
type V = BytesVec<usize, u32>;
#[test]
fn basic_single_rollback() -> Result<()> {
run_basic_single_rollback::<V>()
}
#[test]
fn rollback_with_truncation() -> Result<()> {
run_rollback_with_truncation::<V>()
}
#[test]
fn multiple_sequential_rollbacks() -> Result<()> {
run_multiple_sequential_rollbacks::<V>()
}
#[test]
fn rollback_then_save_new_state() -> Result<()> {
run_rollback_then_save_new_state::<V>()
}
#[test]
fn rollback_with_updates() -> Result<()> {
run_rollback_with_updates::<V>()
}
#[test]
fn rollback_with_holes() -> Result<()> {
run_rollback_with_holes::<V>()
}
#[test]
fn rollback_with_truncation_and_updates() -> Result<()> {
run_rollback_with_truncation_and_updates::<V>()
}
#[test]
fn rollback_with_holes_and_updates() -> Result<()> {
run_rollback_with_holes_and_updates::<V>()
}
#[test]
fn multiple_updates_to_same_index() -> Result<()> {
run_multiple_updates_to_same_index::<V>()
}
#[test]
fn complex_mixed_operations() -> Result<()> {
run_complex_mixed_operations::<V>()
}
#[test]
fn rollback_to_empty() -> Result<()> {
run_rollback_to_empty::<V>()
}
#[test]
fn deep_rollback_chain() -> Result<()> {
run_deep_rollback_chain::<V>()
}
#[test]
fn rollback_all_elements_updated() -> Result<()> {
run_rollback_all_elements_updated::<V>()
}
#[test]
fn multiple_holes_then_rollback() -> Result<()> {
run_multiple_holes_then_rollback::<V>()
}
#[test]
fn rollback_before() -> Result<()> {
run_rollback_before::<V>()
}
#[test]
fn reset() -> Result<()> {
run_reset::<V>()
}
#[test]
fn rollback_after_rollback_with_delete() -> Result<()> {
run_rollback_after_rollback_with_delete::<V>()
}
}
}
mod integration {
use crate::raw_rollback::{RollbackOps, RollbackVec};
use super::*;
use sha2::{Digest, Sha256};
use std::fs;
use std::path::Path;
fn compute_directory_hash(dir: &Path) -> Result<String> {
use std::path::PathBuf;
let mut hasher = Sha256::new();
let mut files: Vec<PathBuf> = Vec::new();
let data_file = dir.join("data");
if data_file.exists() && data_file.is_file() {
files.push(data_file);
}
let regions_dir = dir.join("regions");
if regions_dir.exists() {
fn collect_files(dir: &Path, files: &mut Vec<PathBuf>) {
let Ok(entries) = fs::read_dir(dir) else {
return;
};
for entry in entries.filter_map(|e| e.ok()) {
let path = entry.path();
if path.components().any(|c| c.as_os_str() == "changes") {
continue;
}
if path.is_dir() {
collect_files(&path, files);
} else if path.is_file() {
files.push(path);
}
}
}
collect_files(®ions_dir, &mut files);
}
files.sort();
for file_path in &files {
if let Ok(rel_path) = file_path.strip_prefix(dir) {
hasher.update(rel_path.to_string_lossy().as_bytes());
}
let contents = fs::read(file_path)?;
hasher.update(&contents);
}
let hash = hasher.finalize();
Ok(hash.iter().map(|b| format!("{:02x}", b)).collect())
}
fn run_data_integrity_rollback_flush_reopen<V>() -> Result<()>
where
V: RollbackVec,
V::Target: RollbackOps,
{
let (database, temp) = setup_db()?;
let test_path = temp.path();
let (mut vec, _) = V::import_with_changes(&database, "vec", 10)?;
for i in 0..5 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(1))?;
for i in 5..10 {
vec.push(i);
}
vec.deref_mut().stamped_write_with_changes(Stamp::new(2))?;
let checkpoint1_data = vec.deref_mut().collect_holed()?;
let checkpoint1_stamp = vec.deref_mut().stamp();
let _checkpoint1_hash = compute_directory_hash(test_path)?;
vec.deref_mut().update(2, 100)?;
vec.deref_mut().update(7, 200)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(3))?;
vec.push(20);
vec.push(21);
vec.deref_mut().stamped_write_with_changes(Stamp::new(4))?;
vec.deref_mut().take(5)?;
vec.push(30);
vec.deref_mut().stamped_write_with_changes(Stamp::new(5))?;
let checkpoint2_data = vec.deref_mut().collect_holed()?;
let checkpoint2_stamp = vec.deref_mut().stamp();
let _checkpoint2_hash = compute_directory_hash(test_path)?;
vec.deref_mut().rollback()?;
vec.deref_mut().rollback()?;
vec.deref_mut().rollback()?;
let after_undo_data = vec.deref_mut().collect_holed()?;
let after_undo_stamp = vec.deref_mut().stamp();
assert_eq!(after_undo_stamp, checkpoint1_stamp);
assert_eq!(after_undo_data, checkpoint1_data);
vec.deref_mut()
.stamped_write_with_changes(checkpoint1_stamp)?;
let _after_flush_hash = compute_directory_hash(test_path)?;
drop(vec);
let (mut vec, _) = V::import_with_changes(&database, "vec", 10)?;
let reader = vec.deref_mut().create_reader();
let mut data_via_gets = Vec::new();
for i in 0..vec.len() {
let value = vec.get_any_or_read(i, &reader)?;
data_via_gets.push(value);
}
drop(reader);
assert_eq!(data_via_gets, checkpoint1_data);
let data_via_iter = vec.deref_mut().collect_holed()?;
assert_eq!(data_via_iter, checkpoint1_data);
vec.deref_mut().update(2, 100)?;
vec.deref_mut().update(7, 200)?;
vec.deref_mut().stamped_write_with_changes(Stamp::new(3))?;
vec.push(20);
vec.push(21);
vec.deref_mut().stamped_write_with_changes(Stamp::new(4))?;
vec.deref_mut().take(5)?;
vec.push(30);
vec.deref_mut().stamped_write_with_changes(Stamp::new(5))?;
let after_redo_data = vec.deref_mut().collect_holed()?;
let after_redo_stamp = vec.deref_mut().stamp();
assert_eq!(after_redo_stamp, checkpoint2_stamp);
assert_eq!(after_redo_data, checkpoint2_data);
vec.deref_mut()
.stamped_write_with_changes(checkpoint2_stamp)?;
drop(vec);
let (vec, _) = V::import_with_changes(&database, "vec", 10)?;
let reader = vec.deref().create_reader();
let mut data_via_gets = Vec::new();
for i in 0..vec.len() {
let value = vec.get_any_or_read(i, &reader)?;
data_via_gets.push(value);
}
drop(reader);
assert_eq!(data_via_gets, checkpoint2_data);
let data_via_iter = vec.deref().collect_holed()?;
assert_eq!(data_via_iter, checkpoint2_data);
Ok(())
}
#[cfg(feature = "zerocopy")]
mod zerocopy {
use super::*;
use vecdb::ZeroCopyVec;
type V = ZeroCopyVec<usize, u32>;
#[test]
fn data_integrity_rollback_flush_reopen() -> Result<()> {
run_data_integrity_rollback_flush_reopen::<V>()
}
}
mod bytes {
use super::*;
use vecdb::BytesVec;
type V = BytesVec<usize, u32>;
#[test]
fn data_integrity_rollback_flush_reopen() -> Result<()> {
run_data_integrity_rollback_flush_reopen::<V>()
}
}
}