#![cfg(feature = "trace")]
use datalogic_rs::{CustomOperator, DataValue, Engine, Error, operator::EvalContext};
struct Fail;
impl CustomOperator for Fail {
fn evaluate<'a>(
&self,
_args: &[&'a DataValue<'a>],
_ctx: &mut EvalContext<'_, 'a>,
_arena: &'a datalogic_rs::bumpalo::Bump,
) -> datalogic_rs::Result<&'a DataValue<'a>> {
Err(Error::custom_message("boom"))
}
}
fn reported(engine: &Engine, rule: &str, data: &str) -> [Option<String>; 4] {
let name = |e: Error| e.operator().map(str::to_owned);
let compiled = engine.compile(rule).unwrap();
let arena = datalogic_rs::bumpalo::Bump::new();
let evaluate = engine.evaluate(&compiled, data, &arena).unwrap_err();
let one_shot = engine.eval_str(rule, data).unwrap_err();
let session = engine.session().eval(&compiled, data).unwrap_err();
let traced = engine.trace().eval_str(rule, data).result.unwrap_err();
[name(evaluate), name(one_shot), name(session), name(traced)]
}
#[test]
fn names_the_innermost_failing_operator_on_every_path() {
let engine = Engine::builder().add_operator("fail", Fail).build();
let data = r#"{"x": 1, "y": "a"}"#;
for (rule, want) in [
(
r#"{"if": [true, {"+": [1, {"fail": [{"var": "x"}]}]}, 0]}"#,
"fail",
),
(
r#"{"if": [{"var": "x"}, {"+": [1, {"var": "y"}]}, 0]}"#,
"+",
),
(r#"{"if": [{"var": "x"}, {"and": {"var": "x"}}, 0]}"#, "and"),
(r#"{"fail": []}"#, "fail"),
(
r#"{"map": [[1, 2], {"cat": ["n", {"fail": [{"var": ""}]}]}]}"#,
"fail",
),
] {
let want = Some(want.to_owned());
assert_eq!(
reported(&engine, rule, data),
[want.clone(), want.clone(), want.clone(), want],
"{rule}"
);
}
}
#[test]
fn keeps_a_name_set_by_the_raising_site() {
struct Named;
impl CustomOperator for Named {
fn evaluate<'a>(
&self,
_args: &[&'a DataValue<'a>],
_ctx: &mut EvalContext<'_, 'a>,
_arena: &'a datalogic_rs::bumpalo::Bump,
) -> datalogic_rs::Result<&'a DataValue<'a>> {
Err(Error::custom_message("boom").with_operator("inner_step"))
}
}
let engine = Engine::builder().add_operator("named", Named).build();
let want = Some("inner_step".to_owned());
assert_eq!(
reported(&engine, r#"{"+": [1, {"named": []}]}"#, "{}"),
[want.clone(), want.clone(), want.clone(), want]
);
}