use std::path::{Path, PathBuf};
use std::process::Command;
const EXPLANATION: &str = "no metadata.kind, judged kernel by default";
fn pv_bin() -> PathBuf {
PathBuf::from(env!("CARGO_BIN_EXE_pv"))
}
fn fixture(name: &str) -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../tests/fixtures/ont/kind-default")
.join(name)
}
struct Run {
code: i32,
out: String,
}
fn validate(name: &str) -> Run {
let path = fixture(name);
assert!(path.is_file(), "fixture {name} is tracked and readable");
let out = Command::new(pv_bin())
.arg("validate")
.arg(&path)
.output()
.expect("failed to spawn pv");
let mut merged = String::from_utf8_lossy(&out.stdout).into_owned();
merged.push_str(&String::from_utf8_lossy(&out.stderr));
Run {
code: out.status.code().unwrap_or(-1),
out: merged,
}
}
fn first_error(out: &str) -> &str {
out.lines()
.find(|l| l.contains("[ERROR]"))
.unwrap_or("<no [ERROR] line>")
}
#[test]
fn kindless_failing_names_the_default_on_its_first_error() {
let r = validate("kindless-failing.yaml");
assert_eq!(
r.code, 1,
"a kind-less contract with no kernel blocks is rejected\n{}",
r.out
);
let first = first_error(&r.out);
assert!(
first.contains(EXPLANATION),
"the FIRST error must carry the explanation; it read:\n {first}\nfull output:\n{}",
r.out
);
}
#[test]
fn the_explanation_is_printed_once_not_once_per_kernel_rule() {
let r = validate("kindless-failing.yaml");
let hits = r.out.matches(EXPLANATION).count();
assert_eq!(
hits, 1,
"the default is explained once, not on every kernel-only error (found {hits})\n{}",
r.out
);
let errors = r.out.matches("[ERROR]").count();
assert!(
errors > 1,
"fixture must produce MORE than one error for the `once` assertion to mean anything (found {errors})\n{}",
r.out
);
}
#[test]
fn declared_kernel_is_judged_by_the_kind_it_declares_and_says_nothing_about_a_default() {
let r = validate("declared-kernel-failing.yaml");
assert_eq!(
r.code, 1,
"a declared kernel with no kernel blocks is still rejected\n{}",
r.out
);
assert!(
!r.out.contains("judged kernel by default"),
"a DECLARED kernel had no default applied and must not claim one\n{}",
r.out
);
}
#[test]
fn the_two_failing_fixtures_differ_only_by_the_explanation() {
let kindless = validate("kindless-failing.yaml");
let declared = validate("declared-kernel-failing.yaml");
assert_eq!(
kindless.code, declared.code,
"same rules fire on both; only the explanation may differ"
);
let stripped = kindless.out.replace(&format!(" ({EXPLANATION})"), "");
assert_eq!(
stripped, declared.out,
"removing the explanation from the kind-less output must reproduce the declared-kernel \
output exactly — anything else means the default changed which RULES ran, not just what \
was said about them\nkind-less:\n{}\ndeclared:\n{}",
kindless.out, declared.out
);
}
#[test]
fn kindless_but_complete_passes_and_never_mentions_kind() {
let r = validate("kindless-passing.yaml");
assert_eq!(
r.code, 0,
"a kind-less contract carrying all four kernel blocks is valid — 666 of this corpus's \
contracts are this shape\n{}",
r.out
);
assert!(
!r.out.contains("judged kernel by default"),
"nothing failed, so there is no verdict for the default to explain\n{}",
r.out
);
}
#[test]
fn a_declared_non_kernel_kind_never_reaches_the_explanation() {
let r = validate("pattern.yaml");
assert_eq!(
r.code, 0,
"the kernel rules do not apply to `kind: pattern`\n{}",
r.out
);
assert!(
!r.out.contains("judged kernel by default"),
"a pattern contract was never judged as a kernel\n{}",
r.out
);
}