use dejadb_core::types::{Fact, Grain};
use dejadb_store::DejaDB;
use tempfile::TempDir;
fn fact(ns: &str, s: &str, r: &str, o: &str) -> Fact {
let mut f = Fact::new(s, r, o).confidence(0.9).source_type("user_explicit");
f.common.namespace = Some(ns.to_string());
f
}
#[test]
fn blob_cas_roundtrip_dedup_gc() {
let dir = TempDir::new().unwrap();
let path = dir.path().join("m.db");
let mut m = DejaDB::open(path.to_str().unwrap()).unwrap();
let audio = vec![7u8; 4096];
let uri = m.put_blob(&audio).unwrap();
assert!(uri.starts_with("cas://sha256:"));
let uri2 = m.put_blob(&audio).unwrap();
assert_eq!(uri, uri2);
assert_eq!(m.get_blob(&uri).unwrap(), audio);
let mut f = fact("caller", "alice", "said", "play my message");
f.common.content_refs = vec![dejadb_core::types::ContentRef {
uri: uri.clone(),
modality: Some("audio".to_string()),
mime_type: Some("audio/wav".to_string()),
size_bytes: Some(4096),
checksum: Some(uri.trim_start_matches("cas://").to_string()),
metadata: None,
}];
m.add(&f).unwrap();
let orphan = m.put_blob(&[9u8; 128]).unwrap();
let removed = m.gc_blobs().unwrap();
assert_eq!(removed, 1);
assert!(m.get_blob(&uri).is_ok());
assert!(m.get_blob(&orphan).is_err());
}
#[test]
fn bundle_fast_forward_replication() {
let da = TempDir::new().unwrap();
let db_ = TempDir::new().unwrap();
let pa = da.path().join("a.db");
let pb = db_.path().join("b.db");
let mut a = DejaDB::open(pa.to_str().unwrap()).unwrap();
let h1 = a.add(&fact("ns", "alice", "prefers", "tea")).unwrap();
let h2 = a.add(&fact("ns", "alice", "lives_in", "Berlin")).unwrap();
a.add(&fact("ns", "bob", "prefers", "coffee")).unwrap();
let mut mv = fact("ns", "alice", "lives_in", "Munich");
a.supersede(&h2, &mut mv).unwrap();
a.forget(&h1).unwrap();
let bpath = da.path().join("delta.mgb");
let stats = a.bundle_since(0, bpath.to_str().unwrap()).unwrap();
assert_eq!(stats.ops, 6);
let mut b = DejaDB::open(pb.to_str().unwrap()).unwrap();
let imp = b.import_bundle(bpath.to_str().unwrap()).unwrap();
assert!(imp.applied >= 4);
let head = b.latest("ns", "alice", "lives_in").unwrap().unwrap();
assert_eq!(head.get_str("object"), Some("Munich"));
assert_eq!(b.recall("ns", "alice", Some("prefers"), 16).unwrap().len(), 0); assert_eq!(b.recall("ns", "bob", None, 16).unwrap().len(), 1);
assert_eq!(
b.recall("ns", "alice", Some("lives_in"), 16).unwrap().len(),
1
);
let again = b.import_bundle(bpath.to_str().unwrap()).unwrap();
assert_eq!(again.applied, 0);
a.add(&fact("ns", "alice", "speaks", "German")).unwrap();
let b2 = da.path().join("delta2.mgb");
let s2 = a.bundle_since(stats.last_op_seq, b2.to_str().unwrap()).unwrap();
assert_eq!(s2.ops, 1);
b.import_bundle(b2.to_str().unwrap()).unwrap();
assert_eq!(
b.recall("ns", "alice", Some("speaks"), 16).unwrap().len(),
1
);
}