pipecircuit 0.0.12

Correct. Robust. Fast. Portable.
Documentation
use core::num::NonZeroUsize;

use super::{
    BytePool, BytePoolLeaseOutcome, BytePoolMaterializeOutcome, BytePoolRecycleOutcome,
    BytePoolReserveOutcome, BytePoolResumeOutcome, BytePoolStatistics,
};

fn nonzero(value: usize) -> Result<NonZeroUsize, &'static str> {
    NonZeroUsize::new(value).ok_or("test capacity was zero")
}

#[test]
fn leases_borrow_exact_pool_storage_and_recycle_on_drop() -> Result<(), &'static str> {
    let mut pool = BytePool::try_new(nonzero(16)?, nonzero(4)?).map_err(|_| "pool unavailable")?;
    let BytePoolLeaseOutcome::Leased(mut first) = pool.lease(nonzero(6)?) else {
        return Err("first extent was unavailable");
    };
    let first_address = first.bytes().as_ptr();
    first.bytes_mut().copy_from_slice(b"first!");
    assert_eq!(first.byte_capacity(), 6);
    assert_eq!(first.bytes(), b"first!");
    drop(first);

    assert_eq!(
        pool.statistics(),
        BytePoolStatistics {
            byte_capacity: 16,
            free_byte_capacity: 16,
            maximum_lease_count: 4,
            active_lease_count: 0,
        }
    );
    let BytePoolLeaseOutcome::Leased(second) = pool.lease(nonzero(16)?) else {
        return Err("coalesced extent was unavailable");
    };
    assert_eq!(second.byte_capacity(), 16);
    assert_eq!(second.bytes().as_ptr(), first_address);
    Ok(())
}

#[test]
fn retained_extents_resume_without_moving_and_do_not_block_other_extents()
-> Result<(), &'static str> {
    let mut pool = BytePool::try_new(nonzero(16)?, nonzero(4)?).map_err(|_| "pool unavailable")?;
    let BytePoolLeaseOutcome::Leased(mut retained) = pool.lease(nonzero(8)?) else {
        return Err("retained extent was unavailable");
    };
    retained.bytes_mut().copy_from_slice(b"retained");
    let retained_address = retained.bytes().as_ptr();
    let retained = retained.retain();

    let BytePoolLeaseOutcome::Leased(mut independent) = pool.lease(nonzero(8)?) else {
        return Err("independent extent was unavailable");
    };
    independent.bytes_mut().copy_from_slice(b"separate");
    assert_ne!(independent.bytes().as_ptr(), retained_address);
    drop(independent);
    assert_eq!(pool.statistics().free_byte_capacity, 8);

    let BytePoolResumeOutcome::Resumed(resumed) = pool.resume(retained) else {
        return Err("retained extent did not resume");
    };
    assert_eq!(resumed.bytes(), b"retained");
    assert_eq!(resumed.bytes().as_ptr(), retained_address);
    drop(resumed);
    assert_eq!(pool.statistics().free_byte_capacity, 16);
    Ok(())
}

#[test]
fn byte_and_lease_exhaustion_remain_distinct() -> Result<(), &'static str> {
    let mut bytes = BytePool::try_new(nonzero(4)?, nonzero(2)?).map_err(|_| "pool unavailable")?;
    let BytePoolLeaseOutcome::Leased(first) = bytes.lease(nonzero(4)?) else {
        return Err("first byte extent was unavailable");
    };
    let first = first.retain();
    assert!(matches!(
        bytes.lease(nonzero(1)?),
        BytePoolLeaseOutcome::Exhausted { .. }
    ));
    assert_eq!(bytes.recycle(first), BytePoolRecycleOutcome::Recycled);

    let mut leases = BytePool::try_new(nonzero(8)?, nonzero(1)?).map_err(|_| "pool unavailable")?;
    let BytePoolLeaseOutcome::Leased(first) = leases.lease(nonzero(4)?) else {
        return Err("first lease was unavailable");
    };
    let first = first.retain();
    assert!(matches!(
        leases.lease(nonzero(1)?),
        BytePoolLeaseOutcome::LeaseCapacityReached { .. }
    ));
    assert_eq!(leases.recycle(first), BytePoolRecycleOutcome::Recycled);
    Ok(())
}

#[test]
fn retained_leases_can_be_explicitly_recycled() -> Result<(), &'static str> {
    let mut pool = BytePool::try_new(nonzero(8)?, nonzero(2)?).map_err(|_| "pool unavailable")?;
    let BytePoolLeaseOutcome::Leased(lease) = pool.lease(nonzero(8)?) else {
        return Err("lease was unavailable");
    };
    let retained = lease.retain();
    assert_eq!(retained.byte_capacity(), 8);
    assert_eq!(pool.recycle(retained), BytePoolRecycleOutcome::Recycled);
    assert_eq!(pool.statistics().free_byte_capacity, 8);
    Ok(())
}

