refactor: Separate tests into dedicated files to reduce source file sizes
- Extract all tests from cache.rs, files.rs, config.rs to separate test files - Create cache_tests.rs, files_tests.rs, config_tests.rs - Reduce cache.rs: 421 -> 220 lines (-191 lines) - Reduce files.rs: 390 -> 264 lines (-126 lines) - Reduce config.rs: 354 -> 275 lines (-79 lines) - Total reduction: 396 lines from main source files - All 31 tests still passing
This commit is contained in:
@@ -1,2 +0,0 @@
|
|||||||
GEMINI_API_KEY=
|
|
||||||
DOWNLOAD_FOLDER=
|
|
||||||
205
src/cache.rs
205
src/cache.rs
@@ -216,206 +216,5 @@ impl Cache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
#[path = "cache_tests.rs"]
|
||||||
use super::*;
|
mod tests;
|
||||||
use crate::files::FileCategory;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_new() {
|
|
||||||
let cache = Cache::new();
|
|
||||||
assert_eq!(cache.max_entries, 1000);
|
|
||||||
assert_eq!(cache.entries.len(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_with_max_entries() {
|
|
||||||
let cache = Cache::with_max_entries(5);
|
|
||||||
assert_eq!(cache.max_entries, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_default() {
|
|
||||||
let cache = Cache::default();
|
|
||||||
assert_eq!(cache.max_entries, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_response_and_retrieve() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let base_path = temp_dir.path();
|
|
||||||
|
|
||||||
let mut cache = Cache::new();
|
|
||||||
let filenames = vec!["file1.txt".to_string(), "file2.txt".to_string()];
|
|
||||||
|
|
||||||
for filename in &filenames {
|
|
||||||
let file_path = base_path.join(filename);
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(b"test content").unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let response = OrganizationPlan {
|
|
||||||
files: vec![FileCategory {
|
|
||||||
filename: "file1.txt".to_string(),
|
|
||||||
category: "Documents".to_string(),
|
|
||||||
sub_category: "Text".to_string(),
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
|
|
||||||
cache.cache_response(&filenames, response.clone(), base_path);
|
|
||||||
|
|
||||||
let cached = cache.get_cached_response(&filenames, base_path);
|
|
||||||
assert!(cached.is_some());
|
|
||||||
assert_eq!(cached.unwrap().files[0].category, "Documents");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_response_file_changed() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let base_path = temp_dir.path();
|
|
||||||
|
|
||||||
let mut cache = Cache::new();
|
|
||||||
let filenames = vec!["file1.txt".to_string()];
|
|
||||||
|
|
||||||
let file_path = base_path.join("file1.txt");
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(b"original content").unwrap();
|
|
||||||
|
|
||||||
let response = OrganizationPlan {
|
|
||||||
files: vec![FileCategory {
|
|
||||||
filename: "file1.txt".to_string(),
|
|
||||||
category: "Documents".to_string(),
|
|
||||||
sub_category: "Text".to_string(),
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
|
|
||||||
cache.cache_response(&filenames, response.clone(), base_path);
|
|
||||||
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
|
||||||
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(b"modified content longer than original").unwrap();
|
|
||||||
|
|
||||||
let cached = cache.get_cached_response(&filenames, base_path);
|
|
||||||
assert!(cached.is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_save_and_load() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let cache_path = temp_dir.path().join("cache.json");
|
|
||||||
let base_path = temp_dir.path();
|
|
||||||
|
|
||||||
let mut cache = Cache::new();
|
|
||||||
let filenames = vec!["file1.txt".to_string()];
|
|
||||||
|
|
||||||
let file_path = base_path.join("file1.txt");
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(b"test").unwrap();
|
|
||||||
|
|
||||||
let response = OrganizationPlan {
|
|
||||||
files: vec![FileCategory {
|
|
||||||
filename: "file1.txt".to_string(),
|
|
||||||
category: "Documents".to_string(),
|
|
||||||
sub_category: "Text".to_string(),
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
|
|
||||||
cache.cache_response(&filenames, response, base_path);
|
|
||||||
cache.save(&cache_path).unwrap();
|
|
||||||
|
|
||||||
let loaded_cache = Cache::load_or_create(&cache_path);
|
|
||||||
assert_eq!(loaded_cache.entries.len(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_cleanup_old_entries() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let base_path = temp_dir.path();
|
|
||||||
|
|
||||||
let mut cache = Cache::new();
|
|
||||||
let filenames = vec!["file1.txt".to_string()];
|
|
||||||
|
|
||||||
let file_path = base_path.join("file1.txt");
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(b"test").unwrap();
|
|
||||||
|
|
||||||
let response = OrganizationPlan {
|
|
||||||
files: vec![FileCategory {
|
|
||||||
filename: "file1.txt".to_string(),
|
|
||||||
category: "Documents".to_string(),
|
|
||||||
sub_category: "Text".to_string(),
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
|
|
||||||
cache.cache_response(&filenames, response, base_path);
|
|
||||||
|
|
||||||
cache.cleanup_old_entries(0);
|
|
||||||
assert_eq!(cache.entries.len(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_max_entries_eviction() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let base_path = temp_dir.path();
|
|
||||||
|
|
||||||
let mut cache = Cache::with_max_entries(2);
|
|
||||||
|
|
||||||
for i in 1..=3 {
|
|
||||||
let filename = format!("file{}.txt", i);
|
|
||||||
let file_path = base_path.join(&filename);
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(b"test").unwrap();
|
|
||||||
|
|
||||||
let response = OrganizationPlan {
|
|
||||||
files: vec![FileCategory {
|
|
||||||
filename: filename.clone(),
|
|
||||||
category: "Documents".to_string(),
|
|
||||||
sub_category: "Text".to_string(),
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
|
|
||||||
cache.cache_response(&vec![filename], response, base_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(cache.entries.len(), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_serialization() {
|
|
||||||
let cache = Cache::new();
|
|
||||||
let json = serde_json::to_string(&cache).unwrap();
|
|
||||||
let deserialized: Cache = serde_json::from_str(&json).unwrap();
|
|
||||||
assert_eq!(cache.max_entries, deserialized.max_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_file_metadata_equality() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let file_path = temp_dir.path().join("test.txt");
|
|
||||||
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(b"test content").unwrap();
|
|
||||||
|
|
||||||
let metadata1 = Cache::get_file_metadata(&file_path).unwrap();
|
|
||||||
let metadata2 = Cache::get_file_metadata(&file_path).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(metadata1, metadata2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cache_key_generation() {
|
|
||||||
let cache = Cache::new();
|
|
||||||
let filenames1 = vec!["a.txt".to_string(), "b.txt".to_string()];
|
|
||||||
let filenames2 = vec!["b.txt".to_string(), "a.txt".to_string()];
|
|
||||||
let filenames3 = vec!["c.txt".to_string()];
|
|
||||||
|
|
||||||
let key1 = cache.generate_cache_key(&filenames1);
|
|
||||||
let key2 = cache.generate_cache_key(&filenames2);
|
|
||||||
let key3 = cache.generate_cache_key(&filenames3);
|
|
||||||
|
|
||||||
assert_eq!(key1, key2);
|
|
||||||
assert_ne!(key1, key3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
201
src/cache_tests.rs
Normal file
201
src/cache_tests.rs
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
use crate::cache::*;
|
||||||
|
use crate::files::FileCategory;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_new() {
|
||||||
|
let cache = Cache::new();
|
||||||
|
assert_eq!(cache.max_entries, 1000);
|
||||||
|
assert_eq!(cache.entries.len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_with_max_entries() {
|
||||||
|
let cache = Cache::with_max_entries(5);
|
||||||
|
assert_eq!(cache.max_entries, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_default() {
|
||||||
|
let cache = Cache::default();
|
||||||
|
assert_eq!(cache.max_entries, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_response_and_retrieve() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let base_path = temp_dir.path();
|
||||||
|
|
||||||
|
let mut cache = Cache::new();
|
||||||
|
let filenames = vec!["file1.txt".to_string(), "file2.txt".to_string()];
|
||||||
|
|
||||||
|
for filename in &filenames {
|
||||||
|
let file_path = base_path.join(filename);
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(b"test content").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let response = OrganizationPlan {
|
||||||
|
files: vec![FileCategory {
|
||||||
|
filename: "file1.txt".to_string(),
|
||||||
|
category: "Documents".to_string(),
|
||||||
|
sub_category: "Text".to_string(),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
cache.cache_response(&filenames, response.clone(), base_path);
|
||||||
|
|
||||||
|
let cached = cache.get_cached_response(&filenames, base_path);
|
||||||
|
assert!(cached.is_some());
|
||||||
|
assert_eq!(cached.unwrap().files[0].category, "Documents");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_response_file_changed() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let base_path = temp_dir.path();
|
||||||
|
|
||||||
|
let mut cache = Cache::new();
|
||||||
|
let filenames = vec!["file1.txt".to_string()];
|
||||||
|
|
||||||
|
let file_path = base_path.join("file1.txt");
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(b"original content").unwrap();
|
||||||
|
|
||||||
|
let response = OrganizationPlan {
|
||||||
|
files: vec![FileCategory {
|
||||||
|
filename: "file1.txt".to_string(),
|
||||||
|
category: "Documents".to_string(),
|
||||||
|
sub_category: "Text".to_string(),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
cache.cache_response(&filenames, response.clone(), base_path);
|
||||||
|
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
|
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(b"modified content longer than original").unwrap();
|
||||||
|
|
||||||
|
let cached = cache.get_cached_response(&filenames, base_path);
|
||||||
|
assert!(cached.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_save_and_load() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let cache_path = temp_dir.path().join("cache.json");
|
||||||
|
let base_path = temp_dir.path();
|
||||||
|
|
||||||
|
let mut cache = Cache::new();
|
||||||
|
let filenames = vec!["file1.txt".to_string()];
|
||||||
|
|
||||||
|
let file_path = base_path.join("file1.txt");
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(b"test").unwrap();
|
||||||
|
|
||||||
|
let response = OrganizationPlan {
|
||||||
|
files: vec![FileCategory {
|
||||||
|
filename: "file1.txt".to_string(),
|
||||||
|
category: "Documents".to_string(),
|
||||||
|
sub_category: "Text".to_string(),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
cache.cache_response(&filenames, response, base_path);
|
||||||
|
cache.save(&cache_path).unwrap();
|
||||||
|
|
||||||
|
let loaded_cache = Cache::load_or_create(&cache_path);
|
||||||
|
assert_eq!(loaded_cache.entries.len(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_cleanup_old_entries() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let base_path = temp_dir.path();
|
||||||
|
|
||||||
|
let mut cache = Cache::new();
|
||||||
|
let filenames = vec!["file1.txt".to_string()];
|
||||||
|
|
||||||
|
let file_path = base_path.join("file1.txt");
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(b"test").unwrap();
|
||||||
|
|
||||||
|
let response = OrganizationPlan {
|
||||||
|
files: vec![FileCategory {
|
||||||
|
filename: "file1.txt".to_string(),
|
||||||
|
category: "Documents".to_string(),
|
||||||
|
sub_category: "Text".to_string(),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
cache.cache_response(&filenames, response, base_path);
|
||||||
|
|
||||||
|
cache.cleanup_old_entries(0);
|
||||||
|
assert_eq!(cache.entries.len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_max_entries_eviction() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let base_path = temp_dir.path();
|
||||||
|
|
||||||
|
let mut cache = Cache::with_max_entries(2);
|
||||||
|
|
||||||
|
for i in 1..=3 {
|
||||||
|
let filename = format!("file{}.txt", i);
|
||||||
|
let file_path = base_path.join(&filename);
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(b"test").unwrap();
|
||||||
|
|
||||||
|
let response = OrganizationPlan {
|
||||||
|
files: vec![FileCategory {
|
||||||
|
filename: filename.clone(),
|
||||||
|
category: "Documents".to_string(),
|
||||||
|
sub_category: "Text".to_string(),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
cache.cache_response(&vec![filename], response, base_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(cache.entries.len(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_serialization() {
|
||||||
|
let cache = Cache::new();
|
||||||
|
let json = serde_json::to_string(&cache).unwrap();
|
||||||
|
let deserialized: Cache = serde_json::from_str(&json).unwrap();
|
||||||
|
assert_eq!(cache.max_entries, deserialized.max_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_file_metadata_equality() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let file_path = temp_dir.path().join("test.txt");
|
||||||
|
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(b"test content").unwrap();
|
||||||
|
|
||||||
|
let metadata1 = Cache::get_file_metadata(&file_path).unwrap();
|
||||||
|
let metadata2 = Cache::get_file_metadata(&file_path).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(metadata1, metadata2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cache_key_generation() {
|
||||||
|
let cache = Cache::new();
|
||||||
|
let filenames1 = vec!["a.txt".to_string(), "b.txt".to_string()];
|
||||||
|
let filenames2 = vec!["b.txt".to_string(), "a.txt".to_string()];
|
||||||
|
let filenames3 = vec!["c.txt".to_string()];
|
||||||
|
|
||||||
|
let key1 = cache.generate_cache_key(&filenames1);
|
||||||
|
let key2 = cache.generate_cache_key(&filenames2);
|
||||||
|
let key3 = cache.generate_cache_key(&filenames3);
|
||||||
|
|
||||||
|
assert_eq!(key1, key2);
|
||||||
|
assert_ne!(key1, key3);
|
||||||
|
}
|
||||||
@@ -271,84 +271,5 @@ fn expand_home(path: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
#[path = "config_tests.rs"]
|
||||||
use super::*;
|
mod tests;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_config_serialization() {
|
|
||||||
let config = Config {
|
|
||||||
api_key: "test_key_12345".to_string(),
|
|
||||||
download_folder: PathBuf::from("/test/path"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let toml_str = toml::to_string_pretty(&config).unwrap();
|
|
||||||
assert!(toml_str.contains("test_key_12345"));
|
|
||||||
|
|
||||||
let deserialized: Config = toml::from_str(&toml_str).unwrap();
|
|
||||||
assert_eq!(config.api_key, deserialized.api_key);
|
|
||||||
assert_eq!(config.download_folder, deserialized.download_folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_validate_api_key_valid() {
|
|
||||||
assert!(validate_api_key("AIzaSyB1234567890123456789012345678"));
|
|
||||||
assert!(validate_api_key("AIzaSyB123456789012345678901234567890"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_validate_api_key_invalid() {
|
|
||||||
assert!(!validate_api_key(""));
|
|
||||||
assert!(!validate_api_key("invalid_key"));
|
|
||||||
assert!(!validate_api_key("BizaSyB1234567890123456789012345678"));
|
|
||||||
assert!(!validate_api_key("short"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_validate_folder_path_valid() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
assert!(validate_folder_path(temp_dir.path()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_validate_folder_path_invalid() {
|
|
||||||
assert!(!validate_folder_path(Path::new("/nonexistent/path/that/does/not/exist")));
|
|
||||||
|
|
||||||
let temp_file = tempfile::NamedTempFile::new().unwrap();
|
|
||||||
assert!(!validate_folder_path(temp_file.path()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_expand_home_with_tilde() {
|
|
||||||
if let Some(base_dirs) = BaseDirs::new() {
|
|
||||||
let home = base_dirs.home_dir();
|
|
||||||
let expanded = expand_home("~/test/path");
|
|
||||||
assert!(expanded.starts_with(home.to_string_lossy().as_ref()));
|
|
||||||
assert!(expanded.contains("test/path"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_expand_home_without_tilde() {
|
|
||||||
let expanded = expand_home("/absolute/path");
|
|
||||||
assert_eq!(expanded, "/absolute/path");
|
|
||||||
|
|
||||||
let expanded = expand_home("relative/path");
|
|
||||||
assert_eq!(expanded, "relative/path");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_get_default_downloads_folder() {
|
|
||||||
let path = get_default_downloads_folder();
|
|
||||||
assert!(path.ends_with("Downloads"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_config_empty_api_key_error() {
|
|
||||||
let config = Config {
|
|
||||||
api_key: String::new(),
|
|
||||||
download_folder: PathBuf::from("/test/path"),
|
|
||||||
};
|
|
||||||
|
|
||||||
assert!(config.api_key.is_empty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
79
src/config_tests.rs
Normal file
79
src/config_tests.rs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
use crate::config::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_config_serialization() {
|
||||||
|
let config = Config {
|
||||||
|
api_key: "test_key_12345".to_string(),
|
||||||
|
download_folder: PathBuf::from("/test/path"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let toml_str = toml::to_string_pretty(&config).unwrap();
|
||||||
|
assert!(toml_str.contains("test_key_12345"));
|
||||||
|
|
||||||
|
let deserialized: Config = toml::from_str(&toml_str).unwrap();
|
||||||
|
assert_eq!(config.api_key, deserialized.api_key);
|
||||||
|
assert_eq!(config.download_folder, deserialized.download_folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_validate_api_key_valid() {
|
||||||
|
assert!(validate_api_key("AIzaSyB1234567890123456789012345678"));
|
||||||
|
assert!(validate_api_key("AIzaSyB123456789012345678901234567890"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_validate_api_key_invalid() {
|
||||||
|
assert!(!validate_api_key(""));
|
||||||
|
assert!(!validate_api_key("invalid_key"));
|
||||||
|
assert!(!validate_api_key("BizaSyB1234567890123456789012345678"));
|
||||||
|
assert!(!validate_api_key("short"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_validate_folder_path_valid() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
assert!(validate_folder_path(temp_dir.path()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_validate_folder_path_invalid() {
|
||||||
|
assert!(!validate_folder_path(Path::new("/nonexistent/path/that/does/not/exist")));
|
||||||
|
|
||||||
|
let temp_file = tempfile::NamedTempFile::new().unwrap();
|
||||||
|
assert!(!validate_folder_path(temp_file.path()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_expand_home_with_tilde() {
|
||||||
|
if let Some(base_dirs) = BaseDirs::new() {
|
||||||
|
let home = base_dirs.home_dir();
|
||||||
|
let expanded = expand_home("~/test/path");
|
||||||
|
assert!(expanded.starts_with(home.to_string_lossy().as_ref()));
|
||||||
|
assert!(expanded.contains("test/path"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_expand_home_without_tilde() {
|
||||||
|
let expanded = expand_home("/absolute/path");
|
||||||
|
assert_eq!(expanded, "/absolute/path");
|
||||||
|
|
||||||
|
let expanded = expand_home("relative/path");
|
||||||
|
assert_eq!(expanded, "relative/path");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_default_downloads_folder() {
|
||||||
|
let path = get_default_downloads_folder();
|
||||||
|
assert!(path.ends_with("Downloads"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_config_empty_api_key_error() {
|
||||||
|
let config = Config {
|
||||||
|
api_key: String::new(),
|
||||||
|
download_folder: PathBuf::from("/test/path"),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(config.api_key.is_empty());
|
||||||
|
}
|
||||||
130
src/files.rs
130
src/files.rs
@@ -260,131 +260,5 @@ pub fn read_file_sample(path: &Path, max_chars: usize) -> Option<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
#[path = "files_tests.rs"]
|
||||||
use super::*;
|
mod tests;
|
||||||
use std::fs::{self, File};
|
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_is_text_file_with_text_extensions() {
|
|
||||||
assert!(is_text_file(Path::new("test.txt")));
|
|
||||||
assert!(is_text_file(Path::new("test.rs")));
|
|
||||||
assert!(is_text_file(Path::new("test.py")));
|
|
||||||
assert!(is_text_file(Path::new("test.md")));
|
|
||||||
assert!(is_text_file(Path::new("test.json")));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_is_text_file_with_binary_extensions() {
|
|
||||||
assert!(!is_text_file(Path::new("test.exe")));
|
|
||||||
assert!(!is_text_file(Path::new("test.bin")));
|
|
||||||
assert!(!is_text_file(Path::new("test.jpg")));
|
|
||||||
assert!(!is_text_file(Path::new("test.pdf")));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_is_text_file_case_insensitive() {
|
|
||||||
assert!(is_text_file(Path::new("test.TXT")));
|
|
||||||
assert!(is_text_file(Path::new("test.RS")));
|
|
||||||
assert!(is_text_file(Path::new("test.Py")));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_file_batch_from_path() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let dir_path = temp_dir.path();
|
|
||||||
|
|
||||||
File::create(dir_path.join("file1.txt")).unwrap();
|
|
||||||
File::create(dir_path.join("file2.rs")).unwrap();
|
|
||||||
fs::create_dir(dir_path.join("subdir")).unwrap();
|
|
||||||
|
|
||||||
let batch = FileBatch::from_path(dir_path.to_path_buf());
|
|
||||||
assert_eq!(batch.count(), 2);
|
|
||||||
assert!(batch.filenames.contains(&"file1.txt".to_string()));
|
|
||||||
assert!(batch.filenames.contains(&"file2.rs".to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_file_batch_from_path_nonexistent() {
|
|
||||||
let batch = FileBatch::from_path(PathBuf::from("/nonexistent/path"));
|
|
||||||
assert_eq!(batch.count(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_read_file_sample() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let file_path = temp_dir.path().join("test.txt");
|
|
||||||
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(b"Hello, World!").unwrap();
|
|
||||||
|
|
||||||
let content = read_file_sample(&file_path, 1000);
|
|
||||||
assert_eq!(content, Some("Hello, World!".to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_read_file_sample_with_limit() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let file_path = temp_dir.path().join("test.txt");
|
|
||||||
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(b"Hello, World! This is a long text.").unwrap();
|
|
||||||
|
|
||||||
let content = read_file_sample(&file_path, 5);
|
|
||||||
assert_eq!(content, Some("Hello".to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_read_file_sample_binary_file() {
|
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
|
||||||
let file_path = temp_dir.path().join("test.bin");
|
|
||||||
|
|
||||||
let mut file = File::create(&file_path).unwrap();
|
|
||||||
file.write_all(&[0x00, 0xFF, 0x80, 0x90]).unwrap();
|
|
||||||
|
|
||||||
let content = read_file_sample(&file_path, 1000);
|
|
||||||
assert_eq!(content, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_read_file_sample_nonexistent() {
|
|
||||||
let content = read_file_sample(Path::new("/nonexistent/file.txt"), 1000);
|
|
||||||
assert_eq!(content, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_organization_plan_serialization() {
|
|
||||||
let plan = OrganizationPlan {
|
|
||||||
files: vec![
|
|
||||||
FileCategory {
|
|
||||||
filename: "test.txt".to_string(),
|
|
||||||
category: "Documents".to_string(),
|
|
||||||
sub_category: "Text".to_string(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
let json = serde_json::to_string(&plan).unwrap();
|
|
||||||
assert!(json.contains("test.txt"));
|
|
||||||
assert!(json.contains("Documents"));
|
|
||||||
|
|
||||||
let deserialized: OrganizationPlan = serde_json::from_str(&json).unwrap();
|
|
||||||
assert_eq!(deserialized.files[0].filename, "test.txt");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_file_category_serialization() {
|
|
||||||
let fc = FileCategory {
|
|
||||||
filename: "file.rs".to_string(),
|
|
||||||
category: "Code".to_string(),
|
|
||||||
sub_category: "Rust".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let json = serde_json::to_string(&fc).unwrap();
|
|
||||||
let deserialized: FileCategory = serde_json::from_str(&json).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(fc.filename, deserialized.filename);
|
|
||||||
assert_eq!(fc.category, deserialized.category);
|
|
||||||
assert_eq!(fc.sub_category, deserialized.sub_category);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
126
src/files_tests.rs
Normal file
126
src/files_tests.rs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
use crate::files::*;
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_text_file_with_text_extensions() {
|
||||||
|
assert!(is_text_file(Path::new("test.txt")));
|
||||||
|
assert!(is_text_file(Path::new("test.rs")));
|
||||||
|
assert!(is_text_file(Path::new("test.py")));
|
||||||
|
assert!(is_text_file(Path::new("test.md")));
|
||||||
|
assert!(is_text_file(Path::new("test.json")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_text_file_with_binary_extensions() {
|
||||||
|
assert!(!is_text_file(Path::new("test.exe")));
|
||||||
|
assert!(!is_text_file(Path::new("test.bin")));
|
||||||
|
assert!(!is_text_file(Path::new("test.jpg")));
|
||||||
|
assert!(!is_text_file(Path::new("test.pdf")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_text_file_case_insensitive() {
|
||||||
|
assert!(is_text_file(Path::new("test.TXT")));
|
||||||
|
assert!(is_text_file(Path::new("test.RS")));
|
||||||
|
assert!(is_text_file(Path::new("test.Py")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_file_batch_from_path() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let dir_path = temp_dir.path();
|
||||||
|
|
||||||
|
File::create(dir_path.join("file1.txt")).unwrap();
|
||||||
|
File::create(dir_path.join("file2.rs")).unwrap();
|
||||||
|
fs::create_dir(dir_path.join("subdir")).unwrap();
|
||||||
|
|
||||||
|
let batch = FileBatch::from_path(dir_path.to_path_buf());
|
||||||
|
assert_eq!(batch.count(), 2);
|
||||||
|
assert!(batch.filenames.contains(&"file1.txt".to_string()));
|
||||||
|
assert!(batch.filenames.contains(&"file2.rs".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_file_batch_from_path_nonexistent() {
|
||||||
|
let batch = FileBatch::from_path(PathBuf::from("/nonexistent/path"));
|
||||||
|
assert_eq!(batch.count(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_read_file_sample() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let file_path = temp_dir.path().join("test.txt");
|
||||||
|
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(b"Hello, World!").unwrap();
|
||||||
|
|
||||||
|
let content = read_file_sample(&file_path, 1000);
|
||||||
|
assert_eq!(content, Some("Hello, World!".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_read_file_sample_with_limit() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let file_path = temp_dir.path().join("test.txt");
|
||||||
|
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(b"Hello, World! This is a long text.").unwrap();
|
||||||
|
|
||||||
|
let content = read_file_sample(&file_path, 5);
|
||||||
|
assert_eq!(content, Some("Hello".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_read_file_sample_binary_file() {
|
||||||
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
let file_path = temp_dir.path().join("test.bin");
|
||||||
|
|
||||||
|
let mut file = File::create(&file_path).unwrap();
|
||||||
|
file.write_all(&[0x00, 0xFF, 0x80, 0x90]).unwrap();
|
||||||
|
|
||||||
|
let content = read_file_sample(&file_path, 1000);
|
||||||
|
assert_eq!(content, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_read_file_sample_nonexistent() {
|
||||||
|
let content = read_file_sample(Path::new("/nonexistent/file.txt"), 1000);
|
||||||
|
assert_eq!(content, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_organization_plan_serialization() {
|
||||||
|
let plan = OrganizationPlan {
|
||||||
|
files: vec![
|
||||||
|
FileCategory {
|
||||||
|
filename: "test.txt".to_string(),
|
||||||
|
category: "Documents".to_string(),
|
||||||
|
sub_category: "Text".to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
let json = serde_json::to_string(&plan).unwrap();
|
||||||
|
assert!(json.contains("test.txt"));
|
||||||
|
assert!(json.contains("Documents"));
|
||||||
|
|
||||||
|
let deserialized: OrganizationPlan = serde_json::from_str(&json).unwrap();
|
||||||
|
assert_eq!(deserialized.files[0].filename, "test.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_file_category_serialization() {
|
||||||
|
let fc = FileCategory {
|
||||||
|
filename: "file.rs".to_string(),
|
||||||
|
category: "Code".to_string(),
|
||||||
|
sub_category: "Rust".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let json = serde_json::to_string(&fc).unwrap();
|
||||||
|
let deserialized: FileCategory = serde_json::from_str(&json).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(fc.filename, deserialized.filename);
|
||||||
|
assert_eq!(fc.category, deserialized.category);
|
||||||
|
assert_eq!(fc.sub_category, deserialized.sub_category);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user