mockforge_core/
error.rs

1//! Error types for MockForge Core
2
3/// Result type alias for MockForge operations
4pub type Result<T> = std::result::Result<T, Error>;
5
6/// Core error types for MockForge operations
7#[derive(Debug, thiserror::Error)]
8pub enum Error {
9    /// Validation error (schema/format validation failed)
10    #[error("Validation error: {message}")]
11    Validation {
12        /// Validation error message
13        message: String,
14    },
15
16    /// Routing error (route not found or invalid)
17    #[error("Routing error: {message}")]
18    Routing {
19        /// Routing error message
20        message: String,
21    },
22
23    /// Proxy error (proxy request failed)
24    #[error("Proxy error: {message}")]
25    Proxy {
26        /// Proxy error message
27        message: String,
28    },
29
30    /// Latency simulation error (latency injection failed)
31    #[error("Latency simulation error: {message}")]
32    Latency {
33        /// Latency error message
34        message: String,
35    },
36
37    /// Configuration error (invalid config or missing required fields)
38    #[error("Configuration error: {message}")]
39    Config {
40        /// Configuration error message
41        message: String,
42    },
43
44    /// Protocol not found (requested protocol is not registered)
45    #[error("Protocol not found: {message}")]
46    ProtocolNotFound {
47        /// Protocol not found error message
48        message: String,
49    },
50
51    /// Protocol disabled (protocol exists but is disabled)
52    #[error("Protocol disabled: {message}")]
53    ProtocolDisabled {
54        /// Protocol disabled error message
55        message: String,
56    },
57
58    /// Protocol handler in use (handler already registered)
59    #[error("Protocol handler in use: {message}")]
60    ProtocolHandlerInUse {
61        /// Protocol handler conflict error message
62        message: String,
63    },
64
65    /// Protocol validation error (protocol-specific validation failed)
66    #[error("Protocol validation error: {message}")]
67    ProtocolValidationError {
68        /// Protocol name that failed validation
69        protocol: String,
70        /// Validation error message
71        message: String,
72    },
73
74    /// I/O error (file read/write operations)
75    #[error("IO error: {0}")]
76    Io(#[from] std::io::Error),
77
78    /// JSON serialization/deserialization error
79    #[error("JSON error: {0}")]
80    Json(#[from] serde_json::Error),
81
82    /// YAML serialization/deserialization error
83    #[error("YAML error: {0}")]
84    Yaml(#[from] serde_yaml::Error),
85
86    /// HTTP client request error
87    #[error("HTTP error: {0}")]
88    Http(#[from] reqwest::Error),
89
90    /// URL parsing error
91    #[error("URL parse error: {0}")]
92    UrlParse(#[from] url::ParseError),
93
94    /// Regular expression compilation error
95    #[error("Regex error: {0}")]
96    Regex(#[from] regex::Error),
97
98    /// Generic error with message string
99    #[error("Generic error: {0}")]
100    Generic(String),
101
102    /// Encryption/decryption operation error
103    #[error("Encryption error: {0}")]
104    Encryption(#[from] crate::encryption::EncryptionError),
105
106    /// JavaScript evaluation error (template engine, etc.)
107    #[error("JavaScript error: {0}")]
108    JavaScript(#[from] rquickjs::Error),
109}
110
111impl From<String> for Error {
112    fn from(message: String) -> Self {
113        Self::Generic(message)
114    }
115}
116
117impl Error {
118    /// Create a validation error
119    pub fn validation<S: Into<String>>(message: S) -> Self {
120        Self::Validation {
121            message: message.into(),
122        }
123    }
124
125    /// Create a routing error
126    pub fn routing<S: Into<String>>(message: S) -> Self {
127        Self::Routing {
128            message: message.into(),
129        }
130    }
131
132    /// Create a proxy error
133    pub fn proxy<S: Into<String>>(message: S) -> Self {
134        Self::Proxy {
135            message: message.into(),
136        }
137    }
138
139    /// Create a latency error
140    pub fn latency<S: Into<String>>(message: S) -> Self {
141        Self::Latency {
142            message: message.into(),
143        }
144    }
145
146    /// Create a config error
147    pub fn config<S: Into<String>>(message: S) -> Self {
148        Self::Config {
149            message: message.into(),
150        }
151    }
152
153    /// Create a protocol not found error
154    pub fn protocol_not_found<S: Into<String>>(message: S) -> Self {
155        Self::ProtocolNotFound {
156            message: message.into(),
157        }
158    }
159
160    /// Create a protocol disabled error
161    pub fn protocol_disabled<S: Into<String>>(message: S) -> Self {
162        Self::ProtocolDisabled {
163            message: message.into(),
164        }
165    }
166
167    /// Create a protocol handler in use error
168    pub fn protocol_handler_in_use<S: Into<String>>(message: S) -> Self {
169        Self::ProtocolHandlerInUse {
170            message: message.into(),
171        }
172    }
173
174    /// Create a protocol validation error
175    pub fn protocol_validation_error<S: Into<String>>(protocol: S, message: S) -> Self {
176        Self::ProtocolValidationError {
177            protocol: protocol.into(),
178            message: message.into(),
179        }
180    }
181
182    /// Create a generic error
183    pub fn generic<S: Into<String>>(message: S) -> Self {
184        Self::Generic(message.into())
185    }
186}
187
188#[cfg(test)]
189mod tests {
190    use super::*;
191
192    #[test]
193    fn test_validation_error() {
194        let err = Error::validation("test validation");
195        assert!(err.to_string().contains("Validation error"));
196        assert!(err.to_string().contains("test validation"));
197    }
198
199    #[test]
200    fn test_routing_error() {
201        let err = Error::routing("test routing");
202        assert!(err.to_string().contains("Routing error"));
203        assert!(err.to_string().contains("test routing"));
204    }
205
206    #[test]
207    fn test_proxy_error() {
208        let err = Error::proxy("test proxy");
209        assert!(err.to_string().contains("Proxy error"));
210        assert!(err.to_string().contains("test proxy"));
211    }
212
213    #[test]
214    fn test_latency_error() {
215        let err = Error::latency("test latency");
216        assert!(err.to_string().contains("Latency simulation error"));
217        assert!(err.to_string().contains("test latency"));
218    }
219
220    #[test]
221    fn test_config_error() {
222        let err = Error::config("test config");
223        assert!(err.to_string().contains("Configuration error"));
224        assert!(err.to_string().contains("test config"));
225    }
226
227    #[test]
228    fn test_generic_error() {
229        let err = Error::generic("test generic");
230        assert!(err.to_string().contains("Generic error"));
231        assert!(err.to_string().contains("test generic"));
232    }
233
234    #[test]
235    fn test_from_string() {
236        let err: Error = "test message".to_string().into();
237        assert!(matches!(err, Error::Generic(_)));
238        assert!(err.to_string().contains("test message"));
239    }
240
241    #[test]
242    fn test_json_error_conversion() {
243        let json_err = serde_json::from_str::<serde_json::Value>("invalid json");
244        assert!(json_err.is_err());
245        let err: Error = json_err.unwrap_err().into();
246        assert!(matches!(err, Error::Json(_)));
247    }
248
249    #[test]
250    fn test_url_parse_error_conversion() {
251        let url_err = url::Url::parse("not a url");
252        assert!(url_err.is_err());
253        let err: Error = url_err.unwrap_err().into();
254        assert!(matches!(err, Error::UrlParse(_)));
255    }
256
257    #[test]
258    #[allow(clippy::invalid_regex)]
259    fn test_regex_error_conversion() {
260        let regex_err = regex::Regex::new("[invalid(");
261        assert!(regex_err.is_err());
262        let err: Error = regex_err.unwrap_err().into();
263        assert!(matches!(err, Error::Regex(_)));
264    }
265
266    #[test]
267    fn test_error_display() {
268        let errors = vec![
269            (Error::validation("msg"), "Validation error: msg"),
270            (Error::routing("msg"), "Routing error: msg"),
271            (Error::proxy("msg"), "Proxy error: msg"),
272            (Error::latency("msg"), "Latency simulation error: msg"),
273            (Error::config("msg"), "Configuration error: msg"),
274            (Error::generic("msg"), "Generic error: msg"),
275        ];
276
277        for (err, expected) in errors {
278            assert_eq!(err.to_string(), expected);
279        }
280    }
281}