use crate::network::FetchError;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ApiError {
#[cfg(windows)]
#[error("Windows API error: {0}")]
WindowsApi(#[from] windows::core::Error),
#[error("Listener stopped unexpectedly")]
Stopped,
}
#[derive(Debug, Error)]
pub enum MonitorError {
#[error("Failed to fetch addresses: {0}")]
Fetch(#[from] FetchError),
#[error("API listener failed: {0}")]
ApiListenerFailed(#[source] ApiError),
}
#[cfg(test)]
mod tests {
use super::*;
mod api_error {
use super::*;
#[test]
fn stopped_displays_message() {
let error = ApiError::Stopped;
assert_eq!(error.to_string(), "Listener stopped unexpectedly");
}
#[cfg(windows)]
#[test]
fn windows_api_error_preserves_source() {
use windows::core::{Error as WinError, HRESULT};
let win_error = WinError::from_hresult(HRESULT(-2_147_024_809)); let api_error: ApiError = win_error.into();
assert!(api_error.to_string().contains("Windows API error"));
}
}
mod monitor_error {
use super::*;
use std::error::Error;
#[test]
fn fetch_error_displays_with_context() {
let fetch_error = FetchError::Platform {
message: "test failure".to_string(),
};
let monitor_error = MonitorError::Fetch(fetch_error);
assert!(monitor_error.to_string().contains("Failed to fetch"));
assert!(monitor_error.to_string().contains("test failure"));
}
#[test]
fn fetch_error_preserves_source_chain() {
let fetch_error = FetchError::Platform {
message: "inner error".to_string(),
};
let monitor_error = MonitorError::Fetch(fetch_error);
let source = monitor_error.source();
assert!(source.is_some());
assert!(source.unwrap().to_string().contains("inner error"));
}
#[test]
fn api_listener_failed_displays_with_context() {
let api_error = ApiError::Stopped;
let monitor_error = MonitorError::ApiListenerFailed(api_error);
assert!(monitor_error.to_string().contains("API listener failed"));
}
#[test]
fn api_listener_failed_preserves_source() {
let api_error = ApiError::Stopped;
let monitor_error = MonitorError::ApiListenerFailed(api_error);
let source = monitor_error.source();
assert!(source.is_some());
assert!(
source
.unwrap()
.to_string()
.contains("Listener stopped unexpectedly")
);
}
#[test]
fn from_fetch_error_conversion() {
let fetch_error = FetchError::PermissionDenied {
context: "elevated required".to_string(),
};
let monitor_error: MonitorError = fetch_error.into();
assert!(matches!(monitor_error, MonitorError::Fetch(_)));
}
}
}