use std::path::PathBuf;
fn scorecard_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("scorecard")
.join("local.json")
}
#[test]
fn local_scorecard_exists() {
assert!(
scorecard_path().is_file(),
"scorecard/local.json must exist, run `python3 tools/local_scorecard.py`"
);
}
#[test]
fn local_scorecard_has_expected_schema() {
let body = std::fs::read_to_string(scorecard_path()).expect("read scorecard");
let v: serde_json::Value = serde_json::from_str(&body).expect("scorecard is valid JSON");
assert_eq!(v["schema"], "captchaforge-bench-report-1");
assert!(v["summary"].is_object());
assert!(v["aggregates"].is_array());
}
#[test]
fn local_scorecard_meets_minimum_floors() {
let body = std::fs::read_to_string(scorecard_path()).expect("read scorecard");
let v: serde_json::Value = serde_json::from_str(&body).expect("scorecard parses");
let s = &v["summary"];
let solvers = s["solvers_in_default_chain"].as_u64().unwrap_or(0);
let rules = s["community_rules"].as_u64().unwrap_or(0);
let fixtures = s["bench_fixtures"].as_u64().unwrap_or(0);
let fps = s["challenge_fingerprints"].as_u64().unwrap_or(0);
let tests = s["integration_test_files"].as_u64().unwrap_or(0);
assert!(
solvers >= 17,
"solver chain must have ≥17 solvers, got {solvers}"
);
assert!(rules >= 158, "community rules must have ≥158, got {rules}");
assert!(
fixtures >= 35,
"bench fixtures must have ≥35, got {fixtures}"
);
assert!(fps >= 12, "challenge fingerprints must have ≥12, got {fps}");
assert!(
tests >= 40,
"integration test files must have ≥40, got {tests}"
);
}
#[test]
fn local_scorecard_aggregates_have_real_success_rates() {
let body = std::fs::read_to_string(scorecard_path()).expect("read");
let v: serde_json::Value = serde_json::from_str(&body).unwrap();
let aggregates = v["aggregates"].as_array().expect("aggregates is array");
assert!(!aggregates.is_empty(), "scorecard must have aggregates");
for agg in aggregates {
let rate = agg["success_rate"].as_f64().unwrap_or(-1.0);
assert!(
(0.0..=1.0).contains(&rate),
"success_rate must be in [0,1], got {rate} for {agg:?}"
);
}
}