Coverage Report

Created: 2025-10-06 12:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}