use super::*;
use crate::storage::byte_pool::BytePoolStatistics;
fn nonzero(value: usize) -> Result<NonZeroUsize, &'static str> {
NonZeroUsize::new(value).ok_or("zero capacity")
}
fn pool() -> Result<BytePool, &'static str> {
BytePool::try_new(nonzero(8)?, nonzero(2)?).map_err(|_| "pool allocation")
}
#[test]
fn malformed_reservation_metadata_preserves_storage_and_available_identity()
-> Result<(), &'static str> {
for (head, status, generation, extents, reason) in [
(
Some(7),
LeaseStatus::Vacant,
0,
alloc::vec![0..8],
BytePoolInconsistency::LeaseUnavailable { slot: 7 },
),
(
Some(0),
LeaseStatus::Leased,
0,
alloc::vec![0..8],
BytePoolInconsistency::LeaseUnavailable { slot: 0 },
),
(
Some(0),
LeaseStatus::Vacant,
u64::MAX,
alloc::vec![0..8],
BytePoolInconsistency::LeaseUnavailable { slot: 0 },
),
(
Some(0),
LeaseStatus::Vacant,
0,
alloc::vec![7..10],
BytePoolInconsistency::StorageUnavailable { start: 7, end: 10 },
),
] {
let mut pool = pool()?;
pool.available_lease_head = head;
let record = pool.leases.first_mut().ok_or("lease")?;
record.status.set(status);
record.generation = generation;
pool.free_extents = extents.clone();
let BytePoolLeaseOutcome::Inconsistent {
requested_maximum,
reason: found,
} = pool.lease(nonzero(3)?)
else {
return Err("malformed reservation was accepted");
};
assert_eq!(requested_maximum.get(), 3);
assert_eq!(found, reason);
assert_eq!(pool.available_lease_head, head);
assert_eq!(pool.free_extents, extents);
assert_eq!(
pool.leases
.first()
.map(|record| (record.status.get(), record.generation)),
Some((status, generation))
);
assert_eq!(pool.storage.as_ref(), &[0; 8]);
#[cfg(feature = "performance-evidence")]
{
assert_eq!(pool.evidence().inconsistencies().total(), 1);
assert_eq!(pool.evidence().materializations().total(), 0);
}
}
Ok(())
}
#[test]
fn empty_extents_and_overflowing_reservation_bounds_preserve_admission() -> Result<(), &'static str>
{
let mut pool = pool()?;
pool.free_extents = alloc::vec![5..5];
assert!(
matches!(pool.reserve_up_to(nonzero(3)?), BytePoolReserveOutcome::Exhausted { requested_maximum } if requested_maximum.get() == 3)
);
assert_eq!(pool.available_lease_head, Some(0));
assert_eq!(pool.free_extents, alloc::vec![5..5]);
let BytePoolReserveOutcome::Inconsistent {
requested_maximum,
reason,
} = pool.reserve_extent(0, 0, usize::MAX, NonZeroUsize::MIN, nonzero(3)?)
else {
return Err("overflowing extent accepted");
};
assert_eq!(requested_maximum.get(), 3);
assert_eq!(
reason,
BytePoolInconsistency::StorageUnavailable {
start: usize::MAX,
end: usize::MAX
}
);
assert_eq!(pool.available_lease_head, Some(0));
#[cfg(feature = "performance-evidence")]
{
assert_eq!(pool.evidence().exhausted_reservations().total(), 1);
assert_eq!(pool.evidence().inconsistencies().total(), 1);
}
Ok(())
}
#[test]
fn materialization_refuses_each_invalid_binding_without_consuming_a_lease()
-> Result<(), &'static str> {
for (extent_index, extent, slot, head, status, generation, requested, reason) in [
(
4,
0..8,
0,
Some(0),
LeaseStatus::Vacant,
0,
3,
BytePoolInconsistency::StorageUnavailable { start: 0, end: 3 },
),
(
0,
usize::MAX..usize::MAX,
0,
Some(0),
LeaseStatus::Vacant,
0,
3,
BytePoolInconsistency::StorageUnavailable {
start: usize::MAX,
end: usize::MAX,
},
),
(
0,
0..2,
0,
Some(0),
LeaseStatus::Vacant,
0,
3,
BytePoolInconsistency::StorageUnavailable { start: 0, end: 3 },
),
(
0,
0..8,
7,
Some(0),
LeaseStatus::Vacant,
0,
3,
BytePoolInconsistency::LeaseUnavailable { slot: 7 },
),
(
0,
0..8,
0,
Some(1),
LeaseStatus::Vacant,
0,
3,
BytePoolInconsistency::LeaseUnavailable { slot: 0 },
),
(
0,
0..8,
0,
Some(0),
LeaseStatus::Leased,
0,
3,
BytePoolInconsistency::LeaseUnavailable { slot: 0 },
),
(
0,
0..8,
0,
Some(0),
LeaseStatus::Vacant,
u64::MAX,
3,
BytePoolInconsistency::LeaseUnavailable { slot: 0 },
),
(
0,
7..10,
0,
Some(0),
LeaseStatus::Vacant,
0,
3,
BytePoolInconsistency::StorageUnavailable { start: 7, end: 10 },
),
] {
let mut pool = pool()?;
pool.free_extents = alloc::vec![extent.clone()];
pool.available_lease_head = head;
let record = pool.leases.first_mut().ok_or("lease")?;
record.status.set(status);
record.generation = generation;
let Err(found) = pool.materialize(slot, extent_index, nonzero(requested)?) else {
return Err("invalid materialization succeeded");
};
assert_eq!(found, reason);
assert_eq!(pool.free_extents, alloc::vec![extent]);
assert_eq!(pool.available_lease_head, head);
assert_eq!(
pool.leases
.first()
.map(|record| (record.status.get(), record.generation)),
Some((status, generation))
);
assert_eq!(pool.storage.as_ref(), &[0; 8]);
}
Ok(())
}
#[test]
fn oversized_materialization_releases_the_reservation_without_leasing_bytes()
-> Result<(), &'static str> {
let mut pool = pool()?;
let before = pool.statistics();
let BytePoolReserveOutcome::Reserved(reservation) = pool.reserve_exact(nonzero(3)?) else {
return Err("reserve");
};
let outcome = reservation.materialize(nonzero(4)?);
let BytePoolMaterializeOutcome::ReservationExceeded {
requested,
reserved_maximum,
} = outcome
else {
return Err("oversize accepted");
};
assert_eq!(requested.get(), 4);
assert_eq!(reserved_maximum.get(), 3);
assert!(
matches!(lease_outcome(outcome, nonzero(7)?), BytePoolLeaseOutcome::Exhausted { requested_maximum } if requested_maximum.get() == 7)
);
assert_eq!(pool.statistics(), before);
assert_eq!(pool.leases.first().map(|record| record.generation), Some(0));
let reservation = ByteLeaseReservation {
pool: &mut pool,
slot: 7,
extent_index: 0,
reserved_maximum: nonzero(3)?,
};
let outcome = reservation.materialize(nonzero(3)?);
let BytePoolMaterializeOutcome::Inconsistent { requested, reason } = &outcome else {
return Err("missing slot accepted");
};
assert_eq!(requested.get(), 3);
assert_eq!(*reason, BytePoolInconsistency::LeaseUnavailable { slot: 7 });
assert!(
matches!(lease_outcome(outcome, nonzero(7)?), BytePoolLeaseOutcome::Inconsistent { requested_maximum, reason: BytePoolInconsistency::LeaseUnavailable { slot: 7 } } if requested_maximum.get() == 7)
);
assert_eq!(pool.statistics(), before);
Ok(())
}
#[test]
fn exact_reservations_accept_the_entire_remaining_contiguous_extent() -> Result<(), &'static str> {
let mut pool = pool()?;
let BytePoolLeaseOutcome::Leased(lease) = pool.lease(nonzero(3)?) else {
return Err("first lease");
};
let first = lease.retain();
let before = pool.statistics();
assert!(
matches!(pool.reserve_exact(nonzero(6)?), BytePoolReserveOutcome::Exhausted { requested_maximum } if requested_maximum.get() == 6)
);
assert_eq!(pool.statistics(), before);
let BytePoolReserveOutcome::Reserved(reservation) = pool.reserve_exact(nonzero(5)?) else {
return Err("exact fit refused");
};
assert_eq!(reservation.reserved_maximum().get(), 5);
let BytePoolMaterializeOutcome::Leased(lease) = reservation.materialize(nonzero(5)?) else {
return Err("exact fit not materialized");
};
assert_eq!(lease.byte_capacity(), 5);
let second = lease.retain();
assert_eq!(pool.statistics().free_byte_capacity, 0);
assert_eq!(pool.statistics().active_lease_count, 2);
assert_eq!(pool.recycle(first), BytePoolRecycleOutcome::Recycled);
assert_eq!(pool.recycle(second), BytePoolRecycleOutcome::Recycled);
let BytePoolReserveOutcome::Reserved(reservation) = pool.reserve_exact(nonzero(8)?) else {
return Err("coalesced exact fit refused");
};
assert_eq!(reservation.reserved_maximum().get(), 8);
drop(reservation);
assert_eq!(pool.statistics().free_byte_capacity, 8);
Ok(())
}
#[test]
fn the_last_identity_is_usable_once_and_then_permanently_exhausted() -> Result<(), &'static str> {
let mut pool = BytePool::try_new(nonzero(8)?, NonZeroUsize::MIN).map_err(|_| "pool")?;
pool.leases.first_mut().ok_or("lease")?.generation = u64::MAX.saturating_sub(1);
let BytePoolLeaseOutcome::Leased(lease) = pool.lease(nonzero(3)?) else {
return Err("last identity refused");
};
assert_eq!(lease.generation, u64::MAX);
let retained = lease.retain();
assert_eq!(retained, retained);
assert_eq!(pool.recycle(retained), BytePoolRecycleOutcome::Recycled);
assert_eq!(
pool.statistics(),
BytePoolStatistics {
byte_capacity: 8,
free_byte_capacity: 8,
maximum_lease_count: 1,
active_lease_count: 0
}
);
assert_eq!(pool.exhausted_lease_count, 1);
assert_eq!(
pool.leases.first().map(|record| record.status.get()),
Some(LeaseStatus::Exhausted)
);
for _ in 0..2 {
assert!(
matches!(pool.lease(nonzero(3)?), BytePoolLeaseOutcome::LeaseIdentitiesExhausted { requested_maximum } if requested_maximum.get() == 3)
);
assert_eq!(pool.exhausted_lease_count, 1);
}
#[cfg(feature = "performance-evidence")]
{
assert_eq!(pool.evidence().lease_identity_refusals().total(), 2);
assert_eq!(pool.evidence().released_leases_collected().total(), 1);
assert_eq!(pool.evidence().active_leases().current(), 0);
assert!(pool.evidence().valid());
}
Ok(())
}
#[test]
fn missing_active_and_released_slots_cannot_bind_storage() -> Result<(), &'static str> {
let mut pool = pool()?;
let Err(reason) = pool.active_lease(7) else {
return Err("missing active lease accepted");
};
assert_eq!(reason, BytePoolInconsistency::LeaseUnavailable { slot: 7 });
pool.released_lease_head.set(Some(7));
let before = pool.free_extents.clone();
pool.collect_released();
assert_eq!(pool.released_lease_head.get(), None);
assert_eq!(pool.available_lease_head, Some(0));
assert_eq!(pool.free_extents, before);
Ok(())
}
#[test]
fn each_retained_binding_fact_is_required_before_resuming_or_recycling() -> Result<(), &'static str>
{
for field in 0..4 {
let mut pool = pool()?;
let BytePoolLeaseOutcome::Leased(mut lease) = pool.lease(nonzero(3)?) else {
return Err("lease");
};
lease.bytes_mut().copy_from_slice(&[1, 2, 3]);
let mut retained = lease.retain();
let identity = retained.identity.as_ptr();
let slot = retained.slot;
let generation = retained.generation;
let range = retained.range.clone();
match field {
0 => retained.slot = 7,
1 => retained.generation = generation.saturating_add(1),
2 => retained.range.end = 2,
3 => pool
.leases
.get(slot)
.ok_or("slot")?
.status
.set(LeaseStatus::Vacant),
_ => return Err("unknown binding field"),
}
let BytePoolResumeOutcome::Unavailable { retained } = pool.resume(retained) else {
return Err("mismatched binding resumed");
};
assert_eq!(retained.identity.as_ptr(), identity);
let BytePoolRecycleOutcome::Unavailable { mut retained } = pool.recycle(retained) else {
return Err("mismatched binding recycled");
};
assert_eq!(retained.identity.as_ptr(), identity);
assert_eq!(pool.storage.get(..3), Some([1, 2, 3].as_slice()));
assert_eq!(pool.free_extents, alloc::vec![3..8]);
retained.slot = slot;
retained.generation = generation;
retained.range = range;
pool.leases
.get(slot)
.ok_or("slot")?
.status
.set(LeaseStatus::Leased);
let BytePoolResumeOutcome::Resumed(lease) = pool.resume(retained) else {
return Err("valid binding lost");
};
assert_eq!(lease.bytes(), &[1, 2, 3]);
drop(lease);
assert_eq!(pool.statistics().free_byte_capacity, 8);
}
Ok(())
}
#[cfg(feature = "performance-evidence")]
#[test]
fn rejected_owner_operations_have_distinct_exact_counters() -> Result<(), &'static str> {
let mut first = BytePool::try_new(nonzero(8)?, NonZeroUsize::MIN).map_err(|_| "first")?;
let mut second = BytePool::try_new(nonzero(8)?, NonZeroUsize::MIN).map_err(|_| "second")?;
let BytePoolLeaseOutcome::Leased(lease) = first.lease(nonzero(3)?) else {
return Err("lease");
};
let retained = lease.retain();
assert!(matches!(
first.lease(NonZeroUsize::MIN),
BytePoolLeaseOutcome::LeaseCapacityReached { .. }
));
let BytePoolResumeOutcome::Unavailable { retained } = second.resume(retained) else {
return Err("foreign owner resumed");
};
let BytePoolRecycleOutcome::Unavailable { retained } = second.recycle(retained) else {
return Err("foreign owner recycled");
};
assert_eq!(first.recycle(retained), BytePoolRecycleOutcome::Recycled);
let original = first.take_evidence();
assert_eq!(original.lease_capacity_refusals().total(), 1);
assert_eq!(original.recycle_attempts().total(), 1);
assert_eq!(original.recycled_leases().total(), 1);
assert_eq!(original.recycle_refusals().total(), 0);
assert_eq!(original.resume_refusals().total(), 0);
assert!(original.valid());
let foreign = second.take_evidence();
assert_eq!(foreign.lease_capacity_refusals().total(), 0);
assert_eq!(foreign.resume_attempts().total(), 1);
assert_eq!(foreign.resume_refusals().total(), 1);
assert_eq!(foreign.recycle_attempts().total(), 1);
assert_eq!(foreign.recycled_leases().total(), 0);
assert_eq!(foreign.recycle_refusals().total(), 1);
assert!(foreign.valid());
assert_eq!(first.statistics(), second.statistics());
Ok(())
}
#[cfg(feature = "performance-evidence")]
#[test]
fn evidence_windows_carry_live_leases_until_their_later_release() -> Result<(), &'static str> {
let mut pool = pool()?;
let BytePoolLeaseOutcome::Leased(lease) = pool.lease(nonzero(3)?) else {
return Err("lease");
};
let retained = lease.retain();
let first = pool.take_evidence();
assert_eq!(first.active_leases_at_start(), 0);
assert_eq!(first.materializations().total(), 1);
assert_eq!(first.active_leases().current(), 1);
assert_eq!(first.active_leases().high_water().maximum(), 1);
let current = pool.evidence();
assert_eq!(current.active_leases_at_start(), 1);
assert_eq!(current.materializations().total(), 0);
assert_eq!(current.active_leases().current(), 1);
assert_eq!(current.active_leases().high_water().maximum(), 1);
assert!(current.valid());
assert_eq!(pool.recycle(retained), BytePoolRecycleOutcome::Recycled);
let second = pool.take_evidence();
assert_eq!(second.active_leases_at_start(), 1);
assert_eq!(second.materializations().total(), 0);
assert_eq!(second.released_leases_collected().total(), 1);
assert_eq!(second.active_leases().current(), 0);
assert_eq!(second.active_leases().high_water().maximum(), 1);
assert!(second.valid());
assert_eq!(pool.evidence(), super::super::BytePoolEvidence::new());
Ok(())
}
proptest::proptest! {
#[test]
fn free_extents_are_the_canonical_union_of_released_ranges(
releases in proptest::collection::vec((0_usize..32, 1_usize..=32), 0..64)
) {
use proptest::{prop_assert, prop_assert_eq, test_runner::TestCaseError};
let mut extents = alloc::vec::Vec::new();
let mut expected = [false; 32];
for (start, length) in releases {
let end = start.saturating_add(length).min(32);
expected.get_mut(start..end).ok_or_else(|| TestCaseError::fail("model range"))?.fill(true);
BytePool::insert_free_extent(&mut extents, start..end);
prop_assert!(extents.windows(2).all(|pair| matches!(pair, [left, right] if left.end < right.start)));
let mut observed = [false; 32];
for extent in &extents {
prop_assert!(extent.start < extent.end);
let bytes = observed.get_mut(extent.clone()).ok_or_else(|| TestCaseError::fail("extent outside arena"))?;
for byte in bytes {
prop_assert!(!*byte);
*byte = true;
}
}
prop_assert_eq!(observed, expected);
}
}
}