pipecircuit 0.0.20

Correct. Robust. Fast. Portable. Pick four.
Documentation
use super::*;
use alloc::boxed::Box;
use core::num::{NonZeroU32, NonZeroU64};

struct Worker;
impl Pipe for Worker {
    type In<'message> = Box<[u8]>;
    type Out<'message> = ();
}

#[test]
fn impossible_column_capacity_preserves_the_creation_failure() -> Result<(), &'static str> {
    let capacity = Capacity::new(NonZeroU32::MIN.saturating_add(2_048));
    let Err(error) = ContinuationLedger::<[u8; (isize::MAX as usize) / 1_024]>::try_new(capacity)
    else {
        return Err("unrepresentable columns were allocated");
    };
    assert_eq!(
        error.failure(),
        ContinuationLedgerCreationFailure::StorageUnavailable
    );
    assert!(matches!(
        error._source,
        WarpTableCreationError::ColumnsUnavailable { .. }
    ));
    Ok(())
}

#[test]
fn exhausted_identifier_outcome_preserves_address_input_and_deadline() -> Result<(), &'static str> {
    let ledger =
        ContinuationLedger::try_new(Capacity::new(NonZeroU32::MIN)).map_err(|_| "ledger")?;
    let return_to = Box::new(37_u8);
    let address = core::ptr::from_ref(return_to.as_ref());
    let input = Box::<[u8]>::from([3, 7, 9]);
    let bytes = input.as_ptr();
    let after = crate::TimeoutAfter::microseconds(NonZeroU64::MIN.saturating_add(12));
    let outcome = ledger.admission_outcome::<Worker>(
        WarpTableInsertOutcome::IdentifiersExhausted {
            rejected: PendingContinuation { return_to },
        },
        Owed::new(input, after),
    );
    let ContinuationAdmissionOutcome::Refused {
        return_to,
        result: Err(ContinuationFailure::Unavailable { reason, rejected }),
    } = outcome
    else {
        return Err("exhaustion did not return owned work");
    };
    assert_eq!(reason, ContinuationUnavailable::IdentifiersExhausted);
    assert_eq!(*return_to, 37);
    assert_eq!(core::ptr::from_ref(return_to.as_ref()), address);
    let (input, returned_after) = rejected.into_parts();
    assert_eq!(input.as_ref(), &[3, 7, 9]);
    assert_eq!(input.as_ptr(), bytes);
    assert_eq!(returned_after, after);
    assert!(ledger.is_empty());
    Ok(())
}

#[test]
fn late_arm_refusal_preserves_owned_work_after_expiry() -> Result<(), &'static str> {
    let mut ledger =
        ContinuationLedger::try_new(Capacity::new(NonZeroU32::MIN)).map_err(|_| "ledger")?;
    let input = Box::<[u8]>::from([1, 2, 3]);
    let bytes = input.as_ptr();
    let after = crate::TimeoutAfter::microseconds(NonZeroU64::MIN.saturating_add(7));
    let ContinuationAdmissionOutcome::Admitted { admission } =
        ledger.admit::<Worker>(37_u8, Owed::new(input, after))
    else {
        return Err("admission");
    };
    let token = admission.timer_token();
    let ContinuationExpirationOutcome::Expired {
        return_to,
        expiration,
    } = ledger.expire(token)
    else {
        return Err("expiry");
    };
    assert_eq!(return_to, 37);
    assert_eq!(expiration.token(), token);
    let reason = crate::TimerArmRefusal::AtCapacity {
        maximum_deadlines: 9,
    };
    let output = crate::TimerOut::ArmRefused {
        token,
        after,
        reason,
    }
    .into_arm_outcome()
    .map_err(|_| "arm output")?;
    let crate::ContinuationArmOutcome::Refused { refusal } = admission
        .settle_timer_arm(output)
        .map_err(|_| "arm mismatch")?
    else {
        return Err("refusal");
    };
    let ContinuationRefusalOutcome::Stale { refusal } = ledger.refuse(refusal) else {
        return Err("expired work was resolved twice");
    };
    assert_eq!(refusal.reason(), reason);
    assert_eq!(refusal.id.value(), token.value());
    let (returned, returned_after) = refusal.owed.into_parts();
    assert_eq!(returned.as_ptr(), bytes);
    assert_eq!(returned.as_ref(), &[1, 2, 3]);
    assert_eq!(returned_after, after);
    assert!(ledger.is_empty());
    Ok(())
}