#[cfg(test)]
mod tests {
use crate::worker::tools::ToolBox;
use serde_json::json;
use std::path::PathBuf;
use tokio::runtime::Runtime;
fn get_test_paths() -> (PathBuf, PathBuf) {
let root = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let linux_path = root.clone();
let prompts_path = root.join("third_party/prompts/kernel");
(linux_path, prompts_path)
}
#[test]
fn test_list_dir_linux() {
let (linux_path, _prompts_path) = get_test_paths();
let toolbox = ToolBox::new(linux_path, None);
let rt = Runtime::new().unwrap();
let args = json!({ "path": "." });
let result = rt.block_on(toolbox.call("list_dir", args)).unwrap();
let entries = result["entries"].as_array().unwrap();
assert!(entries.iter().any(|e| e["name"] == "README.md"));
assert!(entries.iter().any(|e| e["name"] == "Cargo.toml"));
}
#[test]
fn test_read_files_linux_readme() {
let (linux_path, _prompts_path) = get_test_paths();
let toolbox = ToolBox::new(linux_path, None);
let rt = Runtime::new().unwrap();
let args = json!({
"files": [
{ "path": "README.md", "start_line": 1, "end_line": 5 }
]
});
let result = rt.block_on(toolbox.call("read_files", args)).unwrap();
let results = result["results"].as_array().unwrap();
assert_eq!(results.len(), 1);
let content = results[0]["content"].as_str().unwrap();
assert!(!content.is_empty());
assert!(content.contains("Sashiko"));
}
#[test]
fn test_git_log() {
let (linux_path, _prompts_path) = get_test_paths();
let toolbox = ToolBox::new(linux_path, None);
let rt = Runtime::new().unwrap();
let args = json!({ "args": ["-n", "1"] });
let result = rt.block_on(toolbox.call("git_log", args)).unwrap();
let output = result["output"].as_str().unwrap();
assert!(output.contains("commit"));
assert!(output.contains("Author:"));
}
#[test]
fn test_git_show_head() {
let (linux_path, _prompts_path) = get_test_paths();
let toolbox = ToolBox::new(linux_path, None);
let rt = Runtime::new().unwrap();
let args = json!({ "object": "HEAD" });
let result = rt.block_on(toolbox.call("git_show", args)).unwrap();
let content = result["content"].as_str().unwrap();
assert!(content.contains("commit"));
assert!(content.contains("Author:"));
}
#[test]
fn test_git_blame_readme() {
let (linux_path, _prompts_path) = get_test_paths();
let toolbox = ToolBox::new(linux_path, None);
let rt = Runtime::new().unwrap();
let args = json!({ "path": "README.md", "start_line": 1, "end_line": 3 });
let result = rt.block_on(toolbox.call("git_blame", args)).unwrap();
let content = result["content"].as_str().unwrap();
assert!(!content.is_empty());
}
#[test]
fn test_search_file_content_relative_path() {
let (linux_path, _prompts_path) = get_test_paths();
let toolbox = ToolBox::new(linux_path, None);
let rt = Runtime::new().unwrap();
let args = json!({
"pattern": "Sashiko",
"path": "."
});
let result = rt
.block_on(toolbox.call("search_file_content", args))
.unwrap();
let content = result["content"].as_str().unwrap();
assert!(!content.is_empty());
for line in content.lines() {
assert!(
!line.starts_with("/"),
"Line starts with absolute path: {}",
line
);
}
assert!(content.contains("README.md") || content.contains("./README.md"));
}
#[test]
fn test_read_prompt() {
let (linux_path, prompts_path) = get_test_paths();
let toolbox = ToolBox::new(linux_path.clone(), Some(prompts_path.clone()));
let rt = Runtime::new().unwrap();
let args = json!({ "name": "technical-patterns.md" });
if prompts_path.join("technical-patterns.md").exists() {
let result = rt
.block_on(toolbox.call("read_prompt", args.clone()))
.expect("Failed to call read_prompt");
assert!(result.get("content").is_some());
} else {
println!("Skipping read_prompt content check: technical-patterns.md not found");
}
let toolbox_disabled = ToolBox::new(linux_path, None);
let result = rt.block_on(toolbox_disabled.call("read_prompt", args));
assert!(result.is_err());
}
}