#[cfg(test)]
mod tests {
use super::*;
use crate::traits::*;
use crate::util::test_utils::*;
use std::path::PathBuf;
use std::fs;
mod basic_dictionary_tests {
use super::*;
#[test]
fn test_dict_loader_basic() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("test.mdict");
let entries = generate_test_entries(10);
create_test_dict(&dict_path, "mdict", &entries).unwrap();
let loader = DictLoader::new();
let format = loader.detect_format(&dict_path).unwrap();
assert_eq!(format, "mdict");
assert!(loader.is_dictionary_file(&dict_path));
}
#[test]
fn test_format_detection_edge_cases() {
let temp_dir = temp_dir().unwrap();
let loader = DictLoader::new();
let test_cases = vec![
("test.mdict", "mdict"),
("test.dict", "stardict"),
("test.zim", "zim"),
("test.unknown", ""),
];
for (filename, expected_format) in test_cases {
let file_path = temp_dir.path().join(filename);
if !expected_format.is_empty() {
std::fs::write(&file_path, "test content").unwrap();
}
let result = loader.detect_format(&file_path);
if expected_format.is_empty() {
assert!(result.is_err());
} else {
assert_eq!(result.unwrap(), expected_format);
}
}
}
#[test]
fn test_multiple_format_support() {
let temp_dir = temp_dir().unwrap();
let loader = DictLoader::new();
let formats = loader.supported_formats();
assert_eq!(formats.len(), 3);
assert!(formats.contains(&"mdict".to_string()));
assert!(formats.contains(&"stardict".to_string()));
assert!(formats.contains(&"zim".to_string()));
}
#[test]
fn test_directory_scanning() {
let temp_dir = temp_dir().unwrap();
let mdict_file = temp_dir.path().join("test1.mdict");
let dict_file = temp_dir.path().join("test2.dict");
let zim_file = temp_dir.path().join("test3.zim");
let other_file = temp_dir.path().join("other.txt");
std::fs::write(&mdict_file, "mdict content").unwrap();
std::fs::write(&dict_file, "dict content").unwrap();
std::fs::write(&zim_file, "zim content").unwrap();
std::fs::write(&other_file, "other content").unwrap();
let loader = DictLoader::new();
let dict_files = loader.scan_directory(&temp_dir).unwrap();
assert_eq!(dict_files.len(), 3);
let filenames: Vec<String> = dict_files.iter()
.filter_map(|p| p.file_name().and_then(|n| n.to_str()).map(|s| s.to_string()))
.collect();
assert!(filenames.contains(&"test1.mdict".to_string()));
assert!(filenames.contains(&"test2.dict".to_string()));
assert!(filenames.contains(&"test3.zim".to_string()));
assert!(!filenames.contains(&"other.txt".to_string()));
}
}
mod metadata_tests {
use super::*;
#[test]
fn test_metadata_extraction() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("test.mdict");
let entries = generate_test_entries(100);
create_test_dict(&dict_path, "mdict", &entries).unwrap();
let loader = DictLoader::new();
assert!(dict_path.exists());
}
#[test]
fn test_file_size_reporting() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("test.mdict");
let test_content = "Test dictionary content with specific size";
std::fs::write(&dict_path, test_content).unwrap();
let loader = DictLoader::new();
let size = crate::dict::utils::get_dict_size(&dict_path).unwrap();
assert_eq!(size, test_content.len() as u64);
}
}
mod search_tests {
use super::*;
#[test]
fn test_prefix_search_scenarios() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("test.mdict");
let mut entries = Vec::new();
for i in 0..10 {
entries.push((format!("prefix_{:03}", i), format!("Definition {}", i).into_bytes()));
}
for i in 0..10 {
entries.push((format!("other_{:03}", i), format!("Other {}", i).into_bytes()));
}
create_test_dict(&dict_path, "mdict", &entries).unwrap();
assert!(dict_path.exists());
}
#[test]
fn test_fuzzy_search_scenarios() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("test.mdict");
let entries = vec![
("hello".to_string(), b"Hello world definition".to_vec()),
("hell".to_string(), b"Short form of hello".to_vec()),
("helo".to_string(), b"Common misspelling of hello".to_vec()),
("world".to_string(), b"World definition".to_vec()),
];
create_test_dict(&dict_path, "mdict", &entries).unwrap();
assert!(dict_path.exists());
}
#[test]
fn test_fulltext_search_scenarios() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("test.mdict");
let mut entries = Vec::new();
let content_patterns = vec![
"The quick brown fox jumps over the lazy dog",
"Programming languages are fascinating",
"Data structures and algorithms are important",
"Search algorithms can be complex",
];
for (i, pattern) in content_patterns.iter().enumerate() {
entries.push((format!("term_{}", i), pattern.as_bytes().to_vec()));
}
create_test_dict(&dict_path, "mdict", &entries).unwrap();
assert!(dict_path.exists());
}
}
mod batch_operation_tests {
use super::*;
#[test]
fn test_batch_loading() {
let temp_dir = temp_dir().unwrap();
let dict1_path = temp_dir.path().join("dict1.mdict");
let dict2_path = temp_dir.path().join("dict2.mdict");
let dict3_path = temp_dir.path().join("dict3.mdict");
let entries = generate_test_entries(50);
create_test_dict(&dict1_path, "mdict", &entries).unwrap();
create_test_dict(&dict2_path, "mdict", &entries).unwrap();
create_test_dict(&dict3_path, "mdict", &entries).unwrap();
let paths = vec![dict1_path.clone(), dict2_path.clone(), dict3_path.clone()];
let results = crate::dict::BatchOperations::validate_batch(&paths).unwrap();
assert_eq!(results.len(), 3);
for (_, is_valid) in results {
assert!(is_valid);
}
}
#[test]
fn test_batch_search() {
let temp_dir = temp_dir().unwrap();
let dict1_path = temp_dir.path().join("dict1.mdict");
let dict2_path = temp_dir.path().join("dict2.mdict");
let mut entries1 = Vec::new();
let mut entries2 = Vec::new();
for i in 0..20 {
entries1.push((format!("shared_{:03}", i), format!("Dict1 definition {}", i).into_bytes()));
entries2.push((format!("shared_{:03}", i), format!("Dict2 definition {}", i).into_bytes()));
}
create_test_dict(&dict1_path, "mdict", &entries1).unwrap();
create_test_dict(&dict2_path, "mdict", &entries2).unwrap();
assert!(dict1_path.exists());
assert!(dict2_path.exists());
}
#[test]
fn test_parallel_processing_scenarios() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("test.mdict");
let entries = generate_test_entries(1000);
create_test_dict(&dict_path, "mdict", &entries).unwrap();
assert!(dict_path.exists());
let size = dict_path.metadata().unwrap().len();
println!("Dictionary size for parallel processing: {} bytes", size);
}
}
mod performance_integration_tests {
use super::*;
#[test]
fn test_large_dictionary_loading() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("large.mdict");
let entries = generate_large_dataset(10_000);
create_test_dict(&dict_path, "mdict", &entries).unwrap();
assert!(dict_path.exists());
let file_size = dict_path.metadata().unwrap().len();
println!("Large dictionary size: {} bytes", file_size);
assert!(file_size > 0);
}
#[test]
fn test_memory_usage_patterns() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("memory_test.mdict");
let mut entries = Vec::new();
for i in 0..100 {
let large_content = "x".repeat(10_000); entries.push((format!("large_{}", i), large_content.into_bytes()));
}
create_test_dict(&dict_path, "mdict", &entries).unwrap();
assert!(dict_path.exists());
}
#[test]
fn test_concurrent_access_scenarios() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("concurrent.mdict");
let entries = generate_test_entries(500);
create_test_dict(&dict_path, "mdict", &entries).unwrap();
assert!(dict_path.exists());
let metadata = dict_path.metadata().unwrap();
assert!(metadata.len() > 0);
}
}
mod error_recovery_tests {
use super::*;
#[test]
fn test_corrupted_file_handling() {
let temp_dir = temp_dir().unwrap();
let dict_path = temp_dir.path().join("corrupted.mdict");
let corrupted_content = "This is not a valid dictionary file";
std::fs::write(&dict_path, corrupted_content).unwrap();
let loader = DictLoader::new();
let result = loader.detect_format(&dict_path);
assert!(result.is_err());
}
#[test]
fn test_missing_file_handling() {
let temp_dir = temp_dir().unwrap();
let non_existent_path = temp_dir.path().join("nonexistent.mdict");
let loader = DictLoader::new();
assert!(!non_existent_path.exists());
}
#[test]
fn test_permission_denied_scenarios() {
let temp_dir = temp_dir().unwrap();
let protected_path = temp_dir.path().join("protected.mdict");
std::fs::write(&protected_path, "protected content").unwrap();
assert!(protected_path.exists());
assert!(crate::dict::utils::is_readable(&protected_path));
}
#[test]
fn test_partial_file_handling() {
let temp_dir = temp_dir().unwrap();
let partial_path = temp_dir.path().join("partial.mdict");
let incomplete_content = "Incomplete";
std::fs::write(&partial_path, incomplete_content).unwrap();
assert!(partial_path.exists());
let loader = DictLoader::new();
let result = loader.detect_format(&partial_path);
}
}
mod edge_case_integration_tests {
use super::*;
#[test]
fn test_empty_dictionary() {
let temp_dir = temp_dir().unwrap();
let empty_dict_path = temp_dir.path().join("empty.mdict");
let empty_entries = Vec::new();
create_test_dict(&empty_dict_path, "mdict", &empty_entries).unwrap();
assert!(empty_dict_path.exists());
}
#[test]
fn test_single_entry_dictionary() {
let temp_dir = temp_dir().unwrap();
let single_dict_path = temp_dir.path().join("single.mdict");
let single_entry = vec![("single_key".to_string(), b"Single entry content".to_vec())];
create_test_dict(&single_dict_path, "mdict", &single_entry).unwrap();
assert!(single_dict_path.exists());
}
#[test]
fn test_very_long_keys() {
let temp_dir = temp_dir().unwrap();
let long_key_dict_path = temp_dir.path().join("long_key.mdict");
let mut entries = Vec::new();
for i in 0..5 {
let long_key = "a".repeat(1000) + &format!("_{}", i);
entries.push((long_key, format!("Definition for long key {}", i).into_bytes()));
}
create_test_dict(&long_key_dict_path, "mdict", &entries).unwrap();
assert!(long_key_dict_path.exists());
}
#[test]
fn test_unicode_content() {
let temp_dir = temp_dir().unwrap();
let unicode_dict_path = temp_dir.path().join("unicode.mdict");
let unicode_entries = generate_unicode_entries(20);
create_test_dict(&unicode_dict_path, "mdict", &unicode_entries).unwrap();
assert!(unicode_dict_path.exists());
}
#[test]
fn test_mixed_content_sizes() {
let temp_dir = temp_dir().unwrap();
let mixed_dict_path = temp_dir.path().join("mixed.mdict");
let mut entries = Vec::new();
entries.push(("small".to_string(), b"Small".to_vec()));
entries.push(("medium".to_string(), b"This is a medium length entry with some content".to_vec()));
let large_content = "Large content. ".repeat(1000);
entries.push(("large".to_string(), large_content.into_bytes()));
create_test_dict(&mixed_dict_path, "mdict", &entries).unwrap();
assert!(mixed_dict_path.exists());
}
}
}