74 lines
2.5 KiB
Rust
74 lines
2.5 KiB
Rust
//! End-to-end check: run the JSON fixture and verify the resulting bindings
|
|
//! match the `DB.InMemoryTest` "matches evalConjunction on three-atom chain"
|
|
//! case from `external/geolog/geolog-lang/test/DB/InMemoryTest.hs`.
|
|
//!
|
|
//! For `node = {e1, e2, e3}` and `edge = {(e1,e2,ee1), (e2,e3,ee2)}` the
|
|
//! conjunction `node(a), edge(a, b, _), edge(b, c, _)` has exactly one
|
|
//! solution: `(a=e1, b=e2, c=e3)`.
|
|
|
|
use std::collections::BTreeMap;
|
|
|
|
use glog_runner::run_json;
|
|
use storage::value::Value;
|
|
|
|
fn fixture() -> &'static str {
|
|
include_str!("../fixtures/three_atom_chain.json")
|
|
}
|
|
|
|
fn ent(path: &str, id: u32) -> Value {
|
|
Value::Str(format!("{path}:{id}"))
|
|
}
|
|
|
|
fn project<'a>(
|
|
columns: &'a [String],
|
|
row: &'a [Value],
|
|
keep: &'a [&'a str],
|
|
) -> BTreeMap<&'a str, &'a Value> {
|
|
keep.iter()
|
|
.map(|name| {
|
|
let pos = columns
|
|
.iter()
|
|
.position(|c| c == name)
|
|
.expect("column missing");
|
|
(*name, &row[pos])
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
#[test]
|
|
fn three_atom_chain_matches_haskell_oracle() {
|
|
let result = run_json(fixture()).expect("fixture should execute");
|
|
|
|
// The plan's root keeps every variable, including the per-atom wildcards
|
|
// `_r1` and `_r2`. The oracle only asserts the (a, b, c) projection.
|
|
let keep = ["a", "b", "c"];
|
|
let mut projected: Vec<BTreeMap<&str, &Value>> = result
|
|
.rows
|
|
.iter()
|
|
.map(|row| project(&result.columns, row, &keep))
|
|
.collect();
|
|
projected.sort_by_key(|m| format!("{m:?}"));
|
|
|
|
let e1 = ent("node", 1);
|
|
let e2 = ent("node", 2);
|
|
let e3 = ent("node", 3);
|
|
let expected = vec![BTreeMap::from([("a", &e1), ("b", &e2), ("c", &e3)])];
|
|
|
|
assert_eq!(projected, expected);
|
|
}
|
|
|
|
#[test]
|
|
fn root_columns_cover_a_b_c_plus_two_wildcards() {
|
|
// The exporter emits unique wildcard variable names for the entity-id
|
|
// column of each edge atom (e.g. `_w0_2`, `_w1_2`); their exact spelling
|
|
// is an implementation detail of the exporter, so this test only checks
|
|
// that the named variables are all present and that the total column
|
|
// count is the three named ones plus two anonymous wildcards.
|
|
let result = run_json(fixture()).expect("fixture should execute");
|
|
let cols: std::collections::HashSet<&str> = result.columns.iter().map(String::as_str).collect();
|
|
for expected in ["a", "b", "c"] {
|
|
assert!(cols.contains(expected), "missing column {expected}");
|
|
}
|
|
assert_eq!(result.columns.len(), 5, "expected 3 named + 2 wildcards");
|
|
}
|