use super::*;
use alloc::vec;
use core::num::NonZeroU32;
#[derive(Clone, Debug, Eq, PartialEq, WarpTableRow)]
#[index(primary = u32)]
struct Stock {
quantity: u32,
}
impl PersistentRow for Stock {
fn own(row: StockRef<'_>) -> Self {
Self {
quantity: *row.quantity,
}
}
fn retained_bytes(&self) -> usize {
4
}
}
fn fresh() -> Result<(RecoveryBuilder<Stock>, Record<Stock, u32>), Error> {
let capacity = super::super::super::Capacity::new(NonZeroU32::MIN);
let history = HistoryId([11; 16]);
let builder = RecoveryBuilder::new(
Recovery {
history,
revision: Revision(0),
reserved_through: 16,
rows: vec![],
outcomes: vec![],
},
Limits {
rows: capacity,
operations: capacity,
sessions: capacity,
changes: 1,
row_bytes: 4,
receipt_bytes: 0,
},
)?;
let record = Record {
receipt: None,
operation: OperationId {
history,
epoch: 1,
session: SessionId(1),
sequence: 1,
},
expected: Revision(0),
revision: Revision(1),
changes: vec![Change::Insert {
id: 7,
row: Stock { quantity: 42 },
}],
};
Ok((builder, record))
}
#[test]
fn corrupted_outcome_capacity_refuses_recovery_assembly() -> Result<(), Error> {
let (mut builder, record) = fresh()?;
builder.outcomes.maximum_rows = 0;
assert_eq!(builder.apply(record), Err(Error::Corrupt));
assert!(builder.outcomes.is_empty());
assert!(builder.order.is_empty());
Ok(())
}
#[test]
fn missing_row_or_outcome_bindings_cannot_produce_a_recovery_snapshot() -> Result<(), Error> {
let (mut builder, record) = fresh()?;
builder.apply(record.clone())?;
builder.table.primary_index =
crate::storage::warp_table::dense_key_index::DenseKeyIndex::try_new(1)
.map_err(|_| Error::Allocation)?;
assert!(matches!(builder.snapshot(), Err(Error::Corrupt)));
assert_eq!(builder.table.ids(), &[7]);
let (mut builder, record) = fresh()?;
let operation = record.operation;
builder.apply(record)?;
builder.outcomes.primary_index =
crate::storage::warp_table::dense_key_index::DenseKeyIndex::try_new(1)
.map_err(|_| Error::Allocation)?;
assert!(matches!(builder.snapshot(), Err(Error::Corrupt)));
assert_eq!(builder.order, [operation]);
Ok(())
}