use std::io;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum PwrzvError {
#[error("I/O error: {0}")]
IoError(#[from] io::Error),
#[error(
"Unsupported platform: {platform}. This library only supports Linux and macOS for now."
)]
UnsupportedPlatform { platform: String },
#[error("Failed to parse system data: {detail}")]
ParseError { detail: String },
#[error("Failed to access system resource: {resource}")]
ResourceAccessError { resource: String },
#[error("Calculation error: {detail}")]
CalculationError { detail: String },
#[error("Invalid value: {detail}")]
InvalidValue { detail: String },
}
impl PwrzvError {
#[allow(dead_code)]
pub(crate) fn unsupported_platform(platform: &str) -> Self {
PwrzvError::UnsupportedPlatform {
platform: platform.to_string(),
}
}
#[allow(dead_code)]
pub(crate) fn parse_error(detail: &str) -> Self {
PwrzvError::ParseError {
detail: detail.to_string(),
}
}
#[allow(dead_code)]
pub(crate) fn resource_access_error(resource: &str) -> Self {
PwrzvError::ResourceAccessError {
resource: resource.to_string(),
}
}
#[allow(dead_code)]
pub(crate) fn calculation_error(detail: &str) -> Self {
PwrzvError::CalculationError {
detail: detail.to_string(),
}
}
#[allow(dead_code)]
pub(crate) fn collection_error(detail: &str) -> Self {
PwrzvError::ResourceAccessError {
resource: detail.to_string(),
}
}
#[allow(dead_code)]
pub(crate) fn invalid_value(detail: &str) -> Self {
PwrzvError::InvalidValue {
detail: detail.to_string(),
}
}
}
pub type PwrzvResult<T> = Result<T, PwrzvError>;
#[cfg(test)]
mod tests {
use super::*;
use std::io;
#[test]
fn test_unsupported_platform_error() {
let error = PwrzvError::unsupported_platform("windows");
assert!(matches!(error, PwrzvError::UnsupportedPlatform { .. }));
let error_str = error.to_string();
assert!(error_str.contains("windows"));
assert!(error_str.contains("Unsupported platform"));
}
#[test]
fn test_parse_error() {
let error = PwrzvError::parse_error("invalid JSON format");
assert!(matches!(error, PwrzvError::ParseError { .. }));
let error_str = error.to_string();
assert!(error_str.contains("invalid JSON format"));
assert!(error_str.contains("Failed to parse"));
}
#[test]
fn test_resource_access_error() {
let error = PwrzvError::resource_access_error("/proc/meminfo");
assert!(matches!(error, PwrzvError::ResourceAccessError { .. }));
let error_str = error.to_string();
assert!(error_str.contains("/proc/meminfo"));
assert!(error_str.contains("Failed to access"));
}
#[test]
fn test_calculation_error() {
let error = PwrzvError::calculation_error("division by zero");
assert!(matches!(error, PwrzvError::CalculationError { .. }));
let error_str = error.to_string();
assert!(error_str.contains("division by zero"));
assert!(error_str.contains("Calculation error"));
}
#[test]
fn test_collection_error() {
let error = PwrzvError::collection_error("unable to read CPU stats");
assert!(matches!(error, PwrzvError::ResourceAccessError { .. }));
let error_str = error.to_string();
assert!(error_str.contains("unable to read CPU stats"));
}
#[test]
fn test_invalid_value_error() {
let error = PwrzvError::invalid_value("negative memory usage");
assert!(matches!(error, PwrzvError::InvalidValue { .. }));
let error_str = error.to_string();
assert!(error_str.contains("negative memory usage"));
assert!(error_str.contains("Invalid value"));
}
#[test]
fn test_io_error_conversion() {
let io_error = io::Error::new(io::ErrorKind::PermissionDenied, "Access denied");
let pwrzv_error: PwrzvError = io_error.into();
assert!(matches!(pwrzv_error, PwrzvError::IoError(_)));
let error_str = pwrzv_error.to_string();
assert!(error_str.contains("I/O error"));
assert!(error_str.contains("Access denied"));
}
#[test]
fn test_error_debug_format() {
let error = PwrzvError::parse_error("test error");
let debug_str = format!("{error:?}");
assert!(debug_str.contains("ParseError"));
}
#[test]
fn test_error_is_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<PwrzvError>();
assert_sync::<PwrzvError>();
}
#[test]
fn test_result_type() {
let success: PwrzvResult<i32> = Ok(42);
assert!(success.is_ok());
if let Ok(value) = success {
assert_eq!(value, 42);
}
let failure: PwrzvResult<i32> = Err(PwrzvError::parse_error("test"));
assert!(failure.is_err());
}
#[test]
fn test_error_chain() {
let io_error = io::Error::new(io::ErrorKind::NotFound, "File not found");
let pwrzv_error: PwrzvError = io_error.into();
let error_str = pwrzv_error.to_string();
assert!(error_str.contains("File not found"));
}
#[test]
fn test_error_construction_consistency() {
let detail = "test detail message";
let parse_error = PwrzvError::parse_error(detail);
let resource_error = PwrzvError::resource_access_error(detail);
let calc_error = PwrzvError::calculation_error(detail);
let invalid_error = PwrzvError::invalid_value(detail);
assert!(parse_error.to_string().contains(detail));
assert!(resource_error.to_string().contains(detail));
assert!(calc_error.to_string().contains(detail));
assert!(invalid_error.to_string().contains(detail));
}
}