#[cfg(test)]
mod tests_any_error {
use std::error::Error;
use std::rc::Rc;
use std::thread;
use bt_any_error::any_err::{AnyErr, IntoAnyErr};
#[derive(Debug)]
struct LocalError(Rc<String>);
impl std::fmt::Display for LocalError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Local thread-bound error: {}", self.0)
}
}
impl Error for LocalError {}
#[test]
fn test_convert_plain_box_error() {
let legacy_result: Result<(), Box<dyn Error>> =
Err(Box::new(LocalError(Rc::new("Danger!".to_string()))));
let converted: Result<(), AnyErr> = legacy_result.any();
assert!(converted.is_err());
assert_eq!(
converted.unwrap_err().to_string(),
"Local thread-bound error: Danger!"
);
}
#[test]
fn test_convert_string_and_str() {
let str_result: Result<(), &str> = Err("primitive string slice error");
let converted_str = str_result.any();
assert_eq!(converted_str.unwrap_err().to_string(), "primitive string slice error");
let string_result: Result<(), String> = Err("owned string error".to_string());
let converted_string = string_result.any();
assert_eq!(converted_string.unwrap_err().to_string(), "owned string error");
}
#[test]
fn test_ok_passes_through_unmodified() {
let success_result: Result<&str, &str> = Ok("everything is fine");
let converted = success_result.any();
assert!(converted.is_ok());
assert_eq!(converted.unwrap(), "everything is fine");
}
#[test]
fn test_thread_safety_send_and_sync() {
let local_result: Result<(), Box<dyn Error>> =
Err(Box::new(LocalError(Rc::new("Rc cannot cross threads".to_string()))));
let thread_safe_result: Result<(), AnyErr> = local_result.any();
let handle = thread::spawn(move || {
assert!(thread_safe_result.is_err());
let err = thread_safe_result.unwrap_err();
assert_eq!(err.to_string(), "Local thread-bound error: Rc cannot cross threads");
});
handle.join().expect("Thread should not panic");
}
}