use atheneum::graph::{AtheneumGraph, EdgeType};
use serde_json::json;
fn make_chain_graph() -> anyhow::Result<(AtheneumGraph, i64, i64, i64)> {
let g = AtheneumGraph::open_in_memory()?;
let agent = g.insert_agent("claude1", json!({}))?;
let discovery = g.store_discovery(
"claude1",
"Symbol",
"build_router",
json!({"file":"src/http.rs","summary":"builds axum router"}),
)?;
let event = g.insert_event(
"discovery-stored",
json!({"agent":"claude1","discovery_id":discovery}),
)?;
g.insert_edge(event, discovery, EdgeType::Created, json!({}))?;
g.insert_edge(event, agent, EdgeType::PerformedBy, json!({}))?;
Ok((g, agent, discovery, event))
}
#[test]
fn test_get_entity() {
let (g, _agent, discovery, _event) = make_chain_graph().expect("setup");
let e = g.get_entity(discovery).expect("get_entity");
assert_eq!(e.kind, "Discovery");
assert_eq!(e.name, "claude1: build_router");
}
#[test]
fn test_get_edge() {
let g = AtheneumGraph::open_in_memory().expect("open");
let a = g.insert_agent("a", json!({})).expect("insert");
let b = g.insert_agent("b", json!({})).expect("insert");
let eid = g
.insert_edge(a, b, EdgeType::RelatedTo, json!({}))
.expect("edge");
let edge = g.get_edge(eid).expect("get_edge");
assert_eq!(edge.from_id, a);
assert_eq!(edge.to_id, b);
assert_eq!(edge.edge_type, "related_to");
}
#[test]
fn test_get_neighbors_returns_outgoing_and_incoming() {
let (g, _agent, discovery, _event) = make_chain_graph().expect("setup");
let (outgoing, incoming) = g.get_neighbors(discovery).expect("get_neighbors");
assert_eq!(incoming.len(), 1, "discovery should have 1 incoming edge");
assert_eq!(incoming[0].edge_type, "created");
assert_eq!(outgoing.len(), 0, "discovery should have 0 outgoing edges");
}
#[test]
fn test_get_neighbors_for_event() {
let (g, _agent, _discovery, event) = make_chain_graph().expect("setup");
let (outgoing, incoming) = g.get_neighbors(event).expect("get_neighbors");
assert_eq!(outgoing.len(), 2, "event should have 2 outgoing edges");
let types: Vec<&str> = outgoing.iter().map(|e| e.edge_type.as_str()).collect();
assert!(types.contains(&"created"));
assert!(types.contains(&"performed_by"));
assert_eq!(incoming.len(), 0);
}
#[test]
fn test_get_subgraph_depth_0() {
let (g, _agent, discovery, _event) = make_chain_graph().expect("setup");
let sg = g.get_subgraph(discovery, 0).expect("get_subgraph");
assert_eq!(sg.entry.id, discovery);
assert_eq!(sg.depth, 0);
assert!(sg.edges.is_empty());
assert!(sg.entities.is_empty() || sg.entities.len() == 1); }
#[test]
fn test_get_subgraph_depth_1() {
let (g, agent, discovery, event) = make_chain_graph().expect("setup");
let sg = g.get_subgraph(discovery, 1).expect("get_subgraph");
let entity_ids: Vec<i64> = sg.entities.iter().map(|e| e.id).collect();
assert!(
entity_ids.contains(&event),
"depth 1 should include event (the event that created discovery)"
);
assert!(
!entity_ids.contains(&agent),
"depth 1 should NOT include agent"
);
assert!(!sg.edges.is_empty(), "subgraph should have edges");
let edge_types: Vec<&str> = sg.edges.iter().map(|e| e.edge_type.as_str()).collect();
assert!(edge_types.contains(&"created") || edge_types.contains(&"performed_by"));
}
#[test]
fn test_get_subgraph_depth_2() {
let (g, agent, discovery, _event) = make_chain_graph().expect("setup");
let sg = g.get_subgraph(discovery, 2).expect("get_subgraph");
let entity_ids: Vec<i64> = sg.entities.iter().map(|e| e.id).collect();
assert!(
entity_ids.contains(&agent),
"depth 2 should reach agent (discovery→event→agent)"
);
}
#[test]
fn test_navigate_finds_entry_points_and_walks() {
let (g, _agent, _discovery, _event) = make_chain_graph().expect("setup");
let views = g
.navigate("router construction axum", 5, 2, None)
.expect("navigate");
assert!(
!views.is_empty(),
"navigate should return at least one subgraph view"
);
let sg = &views[0];
assert!(
sg.entry.name.contains("build_router"),
"entry should be build_router: {}",
sg.entry.name
);
let names: Vec<&str> = sg.entities.iter().map(|e| e.name.as_str()).collect();
assert!(
names.iter().any(|n| n.contains("claude1: build_router")),
"subgraph should contain discovery entity"
);
}
#[test]
fn test_graph_stats_returns_counts() {
let g = AtheneumGraph::open_in_memory().expect("open");
let stats = g.graph_stats().expect("graph_stats");
assert_eq!(stats.total_entities, 0, "fresh DB has 0 entities");
assert_eq!(stats.entity_counts.len(), 0, "fresh DB has no kinds");
g.insert_agent("new_agent", json!({"status":"active"}))
.expect("insert");
let stats_after = g.graph_stats().expect("graph_stats");
let agent_count = stats_after
.entity_counts
.iter()
.find(|(k, _)| k == "Agent")
.map(|(_, c)| *c)
.unwrap_or(0);
assert_eq!(agent_count, 1, "Agent count should be 1 after insert");
assert_eq!(stats_after.total_entities, 1, "total_entities should be 1");
}
#[test]
fn test_discovery_auto_indexed() {
let g = AtheneumGraph::open_in_memory().expect("open");
g.store_discovery(
"agent",
"Symbol",
"semantic_navigation",
json!({"summary":"navigate with HNSW and graph traversals"}),
)
.expect("store_discovery");
let results = g
.lexical_search("semantic navigation HNSW traversal", 5, None)
.expect("semantic_search");
assert!(
!results.is_empty(),
"auto-indexed discovery should be searchable immediately (got 0 results)"
);
assert_eq!(
results[0].name, "agent: semantic_navigation",
"best match should be the discovery we just stored"
);
}