diff --git a/src-tauri/src/commands/search.rs b/src-tauri/src/commands/search.rs index 7a2d3c6..8631b73 100644 --- a/src-tauri/src/commands/search.rs +++ b/src-tauri/src/commands/search.rs @@ -305,4 +305,69 @@ mod tests { // Empty string is contained in all strings, so should match assert_eq!(results.len(), 1); } + + #[cfg(unix)] + #[tokio::test] + async fn test_search_files_handles_permission_errors() { + use std::os::unix::fs::PermissionsExt; + + let temp_dir = TempDir::new().unwrap(); + + // Create a subdirectory with a file + let restricted_dir = temp_dir.path().join("restricted"); + fs::create_dir(&restricted_dir).unwrap(); + fs::write(restricted_dir.join("secret.txt"), "searchterm").unwrap(); + + // Remove read permissions from the directory + let mut perms = fs::metadata(&restricted_dir).unwrap().permissions(); + perms.set_mode(0o000); + fs::set_permissions(&restricted_dir, perms).unwrap(); + + // Create an accessible file + fs::write(temp_dir.path().join("accessible.txt"), "searchterm").unwrap(); + + let root = temp_dir.path().to_path_buf(); + let results = search_files_impl("searchterm".to_string(), root) + .await + .unwrap(); + + // Should find the accessible file, walker error for restricted dir is logged but not fatal + assert_eq!(results.len(), 1); + assert_eq!(results[0].path, "accessible.txt"); + + // Restore permissions for cleanup + let mut perms = fs::metadata(&restricted_dir).unwrap().permissions(); + perms.set_mode(0o755); + fs::set_permissions(&restricted_dir, perms).unwrap(); + } + + #[tokio::test] + async fn test_search_files_handles_broken_symlink() { + let temp_dir = TempDir::new().unwrap(); + + // Create a broken symlink (points to non-existent file) + #[cfg(unix)] + { + use std::os::unix::fs as unix_fs; + unix_fs::symlink("/nonexistent/path", temp_dir.path().join("broken_link")).unwrap(); + } + #[cfg(windows)] + { + use std::os::windows::fs as windows_fs; + windows_fs::symlink_file("C:\\nonexistent\\path", temp_dir.path().join("broken_link")) + .unwrap(); + } + + // Create a normal file + fs::write(temp_dir.path().join("normal.txt"), "searchterm").unwrap(); + + let root = temp_dir.path().to_path_buf(); + let results = search_files_impl("searchterm".to_string(), root) + .await + .unwrap(); + + // Should find the normal file, broken symlink error is logged but not fatal + assert_eq!(results.len(), 1); + assert_eq!(results[0].path, "normal.txt"); + } }