use geez::geez;
use std::error::Error;
use std::io;
geez! {
pub enum AppError {
#[from]
Io(io::Error),
#[transparent]
Other(OtherError),
#[source]
Wrapped(io::Error),
#[error("parse failed: {0}")]
Parse(String),
Timeout => "request timed out",
NotFound,
}
}
#[derive(Debug)]
pub struct OtherError;
impl std::fmt::Display for OtherError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "other blew up")
}
}
impl Error for OtherError {}
#[test]
fn unit_default_message() {
assert_eq!(AppError::NotFound.to_string(), "NotFound");
}
#[test]
fn arrow_message() {
assert_eq!(AppError::Timeout.to_string(), "request timed out");
}
#[test]
fn error_attr_message() {
let err = AppError::Parse("nope".into());
assert_eq!(err.to_string(), "parse failed: nope");
assert!(err.source().is_none());
}
#[test]
fn from_io_and_question_mark() {
fn boom() -> Result<()> {
Err(io::Error::new(io::ErrorKind::NotFound, "missing"))?;
Ok(())
}
let err = boom().unwrap_err();
assert!(matches!(err, AppError::Io(_)));
assert_eq!(err.source().unwrap().to_string(), "missing");
}
#[test]
fn transparent_forwards_display_and_source() {
let err = AppError::from(OtherError);
assert_eq!(err.to_string(), "other blew up");
assert!(err.source().is_some());
assert_eq!(err.source().unwrap().to_string(), "other blew up");
}
#[test]
fn source_without_from() {
let inner = io::Error::new(io::ErrorKind::Other, "wrapped");
let err = AppError::Wrapped(inner);
assert_eq!(err.source().unwrap().to_string(), "wrapped");
let via_from = AppError::from(io::Error::other("via from"));
assert!(matches!(via_from, AppError::Io(_)));
}
#[test]
fn result_alias_exists() {
let ok: Result<u8> = Ok(7);
assert_eq!(ok.unwrap(), 7);
}