use super::*;
#[test]
fn with_capacity_starts_empty() {
let f = FlatBuf::with_capacity(1024);
assert_eq!(f.len(), 0);
assert_eq!(f.tail(), 0);
assert!(f.cap() >= 1024 + WILDCOPY_OVERLENGTH);
}
#[test]
fn extend_appends_then_len_matches() {
let mut f = FlatBuf::with_capacity(64);
f.extend(&[1, 2, 3, 4]);
assert_eq!(f.len(), 4);
f.extend(&[5, 6]);
assert_eq!(f.len(), 6);
let (s1, s2) = f.as_slices();
assert_eq!(s1, &[1, 2, 3, 4, 5, 6]);
assert!(s2.is_empty(), "flat layout never wraps");
}
#[test]
fn extend_and_fill_appends_repeated_byte() {
let mut f = FlatBuf::with_capacity(64);
f.extend(&[0xAA]);
f.extend_and_fill(0xBB, 5);
let (s1, _) = f.as_slices();
assert_eq!(s1, &[0xAA, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB]);
}
#[test]
fn extend_from_within_unchecked_copies_non_overlapping() {
let mut f = FlatBuf::with_capacity(64);
f.extend(&[10, 20, 30, 40, 50]);
unsafe { f.extend_from_within_unchecked(0, 3) };
let (s1, _) = f.as_slices();
assert_eq!(s1, &[10, 20, 30, 40, 50, 10, 20, 30]);
}
#[test]
fn drop_first_n_advances_head() {
let mut f = FlatBuf::with_capacity(64);
f.extend(&[1, 2, 3, 4, 5]);
f.drop_first_n(2);
assert_eq!(f.len(), 3);
let (s1, _) = f.as_slices();
assert_eq!(s1, &[3, 4, 5]);
unsafe { f.extend_from_within_unchecked(0, 3) };
let (s1, _) = f.as_slices();
assert_eq!(s1, &[3, 4, 5, 3, 4, 5]);
}
#[test]
fn set_tail_rolls_back() {
let mut f = FlatBuf::with_capacity(64);
f.extend(&[1, 2, 3]);
let saved_tail = f.tail();
let saved_cap = f.cap();
f.extend(&[4, 5, 6, 7]);
assert_eq!(f.len(), 7);
assert_eq!(f.cap(), saved_cap, "with_capacity sized to avoid realloc");
unsafe { f.set_tail(saved_tail) };
assert_eq!(f.len(), 3);
let (s1, _) = f.as_slices();
assert_eq!(s1, &[1, 2, 3]);
}
#[test]
fn clear_resets() {
let mut f = FlatBuf::with_capacity(64);
f.extend(&[1, 2, 3]);
f.drop_first_n(1);
assert_eq!(f.len(), 2);
f.clear();
assert_eq!(f.len(), 0);
assert_eq!(f.tail(), 0);
}
#[test]
fn exec_sequence_inline_match_copy_correctness() {
for offset in [4usize, 8, 12, 20, 48, 96] {
let mut f = FlatBuf::with_capacity(512);
let seed: Vec<u8> = (0..256u32).map(|i| ((i * 31 + 7) & 0xFF) as u8).collect();
f.extend(&seed);
let base = f.len();
let match_length = 96usize;
let mut reference = alloc::vec![0u8; base + match_length];
reference[..base].copy_from_slice(&seed);
for i in 0..match_length {
reference[base + i] = reference[base + i - offset];
}
let lits = [0xAAu8; 16];
unsafe {
f.exec_sequence_inline(lits.as_ptr(), 0, offset, match_length)
.unwrap();
}
assert_eq!(f.len(), base + match_length, "offset={offset}");
let (s1, _) = f.as_slices();
for i in 0..match_length {
assert_eq!(
s1[base + i],
reference[base + i],
"offset={offset} byte {i}: got {:#x}, expected {:#x}",
s1[base + i],
reference[base + i],
);
}
}
}
#[cfg(all(target_arch = "x86_64", feature = "std"))]
#[test]
fn exec_sequence_inline_avx2_offset_boundary_correctness() {
if !std::arch::is_x86_feature_detected!("avx2") {
return;
}
for offset in [20usize, 32, 64] {
let mut f = FlatBuf::with_capacity(512);
let seed: Vec<u8> = (0..256u32).map(|i| ((i * 31 + 7) & 0xFF) as u8).collect();
f.extend(&seed);
let base = f.len();
let match_length = 96usize;
let mut reference = alloc::vec![0u8; base + match_length];
reference[..base].copy_from_slice(&seed);
for i in 0..match_length {
reference[base + i] = reference[base + i - offset];
}
let lits = [0xAAu8; 16];
unsafe {
f.exec_sequence_inline_avx2(lits.as_ptr(), 0, offset, match_length)
.unwrap();
}
assert_eq!(f.len(), base + match_length, "offset={offset}");
let (s1, _) = f.as_slices();
for i in 0..match_length {
assert_eq!(
s1[base + i],
reference[base + i],
"offset={offset} byte {i}: got {:#x}, expected {:#x} \
(regression: AVX2 wildcopy at offset < 32)",
s1[base + i],
reference[base + i],
);
}
}
}
#[cfg(target_arch = "x86_64")]
#[test]
fn exec_sequence_inline_capacity_overflow_returns_err() {
let mut f = FlatBuf::with_capacity(32);
f.extend(&[0u8; 16]);
let lits = [0xAAu8; 32];
let result = unsafe { f.exec_sequence_inline(lits.as_ptr(), 17, 8, 100) };
assert!(
matches!(
result,
Err(super::super::errors::ExecuteSequencesError::OutputBufferOverflow { .. })
),
"expected OutputBufferOverflow, got {result:?}"
);
}
#[cfg(all(target_arch = "x86_64", feature = "std"))]
#[test]
fn exec_sequence_inline_avx2_capacity_overflow_returns_err() {
if !std::arch::is_x86_feature_detected!("avx2") {
return;
}
let mut f = FlatBuf::with_capacity(32);
f.extend(&[0u8; 16]);
let lits = [0xAAu8; 32];
let result = unsafe { f.exec_sequence_inline_avx2(lits.as_ptr(), 17, 8, 100) };
assert!(
matches!(
result,
Err(super::super::errors::ExecuteSequencesError::OutputBufferOverflow { .. })
),
"expected OutputBufferOverflow, got {result:?}"
);
}
#[test]
fn try_reserve_rejects_growth_past_block_ceiling() {
let mut f = FlatBuf::with_capacity(64);
f.extend(&[0u8; 32]);
let ceiling = f.len() + 100; f.set_max_capacity(ceiling);
assert!(f.try_reserve(50).is_ok());
assert!(
matches!(
f.try_reserve(200),
Err(super::super::buffer_backend::BackendOverflow { .. })
),
"reserve past the per-block ceiling must be rejected, not grown"
);
}
#[test]
fn try_reserve_rejects_within_capacity_but_past_ceiling() {
let mut f = FlatBuf::with_capacity(4096);
f.extend(&[0u8; 32]);
let ceiling = f.len() + 100; f.set_max_capacity(ceiling);
assert!(
matches!(
f.try_reserve(500),
Err(super::super::buffer_backend::BackendOverflow { .. })
),
"a reserve past the ceiling must be rejected even when it fits the \
current capacity without growth"
);
}