minerva 0.2.0

Causal ordering for distributed systems
use crate::kairos::{Backoff, ConstantBackoff, ExponentialBackoff, ModelBasedBackoff};

#[test]
fn test_backoff_tolerates_unbounded_attempts() {
    // Generation is infallible: backoff has no abort path, and the exponential
    // spin count caps (the shift is bounded at 31), so arbitrarily high attempt
    // counts must complete without panicking or overflowing the shift. Without
    // the cap, `1u32 << (attempt - 1)` would overflow here. Counts stay tiny so
    // the test is fast.
    static SPINS: [u32; 1] = [4];
    ConstantBackoff::new(4, None).backoff(1_000_000);
    ExponentialBackoff::new(1, 16, None).backoff(1_000);
    ModelBasedBackoff::new(&SPINS).backoff(1_000_000);
    // An empty table is a valid no-op, not an out-of-bounds panic.
    ModelBasedBackoff::new(&[]).backoff(1);
}

#[test]
fn test_exponential_backoff_caps_spins() {
    // The spin count doubles per attempt, then pins at max_spins; the shift cap
    // keeps an unbounded attempt count from overflowing.
    let b = ExponentialBackoff::new(2, 100, None);
    assert_eq!(b.spins(1), 2); // 2 << 0
    assert_eq!(b.spins(2), 4); // 2 << 1
    assert_eq!(b.spins(3), 8); // 2 << 2
    assert_eq!(b.spins(7), 100); // 2 << 6 = 128, capped at 100
    assert_eq!(b.spins(1_000_000), 100); // shift capped at 31, saturates, pins at max
}