pipecircuit 0.0.23

Correct. Robust. Fast. Portable. Pick four.
Documentation
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(())
}