use qubit_retry::{RetryError, RetryResult};
use std::error::Error;
use std::io;
use std::time::Duration;
#[test]
fn test_retry_error_display() {
let error = RetryError::max_attempts_exceeded(5, 3);
assert!(error.to_string().contains("Maximum attempts exceeded"));
assert!(error.to_string().contains("5"));
assert!(error.to_string().contains("3"));
}
#[test]
fn test_retry_error_from_io_error() {
let io_error = io::Error::new(io::ErrorKind::NotFound, "File not found");
let retry_error: RetryError = io_error.into();
match retry_error {
RetryError::ExecutionError { source } => {
assert!(source.to_string().contains("File not found"));
}
_ => panic!("Expected ExecutionError"),
}
}
#[test]
fn test_max_attempts_exceeded() {
let error = RetryError::max_attempts_exceeded(10, 5);
let error_msg = error.to_string();
assert!(error_msg.contains("Maximum attempts exceeded"));
assert!(error_msg.contains("10"));
assert!(error_msg.contains("5"));
}
#[test]
fn test_max_duration_exceeded() {
let duration = Duration::from_secs(10);
let max_duration = Duration::from_secs(5);
let error = RetryError::max_duration_exceeded(duration, max_duration);
let error_msg = error.to_string();
assert!(error_msg.contains("Maximum duration exceeded"));
assert!(error_msg.contains("10s"));
assert!(error_msg.contains("5s"));
}
#[test]
fn test_aborted() {
let error = RetryError::aborted("User cancelled operation");
let error_msg = error.to_string();
assert!(error_msg.contains("Operation aborted"));
assert!(error_msg.contains("User cancelled operation"));
}
#[test]
fn test_config_error() {
let error = RetryError::config_error("Maximum retry count cannot be negative");
let error_msg = error.to_string();
assert!(error_msg.contains("Configuration error"));
assert!(error_msg.contains("Maximum retry count cannot be negative"));
}
#[test]
fn test_delay_strategy_error() {
let error = RetryError::delay_strategy_error("Delay time calculation overflow");
let error_msg = error.to_string();
assert!(error_msg.contains("Delay strategy error"));
assert!(error_msg.contains("Delay time calculation overflow"));
}
#[test]
fn test_execution_error() {
let io_error = io::Error::new(io::ErrorKind::NotFound, "File not found");
let retry_error = RetryError::execution_error(io_error);
let error_msg = retry_error.to_string();
assert!(error_msg.contains("Execution error"));
assert!(error_msg.contains("File not found"));
}
#[test]
fn test_execution_error_source() {
let io_error = io::Error::new(io::ErrorKind::NotFound, "File not found");
let retry_error = RetryError::execution_error(io_error);
let source = retry_error.source();
assert!(source.is_some());
assert!(source.unwrap().to_string().contains("File not found"));
}
#[test]
fn test_non_execution_error_source() {
let error = RetryError::config_error("Configuration error");
assert!(error.source().is_none());
let error = RetryError::aborted("abort");
assert!(error.source().is_none());
let error = RetryError::other("Other error");
assert!(error.source().is_none());
}
#[test]
fn test_execution_error_box() {
let io_error = io::Error::new(io::ErrorKind::NotFound, "File not found");
let boxed_error: Box<dyn Error + Send + Sync> = Box::new(io_error);
let retry_error = RetryError::execution_error_box(boxed_error);
let error_msg = retry_error.to_string();
assert!(error_msg.contains("Execution error"));
assert!(error_msg.contains("File not found"));
}
#[test]
fn test_other_error() {
let error = RetryError::other("Unknown error type");
let error_msg = error.to_string();
assert!(error_msg.contains("Other error"));
assert!(error_msg.contains("Unknown error type"));
}
#[test]
fn test_retry_result_success() {
let result: RetryResult<String> = Ok("Operation successful".to_string());
assert!(result.is_ok());
if let Ok(value) = result {
assert_eq!(value, "Operation successful");
}
}
#[test]
fn test_retry_result_failure() {
let result: RetryResult<String> = Err(RetryError::other("Operation failed"));
assert!(result.is_err());
if let Err(error) = result {
assert!(error.to_string().contains("Operation failed"));
}
}
#[test]
fn test_from_boxed_error() {
let io_error = io::Error::new(io::ErrorKind::NotFound, "File not found");
let boxed_error: Box<dyn Error + Send + Sync> = Box::new(io_error);
let retry_error: RetryError = boxed_error.into();
match retry_error {
RetryError::ExecutionError { source } => {
assert!(source.to_string().contains("File not found"));
}
_ => panic!("Expected ExecutionError"),
}
}
#[test]
fn test_io_error_conversion_with_question_mark() {
fn io_operation() -> RetryResult<()> {
let _file = std::fs::File::open("/non-existent-path/test.txt")?;
Ok(())
}
let result = io_operation();
assert!(result.is_err());
let error = result.unwrap_err();
match error {
RetryError::ExecutionError { .. } => {
}
_ => panic!("Expected ExecutionError"),
}
}
#[test]
fn test_debug_format() {
let error = RetryError::max_attempts_exceeded(5, 3);
let debug_str = format!("{:?}", error);
assert!(debug_str.contains("MaxAttemptsExceeded"));
assert!(debug_str.contains("attempts"));
assert!(debug_str.contains("max_attempts"));
}
#[test]
fn test_all_error_display_formats() {
let error = RetryError::MaxAttemptsExceeded {
attempts: 5,
max_attempts: 3,
};
assert!(error.to_string().contains("Maximum attempts exceeded"));
let error = RetryError::MaxDurationExceeded {
duration: Duration::from_secs(10),
max_duration: Duration::from_secs(5),
};
assert!(error.to_string().contains("Maximum duration exceeded"));
let error = RetryError::Aborted {
reason: "Test abort".to_string(),
};
assert!(error.to_string().contains("Operation aborted"));
let error = RetryError::ConfigError {
message: "Test configuration error".to_string(),
};
assert!(error.to_string().contains("Configuration error"));
let error = RetryError::DelayStrategyError {
message: "Test delay strategy error".to_string(),
};
assert!(error.to_string().contains("Delay strategy error"));
let io_error = io::Error::new(io::ErrorKind::NotFound, "Test file not found");
let error = RetryError::ExecutionError {
source: Box::new(io_error),
};
assert!(error.to_string().contains("Execution error"));
let error = RetryError::Other {
message: "Test other error".to_string(),
};
assert!(error.to_string().contains("Other error"));
}
#[test]
fn test_error_chain() {
let io_error = io::Error::new(io::ErrorKind::NotFound, "Original error");
let retry_error = RetryError::execution_error(io_error);
let source = retry_error.source();
assert!(source.is_some());
let source_error = source.unwrap();
assert!(source_error.to_string().contains("Original error"));
}
#[test]
fn test_retry_result_in_practice() {
fn simulate_retry_operation(should_fail: bool) -> RetryResult<i32> {
if should_fail {
Err(RetryError::max_attempts_exceeded(3, 3))
} else {
Ok(42)
}
}
let result = simulate_retry_operation(false);
assert!(result.is_ok());
assert_eq!(result.unwrap(), 42);
let result = simulate_retry_operation(true);
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("Maximum attempts exceeded"));
}
#[test]
fn test_operation_timeout_error() {
let duration = Duration::from_secs(10);
let timeout = Duration::from_secs(5);
let error = RetryError::operation_timeout(duration, timeout);
let error_msg = error.to_string();
assert!(error_msg.contains("Operation timeout"));
assert!(error_msg.contains("10s"));
assert!(error_msg.contains("5s"));
}
#[test]
fn test_operation_timeout_enum_variant() {
let error = RetryError::OperationTimeout {
duration: Duration::from_secs(10),
timeout: Duration::from_secs(5),
};
let error_msg = error.to_string();
assert!(error_msg.contains("Operation timeout"));
assert!(error_msg.contains("10s"));
assert!(error_msg.contains("5s"));
}