use std::path::PathBuf;
use vexil_lang::diagnostic::Severity;
use vexil_lang::resolve::FilesystemLoader;
fn corpus_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap()
.parent()
.unwrap()
.join("corpus")
.join("projects")
}
fn compile_and_generate(project_name: &str, root_ns: &str, expected_schema_count: usize) {
let project_dir = corpus_dir().join(project_name);
let root_segments: Vec<&str> = root_ns.split('.').collect();
let mut root_path = project_dir.clone();
for seg in &root_segments {
root_path.push(seg);
}
root_path.set_extension("vexil");
let source = std::fs::read_to_string(&root_path)
.unwrap_or_else(|e| panic!("failed to read {}: {e}", root_path.display()));
let loader = FilesystemLoader::new(vec![project_dir]);
let result = vexil_lang::compile_project(&source, &root_path, &loader)
.unwrap_or_else(|e| panic!("compile_project failed for {project_name}: {e}"));
let errors: Vec<_> = result
.diagnostics
.iter()
.filter(|d| d.severity == Severity::Error)
.collect();
assert!(
errors.is_empty(),
"unexpected errors in {project_name}: {errors:?}"
);
assert_eq!(
result.schemas.len(),
expected_schema_count,
"{project_name}: expected {expected_schema_count} schemas, got {}",
result.schemas.len()
);
for (ns, compiled) in &result.schemas {
let code = vexil_codegen_rust::generate(compiled)
.unwrap_or_else(|e| panic!("codegen failed for {ns}: {e}"));
assert!(!code.is_empty(), "empty codegen output for {ns}");
assert!(
code.contains("// Code generated by vexilc"),
"missing header in {ns}"
);
}
eprintln!(
"{project_name}: {} schemas compiled and generated successfully",
result.schemas.len()
);
}
#[test]
fn project_simple() {
compile_and_generate("simple", "simple.main", 2);
}
#[test]
fn project_diamond() {
compile_and_generate("diamond", "diamond.root", 4);
}
#[test]
fn project_mixed() {
compile_and_generate("mixed", "mix.app", 3);
}