use super::*;
#[test]
fn idle_tracker_reports_no_work() {
let t = WorkerLiveness::new();
assert_eq!(t.in_flight(), 0);
assert_eq!(t.oldest_age(), None);
assert!(!t.is_wedged(Duration::from_millis(0)));
}
#[test]
fn in_flight_counts_active_operations() {
let t = WorkerLiveness::new();
let a = t.track();
assert_eq!(t.in_flight(), 1);
let b = t.track();
assert_eq!(t.in_flight(), 2);
drop(a);
assert_eq!(t.in_flight(), 1);
drop(b);
assert_eq!(t.in_flight(), 0);
}
#[test]
fn guard_releases_slot_on_drop() {
let t = WorkerLiveness::new();
{
let _g = t.track();
assert_eq!(t.in_flight(), 1);
}
assert_eq!(t.in_flight(), 0);
assert_eq!(t.oldest_age(), None);
}
#[test]
fn guard_releases_slot_on_panic() {
let t = WorkerLiveness::new();
let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
let _g = t.track();
assert_eq!(t.in_flight(), 1);
panic!("simulated failure inside a tracked operation");
}));
assert!(res.is_err(), "the panic must propagate");
assert_eq!(
t.in_flight(),
0,
"slot must be released when the operation unwinds"
);
}
#[test]
fn oldest_age_tracks_the_earliest_operation() {
let t = WorkerLiveness::new();
let _old = t.track();
std::thread::sleep(Duration::from_millis(30));
let _new = t.track();
let age = t.oldest_age().expect("two operations are in flight");
assert!(
age >= Duration::from_millis(30),
"oldest_age must report the EARLIEST operation, got {age:?}"
);
}
#[test]
fn oldest_age_recovers_when_the_slow_operation_finishes() {
let t = WorkerLiveness::new();
let old = t.track();
std::thread::sleep(Duration::from_millis(30));
drop(old);
let _fresh = t.track();
let age = t.oldest_age().expect("one operation is in flight");
assert!(
age < Duration::from_millis(30),
"age must drop back once the slow operation completes, got {age:?}"
);
}
#[test]
fn wedged_when_oldest_exceeds_threshold() {
let t = WorkerLiveness::new();
let _g = t.track();
std::thread::sleep(Duration::from_millis(30));
assert!(
t.is_wedged(Duration::from_millis(10)),
"an operation older than the threshold must read as wedged"
);
assert!(
!t.is_wedged(Duration::from_secs(60)),
"the same operation must NOT read as wedged under a generous threshold"
);
}
#[test]
fn wedge_threshold_exceeds_the_open_queue_bound() {
if std::env::var("TRUSTY_WEDGE_THRESHOLD_SECS").is_ok() {
return; }
let bound = trusty_common::memory_core::timeouts::open_queue_timeout();
assert!(
wedge_threshold() > bound,
"wedge threshold {:?} must exceed the open-queue bound {bound:?}, or normal \
contention would read as a wedge",
wedge_threshold()
);
}
#[test]
fn overflow_is_counted_when_slots_exhausted() {
let t = WorkerLiveness::new();
let guards: Vec<_> = (0..SLOTS + 2).map(|_| t.track()).collect();
assert_eq!(t.in_flight(), SLOTS + 2);
assert!(t.oldest_age().is_some());
drop(guards);
assert_eq!(t.in_flight(), 0, "overflow must unwind cleanly");
assert_eq!(t.oldest_age(), None);
}