use areev_core::types::*;
use areev_store::Areev;
use tempfile::TempDir;
fn open_mem() -> (Areev, TempDir) {
let d = TempDir::new().unwrap();
let m = Areev::open(d.path().join("m.db").to_str().unwrap()).unwrap();
(m, d)
}
fn fact(s: &str, r: &str, o: &str, at: i64) -> Fact {
Fact::new(s, r, o).created_at(at).namespace("kb")
}
#[test]
fn nearest_vector_ranks_by_cosine_without_an_embedder() {
let (mut m, _d) = open_mem();
let a = m
.add_with_embedding(&fact("cats", "are", "mammals", 1), &[1.0, 0.0, 0.0])
.unwrap();
let b = m
.add_with_embedding(&fact("rust", "is", "compiled", 2), &[0.0, 1.0, 0.0])
.unwrap();
let c = m
.add_with_embedding(&fact("dogs", "are", "mammals", 3), &[0.9, 0.1, 0.0])
.unwrap();
let hits = m.nearest_vector("kb", None, None, &[1.0, 0.0, 0.0], 3).unwrap();
let order: Vec<_> = hits.iter().map(|(h, _)| *h).collect();
assert_eq!(order[0], a, "exact match first");
assert_eq!(order[1], c, "near vector second");
assert_eq!(order[2], b, "orthogonal vector last");
assert!(hits[0].1 > hits[1].1 && hits[1].1 > hits[2].1);
let scoped = m
.nearest_vector("kb", None, Some("are"), &[1.0, 0.0, 0.0], 5)
.unwrap();
assert_eq!(scoped.len(), 2);
assert!(scoped.iter().all(|(h, _)| *h == a || *h == c));
}
#[test]
fn dimension_is_declared_once_and_enforced_everywhere() {
let (mut m, _d) = open_mem();
assert_eq!(m.declared_embedding(), None);
m.add_with_embedding(&fact("a", "b", "c", 1), &[0.1, 0.2, 0.3])
.unwrap();
assert_eq!(m.declared_embedding(), Some(("external", 3)));
let write_err = m
.add_with_embedding(&fact("d", "e", "f", 2), &[0.1, 0.2])
.unwrap_err();
assert!(write_err.to_string().contains("dimension mismatch"), "{write_err}");
let read_err = m
.nearest_vector("kb", None, None, &[0.1, 0.2, 0.3, 0.4], 3)
.unwrap_err();
assert!(read_err.to_string().contains("dimension mismatch"), "{read_err}");
let empty_err = m.nearest_vector("kb", None, None, &[], 3).unwrap_err();
assert!(empty_err.to_string().contains("non-empty"), "{empty_err}");
}
#[test]
fn set_grain_embedding_backfills_replaces_and_rejects_unknown_hashes() {
let (mut m, _d) = open_mem();
let h = m.add(&fact("late", "gets", "vector", 1)).unwrap();
assert!(m.nearest_vector("kb", None, None, &[1.0, 0.0], 3).unwrap().is_empty());
m.set_grain_embedding(&h, &[1.0, 0.0]).unwrap();
let hits = m.nearest_vector("kb", None, None, &[1.0, 0.0], 3).unwrap();
assert_eq!(hits.len(), 1);
assert!(hits[0].1 > 0.99);
m.set_grain_embedding(&h, &[0.0, 1.0]).unwrap();
let hits = m.nearest_vector("kb", None, None, &[1.0, 0.0], 3).unwrap();
assert_eq!(hits.len(), 1, "one row per grain, not two");
assert!(hits[0].1 < 0.01, "the old vector must be gone");
let missing = areev_core::error::Hash::from_hex(&"0".repeat(64)).unwrap();
assert!(m.set_grain_embedding(&missing, &[1.0, 0.0]).is_err());
}
#[test]
fn superseded_grains_leave_vector_search() {
let (mut m, _d) = open_mem();
let old = m
.add_with_embedding(&fact("policy", "window", "14 days", 1), &[1.0, 0.0])
.unwrap();
let mut newer = fact("policy", "window", "30 days", 2);
let new_hash = m.supersede(&old, &mut newer).unwrap();
m.set_grain_embedding(&new_hash, &[0.9, 0.1]).unwrap();
let hits = m.nearest_vector("kb", None, None, &[1.0, 0.0], 5).unwrap();
let hashes: Vec<_> = hits.iter().map(|(h, _)| *h).collect();
assert!(!hashes.contains(&old), "superseded vector resurfaced");
assert_eq!(hashes, vec![new_hash]);
}
#[test]
fn nearest_vector_accepts_a_prefix_scope() {
let (mut m, _d) = open_mem();
let mk = |s: &str, ns: &str, at: i64| Fact::new(s, "is", "x").created_at(at).namespace(ns);
let health = m
.add_with_embedding(&mk("h1", "deal.health.1", 1), &[1.0, 0.0, 0.0])
.unwrap();
let health2 = m
.add_with_embedding(&mk("h2", "deal.health.2", 2), &[0.98, 0.02, 0.0])
.unwrap();
let indus = m
.add_with_embedding(&mk("i1", "deal.industrial.1", 3), &[0.96, 0.04, 0.0])
.unwrap();
let outside = m
.add_with_embedding(&mk("o1", "other.1", 4), &[1.0, 0.0, 0.0])
.unwrap();
let hits = m.nearest_vector("deal.health.1", None, None, &[1.0, 0.0, 0.0], 10).unwrap();
let got: Vec<_> = hits.iter().map(|(h, _)| *h).collect();
assert_eq!(got, vec![health], "exact scope stays exact");
let hits = m.nearest_vector("deal.health.*", None, None, &[1.0, 0.0, 0.0], 10).unwrap();
let got: Vec<_> = hits.iter().map(|(h, _)| *h).collect();
assert_eq!(got.len(), 2, "sector scope selects its own sub-tree: {got:?}");
assert!(got.contains(&health) && got.contains(&health2));
assert!(!got.contains(&indus), "a sibling sector must not leak in");
assert!(!got.contains(&outside), "the nearest vector outside the scope must stay out");
let hits = m.nearest_vector("deal.*", None, None, &[1.0, 0.0, 0.0], 10).unwrap();
let got: Vec<_> = hits.iter().map(|(h, _)| *h).collect();
assert_eq!(got.len(), 3, "tree scope selects every descendant: {got:?}");
assert!(!got.contains(&outside), "scoping must not fail open to the whole file");
assert_eq!(got[0], health, "ranking is still by cosine within the scope");
let hits = m.nearest_vector("nosuch.*", None, None, &[1.0, 0.0, 0.0], 10).unwrap();
assert!(hits.is_empty(), "an unmatched scope returns nothing, never the whole file");
}
#[test]
fn a_prefix_scope_still_honours_the_subject_filter() {
let (mut m, _d) = open_mem();
let mk = |s: &str, ns: &str, at: i64| Fact::new(s, "is", "x").created_at(at).namespace(ns);
let want = m.add_with_embedding(&mk("acme", "deal.a", 1), &[1.0, 0.0, 0.0]).unwrap();
let _other_subject =
m.add_with_embedding(&mk("beta", "deal.b", 2), &[1.0, 0.0, 0.0]).unwrap();
let hits = m.nearest_vector("deal.*", Some("acme"), None, &[1.0, 0.0, 0.0], 10).unwrap();
let got: Vec<_> = hits.iter().map(|(h, _)| *h).collect();
assert_eq!(got, vec![want], "subject filter applies across the scope, not just within one ns");
let none = m.nearest_vector("deal.*", Some("ghost"), None, &[1.0, 0.0, 0.0], 10).unwrap();
assert!(none.is_empty(), "an uninterned subject short-circuits instead of scanning");
}
#[test]
fn set_grain_embeddings_writes_a_multi_chunk_batch_atomically() {
let (mut m, _d) = open_mem();
let n = areev_store::EMBEDDING_BATCH_CHUNK + 50; let mut items = Vec::with_capacity(n);
for i in 0..n {
let h = m.add(&fact(&format!("g{i}"), "is", "a grain", 100 + i as i64)).unwrap();
let a = i as f32;
items.push((h, vec![a.cos(), a.sin(), (a * 0.5).cos(), (a * 0.5).sin()]));
}
assert_eq!(m.set_grain_embeddings(&items).unwrap(), n);
assert_eq!(m.declared_embedding(), Some(("external", 4)));
for (h, v) in items.iter().step_by(37) {
let near = m.nearest_vector("kb", None, None, v, 1).unwrap();
assert_eq!(near[0].0, *h);
assert!(near[0].1 > 0.999, "{}", near[0].1);
}
let (h0, _) = items[0].clone();
let twice = vec![(h0, vec![1.0, 0.0, 0.0, 0.0]), (h0, vec![0.0, 1.0, 0.0, 0.0])];
assert_eq!(m.set_grain_embeddings(&twice).unwrap(), 1);
let near = m.nearest_vector("kb", None, None, &[0.0, 1.0, 0.0, 0.0], 1).unwrap();
assert_eq!(near[0].0, h0);
assert_eq!(m.set_grain_embeddings(&[]).unwrap(), 0);
}
#[test]
fn set_grain_embeddings_is_all_or_nothing() {
let (mut m, _d) = open_mem();
let a = m.add(&fact("a", "is", "x", 1)).unwrap();
let b = m.add(&fact("b", "is", "y", 2)).unwrap();
let missing = areev_core::error::Hash::from_hex(&"9".repeat(64)).unwrap();
let err = m
.set_grain_embeddings(&[(a, vec![1.0, 0.0]), (b, vec![0.0, 1.0, 0.0])])
.unwrap_err();
assert!(err.to_string().contains("dimensions"), "{err}");
assert!(m.nearest_vector("kb", None, None, &[1.0, 0.0], 5).unwrap().is_empty(), "nothing written");
assert!(m.declared_embedding().is_none(), "and no provenance stamped");
let err = m
.set_grain_embeddings(&[(a, vec![1.0, 0.0]), (missing, vec![0.0, 1.0])])
.unwrap_err();
assert!(err.to_string().contains("MEM-E") || err.to_string().contains("not found"), "{err}");
assert!(m.nearest_vector("kb", None, None, &[1.0, 0.0], 5).unwrap().is_empty(), "nothing written");
}
#[test]
fn vector_recall_check_is_trivially_exact_without_an_index() {
let (mut m, _d) = open_mem();
let a = m.add_with_embedding(&fact("a", "is", "x", 1), &[1.0, 0.0]).unwrap();
let _ = a;
let report = m.vector_recall_check("kb", &[vec![1.0, 0.0], vec![0.0, 1.0]], 3).unwrap();
assert_eq!((report.index, report.ef_search), (None, None));
assert_eq!((report.queries, report.k), (0, 3));
assert_eq!(report.recall, Some(1.0));
assert!(m.vector_recall_check("kb", &[vec![1.0, 0.0]], 0).is_err(), "k = 0 is refused");
assert!(m.vector_recall_check("kb", &[], 3).is_err(), "no queries is refused");
assert!(
m.vector_recall_check("kb", &[vec![1.0, 0.0, 0.0]], 3).is_err(),
"a query of the wrong dimension is refused even when no index exists"
);
assert!(
m.set_vector_ef_search(100).unwrap_err().to_string().starts_with("STO-E007"),
"nothing to tune on the embedded engine"
);
assert!(
m.ensure_vector_index(16, 64, 40).unwrap_err().to_string().starts_with("STO-E007"),
"the embedded engine still refuses to build one"
);
assert_eq!(m.vector_index().unwrap(), None);
m.drop_vector_index().unwrap();
assert_eq!(m.vector_index().unwrap(), None);
}