use thiserror::Error;
#[derive(Error, Debug)]
pub enum CoreError {
#[error("Configuration error: {0}")]
Config(String),
#[error("Path resolution failed: {0}")]
PathResolution(String),
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
}
impl From<CoreError> for String {
fn from(err: CoreError) -> Self {
err.to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_core_error_config_display() {
let err = CoreError::Config("invalid setting".to_string());
let msg = err.to_string();
assert!(msg.contains("Configuration error"), "Display should contain variant label");
assert!(msg.contains("invalid setting"), "Display should contain the inner message");
}
#[test]
fn test_core_error_path_resolution_display() {
let err = CoreError::PathResolution("home dir unavailable".to_string());
let msg = err.to_string();
assert!(msg.contains("Path resolution failed"), "Display should contain variant label");
assert!(msg.contains("home dir unavailable"), "Display should contain the inner message");
}
#[test]
fn test_core_error_io_display() {
let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
let err = CoreError::Io(io_err);
let msg = err.to_string();
assert!(msg.contains("I/O error"), "Display should contain variant label");
assert!(msg.contains("access denied"), "Display should contain the inner io message");
}
#[test]
fn test_core_error_into_string() {
let err = CoreError::Config("bad config".to_string());
let s: String = err.into();
assert!(s.contains("Configuration error"));
assert!(s.contains("bad config"));
}
#[test]
fn test_core_error_from_io_error() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let core_err: CoreError = io_err.into();
match core_err {
CoreError::Io(_) => {} other => panic!("Expected Io variant, got {:?}", other),
}
}
#[test]
fn test_core_error_debug_format() {
let err = CoreError::Config("test".to_string());
let debug_str = format!("{:?}", err);
assert!(debug_str.contains("Config"));
}
}