pub mod common;
#[global_allocator]
static ALLOCATOR: Tracker = Tracker;
use std::{
cell::Cell,
collections::hash_map::DefaultHasher,
hash::{Hash as _, Hasher as _},
hint,
mem::size_of,
num::NonZero,
pin::Pin,
};
use common::{
alloc::system::Tracker,
buffer::{Reject, provided::Item},
};
use o3::{
alloc,
buffer::{
bytes::Prefix,
storage::{
inline::{Bytes, CAPACITY, Fill},
provided,
},
write::Sink as _,
},
};
#[test]
fn fills_at_capacity() {
let mut bytes = [b'x'; CAPACITY];
bytes[0] = b'a';
let mut inline = Bytes::<CAPACITY>::new();
let (fill, first) =
Fill::new(&mut inline).write::<{ CAPACITY - 1 }, 1>(Prefix::new(&bytes[..1]));
fill.finish(b"x".into());
assert_eq!(first, b"a");
inline.write_slice(&bytes[2..]).expect("remaining capacity");
assert_eq!(inline.as_ref(), bytes);
assert_eq!(size_of::<Bytes>(), CAPACITY + 1);
assert!(Bytes::<CAPACITY>::from_slice(&[0; CAPACITY + 1]).is_err());
let error = inline.write_byte(0).expect_err("full inline buffer");
let (required, available) = error.into_parts();
assert_eq!((required.get(), available), (1, 0));
}
#[test]
fn converts_bounded_prefix() {
let prefix =
(Prefix::<3>::try_new(b"abc")).expect("the exact-capacity prefix must be accepted");
let inline = Bytes::<3>::from(prefix);
assert_eq!(inline.as_ref(), b"abc");
let error = Prefix::<2>::try_new(b"abc").expect_err("oversized prefix");
assert_eq!(
{
let (required, available) = error.into_parts();
(required.get(), available)
},
(3, 2)
);
let bytes = *b"0123456789abcdef\r\n";
for skip in 0..=bytes.len() {
let mut source = bytes.into_iter();
if skip != 0 {
assert!(source.nth(skip - 1).is_some());
}
let (value, activity) = Tracker::measure(|| Bytes::<18, u16>::from(Prefix::from(&source)));
assert_eq!(activity, [0; 4]);
assert_eq!(value.as_ref(), &bytes[skip..]);
}
}
#[test]
fn uses_typed_capacity() {
let mut inline = (Bytes::<4>::from_slice(b"ab"))
.expect("the two-byte input must fit the typed four-byte capacity");
inline
.write_slice(b"cd")
.as_ref()
.expect("required fixture outcome");
assert_eq!(inline.as_ref(), b"abcd");
assert_eq!(size_of::<Bytes<4>>(), 5);
let error = inline.write_slice(b"e").expect_err("full inline buffer");
assert_eq!(
{
let (required, available) = error.into_parts();
(required.get(), available)
},
(1, 0)
);
}
#[test]
fn compares_active_prefix() {
let mut first =
(Bytes::<8>::from_slice(b"abc")).expect("the first active-prefix input must fit");
let mut second =
(Bytes::<8>::from_slice(b"axy")).expect("the second active-prefix input must fit");
first.truncate(1);
second.truncate(1);
let copied = first;
assert_eq!(copied.as_ref(), b"a");
assert!(first == second);
let mut h1 = DefaultHasher::new();
first.hash(&mut h1);
let mut h2 = DefaultHasher::new();
second.hash(&mut h2);
assert_eq!(h1.finish(), h2.finish());
assert_ne!(&*first.backing_mut(), &*second.backing_mut());
}
#[test]
fn publishes_exact_region() {
let mut bytes = Bytes::<8>::new();
let append = (bytes.try_reserve(2)).expect("the initial two-byte region must fit");
append.write(|output| output.copy_from_slice(b"ab"));
assert_eq!(bytes.as_ref(), b"ab");
let append = (bytes.try_reserve(2)).expect("the rejected two-byte region must fit");
let reject = append.try_write(|output| {
output.copy_from_slice(b"xx");
Err::<(), _>(Reject::Requested)
});
assert!(reject == Err(Reject::Requested));
assert_eq!(bytes.as_ref(), b"ab");
{
let mut append = bytes.try_reserve(2).expect("the abandoned region must fit");
append.as_mut().copy_from_slice(b"zz");
}
assert_eq!(bytes.as_ref(), b"ab");
let mut append = bytes.fit(hint::black_box(usize::MAX));
append.as_mut().copy_from_slice(b"cdefgh");
append.commit();
assert_eq!(bytes.as_ref(), b"abcdefgh");
}
#[test]
fn zeroes_full_backing() {
let mut bytes = (Bytes::<6>::from_slice(b"secret"))
.expect("the six-byte secret must fill the inline backing exactly");
bytes.truncate(2);
{
(bytes.write_slice(&[0; 3]))
.as_ref()
.expect("required fixture outcome");
};
assert_eq!(bytes.as_ref(), b"se\0\0\0");
assert_eq!(bytes.available(), 1);
bytes.backing_mut().fill(0);
assert_eq!(&*bytes.backing_mut(), &[0; 6]);
assert_eq!(bytes.len(), 5);
bytes.clear();
assert!(bytes.is_empty());
}
#[test]
fn keeps_u16_layout() {
let mut inline = Bytes::<514, u16>::new();
{
(inline.write_slice(&[b'x'; 513]))
.as_ref()
.expect("required fixture outcome");
};
inline
.write_byte(b'y')
.as_ref()
.expect("required fixture outcome");
assert_eq!(inline.len(), 514);
assert!(!inline.is_empty());
assert_eq!(inline.as_ref()[513], b'y');
assert_eq!(size_of::<Bytes<514, u16>>(), 516);
assert!(inline.write_byte(0).is_err());
}
#[test]
fn context_failure_frees() {
let (result, stats) = Tracker::activity(|| {
let initialize = provided::Arena::<u8, ()>::try_allocate(NonZero::<u32>::MIN)?;
Ok::<_, alloc::Error>(initialize(hint::black_box(Err::<(), _>(
alloc::Error::Overflow,
))?))
});
assert!(matches!(result, Err(alloc::Error::Overflow)));
assert_eq!(stats.allocations, 1);
assert_eq!(stats.deallocations, 1);
assert_eq!(stats.allocated_bytes, stats.deallocated_bytes);
}
#[test]
fn reuses_rejected_slot() {
let drops = Cell::new(Some(0));
let mut arena = provided::Arena::<Item, _>::try_allocate(NonZero::<u32>::MIN)
.expect("the single slot must allocate")(7_u8);
let buffer = Item::try_new(b"body", &drops).expect("fixture buffer must allocate");
let pointer = buffer.bytes.as_ptr();
let measured = Tracker::begin();
arena.scope(Pin::new(&mut ()), |_, arena, _| {
assert_eq!(*arena.context(), 7);
assert_eq!(arena.capacity(), NonZero::<u32>::MIN);
assert!(arena.vacant().is_some(), "the initial slot must be vacant");
let vacant = arena
.vacant()
.expect("an unused vacancy must return its slot");
let (rejected, stats) = Tracker::activity(|| vacant.try_insert(buffer, 2, Item::bytes_mut));
assert_eq!(stats.allocations, 0);
assert_eq!(stats.deallocations, 0);
let rejected = rejected.expect_err("four bytes exceed the two-byte ceiling");
let (buffer, error) = rejected.into_parts();
assert_eq!(error.projected(), 4);
assert_eq!(error.resident(), 2);
assert_eq!(buffer.bytes.as_ptr(), pointer);
assert_eq!(drops.get(), Some(0));
{
let vacant = arena
.vacant()
.expect("rejection must return its exact slot");
let (owner, stats) =
Tracker::activity(|| vacant.try_insert(buffer, 4, Item::bytes_mut));
assert_eq!(stats.allocations, 0);
assert_eq!(stats.deallocations, 0);
let owner = owner.expect("buffer transition accepted");
assert_eq!(owner.as_slice(), b"body");
assert_eq!(owner.as_slice().as_ptr(), pointer);
}
assert!(arena.has_returned());
{
let returned = arena.pop_returned();
assert!(matches!(&returned, Some(item) if item.bytes.as_ptr() == pointer));
}
assert_eq!(drops.get(), Some(1));
assert!(
arena.vacant().is_some(),
"removal recycles the complete slot"
);
});
assert_eq!(measured.finish().allocations, 0);
}