#[cfg(test)]
mod tests {
use super::*;
use crate::traits::*;
use crate::util::test_utils::*;
use std::io;
mod dict_error_tests {
use super::*;
#[test]
fn test_file_not_found_error() {
let loader = DictLoader::new();
let non_existent_path = std::path::Path::new("nonexistent.mdict");
let result = loader.load(non_existent_path);
assert!(result.is_err());
if let Err(error) = result {
assert!(matches!(error, DictError::FileNotFound(_)));
}
}
#[test]
fn test_invalid_format_error() {
let temp_dir = temp_dir().unwrap();
let invalid_file = temp_dir.path().join("invalid.mdict");
std::fs::write(&invalid_file, "This is not a valid dictionary").unwrap();
let loader = DictLoader::new();
let result = loader.load(&invalid_file);
if result.is_err() {
if let Err(error) = result {
assert!(matches!(error, DictError::InvalidFormat(_)));
}
}
}
#[test]
fn test_unsupported_operation_error() {
let error = DictError::UnsupportedOperation("test operation".to_string());
assert!(matches!(error, DictError::UnsupportedOperation(_)));
let error_str = error.to_string();
assert!(error_str.contains("test operation"));
assert!(error_str.contains("Unsupported operation"));
}
#[test]
fn test_io_error_handling() {
let error = DictError::IoError("I/O test error".to_string());
assert!(matches!(error, DictError::IoError(_)));
let error_str = error.to_string();
assert!(error_str.contains("I/O test error"));
assert!(error_str.contains("I/O error"));
}
#[test]
fn test_index_error_handling() {
let error = DictError::IndexError("Index test error".to_string());
assert!(matches!(error, DictError::IndexError(_)));
let error_str = error.to_string();
assert!(error_str.contains("Index test error"));
assert!(error_str.contains("Index error"));
}
#[test]
fn test_decompression_error_handling() {
let error = DictError::DecompressionError("Decompression test error".to_string());
assert!(matches!(error, DictError::DecompressionError(_)));
let error_str = error.to_string();
assert!(error_str.contains("Decompression test error"));
assert!(error_str.contains("Decompression error"));
}
#[test]
fn test_internal_error_handling() {
let error = DictError::Internal("Internal test error".to_string());
assert!(matches!(error, DictError::Internal(_)));
let error_str = error.to_string();
assert!(error_str.contains("Internal test error"));
assert!(error_str.contains("Internal error"));
}
}
mod io_error_tests {
use super::*;
use std::fs;
#[test]
fn test_permission_denied_error() {
let temp_dir = temp_dir().unwrap();
let restricted_file = temp_dir.path().join("restricted.txt");
std::fs::write(&restricted_file, "test content").unwrap();
assert!(crate::dict::utils::is_readable(&restricted_file));
}
#[test]
fn test_disk_full_simulation() {
let temp_dir = temp_dir().unwrap();
let test_file = temp_dir.path().join("test_file");
let result = std::fs::write(&test_file, "test content");
assert!(result.is_ok());
let _ = std::fs::remove_file(&test_file);
}
#[test]
fn test_concurrent_file_access_errors() {
let temp_dir = temp_dir().unwrap();
let test_file = temp_dir.path().join("concurrent_test.txt");
std::fs::write(&test_file, "initial content").unwrap();
assert!(test_file.exists());
assert!(crate::dict::utils::is_readable(&test_file));
let _ = std::fs::remove_file(&test_file);
}
}
mod format_error_tests {
use super::*;
#[test]
fn test_mdict_format_errors() {
let temp_dir = temp_dir().unwrap();
let mdict_file = temp_dir.path().join("test.mdict");
let invalid_contents = vec![
"", "InvalidHeader", "MDictInvalidVersion", "MDictVersion 1.0.0\x00\x00\x00\x00", ];
for content in invalid_contents {
std::fs::write(&mdict_file, content).unwrap();
let loader = DictLoader::new();
let result = loader.load(&mdict_file);
if result.is_err() {
if let Err(error) = result {
assert!(matches!(error, DictError::InvalidFormat(_) |
DictError::IoError(_) |
DictError::UnsupportedOperation(_)));
}
}
}
}
#[test]
fn test_stardict_format_errors() {
let temp_dir = temp_dir().unwrap();
let dict_file = temp_dir.path().join("test.dict");
let invalid_contents = vec![
"", "InvalidMagic", "StarDict's dictInvalidVersion\x00", ];
for content in invalid_contents {
std::fs::write(&dict_file, content).unwrap();
let loader = DictLoader::new();
let result = loader.load(&dict_file);
if result.is_err() {
if let Err(error) = result {
assert!(matches!(error, DictError::InvalidFormat(_) |
DictError::IoError(_)));
}
}
}
}
#[test]
fn test_zim_format_errors() {
let temp_dir = temp_dir().unwrap();
let zim_file = temp_dir.path().join("test.zim");
let invalid_contents = vec![
"", "ZIM\x00", "ZIM\x01Invalid", ];
for content in invalid_contents {
std::fs::write(&zim_file, content).unwrap();
let loader = DictLoader::new();
let result = loader.load(&zim_file);
if result.is_err() {
if let Err(error) = result {
assert!(matches!(error, DictError::InvalidFormat(_) |
DictError::IoError(_)));
}
}
}
}
}
mod edge_case_tests {
use super::*;
#[test]
fn test_empty_dictionary_handling() {
let temp_dir = temp_dir().unwrap();
let empty_dict = temp_dir.path().join("empty.mdict");
std::fs::write(&empty_dict, "").unwrap();
let loader = DictLoader::new();
let format_result = loader.detect_format(&empty_dict);
let load_result = loader.load(&empty_dict);
if load_result.is_err() {
if let Err(error) = load_result {
assert!(matches!(error, DictError::InvalidFormat(_) |
DictError::IoError(_)));
}
}
}
#[test]
fn test_extremely_long_keys() {
let temp_dir = temp_dir().unwrap();
let long_key_dict = temp_dir.path().join("long_key.mdict");
let long_key = "a".repeat(4096); let content = "This is content for a very long key";
std::fs::write(&long_key_dict, format!("{}\n{}", long_key, content)).unwrap();
assert!(long_key_dict.exists());
}
#[test]
fn test_very_large_entries() {
let temp_dir = temp_dir().unwrap();
let large_entry_dict = temp_dir.path().join("large_entry.mdict");
let large_content = "x".repeat(1024 * 1024); let entry = format!("large_key\n{}", large_content);
std::fs::write(&large_entry_dict, entry).unwrap();
assert!(large_entry_dict.exists());
assert!(large_entry_dict.metadata().unwrap().len() > 1024 * 1024);
}
#[test]
fn test_invalid_utf8_content() {
let temp_dir = temp_dir().unwrap();
let invalid_utf8_dict = temp_dir.path().join("invalid_utf8.mdict");
let invalid_content = vec![0xFF, 0xFE, 0x00, 0x01];
std::fs::write(&invalid_utf8_dict, &invalid_content).unwrap();
assert!(invalid_utf8_dict.exists());
let loader = DictLoader::new();
let result = loader.load(&invalid_utf8_dict);
if result.is_err() {
if let Err(error) = result {
assert!(matches!(error, DictError::InvalidFormat(_) |
DictError::IoError(_)));
}
}
}
#[test]
fn test_maximum_file_size_handling() {
let temp_dir = temp_dir().unwrap();
let large_file = temp_dir.path().join("large_file.mdict");
let large_content = "data".repeat(1024 * 1024 * 10); let write_result = std::fs::write(&large_file, large_content);
if write_result.is_err() {
if let Err(error) = write_result {
assert!(matches!(error, io::ErrorKind::DiskFull |
io::ErrorKind::FileTooLarge |
io::ErrorKind::PermissionDenied));
}
} else {
assert!(large_file.exists());
let size = large_file.metadata().unwrap().len();
assert!(size > 10 * 1024 * 1024);
}
}
}
mod recovery_tests {
use super::*;
#[test]
fn test_format_detection_retry() {
let temp_dir = temp_dir().unwrap();
let ambiguous_file = temp_dir.path().join("ambiguous");
std::fs::write(&ambiguous_file, "MDict version").unwrap();
let loader = DictLoader::new();
let result = loader.detect_format(&ambiguous_file);
if result.is_err() {
if let Err(error) = result {
assert!(matches!(error, DictError::UnsupportedOperation(_)));
}
}
}
#[test]
fn test_partial_file_recovery() {
let temp_dir = temp_dir().unwrap();
let partial_file = temp_dir.path().join("partial.mdict");
let partial_content = "MDict version 1.0.0";
std::fs::write(&partial_file, partial_content).unwrap();
let loader = DictLoader::new();
let result = loader.load(&partial_file);
if result.is_err() {
if let Err(error) = result {
assert!(matches!(error, DictError::InvalidFormat(_) |
DictError::IoError(_)));
}
}
}
#[test]
fn test_concurrent_access_recovery() {
let temp_dir = temp_dir().unwrap();
let shared_file = temp_dir.path().join("shared.mdict");
let content = "MDict version 1.0.0\n1\n0\n0\n0\n";
std::fs::write(&shared_file, content).unwrap();
assert!(shared_file.exists());
assert!(crate::dict::utils::is_readable(&shared_file));
let loader = DictLoader::new();
let format = loader.detect_format(&shared_file);
if let Ok(format_type) = format {
assert_eq!(format_type, "mdict");
}
}
}
mod resource_limit_tests {
use super::*;
#[test]
fn test_memory_limit_handling() {
let temp_dir = temp_dir().unwrap();
for i in 0..10 {
let file_path = temp_dir.path().join(format!("memory_test_{}.mdict", i));
let content = format!("MDict version 1.0.0\n{}", i);
std::fs::write(&file_path, content).unwrap();
}
let loader = DictLoader::new();
let dict_files = loader.scan_directory(&temp_dir).unwrap();
assert_eq!(dict_files.len(), 10);
}
#[test]
fn test_cache_limit_handling() {
let limited_config = DictConfig {
cache_size: 5, batch_size: 10,
..Default::default()
};
let loader = DictLoader::with_config(limited_config);
assert_eq!(loader.default_config().cache_size, 5);
}
#[test]
fn test_concurrent_resource_usage() {
let temp_dir = temp_dir().unwrap();
for i in 0..5 {
let file_path = temp_dir.path().join(format!("concurrent_{}.mdict", i));
let content = format!("MDict version 1.0.0\n{}", i);
std::fs::write(&file_path, content).unwrap();
}
let loader = DictLoader::new();
for i in 0..5 {
let file_path = temp_dir.path().join(format!("concurrent_{}.mdict", i));
assert!(loader.is_dictionary_file(&file_path));
}
}
}
}