use keyhog_profile::{
record_queue_depth_dequeue, record_queue_depth_enqueue, set_queue_depth, QueueId, RunIdentity,
RunState, Session,
};
fn session(name: &str) -> Session {
Session::start(RunIdentity::new(
"0.5.49",
"detectors",
"config",
name,
"test",
"cpu-simd",
))
.expect("start profile")
}
#[test]
fn depth_transitions_produce_exact_occupancy_records() {
let session = session("depth-transitions");
let runtime = session.runtime();
for _ in 0..5 {
record_queue_depth_enqueue(QueueId::ScannerWork);
}
for _ in 0..2 {
record_queue_depth_dequeue(QueueId::ScannerWork);
}
set_queue_depth(QueueId::ScannerWork, 7);
set_queue_depth(QueueId::ScannerWork, 1);
let depths = runtime.take_session_queue_depths();
assert_eq!(depths.len(), 1);
let record = &depths[0];
assert_eq!(record.version, 1);
assert_eq!(record.queue, QueueId::ScannerWork);
assert_eq!(record.current, 1);
assert_eq!(record.high_water, 7);
assert_eq!(record.enqueues, 5);
assert_eq!(record.dequeues, 2);
let _ = session.finish(RunState::Completed);
}
#[test]
fn only_active_queues_appear_in_stable_slot_order() {
let session = session("active-queues");
let runtime = session.runtime();
record_queue_depth_enqueue(QueueId::ResultMerge);
record_queue_depth_enqueue(QueueId::SourceWork);
record_queue_depth_enqueue(QueueId::SourceWork);
let depths = runtime.take_session_queue_depths();
assert_eq!(depths.len(), 2);
assert_eq!(depths[0].queue, QueueId::SourceWork);
assert_eq!(depths[0].current, 2);
assert_eq!(depths[0].high_water, 2);
assert_eq!(depths[1].queue, QueueId::ResultMerge);
assert_eq!(depths[1].current, 1);
let _ = session.finish(RunState::Completed);
}
#[test]
fn high_water_survives_decreases_and_resets_to_current_after_drain() {
let session = session("high-water-reset");
let runtime = session.runtime();
set_queue_depth(QueueId::BackendBatch, 9);
set_queue_depth(QueueId::BackendBatch, 3);
let first = runtime.take_session_queue_depths();
assert_eq!(first.len(), 1);
assert_eq!(first[0].current, 3);
assert_eq!(first[0].high_water, 9);
set_queue_depth(QueueId::BackendBatch, 5);
let second = runtime.take_session_queue_depths();
assert_eq!(second.len(), 1);
assert_eq!(second[0].current, 5);
assert_eq!(second[0].high_water, 5);
assert_eq!(second[0].enqueues, 0);
assert_eq!(second[0].dequeues, 0);
let _ = session.finish(RunState::Completed);
}
#[test]
fn dequeue_from_empty_queue_saturates_and_counts() {
let session = session("saturating-dequeue");
let runtime = session.runtime();
record_queue_depth_dequeue(QueueId::DecoderWork);
record_queue_depth_dequeue(QueueId::DecoderWork);
let depths = runtime.take_session_queue_depths();
assert_eq!(depths.len(), 1);
assert_eq!(depths[0].current, 0);
assert_eq!(depths[0].high_water, 0);
assert_eq!(depths[0].enqueues, 0);
assert_eq!(depths[0].dequeues, 2);
let _ = session.finish(RunState::Completed);
}
#[test]
fn emptied_queue_reports_final_zero_then_disappears() {
let session = session("emptied-queue");
let runtime = session.runtime();
record_queue_depth_enqueue(QueueId::LiveVerification);
record_queue_depth_dequeue(QueueId::LiveVerification);
let first = runtime.take_session_queue_depths();
assert_eq!(first.len(), 1);
assert_eq!(first[0].current, 0);
assert_eq!(first[0].high_water, 1);
assert_eq!(first[0].enqueues, 1);
assert_eq!(first[0].dequeues, 1);
let second = runtime.take_session_queue_depths();
assert!(second.is_empty());
let _ = session.finish(RunState::Completed);
}