1#[derive(Debug, Clone, PartialEq, Eq)]
44pub enum SkillError {
45 InvalidConfig(String),
53
54 ProviderError(String),
63
64 ExecutionFailed(String),
72
73 NotImplemented(String),
81
82 CyclicDependency(String),
90
91 MissingDependency(String),
99}
100
101impl std::fmt::Display for SkillError {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 match self {
104 Self::InvalidConfig(msg) => write!(f, "配置错误: {}", msg),
105 Self::ProviderError(msg) => write!(f, "Provider 错误: {}", msg),
106 Self::ExecutionFailed(msg) => write!(f, "执行失败: {}", msg),
107 Self::NotImplemented(msg) => write!(f, "未实现: {}", msg),
108 Self::CyclicDependency(msg) => write!(f, "循环依赖: {}", msg),
109 Self::MissingDependency(msg) => write!(f, "依赖不存在: {}", msg),
110 }
111 }
112}
113
114impl std::error::Error for SkillError {}
115
116impl SkillError {
117 pub fn invalid_config(msg: impl Into<String>) -> Self {
125 Self::InvalidConfig(msg.into())
126 }
127
128 pub fn provider_error(msg: impl Into<String>) -> Self {
136 Self::ProviderError(msg.into())
137 }
138
139 pub fn execution_failed(msg: impl Into<String>) -> Self {
147 Self::ExecutionFailed(msg.into())
148 }
149
150 pub fn not_implemented(msg: impl Into<String>) -> Self {
158 Self::NotImplemented(msg.into())
159 }
160
161 pub fn cyclic_dependency(msg: impl Into<String>) -> Self {
169 Self::CyclicDependency(msg.into())
170 }
171
172 pub fn missing_dependency(msg: impl Into<String>) -> Self {
180 Self::MissingDependency(msg.into())
181 }
182
183 pub fn is_invalid_config(&self) -> bool {
185 matches!(self, Self::InvalidConfig(_))
186 }
187
188 pub fn is_provider_error(&self) -> bool {
190 matches!(self, Self::ProviderError(_))
191 }
192
193 pub fn is_execution_failed(&self) -> bool {
195 matches!(self, Self::ExecutionFailed(_))
196 }
197
198 pub fn is_not_implemented(&self) -> bool {
200 matches!(self, Self::NotImplemented(_))
201 }
202
203 pub fn is_cyclic_dependency(&self) -> bool {
205 matches!(self, Self::CyclicDependency(_))
206 }
207
208 pub fn is_missing_dependency(&self) -> bool {
210 matches!(self, Self::MissingDependency(_))
211 }
212
213 pub fn message(&self) -> &str {
215 match self {
216 Self::InvalidConfig(msg) => msg,
217 Self::ProviderError(msg) => msg,
218 Self::ExecutionFailed(msg) => msg,
219 Self::NotImplemented(msg) => msg,
220 Self::CyclicDependency(msg) => msg,
221 Self::MissingDependency(msg) => msg,
222 }
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 #[test]
233 fn test_invalid_config_creation() {
234 let err = SkillError::InvalidConfig("缺少 workflow 定义".to_string());
235 assert!(err.is_invalid_config());
236 assert_eq!(err.message(), "缺少 workflow 定义");
237 }
238
239 #[test]
240 fn test_provider_error_creation() {
241 let err = SkillError::ProviderError("API 请求超时".to_string());
242 assert!(err.is_provider_error());
243 assert_eq!(err.message(), "API 请求超时");
244 }
245
246 #[test]
247 fn test_execution_failed_creation() {
248 let err = SkillError::ExecutionFailed("步骤执行失败".to_string());
249 assert!(err.is_execution_failed());
250 assert_eq!(err.message(), "步骤执行失败");
251 }
252
253 #[test]
254 fn test_not_implemented_creation() {
255 let err = SkillError::NotImplemented("Agent 模式".to_string());
256 assert!(err.is_not_implemented());
257 assert_eq!(err.message(), "Agent 模式");
258 }
259
260 #[test]
261 fn test_cyclic_dependency_creation() {
262 let err = SkillError::CyclicDependency("step1 -> step2 -> step1".to_string());
263 assert!(err.is_cyclic_dependency());
264 assert_eq!(err.message(), "step1 -> step2 -> step1");
265 }
266
267 #[test]
268 fn test_missing_dependency_creation() {
269 let err = SkillError::MissingDependency("step_x".to_string());
270 assert!(err.is_missing_dependency());
271 assert_eq!(err.message(), "step_x");
272 }
273
274 #[test]
277 fn test_invalid_config_helper() {
278 let err = SkillError::invalid_config("测试消息");
279 assert!(err.is_invalid_config());
280 assert_eq!(err.message(), "测试消息");
281 }
282
283 #[test]
284 fn test_provider_error_helper() {
285 let err = SkillError::provider_error("测试消息");
286 assert!(err.is_provider_error());
287 assert_eq!(err.message(), "测试消息");
288 }
289
290 #[test]
291 fn test_execution_failed_helper() {
292 let err = SkillError::execution_failed("测试消息");
293 assert!(err.is_execution_failed());
294 assert_eq!(err.message(), "测试消息");
295 }
296
297 #[test]
298 fn test_not_implemented_helper() {
299 let err = SkillError::not_implemented("测试消息");
300 assert!(err.is_not_implemented());
301 assert_eq!(err.message(), "测试消息");
302 }
303
304 #[test]
305 fn test_cyclic_dependency_helper() {
306 let err = SkillError::cyclic_dependency("测试消息");
307 assert!(err.is_cyclic_dependency());
308 assert_eq!(err.message(), "测试消息");
309 }
310
311 #[test]
312 fn test_missing_dependency_helper() {
313 let err = SkillError::missing_dependency("测试消息");
314 assert!(err.is_missing_dependency());
315 assert_eq!(err.message(), "测试消息");
316 }
317
318 #[test]
321 fn test_display_invalid_config() {
322 let err = SkillError::InvalidConfig("缺少必需字段".to_string());
323 assert_eq!(err.to_string(), "配置错误: 缺少必需字段");
324 }
325
326 #[test]
327 fn test_display_provider_error() {
328 let err = SkillError::ProviderError("连接超时".to_string());
329 assert_eq!(err.to_string(), "Provider 错误: 连接超时");
330 }
331
332 #[test]
333 fn test_display_execution_failed() {
334 let err = SkillError::ExecutionFailed("重试耗尽".to_string());
335 assert_eq!(err.to_string(), "执行失败: 重试耗尽");
336 }
337
338 #[test]
339 fn test_display_not_implemented() {
340 let err = SkillError::NotImplemented("Agent 模式".to_string());
341 assert_eq!(err.to_string(), "未实现: Agent 模式");
342 }
343
344 #[test]
345 fn test_display_cyclic_dependency() {
346 let err = SkillError::CyclicDependency("A -> B -> A".to_string());
347 assert_eq!(err.to_string(), "循环依赖: A -> B -> A");
348 }
349
350 #[test]
351 fn test_display_missing_dependency() {
352 let err = SkillError::MissingDependency("unknown_step".to_string());
353 assert_eq!(err.to_string(), "依赖不存在: unknown_step");
354 }
355
356 #[test]
359 fn test_error_trait_implementation() {
360 let err: Box<dyn std::error::Error> =
361 Box::new(SkillError::InvalidConfig("test".to_string()));
362
363 assert!(err.to_string().contains("配置错误"));
365 }
366
367 #[test]
368 fn test_error_source_is_none() {
369 use std::error::Error;
370 let err = SkillError::InvalidConfig("test".to_string());
371 assert!(err.source().is_none());
373 }
374
375 #[test]
378 fn test_clone() {
379 let err = SkillError::InvalidConfig("test".to_string());
380 let cloned = err.clone();
381 assert_eq!(err, cloned);
382 }
383
384 #[test]
385 fn test_partial_eq() {
386 let err1 = SkillError::InvalidConfig("test".to_string());
387 let err2 = SkillError::InvalidConfig("test".to_string());
388 let err3 = SkillError::InvalidConfig("different".to_string());
389 let err4 = SkillError::ProviderError("test".to_string());
390
391 assert_eq!(err1, err2);
392 assert_ne!(err1, err3);
393 assert_ne!(err1, err4);
394 }
395
396 #[test]
399 fn test_debug_format() {
400 let err = SkillError::InvalidConfig("test message".to_string());
401 let debug_str = format!("{:?}", err);
402 assert!(debug_str.contains("InvalidConfig"));
403 assert!(debug_str.contains("test message"));
404 }
405
406 #[test]
409 fn test_is_methods_are_mutually_exclusive() {
410 let errors = vec![
411 SkillError::InvalidConfig("".to_string()),
412 SkillError::ProviderError("".to_string()),
413 SkillError::ExecutionFailed("".to_string()),
414 SkillError::NotImplemented("".to_string()),
415 SkillError::CyclicDependency("".to_string()),
416 SkillError::MissingDependency("".to_string()),
417 ];
418
419 for err in &errors {
420 let checks = [
421 err.is_invalid_config(),
422 err.is_provider_error(),
423 err.is_execution_failed(),
424 err.is_not_implemented(),
425 err.is_cyclic_dependency(),
426 err.is_missing_dependency(),
427 ];
428
429 let true_count = checks.iter().filter(|&&x| x).count();
431 assert_eq!(true_count, 1, "每个错误应该只匹配一个 is_* 方法");
432 }
433 }
434
435 #[test]
438 fn test_empty_message() {
439 let err = SkillError::InvalidConfig(String::new());
440 assert_eq!(err.message(), "");
441 assert_eq!(err.to_string(), "配置错误: ");
442 }
443
444 #[test]
447 fn test_unicode_message() {
448 let err = SkillError::InvalidConfig("配置文件格式错误 🔧".to_string());
449 assert_eq!(err.message(), "配置文件格式错误 🔧");
450 assert!(err.to_string().contains("🔧"));
451 }
452
453 #[test]
456 fn test_long_message() {
457 let long_msg = "a".repeat(10000);
458 let err = SkillError::InvalidConfig(long_msg.clone());
459 assert_eq!(err.message(), long_msg);
460 }
461}