use tensorlogic_compiler::error_recovery::{
compile_tolerant, compile_tolerant_with_strategy, PartialCompilationResult, RecoveryStrategy,
Severity,
};
use tensorlogic_ir::{TLExpr, Term};
fn good(name: &str) -> TLExpr {
TLExpr::pred(name, vec![Term::var("x")])
}
fn broken() -> TLExpr {
TLExpr::exists(
"y",
"MissingDomain",
TLExpr::pred("q", vec![Term::var("y")]),
)
}
#[test]
fn mixed_program_three_good_plus_one_broken() {
let program = vec![good("a"), good("b"), broken(), good("d")];
let res: PartialCompilationResult = compile_tolerant(&program);
assert_eq!(res.graphs.len(), 4);
assert_eq!(res.success_count(), 3, "three good expressions compile");
assert_eq!(res.failure_count(), 1, "one broken expression skipped");
assert_eq!(res.failures(), vec![2]);
let errors = res.diagnostics.errors();
assert_eq!(errors.len(), 1, "exactly one Error diagnostic");
assert_eq!(
errors[0].expression_index,
Some(2),
"diagnostic tied to broken expression's index"
);
assert_eq!(res.diagnostics.count_of(Severity::Fatal), 0);
assert!(!res.aborted);
assert!(res.aborted_at.is_none());
}
#[test]
fn abort_on_any_strategy_stops_at_first_error() {
let program = vec![good("a"), broken(), good("c"), good("d")];
let res = compile_tolerant_with_strategy(&program, RecoveryStrategy::AbortOnAny);
assert_eq!(res.graphs.len(), 4);
assert!(res.graphs[0].is_some());
assert!(res.graphs[1].is_none());
assert!(res.graphs[2].is_none());
assert!(res.graphs[3].is_none());
assert!(res.aborted);
assert_eq!(res.aborted_at, Some(1));
assert_eq!(res.diagnostics.errors().len(), 1);
}
#[test]
fn all_good_program_yields_no_diagnostics() {
let program = vec![good("a"), good("b"), good("c")];
let res = compile_tolerant(&program);
assert!(res.is_all_success());
assert!(res.diagnostics.is_empty());
assert!(!res.aborted);
}