use atheneum::graph::{AtheneumGraph, EntityType};
use serde_json::json;
#[test]
fn test_store_discovery_symbol() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let discovery_id = graph
.store_discovery(
"claude1",
"symbol",
"http_handler",
json!({
"file_path": "src/http.rs",
"line": 42,
"kind": "function",
"signature": "pub fn http_handler(req: Request) -> Response"
}),
)
.expect("Failed to store discovery");
assert!(discovery_id > 0, "Discovery ID should be positive");
let discovery = graph
.get_entity(discovery_id)
.expect("Failed to retrieve discovery");
assert_eq!(discovery.kind, EntityType::Discovery.as_str());
assert_eq!(discovery.name, "claude1: http_handler");
}
#[test]
fn test_store_discovery_cfg() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let discovery_id = graph
.store_discovery(
"claude2",
"cfg",
"process_request",
json!({
"file_path": "src/http.rs",
"function": "process_request",
"cyclomatic_complexity": 8,
"has_loop": true,
"branches": 4
}),
)
.expect("Failed to store discovery");
let discovery = graph
.get_entity(discovery_id)
.expect("Failed to retrieve discovery");
let data = discovery.data.as_object().expect("Data should be object");
assert_eq!(data["discovery_type"], "cfg");
assert_eq!(data["target"], "process_request");
}
#[test]
fn test_query_discoveries_by_target() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
graph
.store_discovery(
"claude1",
"symbol",
"http_handler",
json!({"file": "src/http.rs", "line": 42}),
)
.expect("Failed to store discovery A");
graph
.store_discovery(
"claude2",
"cfg",
"http_handler",
json!({"complexity": 5, "file": "src/http.rs"}),
)
.expect("Failed to store discovery B");
let discoveries = graph
.query_discoveries("http_handler")
.expect("Failed to query discoveries");
assert_eq!(discoveries.len(), 2, "Should find 2 discoveries");
let agents: Vec<_> = discoveries
.iter()
.filter_map(|d| d.data.get("agent"))
.map(|a| a.as_str())
.collect();
assert!(agents.contains(&Some("claude1")), "Should include claude1");
assert!(agents.contains(&Some("claude2")), "Should include claude2");
}
#[test]
fn test_query_discoveries_empty() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let discoveries = graph
.query_discoveries("nonexistent")
.expect("Failed to query");
assert!(
discoveries.is_empty(),
"Should return empty for unknown target"
);
}
#[test]
fn test_store_discovery_creates_provenance() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let discovery_id = graph
.store_discovery(
"hermes",
"pattern",
"clone-escape-hatch",
json!({"description": "Excessive .clone() calls"}),
)
.expect("Failed to store discovery");
let discovery = graph
.get_entity(discovery_id)
.expect("Failed to retrieve discovery");
let data = discovery.data.as_object().expect("Data should be object");
assert!(data.contains_key("agent"), "Should have agent field");
assert!(data.contains_key("timestamp"), "Should have timestamp");
assert_eq!(data["agent"], "hermes");
}
#[test]
fn test_store_discovery_stamps_stable_content_hash() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let first_id = graph
.store_discovery(
"hermes",
"pattern",
"canonical-hash",
json!({
"description": "stable hash",
"evidence": {"line": 42, "file": "src/hash.rs"}
}),
)
.expect("store first discovery");
let second_id = graph
.store_discovery(
"hermes",
"pattern",
"canonical-hash",
json!({
"evidence": {"file": "src/hash.rs", "line": 42},
"description": "stable hash"
}),
)
.expect("store second discovery");
let first = graph.get_entity(first_id).expect("first entity");
let second = graph.get_entity(second_id).expect("second entity");
let first_hash = first
.data
.get("content_hash")
.and_then(|value| value.as_str())
.expect("first content_hash");
let second_hash = second
.data
.get("content_hash")
.and_then(|value| value.as_str())
.expect("second content_hash");
assert_eq!(first_hash, second_hash, "hash should ignore JSON key order");
}
#[test]
fn test_preview_discovery_is_read_only_and_returns_matches() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
graph
.store_discovery(
"claude1",
"symbol",
"http_handler",
json!({"file": "src/http.rs", "line": 42, "project_id": "envoy"}),
)
.expect("seed discovery");
let before = graph
.entities_by_kind(EntityType::Discovery.as_str())
.expect("discovery count before")
.len();
let preview = graph
.preview_discovery(
"claude2",
"cfg",
"http_handler",
json!({"complexity": 5, "project_id": "envoy"}),
5,
0.1,
)
.expect("preview discovery");
let after = graph
.entities_by_kind(EntityType::Discovery.as_str())
.expect("discovery count after")
.len();
assert_eq!(before, after, "preview must not store a discovery");
assert_eq!(preview.proposed_name, "claude2: http_handler");
assert_eq!(preview.exact_matches.len(), 1);
assert!(
preview
.candidate_matches
.iter()
.any(|candidate| candidate.name == "claude1: http_handler"),
"preview should surface the existing discovery candidate"
);
}
#[test]
fn test_store_handoff() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let manifest = json!({
"task": "implement auth",
"files_analyzed": ["src/auth.rs", "src/user.rs"],
"discoveries": 5,
"token_budget_used": 45000,
"token_budget_remaining": 45000,
"next_steps": ["Add JWT validation", "Write tests"]
});
let handoff_id = graph
.store_handoff("claude1", "claude2", manifest)
.expect("Failed to store handoff");
assert!(handoff_id > 0, "Handoff ID should be positive");
let handoff = graph
.get_entity(handoff_id)
.expect("Failed to retrieve handoff");
assert_eq!(handoff.kind, EntityType::Handoff.as_str());
assert_eq!(handoff.name, "claude1 -> claude2");
let data = handoff.data.as_object().expect("Data should be object");
assert_eq!(data["from_agent"], "claude1");
assert_eq!(data["to_agent"], "claude2");
assert!(data.contains_key("manifest"));
}
#[test]
fn test_store_handoff_stamps_stable_content_hash() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let first_id = graph
.store_handoff(
"claude1",
"claude2",
json!({
"task": "implement auth",
"files_analyzed": ["src/auth.rs", "src/user.rs"],
"next_steps": ["write tests", "ship it"]
}),
)
.expect("store first handoff");
let second_id = graph
.store_handoff(
"claude1",
"claude2",
json!({
"next_steps": ["write tests", "ship it"],
"files_analyzed": ["src/auth.rs", "src/user.rs"],
"task": "implement auth"
}),
)
.expect("store second handoff");
let first = graph.get_entity(first_id).expect("first handoff");
let second = graph.get_entity(second_id).expect("second handoff");
let first_hash = first
.data
.get("content_hash")
.and_then(|value| value.as_str())
.expect("first content_hash");
let second_hash = second
.data
.get("content_hash")
.and_then(|value| value.as_str())
.expect("second content_hash");
assert_eq!(
first_hash, second_hash,
"hash should ignore manifest key order"
);
}
#[test]
fn test_preview_handoff_is_read_only_and_returns_existing_matches() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
graph
.store_handoff_in_project(
"claude1",
"claude2",
Some("atheneum"),
json!({
"task": "fix auth bug",
"files_analyzed": ["src/auth.rs"]
}),
)
.expect("seed handoff");
let before = graph
.entities_by_kind(EntityType::Handoff.as_str())
.expect("handoff count before")
.len();
let preview = graph
.preview_handoff(
"claude1",
"claude2",
Some("atheneum"),
json!({"task": "new followup", "token_budget_remaining": 1000}),
5,
0.9,
)
.expect("preview handoff");
let after = graph
.entities_by_kind(EntityType::Handoff.as_str())
.expect("handoff count after")
.len();
assert_eq!(before, after, "preview must not store a handoff");
assert_eq!(preview.proposed_name, "claude1 -> claude2");
assert_eq!(preview.exact_matches.len(), 1);
assert!(
preview
.candidate_matches
.iter()
.any(|candidate| candidate.name == "claude1 -> claude2"),
"preview should surface the existing handoff candidate"
);
}
#[test]
fn test_get_pending_handoff() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let manifest = json!({"task": "fix bug", "context": "analyzed"});
graph
.store_handoff("claude1", "claude2", manifest)
.expect("Failed to store handoff");
let pending = graph
.get_pending_handoff("claude2")
.expect("Failed to get pending handoff");
assert!(pending.is_some(), "Should have a pending handoff");
let handoff = pending.unwrap();
assert_eq!(handoff.data["from_agent"], "claude1");
assert_eq!(handoff.data["to_agent"], "claude2");
}
#[test]
fn test_get_pending_handoff_none() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
graph
.store_handoff("claude1", "claude3", json!({}))
.expect("Failed to store handoff");
let pending = graph
.get_pending_handoff("claude2")
.expect("Failed to get pending handoff");
assert!(
pending.is_none(),
"Should have no pending handoffs for claude2"
);
}
#[test]
fn test_get_pending_handoff_returns_most_recent() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
graph
.store_handoff("claude1", "claude2", json!({"seq": 1}))
.expect("Failed to store handoff 1");
graph
.store_handoff("hermes", "claude2", json!({"seq": 2}))
.expect("Failed to store handoff 2");
let pending = graph
.get_pending_handoff("claude2")
.expect("Failed to get pending handoff");
assert!(pending.is_some(), "Should have a pending handoff");
assert_eq!(pending.unwrap().data["manifest"]["seq"], 2);
}
#[test]
fn test_handoff_marked_claimed() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let handoff_id = graph
.store_handoff("claude1", "claude2", json!({"task": "test"}))
.expect("Failed to store handoff");
graph
.mark_handoff_claimed(handoff_id)
.expect("Failed to mark handoff");
let pending = graph
.get_pending_handoff("claude2")
.expect("Failed to get pending handoff");
assert!(pending.is_none(), "Claimed handoff should not be pending");
}
#[test]
fn test_query_knowledge_aggregates_discoveries() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
graph
.store_discovery(
"claude1",
"symbol",
"http_handler",
json!({"file": "src/http.rs", "lines": 50}),
)
.expect("Failed to store discovery 1");
graph
.store_discovery("claude2", "cfg", "http_handler", json!({"complexity": 8}))
.expect("Failed to store discovery 2");
graph
.store_discovery(
"claude3",
"issue",
"http_handler",
json!({"issue": "missing error handling"}),
)
.expect("Failed to store discovery 3");
let knowledge = graph
.query_knowledge("http_handler")
.expect("Failed to query knowledge");
assert_eq!(knowledge["target"], "http_handler");
assert_eq!(knowledge["discovery_count"], 3);
let discoveries = knowledge["discoveries"].as_array().unwrap();
assert_eq!(discoveries.len(), 3);
}
#[test]
fn test_query_knowledge_includes_handoffs() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
graph
.store_handoff(
"claude1",
"claude2",
json!({
"task": "fix http_handler",
"files_analyzed": ["src/http.rs"],
"token_budget_used": 30000
}),
)
.expect("Failed to store handoff");
let knowledge = graph
.query_knowledge("http_handler")
.expect("Failed to query knowledge");
let handoffs = knowledge["handoffs"].as_array().unwrap();
assert_eq!(handoffs.len(), 1);
assert_eq!(handoffs[0]["data"]["from_agent"], "claude1");
}
#[test]
fn test_query_knowledge_calculates_token_savings() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
graph
.store_discovery(
"claude1",
"symbol",
"large_file.rs",
json!({"file": "src/large_file.rs", "token_count": 15000}),
)
.expect("Failed to store discovery 1");
graph
.store_discovery(
"claude2",
"cfg",
"large_file.rs",
json!({"file": "src/large_file.rs", "token_count": 15000}),
)
.expect("Failed to store discovery 2");
graph
.store_discovery(
"claude3",
"issue",
"large_file.rs",
json!({"file": "src/large_file.rs", "token_count": 15000}),
)
.expect("Failed to store discovery 3");
let knowledge = graph
.query_knowledge("large_file.rs")
.expect("Failed to query knowledge");
let savings = knowledge["token_savings"].as_object().unwrap();
assert!(savings["without_sharing"].as_i64().unwrap() > 0);
assert!(savings["with_sharing"].as_i64().unwrap() > 0);
assert!(savings["saved"].as_i64().unwrap() > 0);
assert!(savings["percentage_reduction"].as_f64().unwrap() > 0.0);
}
#[test]
fn test_query_knowledge_empty_target() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
let knowledge = graph
.query_knowledge("unknown")
.expect("Failed to query knowledge");
assert_eq!(knowledge["target"], "unknown");
assert_eq!(knowledge["discovery_count"], 0);
assert!(knowledge["discoveries"].as_array().unwrap().is_empty());
}
#[test]
fn test_query_knowledge_includes_metadata() {
let graph = AtheneumGraph::open_in_memory().expect("Failed to create graph");
graph
.store_discovery(
"claude1",
"symbol",
"test_target",
json!({"file": "test.rs"}),
)
.expect("Failed to store discovery");
let knowledge = graph
.query_knowledge("test_target")
.expect("Failed to query knowledge");
let obj = knowledge.as_object().expect("Knowledge should be object");
assert!(obj.contains_key("queried_at"));
assert!(obj.contains_key("total_entities"));
}