use gantz_core::{
Edge,
compile::push_pull_entrypoints,
diagnostic::{self, Severity},
node::{self, Node, WithPushEval},
};
use std::fmt::Debug;
trait DebugNode: Debug + Node {}
impl<T> DebugNode for T where T: Debug + Node {}
type Nested = node::graph::Graph<Box<dyn DebugNode>>;
fn no_lookup(_: &gantz_ca::ContentAddr) -> Option<&'static dyn Node> {
None
}
fn node_push() -> node::Push<node::Expr> {
node::expr("'()").unwrap().with_push_eval()
}
#[test]
fn invalid_edge_diagnostic() {
let mut ga = Nested::default();
let inlet = ga.add_node(Box::new(node::graph::Inlet::default()) as Box<dyn DebugNode>);
let inc = ga.add_node(Box::new(node::expr("(+ $l 1)").unwrap()) as Box<_>);
let outlet = ga.add_node(Box::new(node::graph::Outlet::default()) as Box<_>);
ga.add_edge(inlet, inc, Edge::from((0, 0)));
ga.add_edge(inc, outlet, Edge::from((5, 0)));
let mut g = petgraph::graph::DiGraph::new();
let push = g.add_node(Box::new(node_push()) as Box<dyn DebugNode>);
let nested = g.add_node(Box::new(ga) as Box<_>);
g.add_edge(push, nested, Edge::from((0, 0)));
let eps = push_pull_entrypoints(&no_lookup, &g);
let err = gantz_core::compile::module(&no_lookup, &g, &eps, &Default::default()).unwrap_err();
let diags = diagnostic::from_module_error(&err);
let diag = diags
.iter()
.find(|d| d.path == [nested.index(), inc.index()])
.unwrap_or_else(|| panic!("no diagnostic for the inc node in {diags:?}"));
assert_eq!(diag.outputs, vec![5]);
assert_eq!(diag.severity, Severity::Compile);
assert!(diag.message.contains("invalid output index"));
}
#[test]
fn runtime_error_diagnostic() {
let mut g = petgraph::graph::DiGraph::new();
let push = g.add_node(Box::new(node_push()) as Box<dyn DebugNode>);
let boom = g.add_node(Box::new(node::expr("(begin $push (car '()))").unwrap()) as Box<_>);
g.add_edge(push, boom, Edge::from((0, 0)));
let eps = push_pull_entrypoints(&no_lookup, &g);
let (mut vm, compiled) =
gantz_core::vm::init(&no_lookup, &g, &eps, &Default::default()).unwrap();
let ep = &eps[0];
let fn_name = gantz_core::compile::entry_fn_name(&ep.id());
let err = vm
.call_function_by_name_with_args(&fn_name, vec![])
.unwrap_err();
let diag = diagnostic::from_eval_error(&err, &vm, &compiled);
assert_eq!(diag.path, vec![boom.index()]);
assert_eq!(diag.severity, Severity::Runtime);
let span = diag.span.expect("runtime error carries a module span");
assert_eq!(&compiled.src[span], "car");
}