query-engine/tests/regression_tests.rs

96 lines
2.7 KiB
Rust
Raw Normal View History

2026-04-09 10:12:59 +02:00
use query_engine::chase::materialize;
use query_engine::chase::rule::RuleBuilder;
use query_engine::frontend::Session;
use query_engine::{Atom, Instance, Term, chase};
#[test]
fn existential_trigger_stays_inactive_when_head_is_already_satisfied() {
let instance: Instance = vec![
Atom::new("Person", vec![Term::constant("alice")]),
Atom::new(
"HasSSN",
vec![Term::constant("alice"), Term::constant("known")],
),
]
.into_iter()
.collect();
let rule = RuleBuilder::new()
.when("Person", vec![Term::var("X")])
.then("HasSSN", vec![Term::var("X"), Term::var("Y")])
.build();
let result = chase(instance, &[rule]);
assert!(result.terminated);
assert_eq!(result.steps, 0);
assert_eq!(result.instance.facts_for_predicate("HasSSN").len(), 1);
}
#[test]
fn fresh_nulls_skip_existing_input_null_ids() {
let instance: Instance = vec![
Atom::new("Seed", vec![Term::null(0)]),
Atom::new("Person", vec![Term::constant("alice")]),
]
.into_iter()
.collect();
let rule = RuleBuilder::new()
.when("Person", vec![Term::var("X")])
.then("HasSSN", vec![Term::var("X"), Term::var("Y")])
.build();
let result = chase(instance, &[rule]);
assert!(result.terminated);
assert_eq!(result.instance.facts_for_predicate("HasSSN").len(), 1);
let fact = result.instance.facts_for_predicate("HasSSN")[0];
assert!(matches!(fact.terms[1], Term::Null(id) if id > 0));
}
#[test]
fn frontend_materialization_respects_existing_existential_witnesses() {
let mut session = Session::new();
let output = session
.execute_script(
"fact Person(alice).\n\
fact HasSSN(alice, known).\n\
rule Person(?X) -> HasSSN(?X, ?Y).\n\
run.\n\
query HasSSN(alice, ?Y)?",
)
.unwrap();
assert!(output.contains("1 row(s)"));
assert!(output.contains("?Y = known"));
assert!(!output.contains(""));
}
#[test]
fn frontend_materialization_starts_after_existing_null_ids() {
let instance: Instance = vec![
Atom::new("Seed", vec![Term::null(7)]),
Atom::new("Employee", vec![Term::constant("alice")]),
]
.into_iter()
.collect();
let rule = RuleBuilder::new()
.when("Employee", vec![Term::var("X")])
.then("WorksIn", vec![Term::var("X"), Term::var("Dept")])
.build();
let state = materialize(instance, &[rule]);
assert!(state.result.terminated);
assert_eq!(
state.result.instance.facts_for_predicate("WorksIn").len(),
1
);
let fact = state.result.instance.facts_for_predicate("WorksIn")[0];
assert!(matches!(fact.terms[1], Term::Null(id) if id > 7));
}