/home/jgrusewski/Work/foxhunt/config/src/error.rs
Line | Count | Source |
1 | | //! Configuration error types and result handling. |
2 | | //! |
3 | | //! This module defines comprehensive error types for configuration management |
4 | | //! operations, including database errors, vault integration failures, parsing |
5 | | //! errors, and validation issues. Uses thiserror for ergonomic error handling. |
6 | | |
7 | | use thiserror::Error; |
8 | | |
9 | | /// Comprehensive error type for configuration management operations. |
10 | | /// |
11 | | /// Covers all possible error conditions that can occur during configuration |
12 | | /// loading, validation, and management operations. Each variant provides |
13 | | /// specific context about the failure to aid in debugging and error handling. |
14 | | #[derive(Error, Debug)] |
15 | | pub enum ConfigError { |
16 | | /// Database operation failed (connection, query, or transaction error) |
17 | | #[error("Database error: {0}")] |
18 | | Database(#[from] sqlx::Error), |
19 | | |
20 | | /// HashiCorp Vault integration error (authentication, secret retrieval, etc.) |
21 | | #[error("Vault error: {0}")] |
22 | | Vault(String), |
23 | | |
24 | | /// Configuration parsing error (invalid TOML, JSON, or environment variables) |
25 | | #[error("Parse error: {0}")] |
26 | | Parse(String), |
27 | | |
28 | | /// Requested configuration key or resource was not found |
29 | | #[error("Not found: {0}")] |
30 | | NotFound(String), |
31 | | |
32 | | /// Configuration validation failed (invalid values, missing required fields) |
33 | | #[error("Invalid configuration: {0}")] |
34 | | Invalid(String), |
35 | | } |
36 | | |
37 | | /// Result type alias for configuration operations. |
38 | | /// |
39 | | /// Provides a convenient Result type that uses ConfigError as the error type. |
40 | | /// Used throughout the configuration system for consistent error handling. |
41 | | pub type ConfigResult<T> = Result<T, ConfigError>; |
42 | | |
43 | | #[cfg(test)] |
44 | | mod tests { |
45 | | use super::*; |
46 | | |
47 | | #[test] |
48 | 1 | fn test_vault_error_display() { |
49 | 1 | let error = ConfigError::Vault("Connection failed".to_string()); |
50 | 1 | assert_eq!(format!("{}", error), "Vault error: Connection failed"); |
51 | 1 | } |
52 | | |
53 | | #[test] |
54 | 1 | fn test_parse_error_display() { |
55 | 1 | let error = ConfigError::Parse("Invalid JSON".to_string()); |
56 | 1 | assert_eq!(format!("{}", error), "Parse error: Invalid JSON"); |
57 | 1 | } |
58 | | |
59 | | #[test] |
60 | 1 | fn test_not_found_error_display() { |
61 | 1 | let error = ConfigError::NotFound("config_key".to_string()); |
62 | 1 | assert_eq!(format!("{}", error), "Not found: config_key"); |
63 | 1 | } |
64 | | |
65 | | #[test] |
66 | 1 | fn test_invalid_error_display() { |
67 | 1 | let error = ConfigError::Invalid("Missing required field".to_string()); |
68 | 1 | assert_eq!( |
69 | 1 | format!("{}", error), |
70 | | "Invalid configuration: Missing required field" |
71 | | ); |
72 | 1 | } |
73 | | |
74 | | #[test] |
75 | 1 | fn test_error_debug_format() { |
76 | 1 | let error = ConfigError::Vault("Test error".to_string()); |
77 | 1 | let debug_output = format!("{:?}", error); |
78 | 1 | assert!(debug_output.contains("Vault")); |
79 | 1 | assert!(debug_output.contains("Test error")); |
80 | 1 | } |
81 | | |
82 | | #[test] |
83 | 1 | fn test_config_result_ok() { |
84 | 1 | let result: ConfigResult<i32> = Ok(42); |
85 | 1 | assert!(result.is_ok()); |
86 | 1 | match result { |
87 | 1 | Ok(value) => assert_eq!(value, 42), |
88 | 0 | Err(_) => panic!("Expected Ok value"), |
89 | | } |
90 | 1 | } |
91 | | |
92 | | #[test] |
93 | 1 | fn test_config_result_err() { |
94 | 1 | let result: ConfigResult<i32> = Err(ConfigError::NotFound("test".to_string())); |
95 | 1 | assert!(result.is_err()); |
96 | 1 | } |
97 | | |
98 | | #[test] |
99 | 1 | fn test_error_type_matching() { |
100 | 1 | let error = ConfigError::Parse("syntax error".to_string()); |
101 | 1 | match error { |
102 | 1 | ConfigError::Parse(msg) => assert_eq!(msg, "syntax error"), |
103 | 0 | _ => panic!("Expected Parse error"), |
104 | | } |
105 | 1 | } |
106 | | |
107 | | #[test] |
108 | 1 | fn test_vault_error_creation() { |
109 | 1 | let error = ConfigError::Vault("Token expired".to_string()); |
110 | 1 | if let ConfigError::Vault(msg) = error { |
111 | 1 | assert_eq!(msg, "Token expired"); |
112 | | } else { |
113 | 0 | panic!("Expected Vault error"); |
114 | | } |
115 | 1 | } |
116 | | } |