#[cfg(test)]
mod tests {
use crate::Fitter;
use crate::geometry::shapes::{Circle, Ellipse, Square};
use crate::geometry::traits::DiagramShape;
use crate::test_utils::corpus::{CorpusEntry, Fittable, TEST_SEEDS, all};
struct Row {
name: &'static str,
seed: u64,
diag: Option<f64>,
ceiling: f64,
ok: bool,
note: &'static str,
}
fn run<S>(
shape_name: &str,
ceiling_fn: fn(&CorpusEntry) -> f64,
fittable_fn: fn(&CorpusEntry) -> Fittable,
) where
S: DiagramShape + Copy + 'static,
{
use std::sync::atomic::{AtomicUsize, Ordering};
let work: Vec<(&'static CorpusEntry, u64)> = all()
.iter()
.flat_map(|entry| TEST_SEEDS.iter().map(move |&seed| (entry, seed)))
.collect();
let next = AtomicUsize::new(0);
let n_threads = std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(1)
.min(work.len().max(1));
let mut indexed: Vec<(usize, Row)> = std::thread::scope(|scope| {
let work = &work;
let next = &next;
let handles: Vec<_> = (0..n_threads)
.map(|_| {
scope.spawn(move || {
let mut local = Vec::new();
loop {
let i = next.fetch_add(1, Ordering::Relaxed);
let Some(&(entry, seed)) = work.get(i) else {
break;
};
local.push((i, fit_one::<S>(entry, seed, ceiling_fn, fittable_fn)));
}
local
})
})
.collect();
handles
.into_iter()
.flat_map(|h| h.join().expect("corpus worker thread panicked"))
.collect()
});
indexed.sort_by_key(|(i, _)| *i);
let rows: Vec<Row> = indexed.into_iter().map(|(_, row)| row).collect();
print_report(shape_name, &rows);
let failures: Vec<&Row> = rows.iter().filter(|r| !r.ok).collect();
if !failures.is_empty() {
panic!(
"{} corpus quality: {} of {} (spec, seed) rows exceeded ceiling — see table above",
shape_name,
failures.len(),
rows.len()
);
}
}
fn fit_one<S>(
entry: &CorpusEntry,
seed: u64,
ceiling_fn: fn(&CorpusEntry) -> f64,
fittable_fn: fn(&CorpusEntry) -> Fittable,
) -> Row
where
S: DiagramShape + Copy + 'static,
{
let ceiling = ceiling_fn(entry);
let fittable = fittable_fn(entry);
if let Fittable::Skip(reason) = fittable {
return Row {
name: entry.name,
seed,
diag: None,
ceiling,
ok: true,
note: reason,
};
}
let spec = (entry.build)();
let result = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
Fitter::<S>::new(&spec).seed(seed).fit()
})) {
Ok(r) => r,
Err(_) => {
return Row {
name: entry.name,
seed,
diag: None,
ceiling,
ok: false,
note: "PANIC during fit",
};
}
};
match (fittable, result) {
(Fittable::Normal, Ok(layout)) => {
let diag = layout.diag_error();
let ok = diag.is_finite() && diag <= ceiling;
Row {
name: entry.name,
seed,
diag: Some(diag),
ceiling,
ok,
note: if ok { "" } else { "OVER CEILING" },
}
}
(Fittable::Normal, Err(e)) => Row {
name: entry.name,
seed,
diag: None,
ceiling,
ok: false,
note: leak_msg(format!("ERR: {e}")),
},
(Fittable::SanityOnly, Ok(layout)) => {
let ok = layout.loss().is_finite();
Row {
name: entry.name,
seed,
diag: None,
ceiling,
ok,
note: if ok { "sanity-ok" } else { "sanity-loss-nan" },
}
}
(Fittable::SanityOnly, Err(_)) => Row {
name: entry.name,
seed,
diag: None,
ceiling,
ok: true,
note: "sanity-err",
},
(Fittable::Skip(_), _) => unreachable!("Skip handled above the fit"),
}
}
fn print_report(shape_name: &str, rows: &[Row]) {
eprintln!();
eprintln!("# Corpus quality report ({shape_name})");
eprintln!("| spec | seed | diag_error | ceiling | status |");
eprintln!("|------|------|------------|---------|--------|");
for r in rows {
let diag = r
.diag
.map(|d| format!("{d:.3e}"))
.unwrap_or_else(|| "—".to_string());
let status = if r.ok { "OK" } else { "FAIL" };
let note = if r.note.is_empty() {
String::new()
} else {
format!(" ({})", r.note)
};
eprintln!(
"| {} | {} | {} | {:.1e} | {}{} |",
r.name, r.seed, diag, r.ceiling, status, note
);
}
eprintln!();
}
fn leak_msg(s: String) -> &'static str {
Box::leak(s.into_boxed_str())
}
#[test]
#[ignore = "slow fit-quality guardrail; run via `task test-slow`"]
fn corpus_circles_diag_error() {
run::<Circle>("circle", |e| e.ceiling_circle(), |e| e.fittable_circle);
}
#[test]
#[ignore = "slow fit-quality guardrail; run via `task test-slow`"]
fn corpus_ellipses_diag_error() {
run::<Ellipse>("ellipse", |e| e.ceiling_ellipse(), |e| e.fittable_ellipse);
}
#[test]
#[ignore = "slow fit-quality guardrail; run via `task test-slow`"]
fn corpus_squares_diag_error() {
run::<Square>("square", |e| e.ceiling_square(), |e| e.fittable_square);
}
}