#![allow(clippy::unwrap_used, clippy::expect_used, clippy::too_many_arguments)]
use super::*;
fn score(
burst_events: usize,
events: usize,
fail_ratio: f64,
wk: usize,
chain: usize,
excess: Option<f64>,
pipe: f64,
) -> u8 {
score_filter(&ScoreInput {
total_burst_events: burst_events,
event_count: events,
failed_burst_ratio: fail_ratio,
workaround_count: wk,
max_empty_chain: chain,
avg_excess_tokens: excess,
pipe_override_rate: pipe,
})
}
#[test]
fn score_perfect_filter_is_100() {
assert_eq!(score(0, 100, 0.0, 0, 0, None, 0.0), 100);
assert_eq!(score(0, 100, 0.0, 0, 0, Some(-50.0), 0.0), 100);
}
#[test]
fn score_drops_with_burst_rate() {
let baseline = score(0, 100, 0.0, 0, 0, None, 0.0);
let with_bursts = score(50, 100, 0.0, 0, 0, None, 0.0);
assert!(with_bursts < baseline);
}
#[test]
fn score_high_volume_low_burst_rate_is_healthy() {
let s = score(16, 13682, 0.0, 0, 0, None, 0.0);
assert!(
s >= 95,
"high-volume low-burst-rate should score well, got {s}"
);
}
#[test]
fn score_low_volume_high_burst_rate_is_bad() {
let s = score(15, 20, 0.0, 0, 0, None, 0.0);
assert!(
s <= 75,
"low-volume high-burst-rate should score poorly, got {s}"
);
}
#[test]
fn score_failed_bursts_penalized_harder() {
let no_fail = score(10, 100, 0.0, 0, 0, None, 0.0);
let all_fail = score(10, 100, 1.0, 0, 0, None, 0.0);
assert!(
all_fail < no_fail,
"all-fail bursts should be worse: no_fail={no_fail}, all_fail={all_fail}"
);
}
#[test]
fn score_caps_burst_penalty_at_30() {
let s = score(100, 100, 0.0, 0, 0, None, 0.0);
assert_eq!(s, 70, "burst penalty should max out at 30");
}
#[test]
fn score_caps_workaround_penalty_at_15() {
let s = score(0, 100, 0.0, 100, 0, None, 0.0);
assert_eq!(s, 85);
}
#[test]
fn score_empty_chain_penalty() {
let s = score(0, 100, 0.0, 0, 5, None, 0.0);
assert_eq!(s, 90);
let s2 = score(0, 100, 0.0, 0, 20, None, 0.0);
assert_eq!(s2, 85);
}
#[test]
fn score_pipe_override_penalty() {
let s = score(0, 100, 0.0, 0, 0, None, 0.10);
assert_eq!(s, 90);
let s2 = score(0, 100, 0.0, 0, 0, None, 0.50);
assert_eq!(s2, 90);
}
#[test]
fn score_combines_all_signals() {
let s = score(100, 100, 1.0, 100, 20, Some(1000.0), 1.0);
assert_eq!(s, 15);
}
#[test]
fn score_is_monotonic_in_burst_rate() {
let mut prev = score(0, 100, 0.0, 0, 0, None, 0.0);
for n in 1..=100 {
let cur = score(n, 100, 0.0, 0, 0, None, 0.0);
assert!(cur <= prev, "monotonic at n={n}");
prev = cur;
}
}
#[test]
fn score_zero_events_does_not_panic() {
assert_eq!(score(0, 0, 0.0, 0, 0, None, 0.0), 100);
}
fn make_report(name: &str, health: u8, bursts: usize) -> FilterReport {
FilterReport {
filter_name: name.to_string(),
event_count: 10,
burst_count: bursts,
max_burst_size: bursts,
failed_burst_ratio: 0.0,
shape_burst_count: 0,
median_arg_uniqueness: None,
untracked_workaround_flags: vec![],
empty_chain_count: 0,
max_empty_chain: 0,
avg_excess_tokens: None,
pipe_override_rate: 0.0,
burst_time_wasted_ms: 0,
health_score: health,
}
}
#[test]
fn sort_health_ascending() {
let mut reports = vec![
make_report("a", 80, 0),
make_report("b", 30, 5),
make_report("c", 60, 1),
];
sort_reports(&mut reports, SortBy::Health);
assert_eq!(reports[0].filter_name, "b");
assert_eq!(reports[2].filter_name, "a");
}
#[test]
fn sort_health_breaks_ties_by_name() {
let mut reports = vec![make_report("zebra", 50, 1), make_report("alpha", 50, 1)];
sort_reports(&mut reports, SortBy::Health);
assert_eq!(reports[0].filter_name, "alpha");
}
#[test]
fn shape_median_none_for_empty() {
assert!(shape_median_uniqueness(&[]).is_none());
}
#[test]
fn shape_median_single_burst() {
let b = queries::ShapeBurstRow {
filter_name: "f".to_string(),
shape: "s".to_string(),
burst_size: 10,
distinct_commands: 5,
arg_uniqueness: 0.5,
failed_count: 0,
last_seen: "t".to_string(),
};
let m = shape_median_uniqueness(&[&b]).unwrap();
assert!((m - 0.5).abs() < 0.001);
}