use std::path::{Path, PathBuf};
use cgn_core::config::Config;
fn workspace_root() -> PathBuf {
let crate_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
crate_dir
.parent()
.and_then(|p| p.parent())
.and_then(|p| p.parent())
.expect("cgn-core lives at rust/libraries/cgn-core")
.to_path_buf()
}
fn recipe_tomls(root: &Path) -> Vec<PathBuf> {
let mut out = Vec::new();
let mut stack = vec![root.to_path_buf()];
while let Some(d) = stack.pop() {
let entries = match std::fs::read_dir(&d) {
Ok(e) => e,
Err(_) => continue,
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
let name = path.file_name().and_then(|s| s.to_str()).unwrap_or("");
if name.starts_with('_') || name.starts_with('.') {
continue;
}
stack.push(path);
} else if path
.extension()
.and_then(|s| s.to_str())
.is_some_and(|e| e == "toml")
{
out.push(path);
}
}
}
out.sort();
out
}
#[test]
fn every_recipe_toml_parses_against_the_live_schema() {
let root = workspace_root().join("recipes");
if !root.is_dir() {
eprintln!("note: {} not present, skipping", root.display());
return;
}
let tomls = recipe_tomls(&root);
assert!(
!tomls.is_empty(),
"expected at least one TOML under recipes/"
);
let mut failures: Vec<(PathBuf, cgn_core::Error)> = Vec::new();
for p in &tomls {
match Config::load(p) {
Ok(_) => {}
Err(e) => failures.push((p.clone(), e)),
}
}
if !failures.is_empty() {
for (p, e) in &failures {
eprintln!("FAIL: {} → {:?}", p.display(), e);
}
panic!(
"{}/{} recipe TOMLs failed to parse",
failures.len(),
tomls.len()
);
}
}