Skip to main content

sz_rust_cli/
error.rs

1//! CLI 错误类型
2//!
3//! 对齐 PHP `think\console\Command` 的错误处理模式:
4//! - PHP 通过返回 `false` 或抛出异常
5//! - Rust 使用 `Result<T, CliError>` 统一错误处理
6
7use thiserror::Error;
8
9/// CLI 错误
10#[derive(Debug, Error)]
11pub enum CliError {
12    /// 文件 IO 错误(创建文件、读取模板等)
13    #[error("IO error: {0}")]
14    Io(#[from] std::io::Error),
15
16    /// 文件已存在(对齐 PHP `Make::execute` 中 `already exists!` 提示)
17    #[error("File already exists: {0}")]
18    FileExists(String),
19
20    /// clap 参数解析错误(对齐 PHP `console\Input` 验证失败)
21    #[error("Clap error: {0}")]
22    Clap(String),
23
24    /// 代码生成错误(模板替换失败等)
25    #[error("Generation error: {0}")]
26    Generation(String),
27
28    /// 数据库迁移错误
29    #[error("Migration error: {0}")]
30    Migration(String),
31
32    /// 缓存清理错误
33    #[error("Cache error: {0}")]
34    Cache(String),
35
36    /// 调度器错误
37    #[error("Scheduler error: {0}")]
38    Scheduler(String),
39
40    /// 通用错误
41    #[error("{0}")]
42    Generic(String),
43}
44
45impl From<clap::Error> for CliError {
46    fn from(e: clap::Error) -> Self {
47        CliError::Clap(e.to_string())
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_io_error_display() {
57        let err = CliError::Io(std::io::Error::new(
58            std::io::ErrorKind::NotFound,
59            "file not found",
60        ));
61        assert!(err.to_string().contains("IO error"));
62        assert!(err.to_string().contains("file not found"));
63    }
64
65    #[test]
66    fn test_file_exists_error_display() {
67        let err = CliError::FileExists("/path/to/file".to_string());
68        assert!(err.to_string().contains("File already exists"));
69        assert!(err.to_string().contains("/path/to/file"));
70    }
71
72    #[test]
73    fn test_clap_error_conversion() {
74        let clap_err = clap::Error::new(clap::error::ErrorKind::InvalidValue);
75        let cli_err: CliError = clap_err.into();
76        assert!(matches!(cli_err, CliError::Clap(_)));
77    }
78
79    #[test]
80    fn test_generation_error_display() {
81        let err = CliError::Generation("template substitution failed".to_string());
82        assert!(err.to_string().contains("Generation error"));
83    }
84
85    #[test]
86    fn test_migration_error_display() {
87        let err = CliError::Migration("database connection failed".to_string());
88        assert!(err.to_string().contains("Migration error"));
89    }
90
91    #[test]
92    fn test_cache_error_display() {
93        let err = CliError::Cache("redis connection failed".to_string());
94        assert!(err.to_string().contains("Cache error"));
95    }
96
97    #[test]
98    fn test_scheduler_error_display() {
99        let err = CliError::Scheduler("cron parse failed".to_string());
100        assert!(err.to_string().contains("Scheduler error"));
101    }
102}