Skip to main content

crates_docs/cli/
test_cmd.rs

1//! Test command implementation
2
3use rust_mcp_sdk::schema::ContentBlock;
4use std::sync::Arc;
5
6/// Test tool command
7#[allow(clippy::too_many_arguments)]
8pub async fn run_test_command(
9    tool: &str,
10    crate_name: Option<&str>,
11    item_path: Option<&str>,
12    query: Option<&str>,
13    sort: Option<&str>,
14    version: Option<&str>,
15    limit: u32,
16    format: &str,
17) -> Result<(), Box<dyn std::error::Error>> {
18    tracing::info!("Testing tool: {}", tool);
19
20    // Create cache
21    let cache_config = crate::cache::CacheConfig {
22        cache_type: "memory".to_string(),
23        memory_size: Some(1000),
24        default_ttl: Some(3600),
25        redis_url: None,
26        key_prefix: String::new(),
27    };
28
29    let cache = crate::cache::create_cache(&cache_config)?;
30    let cache_arc: Arc<dyn crate::cache::Cache> = Arc::from(cache);
31
32    // Create document service
33    let doc_service = Arc::new(crate::tools::docs::DocService::new(cache_arc));
34
35    // Create tool registry
36    let registry = crate::tools::create_default_registry(&doc_service);
37
38    match tool {
39        "lookup_crate" => {
40            execute_lookup_crate(crate_name, version, format, &registry).await?;
41        }
42        "search_crates" => {
43            execute_search_crates(query, sort, limit, format, &registry).await?;
44        }
45        "lookup_item" => {
46            execute_lookup_item(crate_name, item_path, version, format, &registry).await?;
47        }
48        "health_check" => {
49            execute_health_check(&registry).await?;
50        }
51        _ => {
52            return Err(format!("Unknown tool: {tool}").into());
53        }
54    }
55
56    println!("Tool test completed");
57    Ok(())
58}
59
60/// Execute `lookup_crate` tool
61async fn execute_lookup_crate(
62    crate_name: Option<&str>,
63    version: Option<&str>,
64    format: &str,
65    registry: &crate::tools::ToolRegistry,
66) -> Result<(), Box<dyn std::error::Error>> {
67    if let Some(name) = crate_name {
68        println!("Testing crate lookup: {name} (version: {version:?})");
69        println!("Output format: {format}");
70
71        // Prepare arguments
72        let mut arguments = serde_json::json!({
73            "crate_name": name,
74            "format": format
75        });
76
77        if let Some(v) = version {
78            arguments["version"] = serde_json::Value::String(v.to_string());
79        }
80
81        // Execute tool
82        match registry.execute_tool("lookup_crate", arguments).await {
83            Ok(result) => print_tool_result(&result),
84            Err(e) => eprintln!("Tool execution failed: {e}"),
85        }
86    } else {
87        return Err("lookup_crate requires --crate-name parameter".into());
88    }
89    Ok(())
90}
91
92/// Execute `search_crates` tool
93async fn execute_search_crates(
94    query: Option<&str>,
95    sort: Option<&str>,
96    limit: u32,
97    format: &str,
98    registry: &crate::tools::ToolRegistry,
99) -> Result<(), Box<dyn std::error::Error>> {
100    if let Some(q) = query {
101        println!("Testing crate search: {q} (limit: {limit})");
102        println!("Sort order: {}", sort.unwrap_or("relevance"));
103        println!("Output format: {format}");
104
105        // Prepare arguments
106        let mut arguments = serde_json::json!({
107            "query": q,
108            "limit": limit,
109            "format": format
110        });
111
112        if let Some(sort) = sort {
113            arguments["sort"] = serde_json::Value::String(sort.to_string());
114        }
115
116        // Execute tool
117        match registry.execute_tool("search_crates", arguments).await {
118            Ok(result) => print_tool_result(&result),
119            Err(e) => eprintln!("Tool execution failed: {e}"),
120        }
121    } else {
122        return Err("search_crates requires --query parameter".into());
123    }
124    Ok(())
125}
126
127/// Execute `lookup_item` tool
128async fn execute_lookup_item(
129    crate_name: Option<&str>,
130    item_path: Option<&str>,
131    version: Option<&str>,
132    format: &str,
133    registry: &crate::tools::ToolRegistry,
134) -> Result<(), Box<dyn std::error::Error>> {
135    if let (Some(name), Some(path)) = (crate_name, item_path) {
136        println!("Testing item lookup: {name}::{path} (version: {version:?})");
137        println!("Output format: {format}");
138
139        // Prepare arguments
140        let mut arguments = serde_json::json!({
141            "crate_name": name,
142            "itemPath": path,
143            "format": format
144        });
145
146        if let Some(v) = version {
147            arguments["version"] = serde_json::Value::String(v.to_string());
148        }
149
150        // Execute tool
151        match registry.execute_tool("lookup_item", arguments).await {
152            Ok(result) => print_tool_result(&result),
153            Err(e) => eprintln!("Tool execution failed: {e}"),
154        }
155    } else {
156        return Err("lookup_item requires --crate-name and --item-path parameters".into());
157    }
158    Ok(())
159}
160
161/// Execute `health_check` tool
162async fn execute_health_check(
163    registry: &crate::tools::ToolRegistry,
164) -> Result<(), Box<dyn std::error::Error>> {
165    println!("Testing health check");
166
167    // Prepare arguments
168    let arguments = serde_json::json!({
169        "check_type": "all",
170        "verbose": true
171    });
172
173    // Execute tool
174    match registry.execute_tool("health_check", arguments).await {
175        Ok(result) => print_tool_result(&result),
176        Err(e) => eprintln!("Tool execution failed: {e}"),
177    }
178    Ok(())
179}
180
181/// Print tool execution result
182fn print_tool_result(result: &rust_mcp_sdk::schema::CallToolResult) {
183    println!("Tool executed successfully:");
184    if let Some(content) = result.content.first() {
185        match content {
186            ContentBlock::TextContent(text_content) => {
187                println!("{}", text_content.text);
188            }
189            other => {
190                println!("Non-text content: {other:?}");
191            }
192        }
193    }
194}