use super::*;
use crate::define_error;
use serde_json::json;
#[test]
fn test_error_creation() {
let err = Error::new(ErrorCode::InvalidInput, "invalid_email", "Email is invalid");
assert_eq!(err.code(), ErrorCode::InvalidInput);
assert_eq!(err.error_type(), "invalid_email");
assert_eq!(err.message(), "Email is invalid");
assert!(err.data().is_none());
}
#[test]
fn test_with_data() {
let err = Error::new(ErrorCode::RateLimited, "rate_limit", "Too many requests")
.with_data(json!({"retry_after": 60}));
assert!(err.data().is_some());
assert_eq!(err.data().unwrap()["retry_after"], 60);
}
#[test]
fn test_error_internal() {
use std::io;
let io_error = io::Error::new(io::ErrorKind::NotFound, "file not found");
let err = Error::internal(io_error);
assert_eq!(err.code(), ErrorCode::Internal);
assert_eq!(err.error_type(), "internal_error");
assert_eq!(err.message(), "file not found");
assert!(err.source().is_some());
}
#[test]
fn test_typed_error() {
define_error!(ErrorCode::InvalidInput, TestError);
let err = TestError::error("Test message");
assert_eq!(err.code(), ErrorCode::InvalidInput);
assert_eq!(err.error_type(), "TestError");
assert_eq!(err.message(), "Test message");
}
#[test]
fn test_typed_with_data() {
define_error!(ErrorCode::ResourceNotFound, TestErrorWithData);
let err = TestErrorWithData::error_with_data("Not found", json!({"id": 123}));
assert_eq!(err.code(), ErrorCode::ResourceNotFound);
assert_eq!(err.error_type(), "TestErrorWithData");
assert_eq!(err.message(), "Not found");
assert!(err.data().is_some());
assert_eq!(err.data().unwrap()["id"], 123);
}
#[test]
fn test_error_code_display() {
assert_eq!(ErrorCode::InvalidInput.to_string(), "InvalidInput");
assert_eq!(ErrorCode::Unauthorized.to_string(), "Unauthorized");
assert_eq!(ErrorCode::ResourceNotFound.to_string(), "ResourceNotFound");
}
#[test]
fn test_error_display() {
let err = Error::new(ErrorCode::InvalidInput, "invalid_email", "Email is invalid");
let display = format!("{}", err);
assert!(display.contains("invalid_email"));
assert!(display.contains("InvalidInput"));
assert!(display.contains("Email is invalid"));
}
#[test]
fn test_error_serialization() {
let err = Error::new(ErrorCode::InvalidInput, "invalid_email", "Email is invalid")
.with_data(json!({"field": "email"}));
let serialized = serde_json::to_string(&err).unwrap();
let value: serde_json::Value = serde_json::from_str(&serialized).unwrap();
assert_eq!(value["type"], "invalid_email");
assert_eq!(value["message"], "Email is invalid");
assert_eq!(value["data"]["field"], "email");
}
#[test]
fn test_error_internal_conversion() {
use std::io;
fn returns_io_error() -> std::io::Result<String> {
Err(io::Error::new(io::ErrorKind::NotFound, "file not found"))
}
fn uses_lxy_result() -> Result<String> {
let content = returns_io_error().map_err(Error::internal)?;
Ok(content)
}
let result = uses_lxy_result();
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.code(), ErrorCode::Internal);
assert_eq!(err.error_type(), "internal_error");
}
#[cfg(debug_assertions)]
#[test]
fn test_backtrace_captured() {
let err = Error::new(ErrorCode::Internal, "test_error", "Error with backtrace");
assert!(err.backtrace().is_some());
}
#[test]
fn test_define_errors_macro() {
use crate::define_errors;
define_errors! {
ErrorCode::ResourceNotFound => [
TestUserNotFound,
TestProjectNotFound,
],
ErrorCode::InvalidInput => [
TestInvalidEmail,
],
}
let err: Error = TestUserNotFound.into();
assert_eq!(err.code(), ErrorCode::ResourceNotFound);
assert_eq!(err.error_type(), "TestUserNotFound");
let err: Error = TestProjectNotFound.into();
assert_eq!(err.code(), ErrorCode::ResourceNotFound);
assert_eq!(err.error_type(), "TestProjectNotFound");
let err: Error = TestInvalidEmail.into();
assert_eq!(err.code(), ErrorCode::InvalidInput);
assert_eq!(err.error_type(), "TestInvalidEmail");
}
#[test]
fn test_define_errors_with_message() {
use crate::define_errors;
define_errors! {
ErrorCode::ResourceNotFound => [
TestUser2NotFound,
],
}
let err = TestUser2NotFound::error("User 123 not found");
assert_eq!(err.code(), ErrorCode::ResourceNotFound);
assert_eq!(err.error_type(), "TestUser2NotFound");
assert_eq!(err.message(), "User 123 not found");
}
#[test]
fn test_define_errors_with_data() {
use crate::define_errors;
define_errors! {
ErrorCode::RateLimited => [
TestRateLimit,
],
}
let err = TestRateLimit::error_with_data("Too many requests", json!({"retry_after": 60}));
assert_eq!(err.code(), ErrorCode::RateLimited);
assert_eq!(err.error_type(), "TestRateLimit");
assert!(err.data().is_some());
assert_eq!(err.data().unwrap()["retry_after"], 60);
}
#[test]
fn test_define_error_with_from() {
use crate::define_error;
define_error!(ErrorCode::InvalidInput, TestCustomError);
let err: Error = TestCustomError.into();
assert_eq!(err.code(), ErrorCode::InvalidInput);
assert_eq!(err.error_type(), "TestCustomError");
}
#[test]
fn test_with_source() {
use std::io;
let io_error = io::Error::new(io::ErrorKind::NotFound, "file not found");
let err = Error::new(
ErrorCode::Internal,
"config_load_failed",
"Failed to load config",
)
.with_source(io_error);
assert_eq!(err.code(), ErrorCode::Internal);
assert_eq!(err.error_type(), "config_load_failed");
assert_eq!(err.message(), "Failed to load config");
assert!(err.source().is_some());
let source = err.source().unwrap();
assert_eq!(source.to_string(), "file not found");
}
#[test]
fn test_typed_with_source() {
use crate::define_error;
use std::io;
define_error!(ErrorCode::Internal, ConfigLoadFailed);
let io_error = io::Error::new(io::ErrorKind::PermissionDenied, "permission denied");
let err = ConfigLoadFailed::error_with_source("Failed to load configuration", io_error);
assert_eq!(err.code(), ErrorCode::Internal);
assert_eq!(err.error_type(), "ConfigLoadFailed");
assert_eq!(err.message(), "Failed to load configuration");
assert!(err.source().is_some());
let source = err.source().unwrap();
assert_eq!(source.to_string(), "permission denied");
}
#[test]
fn test_error_chain() {
use std::io;
let io_error = io::Error::new(io::ErrorKind::NotFound, "file.txt not found");
let mid_error = Error::new(
ErrorCode::Internal,
"file_read_failed",
"Failed to read file",
)
.with_source(io_error);
assert!(mid_error.source().is_some());
let source = mid_error.source().unwrap();
assert_eq!(source.to_string(), "file.txt not found");
}
#[test]
fn test_std_error_source() {
use std::error::Error as StdError;
use std::io;
let io_error = io::Error::new(io::ErrorKind::NotFound, "config.toml");
let err = Error::internal(io_error);
let source = StdError::source(&err);
assert!(source.is_some());
assert_eq!(source.unwrap().to_string(), "config.toml");
}