use crate::{AppPath, AppPathError};
use std::error::Error;
use std::fmt::Write;
#[test]
fn test_error_type_display() {
let exec_error =
AppPathError::ExecutableNotFound("Failed to determine executable location".to_string());
let invalid_error = AppPathError::InvalidExecutablePath(
"Library file is not a valid executable path".to_string(),
);
let mut exec_str = String::new();
write!(&mut exec_str, "{exec_error}").unwrap();
assert!(exec_str.contains("Failed to determine executable location"));
let mut invalid_str = String::new();
write!(&mut invalid_str, "{invalid_error}").unwrap();
assert!(invalid_str.contains("Invalid executable path"));
}
#[test]
fn test_error_type_debug() {
let exec_error =
AppPathError::ExecutableNotFound("Cannot access current executable".to_string());
let invalid_error =
AppPathError::InvalidExecutablePath("Dynamic library is not an executable".to_string());
let exec_debug = format!("{exec_error:?}");
let invalid_debug = format!("{invalid_error:?}");
assert!(exec_debug.contains("ExecutableNotFound"));
assert!(invalid_debug.contains("InvalidExecutablePath"));
}
#[test]
fn test_error_type_functionality() {
let exec_error =
AppPathError::ExecutableNotFound("Current executable access failed".to_string());
let invalid_error =
AppPathError::InvalidExecutablePath("Library file is not a valid executable".to_string());
match exec_error {
AppPathError::ExecutableNotFound(msg) => {
assert!(msg.contains("executable access failed"));
}
_ => panic!("Wrong error type"),
}
match invalid_error {
AppPathError::InvalidExecutablePath(msg) => {
assert!(msg.contains("not a valid executable"));
}
_ => panic!("Wrong error type"),
}
}
#[test]
fn test_error_is_std_error() {
let error =
AppPathError::ExecutableNotFound("Failed to determine executable location".to_string());
let _std_error: &dyn std::error::Error = &error;
}
#[test]
fn test_fallible_api_documentation_examples() {
match AppPath::try_with("config.toml") {
Ok(config) => {
assert!(config.ends_with("config.toml"));
}
Err(_e) => {
panic!("try_new should succeed in test environment");
}
}
fn load_config() -> Result<AppPath, AppPathError> {
let config = AppPath::try_with("config.toml")?;
Ok(config)
}
let config = load_config().unwrap();
assert!(config.ends_with("config.toml"));
fn get_config_with_fallback() -> AppPath {
AppPath::try_with("config.toml").unwrap_or_else(|_| {
let temp_config = std::env::temp_dir().join("myapp").join("config.toml");
AppPath::with(temp_config)
})
}
let config = get_config_with_fallback();
assert!(config.is_absolute());
}
#[test]
fn test_io_error_variant_from_real_operation() {
let result = std::fs::File::open("definitely_does_not_exist_12345.txt");
match result {
Err(io_error) => {
let app_error = AppPathError::from(io_error);
match app_error {
AppPathError::IoError(io_err) => {
assert!(!io_err.to_string().is_empty());
}
_ => panic!("Expected IoError variant"),
}
}
Ok(_) => panic!("Expected file not found error"),
}
}
#[test]
fn test_io_error_display_from_real_operation() {
let nonexistent_parent = std::env::temp_dir()
.join("definitely_nonexistent_parent_12345")
.join("child");
let result = std::fs::create_dir(&nonexistent_parent);
match result {
Err(io_error) => {
let app_error = AppPathError::from(io_error);
let error_str = format!("{app_error}");
assert!(error_str.contains("I/O operation failed"));
}
Ok(_) => panic!("Expected directory creation to fail"),
}
}
#[test]
fn test_io_error_debug_from_real_operation() {
let temp_dir = std::env::temp_dir().join("app_path_debug_test");
std::fs::create_dir_all(&temp_dir).unwrap();
let result = std::fs::File::open(&temp_dir);
std::fs::remove_dir_all(&temp_dir).ok();
match result {
Err(io_error) => {
let app_error = AppPathError::from(io_error);
let debug_str = format!("{app_error:?}");
assert!(debug_str.contains("IoError"));
}
Ok(_) => {
let fake_error = std::io::Error::new(std::io::ErrorKind::InvalidInput, "test");
let app_error = AppPathError::from(fake_error);
let debug_str = format!("{app_error:?}");
assert!(debug_str.contains("IoError"));
}
}
}
#[cfg(unix)]
#[test]
fn test_create_parents_permission_error() {
use std::os::unix::fs::PermissionsExt;
let temp_dir = std::env::temp_dir().join("app_path_permission_test");
std::fs::create_dir_all(&temp_dir).unwrap();
let mut perms = std::fs::metadata(&temp_dir).unwrap().permissions();
perms.set_mode(0o444); std::fs::set_permissions(&temp_dir, perms).unwrap();
let protected_file = AppPath::with(temp_dir.join("protected/file.txt"));
let result = protected_file.create_parents();
let mut perms = std::fs::metadata(&temp_dir).unwrap().permissions();
perms.set_mode(0o755); std::fs::set_permissions(&temp_dir, perms).unwrap();
std::fs::remove_dir_all(&temp_dir).ok();
match result {
Err(AppPathError::IoError(io_err)) => {
let msg = io_err.to_string();
assert!(msg.contains("Permission denied") || msg.contains("Access is denied"));
}
_ => panic!("Expected IoError for permission denied, got: {result:?}"),
}
}
#[cfg(unix)]
#[test]
fn test_create_dir_permission_error() {
use std::os::unix::fs::PermissionsExt;
let temp_dir = std::env::temp_dir().join("app_path_dir_permission_test");
std::fs::create_dir_all(&temp_dir).unwrap();
let mut perms = std::fs::metadata(&temp_dir).unwrap().permissions();
perms.set_mode(0o444); std::fs::set_permissions(&temp_dir, perms).unwrap();
let protected_dir = AppPath::with(temp_dir.join("protected"));
let result = protected_dir.create_dir();
let mut perms = std::fs::metadata(&temp_dir).unwrap().permissions();
perms.set_mode(0o755); std::fs::set_permissions(&temp_dir, perms).unwrap();
std::fs::remove_dir_all(&temp_dir).ok();
match result {
Err(AppPathError::IoError(io_err)) => {
let msg = io_err.to_string();
assert!(msg.contains("Permission denied") || msg.contains("Access is denied"));
}
_ => panic!("Expected IoError for permission denied, got: {result:?}"),
}
}
#[test]
fn test_error_variant_completeness() {
let exec_error = AppPathError::ExecutableNotFound("exec error".to_string());
let invalid_error = AppPathError::InvalidExecutablePath("invalid path".to_string());
let io_error = AppPathError::IoError(std::io::Error::other("io error"));
assert!(format!("{exec_error}").contains("Failed to determine executable location"));
assert!(format!("{invalid_error}").contains("Invalid executable path"));
assert!(format!("{io_error}").contains("I/O operation failed"));
assert!(format!("{exec_error:?}").contains("ExecutableNotFound"));
assert!(format!("{invalid_error:?}").contains("InvalidExecutablePath"));
assert!(format!("{io_error:?}").contains("IoError"));
}
#[test]
fn test_error_source_chain() {
let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
let app_error = AppPathError::from(io_err);
assert!(app_error.source().is_some());
match app_error {
AppPathError::IoError(inner) => {
assert_eq!(inner.kind(), std::io::ErrorKind::PermissionDenied);
assert!(inner.to_string().contains("access denied"));
}
_ => panic!("Expected IoError variant"),
}
}
#[test]
fn test_io_error_comprehensive_access() {
use std::io::ErrorKind;
let test_cases = [
(ErrorKind::NotFound, "file not found"),
(ErrorKind::PermissionDenied, "access denied"),
(ErrorKind::AlreadyExists, "already exists"),
(ErrorKind::InvalidInput, "invalid input"),
(ErrorKind::TimedOut, "timed out"),
];
for (kind, message) in test_cases {
let io_err = std::io::Error::new(kind, message);
let app_error = AppPathError::from(io_err);
assert!(app_error.source().is_some());
let source = app_error.source().unwrap();
assert!(source.downcast_ref::<std::io::Error>().is_some());
match app_error {
AppPathError::IoError(inner) => {
assert_eq!(inner.kind(), kind);
assert!(inner.to_string().contains(message));
}
_ => panic!("Expected IoError variant for kind: {kind:?}"),
}
}
}
#[test]
fn test_io_error_raw_os_error_access() {
let io_err = std::io::Error::from(std::io::ErrorKind::PermissionDenied);
let app_error = AppPathError::from(io_err);
match app_error {
AppPathError::IoError(inner) => {
let _os_error = inner.raw_os_error();
match inner.raw_os_error() {
Some(code) => {
assert!(code != 0); }
None => {
}
}
}
_ => panic!("Expected IoError variant"),
}
}
#[test]
fn test_io_error_path_context_preservation() {
use std::path::PathBuf;
let path = PathBuf::from("/some/test/path");
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let app_error = AppPathError::from((io_err, &path));
match app_error {
AppPathError::IoError(inner) => {
assert_eq!(inner.kind(), std::io::ErrorKind::NotFound);
let message = inner.to_string();
assert!(message.contains("file not found"));
assert!(message.contains("/some/test/path"));
}
_ => panic!("Expected IoError variant"),
}
}
#[test]
fn test_directory_creation_error_propagation() {
let temp_dir = std::env::temp_dir().join("app_path_error_propagation_test");
std::fs::create_dir_all(&temp_dir).unwrap();
let blocking_file = temp_dir.join("blocking_file");
std::fs::write(&blocking_file, "content").unwrap();
let blocked_path = AppPath::from(&blocking_file);
let result = blocked_path.create_dir();
std::fs::remove_dir_all(&temp_dir).ok();
match result {
Err(AppPathError::IoError(_)) => {
}
_ => panic!(
"Expected IoError when trying to create directory over existing file, got: {result:?}"
),
}
}
#[test]
fn test_create_parents_with_file_blocking_parent() {
let temp_dir = std::env::temp_dir().join("app_path_parent_block_test");
std::fs::create_dir_all(&temp_dir).unwrap();
let blocking_file = temp_dir.join("logs");
std::fs::write(&blocking_file, "content").unwrap();
let log_file = AppPath::with(temp_dir.join("logs/app.log"));
let result = log_file.create_parents();
std::fs::remove_dir_all(&temp_dir).ok();
match result {
Err(AppPathError::IoError(_)) => {
}
_ => panic!("Expected IoError when file blocks parent creation, got: {result:?}"),
}
}