venus_server/
error.rs

1//! Error types for Venus server.
2
3use std::path::PathBuf;
4
5use venus_core::graph::CellId;
6
7/// Server error type.
8#[derive(Debug, thiserror::Error)]
9pub enum ServerError {
10    /// IO error.
11    #[error("IO error at {path}: {message}")]
12    Io { path: PathBuf, message: String },
13
14    /// Venus core error.
15    #[error("Core error: {0}")]
16    Core(#[from] venus_core::Error),
17
18    /// Cell not found.
19    #[error("Cell not found: {0:?}")]
20    CellNotFound(CellId),
21
22    /// Execution already in progress.
23    #[error("Execution already in progress")]
24    ExecutionInProgress,
25
26    /// WebSocket error.
27    #[error("WebSocket error: {0}")]
28    WebSocket(String),
29
30    /// JSON serialization error.
31    #[error("JSON error: {0}")]
32    Json(#[from] serde_json::Error),
33
34    /// Watch error.
35    #[error("File watch error: {0}")]
36    Watch(String),
37
38    /// Execution was aborted by user request.
39    #[error("Execution aborted")]
40    ExecutionAborted,
41
42    /// Execution timed out.
43    #[error("Execution timed out")]
44    ExecutionTimeout,
45
46    /// Invalid operation.
47    #[error("Invalid operation: {0}")]
48    InvalidOperation(String),
49}
50
51impl From<std::io::Error> for ServerError {
52    fn from(e: std::io::Error) -> Self {
53        Self::Io {
54            path: PathBuf::new(),
55            message: e.to_string(),
56        }
57    }
58}
59
60/// Result type for server operations.
61pub type ServerResult<T> = Result<T, ServerError>;
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn test_error_display() {
69        let err = ServerError::CellNotFound(CellId::new(42));
70        assert_eq!(err.to_string(), "Cell not found: CellId(42)");
71
72        let err = ServerError::ExecutionInProgress;
73        assert_eq!(err.to_string(), "Execution already in progress");
74
75        let err = ServerError::ExecutionAborted;
76        assert_eq!(err.to_string(), "Execution aborted");
77
78        let err = ServerError::ExecutionTimeout;
79        assert_eq!(err.to_string(), "Execution timed out");
80    }
81
82    #[test]
83    fn test_io_error_conversion() {
84        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
85        let server_err: ServerError = io_err.into();
86
87        match server_err {
88            ServerError::Io { path, message } => {
89                assert_eq!(path, PathBuf::new());
90                assert!(message.contains("file not found"));
91            }
92            _ => panic!("Expected Io error"),
93        }
94    }
95
96    #[test]
97    fn test_json_error_conversion() {
98        let json_str = "{invalid json";
99        let json_err = serde_json::from_str::<serde_json::Value>(json_str).unwrap_err();
100        let server_err: ServerError = json_err.into();
101
102        assert!(matches!(server_err, ServerError::Json(_)));
103    }
104
105    #[test]
106    fn test_core_error_conversion() {
107        // Test that venus_core errors convert properly
108        let core_err = venus_core::Error::CellNotFound("test_cell".to_string());
109        let server_err: ServerError = core_err.into();
110
111        assert!(matches!(server_err, ServerError::Core(_)));
112        assert!(server_err.to_string().contains("test_cell"));
113    }
114
115    #[test]
116    fn test_custom_errors() {
117        let err = ServerError::Io {
118            path: PathBuf::from("/test/file.rs"),
119            message: "Permission denied".to_string(),
120        };
121        assert!(err.to_string().contains("/test/file.rs"));
122        assert!(err.to_string().contains("Permission denied"));
123
124        let err = ServerError::Watch("debouncer failed".to_string());
125        assert_eq!(err.to_string(), "File watch error: debouncer failed");
126
127        let err = ServerError::WebSocket("connection closed".to_string());
128        assert_eq!(err.to_string(), "WebSocket error: connection closed");
129
130        let err = ServerError::InvalidOperation("Cannot delete cell with dependencies".to_string());
131        assert!(err
132            .to_string()
133            .contains("Cannot delete cell with dependencies"));
134    }
135}