use nusy_arrow_core::{ArrowGraphStore, Namespace, QuerySpec, Triple, YLayer};
fn triple(subj: &str) -> Triple {
Triple {
subject: subj.to_string(),
predicate: "rdf:type".to_string(),
object: "Entity".to_string(),
graph: None,
confidence: Some(0.9),
source_document: None,
source_chunk_id: None,
extracted_by: Some("bench".to_string()),
caused_by: None,
derived_from: None,
consolidated_at: None,
certifiability_class: None,
}
}
fn build_10k_store() -> ArrowGraphStore {
let mut store = ArrowGraphStore::new();
let layers = [
(YLayer::Prose, 500),
(YLayer::Semantic, 800),
(YLayer::Reasoning, 300),
(YLayer::Experience, 400),
(YLayer::Journal, 200),
(YLayer::Procedural, 200),
(YLayer::Metacognitive, 100),
];
for ns in Namespace::ALL {
for (layer, count) in &layers {
let triples: Vec<Triple> = (0..*count)
.map(|i| triple(&format!("{}:e{}", ns.as_str(), i)))
.collect();
store.add_batch(&triples, ns, *layer).unwrap();
}
}
assert_eq!(store.len(), 2500 * Namespace::ALL.len());
store
}
fn build_350k_store() -> ArrowGraphStore {
let mut store = ArrowGraphStore::new();
let batch_size = 70_000;
for ns in Namespace::ALL {
let triples: Vec<Triple> = (0..batch_size)
.map(|i| triple(&format!("{}:e{}", ns.as_str(), i)))
.collect();
store.add_batch(&triples, ns, YLayer::Semantic).unwrap();
}
assert_eq!(store.len(), batch_size * Namespace::ALL.len());
store
}
#[test]
fn gate_h019_query_latency_10k() {
let store = build_10k_store();
for ns in Namespace::ALL {
let _ = store
.query(&QuerySpec {
namespace: Some(ns),
..Default::default()
})
.unwrap();
}
let mut max_query_ms = 0u128;
for ns in Namespace::ALL {
let start = std::time::Instant::now();
let results = store
.query(&QuerySpec {
namespace: Some(ns),
..Default::default()
})
.unwrap();
let elapsed = start.elapsed().as_millis();
let count: usize = results.iter().map(|b| b.num_rows()).sum();
assert!(count > 0, "Namespace {} should have triples", ns.as_str());
if elapsed > max_query_ms {
max_query_ms = elapsed;
}
}
eprintln!(
"H-019 @10K: max namespace query = {}ms (target: ≤2ms)",
max_query_ms
);
assert!(
max_query_ms <= 10,
"H-019 FAIL: query latency {}ms > 10ms (target ≤2ms)",
max_query_ms
);
}
#[test]
fn gate_h019_query_latency_350k() {
let store = build_350k_store();
for ns in Namespace::ALL {
let _ = store
.query(&QuerySpec {
namespace: Some(ns),
..Default::default()
})
.unwrap();
}
let mut max_query_ms = 0u128;
for ns in Namespace::ALL {
let start = std::time::Instant::now();
let results = store
.query(&QuerySpec {
namespace: Some(ns),
..Default::default()
})
.unwrap();
let elapsed = start.elapsed().as_millis();
let count: usize = results.iter().map(|b| b.num_rows()).sum();
assert_eq!(count, 70_000);
if elapsed > max_query_ms {
max_query_ms = elapsed;
}
}
eprintln!(
"H-019 @350K: max namespace query = {}ms (target: ≤2ms)",
max_query_ms
);
assert!(
max_query_ms <= 50,
"H-019 FAIL @350K: query latency {}ms > 50ms (target ≤2ms)",
max_query_ms
);
}
#[test]
fn gate_hgit1_commit_checkout_10k() {
use nusy_arrow_git::{CommitsTable, GitObjectStore, checkout, create_commit};
let tmp = tempfile::tempdir().unwrap();
let mut obj = GitObjectStore::with_snapshot_dir(tmp.path());
let mut commits = CommitsTable::new();
let layers = [
(YLayer::Prose, 500),
(YLayer::Semantic, 800),
(YLayer::Reasoning, 300),
(YLayer::Experience, 400),
(YLayer::Journal, 200),
(YLayer::Procedural, 200),
(YLayer::Metacognitive, 100),
];
for ns in Namespace::ALL {
for (layer, count) in &layers {
let triples: Vec<Triple> = (0..*count)
.map(|i| triple(&format!("{}:e{}", ns.as_str(), i)))
.collect();
obj.store.add_batch(&triples, ns, *layer).unwrap();
}
}
assert_eq!(obj.store.len(), 2500 * Namespace::ALL.len());
let start = std::time::Instant::now();
let c1 = create_commit(&obj, &mut commits, vec![], "bench", "DGX").unwrap();
let commit_ms = start.elapsed().as_millis();
obj.store.clear();
let start = std::time::Instant::now();
checkout(&mut obj, &commits, &c1.commit_id).unwrap();
let checkout_ms = start.elapsed().as_millis();
assert_eq!(obj.store.len(), 2500 * Namespace::ALL.len());
let total = commit_ms + checkout_ms;
eprintln!(
"H-GIT-1: commit={}ms, checkout={}ms, total={}ms (target: <50ms)",
commit_ms, checkout_ms, total
);
assert!(
total <= 250,
"H-GIT-1 FAIL: commit+checkout {}ms > 250ms (target <50ms)",
total
);
}
#[test]
fn gate_msave_save_restore_10k() {
use nusy_arrow_git::{GitObjectStore, restore, save};
let tmp = tempfile::tempdir().unwrap();
let save_dir = tmp.path().join("save");
let mut obj = GitObjectStore::with_snapshot_dir(tmp.path().join("snap"));
let layers = [
(YLayer::Prose, 500),
(YLayer::Semantic, 800),
(YLayer::Reasoning, 300),
(YLayer::Experience, 400),
(YLayer::Journal, 200),
(YLayer::Procedural, 200),
(YLayer::Metacognitive, 100),
];
for ns in Namespace::ALL {
for (layer, count) in &layers {
let triples: Vec<Triple> = (0..*count)
.map(|i| triple(&format!("{}:e{}", ns.as_str(), i)))
.collect();
obj.store.add_batch(&triples, ns, *layer).unwrap();
}
}
let start = std::time::Instant::now();
save(&obj, &save_dir).unwrap();
let save_ms = start.elapsed().as_millis();
obj.store.clear();
let start = std::time::Instant::now();
restore(&mut obj, &save_dir).unwrap();
let restore_ms = start.elapsed().as_millis();
assert_eq!(obj.store.len(), 2500 * Namespace::ALL.len());
let total = save_ms + restore_ms;
eprintln!(
"M-SAVE: save={}ms, restore={}ms, total={}ms (target: <100ms)",
save_ms, restore_ms, total
);
assert!(
total <= 500,
"M-SAVE FAIL: save+restore {}ms > 500ms (target <100ms)",
total
);
}
#[test]
fn gate_m119_awakening_latency() {
use nusy_arrow_git::{GitObjectStore, restore, save};
let tmp = tempfile::tempdir().unwrap();
let save_dir = tmp.path().join("being-state");
let mut obj = GitObjectStore::with_snapshot_dir(tmp.path().join("snap"));
let layers = [
(YLayer::Prose, 500),
(YLayer::Semantic, 800),
(YLayer::Reasoning, 300),
(YLayer::Experience, 400),
(YLayer::Journal, 200),
(YLayer::Procedural, 200),
(YLayer::Metacognitive, 100),
];
for ns in Namespace::ALL {
for (layer, count) in &layers {
let triples: Vec<Triple> = (0..*count)
.map(|i| triple(&format!("{}:e{}", ns.as_str(), i)))
.collect();
obj.store.add_batch(&triples, ns, *layer).unwrap();
}
}
save(&obj, &save_dir).unwrap();
obj.store.clear();
let start = std::time::Instant::now();
restore(&mut obj, &save_dir).unwrap();
for ns in Namespace::ALL {
let _ = obj
.store
.query(&QuerySpec {
namespace: Some(ns),
..Default::default()
})
.unwrap();
}
let awakening_ms = start.elapsed().as_millis();
eprintln!("M-119: awakening = {}ms (target: <200ms)", awakening_ms);
assert!(
awakening_ms <= 1000,
"M-119 FAIL: awakening {}ms > 1000ms (target <200ms)",
awakening_ms
);
}