1use crate::network::FetchError;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
11pub enum ApiError {
12 #[cfg(windows)]
14 #[error("Windows API error: {0}")]
15 WindowsApi(#[from] windows::core::Error),
16
17 #[error("Listener stopped unexpectedly")]
22 Stopped,
23}
24
25#[derive(Debug, Error)]
30pub enum MonitorError {
31 #[error("Failed to fetch addresses: {0}")]
33 Fetch(#[from] FetchError),
34
35 #[error("API listener failed: {0}")]
40 ApiListenerFailed(#[source] ApiError),
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 mod api_error {
48 use super::*;
49
50 #[test]
51 fn stopped_displays_message() {
52 let error = ApiError::Stopped;
53 assert_eq!(error.to_string(), "Listener stopped unexpectedly");
54 }
55
56 #[cfg(windows)]
57 #[test]
58 fn windows_api_error_preserves_source() {
59 use windows::core::{Error as WinError, HRESULT};
60
61 let win_error = WinError::from_hresult(HRESULT(-2_147_024_809)); let api_error: ApiError = win_error.into();
64
65 assert!(api_error.to_string().contains("Windows API error"));
67 }
68 }
69
70 mod monitor_error {
71 use super::*;
72 use std::error::Error;
73
74 #[test]
75 fn fetch_error_displays_with_context() {
76 let fetch_error = FetchError::Platform {
77 message: "test failure".to_string(),
78 };
79 let monitor_error = MonitorError::Fetch(fetch_error);
80
81 assert!(monitor_error.to_string().contains("Failed to fetch"));
82 assert!(monitor_error.to_string().contains("test failure"));
83 }
84
85 #[test]
86 fn fetch_error_preserves_source_chain() {
87 let fetch_error = FetchError::Platform {
88 message: "inner error".to_string(),
89 };
90 let monitor_error = MonitorError::Fetch(fetch_error);
91
92 let source = monitor_error.source();
93 assert!(source.is_some());
94 assert!(source.unwrap().to_string().contains("inner error"));
95 }
96
97 #[test]
98 fn api_listener_failed_displays_with_context() {
99 let api_error = ApiError::Stopped;
100 let monitor_error = MonitorError::ApiListenerFailed(api_error);
101
102 assert!(monitor_error.to_string().contains("API listener failed"));
103 }
104
105 #[test]
106 fn api_listener_failed_preserves_source() {
107 let api_error = ApiError::Stopped;
108 let monitor_error = MonitorError::ApiListenerFailed(api_error);
109
110 let source = monitor_error.source();
111 assert!(source.is_some());
112 assert!(
113 source
114 .unwrap()
115 .to_string()
116 .contains("Listener stopped unexpectedly")
117 );
118 }
119
120 #[test]
121 fn from_fetch_error_conversion() {
122 let fetch_error = FetchError::PermissionDenied {
123 context: "elevated required".to_string(),
124 };
125 let monitor_error: MonitorError = fetch_error.into();
126
127 assert!(matches!(monitor_error, MonitorError::Fetch(_)));
128 }
129 }
130}