refactor: 清理未使用代码并添加未来功能标记
Some checks failed
CI / Rust Check (push) Has been cancelled
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Rust Check (push) Has been cancelled
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
style: 统一代码格式和注释风格 docs: 更新多个功能文档的完整度和状态 feat(runtime): 添加路径验证工具支持 fix(pipeline): 改进条件判断和变量解析逻辑 test(types): 为ID类型添加全面测试用例 chore: 更新依赖项和Cargo.lock文件 perf(mcp): 优化MCP协议传输和错误处理
This commit is contained in:
@@ -62,3 +62,119 @@ pub enum ZclawError {
|
||||
|
||||
/// Result type alias for ZCLAW operations
|
||||
pub type Result<T> = std::result::Result<T, ZclawError>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_not_found_display() {
|
||||
let err = ZclawError::NotFound("agent-123".to_string());
|
||||
assert_eq!(err.to_string(), "Not found: agent-123");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_permission_denied_display() {
|
||||
let err = ZclawError::PermissionDenied("unauthorized access".to_string());
|
||||
assert_eq!(err.to_string(), "Permission denied: unauthorized access");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_llm_error_display() {
|
||||
let err = ZclawError::LlmError("API rate limit".to_string());
|
||||
assert_eq!(err.to_string(), "LLM error: API rate limit");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tool_error_display() {
|
||||
let err = ZclawError::ToolError("execution failed".to_string());
|
||||
assert_eq!(err.to_string(), "Tool error: execution failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_storage_error_display() {
|
||||
let err = ZclawError::StorageError("disk full".to_string());
|
||||
assert_eq!(err.to_string(), "Storage error: disk full");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_error_display() {
|
||||
let err = ZclawError::ConfigError("missing field".to_string());
|
||||
assert_eq!(err.to_string(), "Configuration error: missing field");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_timeout_display() {
|
||||
let err = ZclawError::Timeout("30s exceeded".to_string());
|
||||
assert_eq!(err.to_string(), "Timeout: 30s exceeded");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_input_display() {
|
||||
let err = ZclawError::InvalidInput("empty string".to_string());
|
||||
assert_eq!(err.to_string(), "Invalid input: empty string");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_loop_detected_display() {
|
||||
let err = ZclawError::LoopDetected("max iterations".to_string());
|
||||
assert_eq!(err.to_string(), "Agent loop detected: max iterations");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rate_limited_display() {
|
||||
let err = ZclawError::RateLimited("100 req/min".to_string());
|
||||
assert_eq!(err.to_string(), "Rate limited: 100 req/min");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_internal_error_display() {
|
||||
let err = ZclawError::Internal("unexpected state".to_string());
|
||||
assert_eq!(err.to_string(), "Internal error: unexpected state");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_export_error_display() {
|
||||
let err = ZclawError::ExportError("PDF generation failed".to_string());
|
||||
assert_eq!(err.to_string(), "Export error: PDF generation failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mcp_error_display() {
|
||||
let err = ZclawError::McpError("connection refused".to_string());
|
||||
assert_eq!(err.to_string(), "MCP error: connection refused");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_security_error_display() {
|
||||
let err = ZclawError::SecurityError("path traversal".to_string());
|
||||
assert_eq!(err.to_string(), "Security error: path traversal");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hand_error_display() {
|
||||
let err = ZclawError::HandError("browser launch failed".to_string());
|
||||
assert_eq!(err.to_string(), "Hand error: browser launch failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialization_error_from_json() {
|
||||
let json_err = serde_json::from_str::<serde_json::Value>("invalid json");
|
||||
let zclaw_err = ZclawError::from(json_err.unwrap_err());
|
||||
assert!(matches!(zclaw_err, ZclawError::SerializationError(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_result_type_ok() {
|
||||
let result: Result<i32> = Ok(42);
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), 42);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_result_type_err() {
|
||||
let result: Result<i32> = Err(ZclawError::NotFound("test".to_string()));
|
||||
assert!(result.is_err());
|
||||
assert!(matches!(result.unwrap_err(), ZclawError::NotFound(_)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,3 +145,114 @@ impl std::fmt::Display for RunId {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_agent_id_new_creates_unique_ids() {
|
||||
let id1 = AgentId::new();
|
||||
let id2 = AgentId::new();
|
||||
assert_ne!(id1, id2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_agent_id_default() {
|
||||
let id = AgentId::default();
|
||||
assert!(!id.0.is_nil());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_agent_id_display() {
|
||||
let id = AgentId::new();
|
||||
let display = format!("{}", id);
|
||||
assert_eq!(display.len(), 36); // UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
assert!(display.contains('-'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_agent_id_from_str_valid() {
|
||||
let id = AgentId::new();
|
||||
let id_str = id.to_string();
|
||||
let parsed: AgentId = id_str.parse().unwrap();
|
||||
assert_eq!(id, parsed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_agent_id_from_str_invalid() {
|
||||
let result: Result<AgentId, _> = "invalid-uuid".parse();
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_agent_id_serialization() {
|
||||
let id = AgentId::new();
|
||||
let json = serde_json::to_string(&id).unwrap();
|
||||
let deserialized: AgentId = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(id, deserialized);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_session_id_new_creates_unique_ids() {
|
||||
let id1 = SessionId::new();
|
||||
let id2 = SessionId::new();
|
||||
assert_ne!(id1, id2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_session_id_default() {
|
||||
let id = SessionId::default();
|
||||
assert!(!id.0.is_nil());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tool_id_new() {
|
||||
let id = ToolId::new("test_tool");
|
||||
assert_eq!(id.as_str(), "test_tool");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tool_id_from_str() {
|
||||
let id: ToolId = "browser".into();
|
||||
assert_eq!(id.as_str(), "browser");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tool_id_from_string() {
|
||||
let id: ToolId = String::from("shell").into();
|
||||
assert_eq!(id.as_str(), "shell");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tool_id_display() {
|
||||
let id = ToolId::new("test");
|
||||
assert_eq!(format!("{}", id), "test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_skill_id_new() {
|
||||
let id = SkillId::new("coding");
|
||||
assert_eq!(id.as_str(), "coding");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_run_id_new_creates_unique_ids() {
|
||||
let id1 = RunId::new();
|
||||
let id2 = RunId::new();
|
||||
assert_ne!(id1, id2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_run_id_default() {
|
||||
let id = RunId::default();
|
||||
assert!(!id.0.is_nil());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_run_id_display() {
|
||||
let id = RunId::new();
|
||||
let display = format!("{}", id);
|
||||
assert_eq!(display.len(), 36);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,3 +161,189 @@ impl ImageSource {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_message_user_creation() {
|
||||
let msg = Message::user("Hello, world!");
|
||||
assert!(msg.is_user());
|
||||
assert_eq!(msg.role(), "user");
|
||||
assert!(!msg.is_assistant());
|
||||
assert!(!msg.is_tool_use());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_assistant_creation() {
|
||||
let msg = Message::assistant("Hello!");
|
||||
assert!(msg.is_assistant());
|
||||
assert_eq!(msg.role(), "assistant");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_assistant_with_thinking() {
|
||||
let msg = Message::assistant_with_thinking("Response", "My reasoning...");
|
||||
assert!(msg.is_assistant());
|
||||
|
||||
if let Message::Assistant { content, thinking } = msg {
|
||||
assert_eq!(content, "Response");
|
||||
assert_eq!(thinking, Some("My reasoning...".to_string()));
|
||||
} else {
|
||||
panic!("Expected Assistant message");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_tool_use_creation() {
|
||||
let input = serde_json::json!({"query": "test"});
|
||||
let msg = Message::tool_use("call-123", ToolId::new("search"), input.clone());
|
||||
assert!(msg.is_tool_use());
|
||||
assert_eq!(msg.role(), "tool_use");
|
||||
|
||||
if let Message::ToolUse { id, tool, input: i } = msg {
|
||||
assert_eq!(id, "call-123");
|
||||
assert_eq!(tool.as_str(), "search");
|
||||
assert_eq!(i, input);
|
||||
} else {
|
||||
panic!("Expected ToolUse message");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_tool_result_creation() {
|
||||
let output = serde_json::json!({"result": "success"});
|
||||
let msg = Message::tool_result("call-123", ToolId::new("search"), output.clone(), false);
|
||||
assert!(msg.is_tool_result());
|
||||
assert_eq!(msg.role(), "tool_result");
|
||||
|
||||
if let Message::ToolResult { tool_call_id, tool, output: o, is_error } = msg {
|
||||
assert_eq!(tool_call_id, "call-123");
|
||||
assert_eq!(tool.as_str(), "search");
|
||||
assert_eq!(o, output);
|
||||
assert!(!is_error);
|
||||
} else {
|
||||
panic!("Expected ToolResult message");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_tool_result_error() {
|
||||
let output = serde_json::json!({"error": "failed"});
|
||||
let msg = Message::tool_result("call-456", ToolId::new("exec"), output, true);
|
||||
|
||||
if let Message::ToolResult { is_error, .. } = msg {
|
||||
assert!(is_error);
|
||||
} else {
|
||||
panic!("Expected ToolResult message");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_system_creation() {
|
||||
let msg = Message::system("You are a helpful assistant.");
|
||||
assert_eq!(msg.role(), "system");
|
||||
assert!(!msg.is_user());
|
||||
assert!(!msg.is_assistant());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_serialization_user() {
|
||||
let msg = Message::user("Test message");
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
assert!(json.contains("\"role\":\"user\""));
|
||||
assert!(json.contains("\"content\":\"Test message\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_serialization_assistant() {
|
||||
let msg = Message::assistant("Response");
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
assert!(json.contains("\"role\":\"assistant\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_deserialization_user() {
|
||||
let json = r#"{"role":"user","content":"Hello"}"#;
|
||||
let msg: Message = serde_json::from_str(json).unwrap();
|
||||
assert!(msg.is_user());
|
||||
|
||||
if let Message::User { content } = msg {
|
||||
assert_eq!(content, "Hello");
|
||||
} else {
|
||||
panic!("Expected User message");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_content_block_text() {
|
||||
let block = ContentBlock::Text { text: "Hello".to_string() };
|
||||
let json = serde_json::to_string(&block).unwrap();
|
||||
assert!(json.contains("\"type\":\"text\""));
|
||||
assert!(json.contains("\"text\":\"Hello\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_content_block_thinking() {
|
||||
let block = ContentBlock::Thinking { thinking: "Reasoning...".to_string() };
|
||||
let json = serde_json::to_string(&block).unwrap();
|
||||
assert!(json.contains("\"type\":\"thinking\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_content_block_tool_use() {
|
||||
let block = ContentBlock::ToolUse {
|
||||
id: "tool-1".to_string(),
|
||||
name: "search".to_string(),
|
||||
input: serde_json::json!({"q": "test"}),
|
||||
};
|
||||
let json = serde_json::to_string(&block).unwrap();
|
||||
assert!(json.contains("\"type\":\"tool_use\""));
|
||||
assert!(json.contains("\"name\":\"search\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_content_block_tool_result() {
|
||||
let block = ContentBlock::ToolResult {
|
||||
tool_use_id: "tool-1".to_string(),
|
||||
content: "Success".to_string(),
|
||||
is_error: false,
|
||||
};
|
||||
let json = serde_json::to_string(&block).unwrap();
|
||||
assert!(json.contains("\"type\":\"tool_result\""));
|
||||
assert!(json.contains("\"is_error\":false"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_content_block_image() {
|
||||
let source = ImageSource::base64("image/png", "base64data");
|
||||
let block = ContentBlock::Image { source };
|
||||
let json = serde_json::to_string(&block).unwrap();
|
||||
assert!(json.contains("\"type\":\"image\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_image_source_base64() {
|
||||
let source = ImageSource::base64("image/png", "abc123");
|
||||
assert_eq!(source.source_type, "base64");
|
||||
assert_eq!(source.media_type, "image/png");
|
||||
assert_eq!(source.data, "abc123");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_image_source_url() {
|
||||
let source = ImageSource::url("https://example.com/image.png");
|
||||
assert_eq!(source.source_type, "url");
|
||||
assert_eq!(source.media_type, "image/*");
|
||||
assert_eq!(source.data, "https://example.com/image.png");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_image_source_serialization() {
|
||||
let source = ImageSource::base64("image/jpeg", "data123");
|
||||
let json = serde_json::to_string(&source).unwrap();
|
||||
assert!(json.contains("\"type\":\"base64\""));
|
||||
assert!(json.contains("\"media_type\":\"image/jpeg\""));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user