#![cfg(feature = "symbolicate")]
use std::thread;
use std::time::{Duration, Instant};
use mod_alloc::ModAlloc;
#[global_allocator]
static GLOBAL: ModAlloc = ModAlloc::new();
#[inline(never)]
fn workload() {
for _ in 0..200 {
let _v: Vec<u8> = Vec::with_capacity(128);
}
}
#[test]
fn concurrent_reports_terminate() {
workload();
let primer = GLOBAL.symbolicated_report();
assert!(!primer.is_empty(), "primer report should observe workload");
let started = Instant::now();
let handles: Vec<_> = (0..8)
.map(|_| {
thread::spawn(|| {
let report = GLOBAL.symbolicated_report();
assert!(!report.is_empty());
report.len()
})
})
.collect();
let mut sizes = Vec::new();
for h in handles {
sizes.push(h.join().expect("symbolicator panicked under contention"));
}
assert!(
started.elapsed() < Duration::from_secs(30),
"symbolicator deadlocked or stalled under concurrent access"
);
let primer_size = primer.len();
let max_size = *sizes.iter().max().unwrap();
for &n in &sizes {
assert!(
n >= primer_size,
"concurrent report ({n}) below primer ({primer_size}); table shrank?"
);
assert!(
n <= max_size,
"concurrent report ({n}) above max ({max_size}); impossible"
);
}
}