#[test]
fn dropped_reservations_do_not_materialize_leases() -> Result<(), &'static str> {
    let mut pool = BytePool::try_new(nonzero(16)?, nonzero(2)?).map_err(|_| "pool unavailable")?;
    let BytePoolReserveOutcome::Reserved(reservation) = pool.reserve_exact(nonzero(12)?) else {
        return Err("reservation was unavailable");
    };
    assert_eq!(reservation.reserved_maximum(), nonzero(12)?);
    drop(reservation);

    assert_eq!(pool.leases.first().map(|lease| lease.generation), Some(0));
    assert_eq!(pool.statistics().free_byte_capacity, 16);
    Ok(())
}

#[test]
fn reservations_materialize_only_the_requested_tail() -> Result<(), &'static str> {
    let mut pool = BytePool::try_new(nonzero(16)?, nonzero(2)?).map_err(|_| "pool unavailable")?;
    let BytePoolReserveOutcome::Reserved(reservation) = pool.reserve_exact(nonzero(12)?) else {
        return Err("reservation was unavailable");
    };
    let BytePoolMaterializeOutcome::Leased(lease) = reservation.materialize(nonzero(3)?) else {
        return Err("reserved tail was unavailable");
    };
    assert_eq!(lease.byte_capacity(), 3);
    drop(lease);
    assert_eq!(pool.statistics().free_byte_capacity, 16);
    Ok(())
}

#[test]
fn out_of_order_releases_coalesce_without_global_sorting() -> Result<(), &'static str> {
    let mut pool = BytePool::try_new(nonzero(16)?, nonzero(4)?).map_err(|_| "pool unavailable")?;
    let BytePoolLeaseOutcome::Leased(first) = pool.lease(nonzero(4)?) else {
        return Err("first lease unavailable");
    };
    let first = first.retain();
    let BytePoolLeaseOutcome::Leased(second) = pool.lease(nonzero(4)?) else {
        return Err("second lease unavailable");
    };
    let second = second.retain();
    let BytePoolLeaseOutcome::Leased(third) = pool.lease(nonzero(4)?) else {
        return Err("third lease unavailable");
    };
    let third = third.retain();
    let BytePoolLeaseOutcome::Leased(fourth) = pool.lease(nonzero(4)?) else {
        return Err("fourth lease unavailable");
    };
    let fourth = fourth.retain();

    assert_eq!(pool.recycle(second), BytePoolRecycleOutcome::Recycled);
    assert_eq!(pool.recycle(fourth), BytePoolRecycleOutcome::Recycled);
    assert!(matches!(
        pool.reserve_exact(nonzero(8)?),
        BytePoolReserveOutcome::Exhausted { .. }
    ));
    assert_eq!(pool.recycle(first), BytePoolRecycleOutcome::Recycled);
    assert_eq!(pool.recycle(third), BytePoolRecycleOutcome::Recycled);
    let BytePoolLeaseOutcome::Leased(coalesced) = pool.lease(nonzero(16)?) else {
        return Err("coalesced lease unavailable");
    };
    assert_eq!(coalesced.byte_capacity(), 16);
    Ok(())
}

#[cfg(feature = "performance-evidence")]
#[test]
fn evidence_accounts_for_pool_searches_and_lease_lifetimes() -> Result<(), &'static str> {
    let mut pool = BytePool::try_new(nonzero(16)?, nonzero(2)?).map_err(|_| "pool unavailable")?;
    let BytePoolLeaseOutcome::Leased(lease) = pool.lease(nonzero(6)?) else {
        return Err("lease unavailable");
    };
    let retained = lease.retain();
    let BytePoolResumeOutcome::Resumed(resumed) = pool.resume(retained) else {
        return Err("retained lease unavailable");
    };
    drop(resumed);

    let evidence = pool.take_evidence();

    assert_eq!(evidence.active_leases_at_start(), 0);
    assert_eq!(evidence.reservation_attempts().total(), 1);
    assert_eq!(evidence.requested_bytes().total(), 6);
    assert_eq!(evidence.free_extents_examined().total(), 1);
    assert_eq!(evidence.free_extent_count_high_water().maximum(), 1);
    assert_eq!(evidence.reservations().total(), 1);
    assert_eq!(evidence.materializations().total(), 1);
    assert_eq!(evidence.materialized_bytes().total(), 6);
    assert_eq!(evidence.resume_attempts().total(), 1);
    assert_eq!(evidence.resumed_leases().total(), 1);
    assert_eq!(evidence.released_leases_collected().total(), 1);
    assert_eq!(evidence.active_leases().current(), 0);
    assert_eq!(evidence.active_leases().high_water().maximum(), 1);
    assert!(evidence.valid());
    assert_eq!(pool.evidence(), super::BytePoolEvidence::new());

    Ok(())
}