use std::sync::{Arc, Barrier};
use super::limits::Limit;
type TestResult = Result<(), Box<dyn std::error::Error>>;
#[test]
fn admission_refuses_over_capacity_and_releases_only_its_owned_permit() -> TestResult {
let limit = Arc::new(Limit::new(1));
let held = limit.enter().ok_or("first permit missing")?;
assert!(limit.enter().is_none());
drop(held);
let next = limit.enter().ok_or("released permit missing")?;
assert!(limit.enter().is_none());
drop(next);
Ok(())
}
#[test]
fn concurrent_admission_never_exceeds_the_configured_bound() -> TestResult {
let limit = Arc::new(Limit::new(1));
let start = Arc::new(Barrier::new(3));
let finish = Arc::new(Barrier::new(3));
let mut tasks = Vec::new();
for _ in 0..2 {
let limit = Arc::clone(&limit);
let start = Arc::clone(&start);
let finish = Arc::clone(&finish);
tasks.push(std::thread::spawn(move || {
start.wait();
let permit = limit.enter();
let admitted = permit.is_some();
finish.wait();
drop(permit);
admitted
}));
}
start.wait();
finish.wait();
let mut admitted = 0;
for task in tasks {
admitted += usize::from(task.join().map_err(|_| "admission task panicked")?);
}
assert_eq!(admitted, 1);
assert!(limit.enter().is_some());
Ok(())
}