#![cfg(feature = "terraphim")]
use std::collections::HashMap;
use terraphim_session_analyzer::kg::{KnowledgeGraphBuilder, KnowledgeGraphSearch, QueryNode};
use terraphim_session_analyzer::models::{ToolCategory, ToolInvocation};
fn create_test_tool(tool_name: &str, command: &str) -> ToolInvocation {
ToolInvocation {
timestamp: jiff::Timestamp::now(),
tool_name: tool_name.to_string(),
tool_category: ToolCategory::PackageManager,
command_line: command.to_string(),
arguments: vec![],
flags: HashMap::new(),
exit_code: Some(0),
agent_context: None,
session_id: "test-session".to_string(),
message_id: "test-message".to_string(),
}
}
#[test]
fn test_build_knowledge_graph_from_tools() {
let tools = vec![
create_test_tool("bun", "bunx wrangler deploy"),
create_test_tool("npm", "npm install packages"),
create_test_tool("cargo", "cargo build --release"),
create_test_tool("wrangler", "npx wrangler deploy --env production"),
];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
assert!(builder.concept_map.contains_key("BUN"));
assert!(builder.concept_map.contains_key("NPM"));
assert!(builder.concept_map.contains_key("INSTALL"));
assert!(builder.concept_map.contains_key("DEPLOY"));
assert!(builder.concept_map.contains_key("CARGO"));
assert!(!builder.thesaurus.is_empty());
}
#[test]
fn test_search_bun_concept() -> anyhow::Result<()> {
let tools = vec![
create_test_tool("bun", "bunx wrangler deploy"),
create_test_tool("npm", "npm install"),
];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let query = QueryNode::Concept("BUN".to_string());
let results = search.search("bunx packages", &query)?;
assert!(!results.is_empty(), "Should find BUN concept");
assert!(
results[0].concepts_matched.contains(&"BUN".to_string()),
"Should match BUN concept"
);
Ok(())
}
#[test]
fn test_search_install_concept() -> anyhow::Result<()> {
let tools = vec![create_test_tool("npm", "npm install packages")];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let query = QueryNode::Concept("INSTALL".to_string());
let results = search.search("npm install packages", &query)?;
assert!(!results.is_empty(), "Should find INSTALL concept");
assert!(
results[0].concepts_matched.contains(&"INSTALL".to_string()),
"Should match INSTALL concept"
);
Ok(())
}
#[test]
fn test_search_bun_and_install() -> anyhow::Result<()> {
let tools = vec![
create_test_tool("bun", "bun install packages"),
create_test_tool("bun", "bunx install deps"),
];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let query = QueryNode::And(
Box::new(QueryNode::Concept("BUN".to_string())),
Box::new(QueryNode::Concept("INSTALL".to_string())),
);
let results = search.search("bun install packages", &query)?;
if !results.is_empty() {
println!("Found {} results", results.len());
for result in &results {
println!(
" - Matched: {:?}, Concepts: {:?}, Score: {}",
result.matched_text, result.concepts_matched, result.relevance_score
);
}
assert!(
!results[0].concepts_matched.is_empty(),
"Should have matched concepts"
);
}
Ok(())
}
#[test]
fn test_search_bun_or_npm() -> anyhow::Result<()> {
let tools = vec![
create_test_tool("bun", "bunx install"),
create_test_tool("npm", "npm install"),
];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let query = QueryNode::Or(
Box::new(QueryNode::Concept("BUN".to_string())),
Box::new(QueryNode::Concept("NPM".to_string())),
);
let results1 = search.search("bunx packages", &query)?;
assert!(!results1.is_empty(), "Should find BUN");
let results2 = search.search("npx packages", &query)?;
assert!(!results2.is_empty(), "Should find NPM");
Ok(())
}
#[test]
fn test_search_deploy_not_test() -> anyhow::Result<()> {
let tools = vec![
create_test_tool("wrangler", "wrangler deploy"),
create_test_tool("npm", "npm test"),
];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let query = QueryNode::And(
Box::new(QueryNode::Concept("DEPLOY".to_string())),
Box::new(QueryNode::Not(Box::new(QueryNode::Concept(
"TEST".to_string(),
)))),
);
let results = search.search("wrangler deploy --env production", &query)?;
println!("Deploy without test: {} results", results.len());
Ok(())
}
#[test]
fn test_search_with_multiple_patterns() -> anyhow::Result<()> {
let tools = vec![
create_test_tool("bun", "bunx wrangler deploy"),
create_test_tool("npm", "npx wrangler deploy"),
create_test_tool("cargo", "cargo install wrangler"),
];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let test_cases = vec![
("bunx wrangler deploy", true, "Should match bunx"),
("npx wrangler deploy", true, "Should match npx"),
("yarn wrangler deploy", true, "Should match yarn"),
("random command", false, "Should not match random"),
];
for (command, should_match, description) in test_cases {
let query = QueryNode::Concept("DEPLOY".to_string());
let results = search.search(command, &query)?;
if should_match {
assert!(!results.is_empty(), "{}: {}", description, command);
}
}
Ok(())
}
#[test]
fn test_search_complex_query() -> anyhow::Result<()> {
let tools = vec![
create_test_tool("bun", "bun install"),
create_test_tool("npm", "npm install"),
create_test_tool("cargo", "cargo build"),
];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let query = QueryNode::And(
Box::new(QueryNode::Or(
Box::new(QueryNode::Concept("BUN".to_string())),
Box::new(QueryNode::Concept("NPM".to_string())),
)),
Box::new(QueryNode::Concept("INSTALL".to_string())),
);
let results1 = search.search("bun install packages", &query)?;
println!("BUN install results: {}", results1.len());
let results2 = search.search("npm install packages", &query)?;
println!("NPM install results: {}", results2.len());
let results3 = search.search("cargo build --release", &query)?;
println!("Cargo build results: {}", results3.len());
Ok(())
}
#[test]
fn test_relevance_scoring() -> anyhow::Result<()> {
let tools = vec![
create_test_tool("bun", "bun install"),
create_test_tool("wrangler", "wrangler deploy"),
];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let query = QueryNode::Concept("DEPLOY".to_string());
let results = search.search("wrangler deploy --env production", &query)?;
if !results.is_empty() {
for result in &results {
assert!(
result.relevance_score > 0.0,
"Relevance score should be positive"
);
}
for i in 1..results.len() {
assert!(
results[i - 1].relevance_score >= results[i].relevance_score,
"Results should be sorted by relevance"
);
}
}
Ok(())
}
#[test]
fn test_concept_map_completeness() {
let tools = vec![
create_test_tool("bun", "bunx wrangler deploy"),
create_test_tool("npm", "npm install"),
];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let bun_patterns = &builder.concept_map["BUN"];
assert!(bun_patterns.contains(&"bunx".to_string()));
assert!(bun_patterns.contains(&"bun install".to_string()));
let install_patterns = &builder.concept_map["INSTALL"];
assert!(install_patterns.contains(&"install".to_string()));
assert!(install_patterns.contains(&"npm install".to_string()));
assert!(builder.concept_map.contains_key("DEPLOY"));
let deploy_patterns = &builder.concept_map["DEPLOY"];
assert!(deploy_patterns.contains(&"deploy".to_string()));
}
#[test]
fn test_search_case_insensitive() -> anyhow::Result<()> {
let tools = vec![create_test_tool("bun", "BUN INSTALL PACKAGES")];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let query = QueryNode::Concept("INSTALL".to_string());
let results = search.search("BUN INSTALL PACKAGES", &query)?;
assert!(
!results.is_empty(),
"Should match regardless of case (terraphim is case-insensitive)"
);
Ok(())
}
#[test]
fn test_empty_results_for_no_match() -> anyhow::Result<()> {
let tools = vec![create_test_tool("npm", "npm install")];
let builder = KnowledgeGraphBuilder::from_tool_invocations(&tools);
let search = KnowledgeGraphSearch::new(builder);
let query = QueryNode::Concept("DEPLOY".to_string());
let results = search.search("echo hello world", &query)?;
println!("Results for non-matching query: {}", results.len());
Ok(())
}