use buffer_core::{
Buffer, BufferKind, BufferLease, BufferLeaseProvider, SharedBufferDescriptor, SimpleBufferPool,
};
use core_types::BufferId;
#[test]
fn buffer_from_vec_stores_data() {
let id = BufferId::new(1);
let buf = Buffer::from_vec(id, vec![10, 20, 30]);
assert_eq!(buf.id, id);
assert_eq!(buf.kind, BufferKind::Owned);
assert_eq!(buf.as_slice(), &[10, 20, 30]);
assert_eq!(buf.len(), 3);
}
#[test]
fn buffer_clone_shares_arc() {
let id = BufferId::new(2);
let buf = Buffer::from_vec(id, vec![1, 2, 3, 4]);
let clone = buf.clone();
assert_eq!(buf.as_slice(), clone.as_slice());
assert_eq!(buf.id, clone.id);
}
#[test]
fn full_lease_covers_entire_buffer() {
let buf = Buffer::from_vec(BufferId::new(10), vec![0u8, 1, 2, 3, 4]);
let lease = BufferLease::full(buf.clone());
assert_eq!(lease.len(), 5);
assert_eq!(lease.as_slice(), &[0, 1, 2, 3, 4]);
assert_eq!(lease.buffer_id(), BufferId::new(10));
}
#[test]
fn slice_returns_sub_lease() {
let buf = Buffer::from_vec(BufferId::new(11), b"hello world".to_vec());
let lease = BufferLease::full(buf);
let sub = lease.slice(0, 5).expect("slice must succeed");
assert_eq!(sub.as_slice(), b"hello");
assert_eq!(sub.len(), 5);
}
#[test]
fn slice_of_slice_is_relative() {
let buf = Buffer::from_vec(BufferId::new(12), b"abcdefgh".to_vec());
let lease = BufferLease::full(buf);
let mid = lease.slice(2, 6).expect("slice must succeed");
assert_eq!(mid.as_slice(), b"cdef");
let sub = mid.slice(1, 3).expect("sub-slice must succeed");
assert_eq!(sub.as_slice(), b"de");
}
#[test]
fn slice_out_of_bounds_returns_none() {
let buf = Buffer::from_vec(BufferId::new(13), vec![1, 2, 3]);
let lease = BufferLease::full(buf);
assert!(lease.slice(0, 10).is_none(), "end > len must fail");
assert!(lease.slice(5, 2).is_none(), "start > end must fail");
}
#[test]
fn slice_empty_range_is_allowed() {
let buf = Buffer::from_vec(BufferId::new(14), vec![1, 2, 3]);
let lease = BufferLease::full(buf);
let empty = lease.slice(1, 1).expect("empty slice must succeed");
assert_eq!(empty.len(), 0);
assert_eq!(empty.as_slice(), &[] as &[u8]);
}
#[test]
fn packet_view_borrows_slice_correctly() {
let buf = Buffer::from_vec(BufferId::new(20), b"viewme".to_vec());
let lease = BufferLease::full(buf);
let view = lease.view();
assert_eq!(view.bytes, b"viewme");
assert_eq!(view.buffer_id, BufferId::new(20));
}
#[test]
fn packet_view_of_sub_lease() {
let buf = Buffer::from_vec(BufferId::new(21), b"0123456789".to_vec());
let lease = BufferLease::full(buf);
let sub = lease.slice(3, 7).unwrap(); let view = sub.view();
assert_eq!(view.bytes, b"3456");
}
#[test]
fn shared_buffer_descriptor_round_trip() {
let desc = SharedBufferDescriptor {
buffer_id: BufferId::new(99),
len: 1024,
};
assert_eq!(desc.buffer_id, BufferId::new(99));
assert_eq!(desc.len, 1024);
let desc2 = desc;
assert_eq!(desc, desc2);
}
#[test]
fn shared_descriptor_from_allocate() {
let mut pool = SimpleBufferPool::default();
let data = vec![0xABu8; 512];
let lease = pool.allocate(data.clone());
let desc = SharedBufferDescriptor {
buffer_id: lease.buffer_id(),
len: lease.len(),
};
let retrieved = pool
.get(desc.buffer_id)
.expect("must find allocated buffer");
assert_eq!(retrieved.as_slice(), &data[..]);
}
#[test]
fn pool_allocate_gives_unique_ids() {
let mut pool = SimpleBufferPool::default();
let l1 = pool.allocate(vec![1]);
let l2 = pool.allocate(vec![2]);
assert_ne!(l1.buffer_id(), l2.buffer_id());
}
#[test]
fn pool_get_returns_correct_data() {
let mut pool = SimpleBufferPool::default();
let data = b"payload".to_vec();
let lease = pool.allocate(data.clone());
let id = lease.buffer_id();
let retrieved = pool.get(id).expect("buffer must exist");
assert_eq!(retrieved.as_slice(), &data[..]);
}
#[test]
fn pool_release_removes_buffer() {
let mut pool = SimpleBufferPool::default();
let lease = pool.allocate(vec![9, 8, 7]);
let id = lease.buffer_id();
assert!(pool.get(id).is_some());
pool.release(id);
assert!(pool.get(id).is_none(), "buffer must be gone after release");
}
#[test]
fn pool_get_after_release_returns_none() {
let mut pool = SimpleBufferPool::default();
let l = pool.allocate(vec![0]);
let id = l.buffer_id();
pool.release(id);
assert!(pool.get(id).is_none());
}
#[test]
fn buffer_clone_is_arc_shared_no_copy() {
let payload = vec![42u8; 65536]; let buf = Buffer::from_vec(BufferId::new(50), payload.clone());
let lease1 = BufferLease::full(buf);
let lease2 = lease1.clone();
assert_eq!(
lease1.as_slice().as_ptr(),
lease2.as_slice().as_ptr(),
"cloned lease must point to the same memory (zero-copy)"
);
}
#[test]
fn sub_slice_shares_backing_allocation() {
let payload = b"ABCDEFGHIJKLMNOP".to_vec();
let buf = Buffer::from_vec(BufferId::new(51), payload.clone());
let full = BufferLease::full(buf);
let sub = full.slice(4, 12).unwrap();
let expected_ptr = unsafe { full.as_slice().as_ptr().add(4) };
assert_eq!(sub.as_slice().as_ptr(), expected_ptr);
}
#[test]
fn pool_outstanding_leases_starts_at_zero() {
let pool = SimpleBufferPool::new();
assert_eq!(pool.outstanding_leases(), 0);
}
#[test]
fn pool_outstanding_leases_increments_on_allocate() {
let mut pool = SimpleBufferPool::new();
pool.allocate(vec![1]);
assert_eq!(pool.outstanding_leases(), 1);
pool.allocate(vec![2]);
assert_eq!(pool.outstanding_leases(), 2);
}
#[test]
fn pool_outstanding_leases_decrements_on_release() {
let mut pool = SimpleBufferPool::new();
let l1 = pool.allocate(vec![1]);
let l2 = pool.allocate(vec![2]);
assert_eq!(pool.outstanding_leases(), 2);
pool.release(l1.buffer_id());
assert_eq!(pool.outstanding_leases(), 1);
pool.release(l2.buffer_id());
assert_eq!(pool.outstanding_leases(), 0);
}
#[test]
fn pool_assert_no_leaks_passes_when_all_released() {
let mut pool = SimpleBufferPool::new();
let l = pool.allocate(vec![0xDE, 0xAD, 0xBE, 0xEF]);
pool.release(l.buffer_id());
pool.assert_no_leaks(); }
#[test]
#[should_panic(expected = "buffer leak detected")]
fn pool_assert_no_leaks_panics_on_unreleased_buffer() {
let mut pool = SimpleBufferPool::new();
let _l = pool.allocate(vec![1, 2, 3]);
pool.assert_no_leaks(); }
#[test]
fn pool_release_unknown_id_does_not_underflow() {
let mut pool = SimpleBufferPool::new();
pool.release(BufferId::new(9999));
assert_eq!(pool.outstanding_leases(), 0);
}
#[test]
fn pool_get_does_not_affect_lease_count() {
let mut pool = SimpleBufferPool::new();
let l = pool.allocate(vec![42]);
let id = l.buffer_id();
assert_eq!(pool.outstanding_leases(), 1);
let _ = pool.get(id);
let _ = pool.get(id);
assert_eq!(pool.outstanding_leases(), 1);
pool.release(id);
assert_eq!(pool.outstanding_leases(), 0);
}
#[test]
fn full_allocate_use_release_cycle() {
let mut pool = SimpleBufferPool::new();
let payloads: Vec<Vec<u8>> = (0..5).map(|i| vec![i; 16]).collect();
let leases: Vec<_> = payloads.iter().map(|p| pool.allocate(p.clone())).collect();
assert_eq!(pool.outstanding_leases(), 5);
for (i, lease) in leases.iter().enumerate() {
assert_eq!(lease.as_slice(), &payloads[i][..]);
}
for lease in &leases {
pool.release(lease.buffer_id());
}
pool.assert_no_leaks(); }