#![cfg(feature = "alloc-global")]
use std::alloc::GlobalAlloc;
use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
use sefer_alloc::SeferMalloc;
#[global_allocator]
static GLOBAL: SeferMalloc = SeferMalloc::new();
static SERIAL: AtomicBool = AtomicBool::new(false);
struct SerialGuard;
impl SerialGuard {
fn acquire() -> Self {
while SERIAL
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{
std::hint::spin_loop();
}
SerialGuard
}
}
impl Drop for SerialGuard {
fn drop(&mut self) {
SERIAL.store(false, Ordering::Release);
}
}
#[test]
fn global_allocator_serves_single_thread_churn() {
let _serial = SerialGuard::acquire();
let mut v: Vec<u64> = Vec::new();
for i in 0..50_000u64 {
v.push(i);
}
let sum: u64 = v.iter().copied().sum();
assert_eq!(sum, (0..50_000u64).sum(), "Vec sum mismatch — corruption");
let strings: Vec<String> = (0..1_000u32).map(|i| format!("item-{i}")).collect();
assert_eq!(strings.len(), 1_000);
assert_eq!(strings[123], "item-123", "String content lost");
let boxes: Vec<Box<u64>> = (0..2_048u64).map(|i| Box::new(i * 7)).collect();
let box_sum: u64 = boxes.iter().map(|b| **b).sum();
let expected_box_sum: u64 = (0..2_048u64).map(|i| i * 7).sum();
assert_eq!(box_sum, expected_box_sum, "Box contents corrupted");
let mut m: HashMap<u64, String> = HashMap::new();
for i in 0..5_000u64 {
m.insert(i, format!("value-{i}"));
}
assert_eq!(m.len(), 5_000, "HashMap lost entries");
assert_eq!(
m.get(&4_321).map(String::as_str),
Some("value-4321"),
"HashMap lookup failed — corruption",
);
let mut w: Vec<[u8; 32]> = Vec::with_capacity(8);
for i in 0..1_024u32 {
let mut block = [0u8; 32];
block[..4].copy_from_slice(&i.to_le_bytes());
w.push(block);
}
for (i, block) in w.iter().enumerate() {
let stored = u32::from_le_bytes(block[..4].try_into().unwrap());
assert_eq!(stored, i as u32, "Vec block {i} corrupted after grow");
}
}
#[test]
fn global_allocator_repeated_churn_reuses_state() {
let _serial = SerialGuard::acquire();
for size in [16usize, 64, 128, 256, 1024] {
let layout = std::alloc::Layout::from_size_align(size, 8).unwrap();
for _ in 0..1_000 {
let p = unsafe { GLOBAL.alloc(layout) };
assert!(!p.is_null(), "alloc({size}) returned null on iteration");
unsafe {
std::ptr::write_bytes(p, 0xAB, size);
assert_eq!((p as *const u8).read(), 0xAB, "byte not retained");
GLOBAL.dealloc(p, layout);
}
}
}
}