#![cfg(test)]
use super::test_util::balanced_sample;
use super::*;
#[test]
fn track_imbalance_and_dsq_reports_worst_cpu_not_first() {
let t = MonitorThresholds {
max_imbalance_ratio: 100.0, max_local_dsq_depth: 1,
..Default::default()
};
let samples = vec![MonitorSample {
prog_stats: None,
elapsed_ms: 100,
cpus: vec![
CpuSnapshot {
nr_running: 1,
local_dsq_depth: 3,
rq_clock: 1000,
..Default::default()
},
CpuSnapshot {
nr_running: 1,
local_dsq_depth: 5,
rq_clock: 2000,
..Default::default()
},
],
}];
let (imbalance, dsq, worst_cpu) = t.track_imbalance_and_dsq(&samples);
assert_eq!(imbalance.worst_run, 0, "imbalance must not be flagged");
assert!(
(dsq.worst_value - 5.0).abs() < f64::EPSILON,
"dsq worst_value must be 5, got {}",
dsq.worst_value
);
assert_eq!(worst_cpu, 1, "worst_dsq_cpu must be 1 (deepest violator)");
}
#[test]
fn track_imbalance_and_dsq_empty_cpus_records_non_violation() {
let t = MonitorThresholds::default();
let samples = vec![
MonitorSample {
prog_stats: None,
elapsed_ms: 100,
cpus: vec![],
},
MonitorSample {
prog_stats: None,
elapsed_ms: 200,
cpus: vec![],
},
];
let (imbalance, dsq, _) = t.track_imbalance_and_dsq(&samples);
assert_eq!(imbalance.consecutive, 0);
assert_eq!(dsq.consecutive, 0);
assert_eq!(imbalance.worst_run, 0);
assert_eq!(dsq.worst_run, 0);
}
#[test]
fn track_stall_sizes_vec_to_max_cpu_count_across_samples() {
let t = MonitorThresholds {
fail_on_stall: true,
..Default::default()
};
let s1 = MonitorSample {
prog_stats: None,
elapsed_ms: 100,
cpus: vec![CpuSnapshot {
nr_running: 1,
rq_clock: 1000,
..Default::default()
}],
};
let s2 = MonitorSample {
prog_stats: None,
elapsed_ms: 200,
cpus: vec![
CpuSnapshot {
nr_running: 1,
rq_clock: 1500,
..Default::default()
},
CpuSnapshot {
nr_running: 1,
rq_clock: 2500,
..Default::default()
},
CpuSnapshot {
nr_running: 1,
rq_clock: 3000,
..Default::default()
},
],
};
let report = MonitorReport {
samples: vec![s1, s2],
summary: MonitorSummary::default(),
..Default::default()
};
let stall = t.track_stall(&report);
assert_eq!(
stall.len(),
3,
"must size vec to max cpu count across samples"
);
}
#[test]
fn track_stall_respects_vcpu_preemption_threshold() {
let t = MonitorThresholds {
fail_on_stall: true,
..Default::default()
};
let s1 = MonitorSample {
prog_stats: None,
elapsed_ms: 100,
cpus: vec![CpuSnapshot {
nr_running: 1,
rq_clock: 5000,
vcpu_cpu_time_ns: Some(1_000_000_000),
..Default::default()
}],
};
let s2 = MonitorSample {
prog_stats: None,
elapsed_ms: 200,
cpus: vec![CpuSnapshot {
nr_running: 1,
rq_clock: 5000, vcpu_cpu_time_ns: Some(1_000_500_000), ..Default::default()
}],
};
let report = MonitorReport {
samples: vec![s1, s2],
summary: MonitorSummary::default(),
preemption_threshold_ns: 10_000_000, watchdog_observation: None,
page_offset: 0,
boot_wait_outcome: BootWaitOutcome::NotConfigured,
};
let stall = t.track_stall(&report);
assert_eq!(stall.len(), 1);
assert_eq!(
stall[0].worst_run, 0,
"preempted vCPU must not register as a stall"
);
}
#[test]
fn track_event_rates_missing_counters_records_non_violation() {
let t = MonitorThresholds {
max_fallback_rate: 0.0,
max_keep_last_rate: 0.0,
..Default::default()
};
let samples = vec![balanced_sample(0, 1000), balanced_sample(100, 1500)];
let (fallback_rate, keep_last_rate) = t.track_event_rates(&samples);
assert_eq!(fallback_rate.consecutive, 0);
assert_eq!(keep_last_rate.consecutive, 0);
assert_eq!(fallback_rate.worst_run, 0);
assert_eq!(keep_last_rate.worst_run, 0);
}
#[test]
fn track_event_rates_zero_interval_does_not_panic() {
let t = MonitorThresholds::default();
let make = |fb| MonitorSample {
prog_stats: None,
elapsed_ms: 100,
cpus: vec![CpuSnapshot {
nr_running: 1,
rq_clock: 1000,
event_counters: Some(ScxEventCounters {
select_cpu_fallback: fb,
..Default::default()
}),
..Default::default()
}],
};
let samples = vec![make(0), make(1000)];
let (fb, kl) = t.track_event_rates(&samples);
assert_eq!(fb.worst_run, 0);
assert_eq!(kl.worst_run, 0);
}
#[test]
fn summarize_three_arms() {
assert_eq!(MonitorThresholds::summarize(false, true, 0), "monitor OK");
assert_eq!(MonitorThresholds::summarize(false, false, 0), "monitor OK");
assert_eq!(
MonitorThresholds::summarize(true, true, 3),
"monitor FAILED: 3 violation(s)"
);
let report_only = MonitorThresholds::summarize(true, false, 2);
assert!(
report_only.contains("flagged 2"),
"report-only must say flagged: {report_only}"
);
assert!(
report_only.contains("report-only"),
"report-only must carry advisory: {report_only}"
);
}