use std::path::PathBuf;
use std::process::Command;
mod common;
fn hermesc_bin() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../../cmake-build-asan/bin/hermesc")
}
fn run_differential(corpus: &str, hermesc_extra: &[&str], ast_dump_extra: &[&str]) {
let hermesc = hermesc_bin();
if !hermesc.exists() {
if std::env::var_os("REQUIRE_DIFFERENTIAL").is_some() {
panic!(
"REQUIRE_DIFFERENTIAL set but hermesc not found at {}; \
build: cmake --build cmake-build-asan --target hermesc",
hermesc.display()
);
}
eprintln!(
"skipping parser_differential: hermesc not found at {} \
(set REQUIRE_DIFFERENTIAL=1 to force)",
hermesc.display()
);
return;
}
let ast_dump = common::tools_bin("ast-dump");
let corpus_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(corpus);
let mut files: Vec<PathBuf> = std::fs::read_dir(&corpus_dir)
.unwrap_or_else(|e| panic!("{} dir missing: {e}", corpus_dir.display()))
.map(|e| e.unwrap().path())
.filter(|p| p.extension().map(|e| e == "js").unwrap_or(false))
.collect();
files.sort();
if files.is_empty() {
eprintln!("parser differential ({corpus}): no .js files (trivial pass)");
return;
}
for f in &files {
let c = Command::new(&hermesc)
.args(["-dump-ast", "-dump-source-location=both"])
.args(hermesc_extra)
.arg(f)
.output()
.expect("failed to run hermesc");
assert!(
c.status.success(),
"hermesc failed on {}:\n{}",
f.display(),
String::from_utf8_lossy(&c.stderr)
);
let r = Command::new(&ast_dump)
.args(["--pretty", "--dump-source-location", "--include-raw-ast-prop"])
.args(ast_dump_extra)
.arg(f)
.output()
.expect("failed to run ast-dump");
assert_eq!(
String::from_utf8_lossy(&c.stdout),
String::from_utf8_lossy(&r.stdout),
"AST dump mismatch for {}",
f.display()
);
}
eprintln!(
"parser differential ({corpus}): {} corpus files matched",
files.len()
);
}
#[test]
fn parser_differential_p0() {
run_differential("tests/parser_corpus", &[], &[]);
}
#[test]
fn parser_differential_flow() {
run_differential("tests/parser_corpus_flow", &["-parse-flow"], &["--parse-flow"]);
}
#[test]
fn parser_differential_flow_component() {
run_differential(
"tests/parser_corpus_flow_component",
&["-parse-flow", "-Xparse-component-syntax"],
&["--parse-flow", "--parse-component-syntax"],
);
}
#[test]
fn parser_differential_flow_records() {
run_differential(
"tests/parser_corpus_flow_records",
&["-parse-flow", "-Xparse-flow-records"],
&["--parse-flow", "--parse-flow-records"],
);
}
#[test]
fn parser_differential_flow_match() {
run_differential(
"tests/parser_corpus_flow_match",
&["-parse-flow", "-Xparse-flow-match"],
&["--parse-flow", "--parse-flow-match"],
);
}
#[test]
fn parser_differential_ts() {
run_differential("tests/parser_corpus_ts", &["-parse-ts"], &["--parse-ts"]);
}
#[test]
fn parser_differential_jsx() {
run_differential("tests/parser_corpus_jsx", &["-parse-jsx"], &["--parse-jsx"]);
}
#[test]
fn parser_differential_jsx_flow() {
run_differential(
"tests/parser_corpus_jsx_flow",
&["-parse-jsx", "-parse-flow"],
&["--parse-jsx", "--parse-flow"],
);
}