90 lines
3.1 KiB
Rust
90 lines
3.1 KiB
Rust
/// Integration test — compile every example .ds file through the full pipeline.
|
|
/// This is the ultimate regression guard: if any of the 51 examples break, this test catches it.
|
|
|
|
use std::fs;
|
|
use std::path::PathBuf;
|
|
|
|
/// Get the workspace root (two levels up from ds-cli's Cargo.toml).
|
|
fn workspace_root() -> PathBuf {
|
|
let manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
manifest.parent().unwrap().parent().unwrap().to_path_buf()
|
|
}
|
|
|
|
/// Compile a .ds source string through the full pipeline (lex → parse → analyze → codegen).
|
|
fn compile_source(source: &str) -> Result<String, String> {
|
|
let mut lexer = ds_parser::Lexer::new(source);
|
|
let tokens = lexer.tokenize();
|
|
|
|
for tok in &tokens {
|
|
if let ds_parser::TokenKind::Error(msg) = &tok.kind {
|
|
return Err(format!("Lexer error at line {}: {}", tok.line, msg));
|
|
}
|
|
}
|
|
|
|
let mut parser = ds_parser::Parser::with_source(tokens, source);
|
|
let program = parser.parse_program().map_err(|e| e.to_string())?;
|
|
|
|
let graph = ds_analyzer::SignalGraph::from_program(&program);
|
|
let views = ds_analyzer::SignalGraph::analyze_views(&program);
|
|
|
|
let html = ds_codegen::JsEmitter::emit_html(&program, &graph, &views, false);
|
|
Ok(html)
|
|
}
|
|
|
|
#[test]
|
|
fn test_compile_all_examples() {
|
|
// Spawn with 8MB stack to handle deeply nested examples
|
|
let builder = std::thread::Builder::new()
|
|
.name("compile_examples".into())
|
|
.stack_size(8 * 1024 * 1024);
|
|
|
|
let handle = builder.spawn(|| {
|
|
let examples_dir = workspace_root().join("examples");
|
|
assert!(examples_dir.exists(), "examples/ directory not found at {:?}", examples_dir);
|
|
|
|
let mut ds_files: Vec<PathBuf> = fs::read_dir(&examples_dir)
|
|
.expect("cannot read examples/")
|
|
.filter_map(|e| e.ok())
|
|
.map(|e| e.path())
|
|
.filter(|p| p.extension().map_or(false, |ext| ext == "ds"))
|
|
.collect();
|
|
|
|
ds_files.sort();
|
|
|
|
assert!(!ds_files.is_empty(), "no .ds files found in examples/");
|
|
|
|
let mut pass = 0;
|
|
let mut fail = 0;
|
|
let mut failures = Vec::new();
|
|
|
|
for path in &ds_files {
|
|
let source = fs::read_to_string(path)
|
|
.unwrap_or_else(|e| panic!("cannot read {}: {}", path.display(), e));
|
|
|
|
let name = path.file_name().unwrap().to_str().unwrap();
|
|
|
|
match compile_source(&source) {
|
|
Ok(html) => {
|
|
assert!(!html.is_empty(), "{}: produced empty output", name);
|
|
pass += 1;
|
|
}
|
|
Err(e) => {
|
|
failures.push(format!(" {} — {}", name, e));
|
|
fail += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
eprintln!("\n Examples: {} passed, {} failed, {} total", pass, fail, ds_files.len());
|
|
|
|
if !failures.is_empty() {
|
|
panic!(
|
|
"\n{} example(s) failed to compile:\n{}\n",
|
|
fail,
|
|
failures.join("\n")
|
|
);
|
|
}
|
|
}).expect("failed to spawn test thread");
|
|
|
|
handle.join().expect("test thread panicked");
|
|
}
|