use std::time::{Duration, Instant};
use fathomdb_engine::{
rerank_passages, Engine, IdSpace, IdSpaceKind, InitialState, PreparedWrite, SearchResult,
};
use fathomdb_schema::SQLITE_SUFFIX;
use sha2::{Digest, Sha256};
use tempfile::TempDir;
fn prior_stable_id_content(body: &str) -> String {
let hex: String = Sha256::digest(body.as_bytes()).iter().map(|b| format!("{b:02x}")).collect();
format!("h:{hex}")
}
fn fixture(name: &str) -> (TempDir, std::path::PathBuf) {
let dir = TempDir::new().unwrap();
let path = dir.path().join(format!("{name}{SQLITE_SUFFIX}"));
(dir, path)
}
fn search_after_projection(engine: &Engine, query: &str, min_cursor: u64) -> SearchResult {
let started = Instant::now();
loop {
let result = engine.search(query).expect("search");
if result.projection_cursor >= min_cursor && !result.results.is_empty() {
return result;
}
if started.elapsed() > Duration::from_secs(10) {
return result;
}
std::thread::sleep(Duration::from_millis(10));
}
}
#[test]
fn governed_hit_id_is_logical_space() {
let (_dir, path) = fixture("tc8_logical");
let opened = Engine::open_without_embedder_for_test(&path).expect("open");
let receipt = opened
.engine
.write(&[PreparedWrite::Node {
kind: "person".to_string(),
body: "tc8 governed logical entity payload".to_string(),
source_id: fathomdb_engine::SourceId::new("test:fixture").expect("test source id"),
logical_id: Some("gov-entity-19".to_string()),
state: InitialState::Active,
reason: None,
valid_from: None,
valid_until: None,
}])
.expect("write");
opened.engine.drain(10_000).expect("drain");
let result = search_after_projection(&opened.engine, "governed", receipt.cursor);
let hit = &result.results[0];
assert_eq!(hit.id.space, IdSpaceKind::Logical);
assert_eq!(hit.id.value, "gov-entity-19");
assert_eq!(hit.id.to_prefixed(), "l:gov-entity-19");
assert_eq!(hit.id, IdSpace::logical("gov-entity-19"));
assert_eq!(hit.write_cursor, receipt.cursor, "positional cursor retained internally");
assert_ne!(hit.id.value, hit.write_cursor.to_string(), "id is NOT the positional cursor");
opened.engine.close().unwrap();
}
#[test]
fn doc_seeded_hit_id_is_content_space() {
let (_dir, path) = fixture("tc8_content");
let opened = Engine::open_without_embedder_for_test(&path).expect("open");
let body = "tc8 anonymous docseeded payload xyzzy";
let receipt = opened
.engine
.write(&[PreparedWrite::Node {
kind: "note".to_string(),
body: body.to_string(),
source_id: fathomdb_engine::SourceId::new("test:fixture").expect("test source id"),
logical_id: None,
state: InitialState::Active,
reason: None,
valid_from: None,
valid_until: None,
}])
.expect("write");
opened.engine.drain(10_000).expect("drain");
let result = search_after_projection(&opened.engine, "docseeded", receipt.cursor);
let hit = &result.results[0];
assert_eq!(hit.id.space, IdSpaceKind::Content);
let prefixed = hit.id.to_prefixed();
assert!(prefixed.starts_with("h:"), "doc-seeded id is content-hash tagged, got {prefixed}");
assert_eq!(prefixed.len(), 2 + 64, "h: + sha256 hex");
assert!(hit.id.value.chars().all(|c| c.is_ascii_hexdigit()), "content hash is lowercase hex");
assert_eq!(prefixed, prior_stable_id_content(body), "content id == prior stable_id bytes");
assert_eq!(
hit.id.value,
prior_stable_id_content(body)["h:".len()..],
"bare value is prefix-stripped"
);
assert_eq!(hit.write_cursor, receipt.cursor);
opened.engine.close().unwrap();
}
#[test]
fn every_hit_id_is_non_null_and_space_total() {
let (_dir, path) = fixture("tc8_total");
let opened = Engine::open_without_embedder_for_test(&path).expect("open");
let r = opened
.engine
.write(&[
PreparedWrite::Node {
kind: "person".to_string(),
body: "tc8 total governed alpha totalterm".to_string(),
source_id: fathomdb_engine::SourceId::new("test:fixture").expect("test source id"),
logical_id: Some("total-gov-1".to_string()),
state: InitialState::Active,
reason: None,
valid_from: None,
valid_until: None,
},
PreparedWrite::Node {
kind: "note".to_string(),
body: "tc8 total anonymous beta totalterm".to_string(),
source_id: fathomdb_engine::SourceId::new("test:fixture").expect("test source id"),
logical_id: None,
state: InitialState::Active,
reason: None,
valid_from: None,
valid_until: None,
},
])
.expect("write");
opened.engine.drain(10_000).expect("drain");
let result = search_after_projection(&opened.engine, "totalterm", r.cursor);
assert!(result.results.len() >= 2, "both docs retrieved");
for hit in &result.results {
assert!(matches!(
hit.id.space,
IdSpaceKind::Logical | IdSpaceKind::Content | IdSpaceKind::Passage
));
assert!(!hit.id.value.is_empty(), "id value is non-null");
assert_eq!(IdSpace::parse(&hit.id.to_prefixed()), Some(hit.id.clone()), "round-trip");
}
assert!(result.results.iter().any(|h| h.id.space == IdSpaceKind::Logical));
assert!(result.results.iter().any(|h| h.id.space == IdSpaceKind::Content));
opened.engine.close().unwrap();
}
#[test]
fn synthetic_passage_id_is_passage_space_from_ordinal() {
let passages = vec![
(11u64, "passage eleven body".to_string(), 0.9_f64),
(22u64, "passage twenty-two body".to_string(), 0.8_f64),
];
let out = rerank_passages("q", passages, 0, 0.3, 0).expect("rerank");
let ordinals: Vec<u64> = out.iter().map(|(id, _, _)| *id).collect();
assert_eq!(ordinals, vec![11, 22], "caller ordinals retained as the positional cursor");
let pid = IdSpace::passage(11u64.to_string());
assert_eq!(pid.space, IdSpaceKind::Passage);
assert_eq!(pid.to_prefixed(), "p:11");
assert_eq!(IdSpace::parse("p:11"), Some(pid));
}