mirror of
https://github.com/readur/readur.git
synced 2026-01-06 06:20:17 -06:00
565 lines
27 KiB
Rust
565 lines
27 KiB
Rust
#[cfg(test)]
|
|
mod tests {
|
|
use std::sync::Arc;
|
|
use readur::{
|
|
AppState,
|
|
models::{CreateWebDAVDirectory, User, AuthProvider},
|
|
services::webdav::{SmartSyncService, SmartSyncStrategy, SmartSyncDecision, WebDAVService, WebDAVConfig},
|
|
test_utils::{TestContext, TestAuthHelper},
|
|
};
|
|
|
|
/// Helper function to create test database and user with automatic cleanup
|
|
async fn create_test_setup() -> (Arc<AppState>, User, TestContext) {
|
|
let test_context = TestContext::new().await;
|
|
let auth_helper = TestAuthHelper::new(test_context.app().clone());
|
|
let test_user = auth_helper.create_test_user().await;
|
|
|
|
// Convert TestUser to User model for compatibility
|
|
let user = User {
|
|
id: test_user.user_response.id,
|
|
username: test_user.user_response.username,
|
|
email: test_user.user_response.email,
|
|
password_hash: Some("hashed_password".to_string()),
|
|
role: test_user.user_response.role,
|
|
created_at: chrono::Utc::now(),
|
|
updated_at: chrono::Utc::now(),
|
|
oidc_subject: None,
|
|
oidc_issuer: None,
|
|
oidc_email: None,
|
|
auth_provider: AuthProvider::Local,
|
|
};
|
|
|
|
(test_context.state().clone(), user, test_context)
|
|
}
|
|
|
|
/// RAII guard to ensure cleanup happens even if test panics
|
|
struct TestCleanupGuard {
|
|
context: Option<TestContext>,
|
|
cleanup_strategy: readur::test_utils::CleanupStrategy,
|
|
connections_only: bool,
|
|
}
|
|
|
|
impl TestCleanupGuard {
|
|
fn new(context: TestContext) -> Self {
|
|
Self {
|
|
context: Some(context),
|
|
cleanup_strategy: readur::test_utils::CleanupStrategy::Standard,
|
|
connections_only: false,
|
|
}
|
|
}
|
|
|
|
fn new_with_strategy(context: TestContext, strategy: readur::test_utils::CleanupStrategy) -> Self {
|
|
Self {
|
|
context: Some(context),
|
|
cleanup_strategy: strategy,
|
|
connections_only: false,
|
|
}
|
|
}
|
|
|
|
fn new_connections_only(context: TestContext) -> Self {
|
|
Self {
|
|
context: Some(context),
|
|
cleanup_strategy: readur::test_utils::CleanupStrategy::Fast, // This won't be used
|
|
connections_only: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for TestCleanupGuard {
|
|
fn drop(&mut self) {
|
|
// Simplified drop without background threads
|
|
// The TestContext and containers will clean up naturally
|
|
// For proper cleanup, use explicit cleanup methods before dropping
|
|
if let Some(_context) = self.context.take() {
|
|
// Context will be dropped naturally here
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Helper function to create WebDAV service for testing
|
|
fn create_test_webdav_service() -> WebDAVService {
|
|
let config = WebDAVConfig {
|
|
server_url: "https://test.example.com".to_string(),
|
|
username: "test".to_string(),
|
|
password: "test".to_string(),
|
|
watch_folders: vec!["/Documents".to_string()],
|
|
file_extensions: vec!["pdf".to_string(), "txt".to_string()],
|
|
timeout_seconds: 30,
|
|
server_type: Some("generic".to_string()),
|
|
};
|
|
|
|
WebDAVService::new(config).expect("Failed to create WebDAV service")
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_deep_scan_resets_directory_etags() {
|
|
// Integration Test: Manual deep scan should reset all directory ETags at all levels
|
|
// Expected: Should clear existing ETags and establish fresh baseline
|
|
|
|
let (state, user, test_context) = create_test_setup().await;
|
|
let _cleanup_guard = TestCleanupGuard::new(test_context);
|
|
|
|
// Pre-populate database with old directory ETags
|
|
let old_directories = vec![
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents".to_string(),
|
|
directory_etag: "old-root-etag".to_string(),
|
|
file_count: 5,
|
|
total_size_bytes: 500000,
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/Projects".to_string(),
|
|
directory_etag: "old-projects-etag".to_string(),
|
|
file_count: 10,
|
|
total_size_bytes: 1000000,
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/Archive".to_string(),
|
|
directory_etag: "old-archive-etag".to_string(),
|
|
file_count: 20,
|
|
total_size_bytes: 2000000,
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/Deep/Nested/Path".to_string(),
|
|
directory_etag: "old-deep-etag".to_string(),
|
|
file_count: 3,
|
|
total_size_bytes: 300000,
|
|
},
|
|
];
|
|
|
|
for dir in &old_directories {
|
|
state.db.create_or_update_webdav_directory(dir).await
|
|
.expect("Failed to create old directory");
|
|
}
|
|
|
|
// Verify old directories were created
|
|
let before_dirs = state.db.list_webdav_directories(user.id).await.unwrap();
|
|
assert_eq!(before_dirs.len(), 4, "Should have 4 old directories");
|
|
|
|
// Simulate deep scan reset - this would happen during a deep scan operation
|
|
// For testing, we'll manually clear directories and add new ones
|
|
|
|
// Clear existing directories (simulating deep scan reset)
|
|
for dir in &before_dirs {
|
|
state.db.delete_webdav_directory(user.id, &dir.directory_path).await
|
|
.expect("Failed to delete old directory");
|
|
}
|
|
|
|
// Verify directories were cleared
|
|
let cleared_dirs = state.db.list_webdav_directories(user.id).await.unwrap();
|
|
assert_eq!(cleared_dirs.len(), 0, "Should have cleared all old directories");
|
|
|
|
// Add new directories with fresh ETags (simulating post-deep-scan discovery)
|
|
let new_directories = vec![
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents".to_string(),
|
|
directory_etag: "fresh-root-etag".to_string(),
|
|
file_count: 8,
|
|
total_size_bytes: 800000,
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/Projects".to_string(),
|
|
directory_etag: "fresh-projects-etag".to_string(),
|
|
file_count: 12,
|
|
total_size_bytes: 1200000,
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/Archive".to_string(),
|
|
directory_etag: "fresh-archive-etag".to_string(),
|
|
file_count: 25,
|
|
total_size_bytes: 2500000,
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/Deep/Nested/Path".to_string(),
|
|
directory_etag: "fresh-deep-etag".to_string(),
|
|
file_count: 5,
|
|
total_size_bytes: 500000,
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/NewDirectory".to_string(),
|
|
directory_etag: "brand-new-etag".to_string(),
|
|
file_count: 2,
|
|
total_size_bytes: 200000,
|
|
},
|
|
];
|
|
|
|
for dir in &new_directories {
|
|
state.db.create_or_update_webdav_directory(dir).await
|
|
.expect("Failed to create new directory");
|
|
}
|
|
|
|
// Verify fresh directories were created
|
|
let after_dirs = state.db.list_webdav_directories(user.id).await.unwrap();
|
|
assert_eq!(after_dirs.len(), 5, "Should have 5 fresh directories after deep scan");
|
|
|
|
// Verify ETags are completely different
|
|
let root_dir = after_dirs.iter().find(|d| d.directory_path == "/Documents").unwrap();
|
|
assert_eq!(root_dir.directory_etag, "fresh-root-etag");
|
|
assert_ne!(root_dir.directory_etag, "old-root-etag");
|
|
|
|
let projects_dir = after_dirs.iter().find(|d| d.directory_path == "/Documents/Projects").unwrap();
|
|
assert_eq!(projects_dir.directory_etag, "fresh-projects-etag");
|
|
assert_ne!(projects_dir.directory_etag, "old-projects-etag");
|
|
|
|
let new_dir = after_dirs.iter().find(|d| d.directory_path == "/Documents/NewDirectory").unwrap();
|
|
assert_eq!(new_dir.directory_etag, "brand-new-etag");
|
|
|
|
println!("✅ Deep scan reset test completed successfully");
|
|
println!(" Cleared {} old directories", old_directories.len());
|
|
println!(" Created {} fresh directories", new_directories.len());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_scheduled_deep_scan() {
|
|
// Integration Test: Scheduled deep scan should reset all directory ETags and track new ones
|
|
// This tests the scenario where a scheduled deep scan runs periodically
|
|
|
|
let (state, user, test_context) = create_test_setup().await;
|
|
let _cleanup_guard = TestCleanupGuard::new(test_context);
|
|
|
|
// Simulate initial sync state
|
|
let initial_directories = vec![
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents".to_string(),
|
|
directory_etag: "initial-root".to_string(),
|
|
file_count: 10,
|
|
total_size_bytes: 1000000,
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/OldProject".to_string(),
|
|
directory_etag: "initial-old-project".to_string(),
|
|
file_count: 15,
|
|
total_size_bytes: 1500000,
|
|
},
|
|
];
|
|
|
|
for dir in &initial_directories {
|
|
state.db.create_or_update_webdav_directory(dir).await
|
|
.expect("Failed to create initial directory");
|
|
}
|
|
|
|
let initial_count = state.db.list_webdav_directories(user.id).await.unwrap().len();
|
|
assert_eq!(initial_count, 2, "Should start with 2 initial directories");
|
|
|
|
// Simulate time passing and directory structure changes
|
|
// During this time, directories may have been added/removed/changed on the WebDAV server
|
|
|
|
// Simulate scheduled deep scan: clear all ETags and rediscover
|
|
let initial_dirs = state.db.list_webdav_directories(user.id).await.unwrap();
|
|
for dir in &initial_dirs {
|
|
state.db.delete_webdav_directory(user.id, &dir.directory_path).await
|
|
.expect("Failed to delete during deep scan reset");
|
|
}
|
|
|
|
// Simulate fresh discovery after deep scan
|
|
let post_scan_directories = vec![
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents".to_string(),
|
|
directory_etag: "scheduled-root".to_string(), // Changed ETag
|
|
file_count: 12, // Changed file count
|
|
total_size_bytes: 1200000, // Changed size
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/NewProject".to_string(), // Different directory
|
|
directory_etag: "scheduled-new-project".to_string(),
|
|
file_count: 8,
|
|
total_size_bytes: 800000,
|
|
},
|
|
CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: "/Documents/Archive".to_string(), // Completely new directory
|
|
directory_etag: "scheduled-archive".to_string(),
|
|
file_count: 30,
|
|
total_size_bytes: 3000000,
|
|
},
|
|
];
|
|
|
|
for dir in &post_scan_directories {
|
|
state.db.create_or_update_webdav_directory(dir).await
|
|
.expect("Failed to create post-scan directory");
|
|
}
|
|
|
|
// Verify the scheduled deep scan results
|
|
let final_dirs = state.db.list_webdav_directories(user.id).await.unwrap();
|
|
assert_eq!(final_dirs.len(), 3, "Should have 3 directories after scheduled deep scan");
|
|
|
|
// Verify the directory structure reflects current state
|
|
let root_dir = final_dirs.iter().find(|d| d.directory_path == "/Documents").unwrap();
|
|
assert_eq!(root_dir.directory_etag, "scheduled-root");
|
|
assert_eq!(root_dir.file_count, 12);
|
|
assert_eq!(root_dir.total_size_bytes, 1200000);
|
|
|
|
let new_project = final_dirs.iter().find(|d| d.directory_path == "/Documents/NewProject").unwrap();
|
|
assert_eq!(new_project.directory_etag, "scheduled-new-project");
|
|
|
|
let archive_dir = final_dirs.iter().find(|d| d.directory_path == "/Documents/Archive").unwrap();
|
|
assert_eq!(archive_dir.directory_etag, "scheduled-archive");
|
|
|
|
// Verify old directory is gone
|
|
assert!(final_dirs.iter().find(|d| d.directory_path == "/Documents/OldProject").is_none(),
|
|
"Old project directory should be removed after scheduled deep scan");
|
|
|
|
println!("✅ Scheduled deep scan test completed successfully");
|
|
println!(" Initial directories: {}", initial_directories.len());
|
|
println!(" Final directories: {}", final_dirs.len());
|
|
println!(" Successfully handled directory structure changes");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_deep_scan_performance_with_many_directories() {
|
|
// Integration Test: Deep scan should perform well even with large numbers of directories
|
|
// This tests the scalability of the deep scan reset operation
|
|
|
|
let test_start_time = std::time::Instant::now();
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Test starting", test_start_time.elapsed());
|
|
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Creating test setup...", test_start_time.elapsed());
|
|
let setup_start = std::time::Instant::now();
|
|
let (state, user, test_context) = create_test_setup().await;
|
|
// Skip database cleanup entirely for this performance test - cleaning up 550+ directories
|
|
// causes the test to hang. Since the test database is ephemeral anyway, we only need to
|
|
// close the database connections to prevent resource leaks.
|
|
let _cleanup_guard = TestCleanupGuard::new_connections_only(test_context);
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Test setup completed in {:?}", test_start_time.elapsed(), setup_start.elapsed());
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - User ID: {}", test_start_time.elapsed(), user.id);
|
|
|
|
// Create a large number of old directories
|
|
let num_old_dirs = 250;
|
|
let mut old_directories = Vec::new();
|
|
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Starting creation of {} old directories", test_start_time.elapsed(), num_old_dirs);
|
|
let create_start = std::time::Instant::now();
|
|
|
|
for i in 0..num_old_dirs {
|
|
if i % 50 == 0 || i < 10 {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Creating directory {}/{} ({}%)",
|
|
test_start_time.elapsed(),
|
|
i + 1,
|
|
num_old_dirs,
|
|
((i + 1) * 100) / num_old_dirs
|
|
);
|
|
}
|
|
|
|
let dir_create_start = std::time::Instant::now();
|
|
let dir = CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: format!("/Documents/Old{:03}", i),
|
|
directory_etag: format!("old-etag-{:03}", i),
|
|
file_count: i as i64 % 20 + 1, // 1-20 files
|
|
total_size_bytes: (i as i64 + 1) * 4000, // Varying sizes
|
|
};
|
|
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - About to call create_or_update_webdav_directory for dir {}", test_start_time.elapsed(), i);
|
|
match state.db.create_or_update_webdav_directory(&dir).await {
|
|
Ok(_) => {
|
|
if i < 10 || dir_create_start.elapsed().as_millis() > 100 {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Successfully created directory {} in {:?}",
|
|
test_start_time.elapsed(), i, dir_create_start.elapsed());
|
|
}
|
|
}
|
|
Err(e) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - ERROR: Failed to create old directory {}: {}", test_start_time.elapsed(), i, e);
|
|
panic!("Failed to create old directory {}: {}", i, e);
|
|
}
|
|
}
|
|
old_directories.push(dir);
|
|
|
|
// Check for potential infinite loops by timing individual operations
|
|
if dir_create_start.elapsed().as_secs() > 5 {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - WARNING: Directory creation {} took {:?} (> 5s)",
|
|
test_start_time.elapsed(), i, dir_create_start.elapsed());
|
|
}
|
|
}
|
|
let create_duration = create_start.elapsed();
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Completed creation of {} directories in {:?}",
|
|
test_start_time.elapsed(), num_old_dirs, create_duration);
|
|
|
|
// Verify old directories were created
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Verifying old directories were created...", test_start_time.elapsed());
|
|
let list_start = std::time::Instant::now();
|
|
let before_count = match state.db.list_webdav_directories(user.id).await {
|
|
Ok(dirs) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Successfully listed {} directories in {:?}",
|
|
test_start_time.elapsed(), dirs.len(), list_start.elapsed());
|
|
dirs.len()
|
|
}
|
|
Err(e) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - ERROR: Failed to list directories: {}", test_start_time.elapsed(), e);
|
|
panic!("Failed to list directories: {}", e);
|
|
}
|
|
};
|
|
assert_eq!(before_count, num_old_dirs, "Should have created {} old directories", num_old_dirs);
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Verification passed: {} directories found", test_start_time.elapsed(), before_count);
|
|
|
|
// Simulate deep scan reset - delete all existing
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Starting deletion phase...", test_start_time.elapsed());
|
|
let delete_start = std::time::Instant::now();
|
|
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Fetching directories to delete...", test_start_time.elapsed());
|
|
let fetch_delete_start = std::time::Instant::now();
|
|
let dirs_to_delete = match state.db.list_webdav_directories(user.id).await {
|
|
Ok(dirs) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Fetched {} directories to delete in {:?}",
|
|
test_start_time.elapsed(), dirs.len(), fetch_delete_start.elapsed());
|
|
dirs
|
|
}
|
|
Err(e) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - ERROR: Failed to fetch directories for deletion: {}", test_start_time.elapsed(), e);
|
|
panic!("Failed to fetch directories for deletion: {}", e);
|
|
}
|
|
};
|
|
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Beginning deletion of {} directories...", test_start_time.elapsed(), dirs_to_delete.len());
|
|
for (idx, dir) in dirs_to_delete.iter().enumerate() {
|
|
if idx % 50 == 0 || idx < 10 {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Deleting directory {}/{} ({}%): {}",
|
|
test_start_time.elapsed(),
|
|
idx + 1,
|
|
dirs_to_delete.len(),
|
|
((idx + 1) * 100) / dirs_to_delete.len(),
|
|
dir.directory_path
|
|
);
|
|
}
|
|
|
|
let delete_item_start = std::time::Instant::now();
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - About to delete directory: {}", test_start_time.elapsed(), dir.directory_path);
|
|
match state.db.delete_webdav_directory(user.id, &dir.directory_path).await {
|
|
Ok(_) => {
|
|
if idx < 10 || delete_item_start.elapsed().as_millis() > 100 {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Successfully deleted directory {} in {:?}",
|
|
test_start_time.elapsed(), dir.directory_path, delete_item_start.elapsed());
|
|
}
|
|
}
|
|
Err(e) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - ERROR: Failed to delete directory {}: {}",
|
|
test_start_time.elapsed(), dir.directory_path, e);
|
|
panic!("Failed to delete directory during deep scan: {}", e);
|
|
}
|
|
}
|
|
|
|
// Check for potential infinite loops
|
|
if delete_item_start.elapsed().as_secs() > 5 {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - WARNING: Directory deletion {} took {:?} (> 5s)",
|
|
test_start_time.elapsed(), dir.directory_path, delete_item_start.elapsed());
|
|
}
|
|
}
|
|
let delete_duration = delete_start.elapsed();
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Completed deletion of {} directories in {:?}",
|
|
test_start_time.elapsed(), dirs_to_delete.len(), delete_duration);
|
|
|
|
// Verify cleanup
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Verifying cleanup...", test_start_time.elapsed());
|
|
let verify_cleanup_start = std::time::Instant::now();
|
|
let cleared_count = match state.db.list_webdav_directories(user.id).await {
|
|
Ok(dirs) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Cleanup verification: {} directories remaining in {:?}",
|
|
test_start_time.elapsed(), dirs.len(), verify_cleanup_start.elapsed());
|
|
dirs.len()
|
|
}
|
|
Err(e) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - ERROR: Failed to verify cleanup: {}", test_start_time.elapsed(), e);
|
|
panic!("Failed to verify cleanup: {}", e);
|
|
}
|
|
};
|
|
assert_eq!(cleared_count, 0, "Should have cleared all directories");
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Cleanup verification passed: 0 directories remaining", test_start_time.elapsed());
|
|
|
|
// Create new directories (simulating rediscovery)
|
|
let num_new_dirs = 300; // Slightly different number
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Starting recreation of {} new directories", test_start_time.elapsed(), num_new_dirs);
|
|
let recreate_start = std::time::Instant::now();
|
|
|
|
for i in 0..num_new_dirs {
|
|
if i % 50 == 0 || i < 10 {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Creating new directory {}/{} ({}%)",
|
|
test_start_time.elapsed(),
|
|
i + 1,
|
|
num_new_dirs,
|
|
((i + 1) * 100) / num_new_dirs
|
|
);
|
|
}
|
|
|
|
let recreate_item_start = std::time::Instant::now();
|
|
let dir = CreateWebDAVDirectory {
|
|
user_id: user.id,
|
|
directory_path: format!("/Documents/New{:03}", i),
|
|
directory_etag: format!("new-etag-{:03}", i),
|
|
file_count: i as i64 % 15 + 1, // 1-15 files
|
|
total_size_bytes: (i as i64 + 1) * 5000, // Different sizing
|
|
};
|
|
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - About to create new directory {}", test_start_time.elapsed(), i);
|
|
match state.db.create_or_update_webdav_directory(&dir).await {
|
|
Ok(_) => {
|
|
if i < 10 || recreate_item_start.elapsed().as_millis() > 100 {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Successfully created new directory {} in {:?}",
|
|
test_start_time.elapsed(), i, recreate_item_start.elapsed());
|
|
}
|
|
}
|
|
Err(e) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - ERROR: Failed to create new directory {}: {}", test_start_time.elapsed(), i, e);
|
|
panic!("Failed to create new directory {}: {}", i, e);
|
|
}
|
|
}
|
|
|
|
// Check for potential infinite loops
|
|
if recreate_item_start.elapsed().as_secs() > 5 {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - WARNING: New directory creation {} took {:?} (> 5s)",
|
|
test_start_time.elapsed(), i, recreate_item_start.elapsed());
|
|
}
|
|
}
|
|
let recreate_duration = recreate_start.elapsed();
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Completed recreation of {} directories in {:?}",
|
|
test_start_time.elapsed(), num_new_dirs, recreate_duration);
|
|
|
|
// Verify final state
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Verifying final state...", test_start_time.elapsed());
|
|
let final_verify_start = std::time::Instant::now();
|
|
let final_count = match state.db.list_webdav_directories(user.id).await {
|
|
Ok(dirs) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Final verification: {} directories found in {:?}",
|
|
test_start_time.elapsed(), dirs.len(), final_verify_start.elapsed());
|
|
dirs.len()
|
|
}
|
|
Err(e) => {
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - ERROR: Failed to verify final state: {}", test_start_time.elapsed(), e);
|
|
panic!("Failed to verify final state: {}", e);
|
|
}
|
|
};
|
|
assert_eq!(final_count, num_new_dirs, "Should have created {} new directories", num_new_dirs);
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Final verification passed: {} directories found", test_start_time.elapsed(), final_count);
|
|
|
|
// Performance assertions - should complete within reasonable time
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Running performance assertions...", test_start_time.elapsed());
|
|
assert!(create_duration.as_secs() < 30, "Creating {} directories should take < 30s, took {:?}", num_old_dirs, create_duration);
|
|
assert!(delete_duration.as_secs() < 15, "Deleting {} directories should take < 15s, took {:?}", num_old_dirs, delete_duration);
|
|
assert!(recreate_duration.as_secs() < 30, "Recreating {} directories should take < 30s, took {:?}", num_new_dirs, recreate_duration);
|
|
|
|
let total_duration = create_duration + delete_duration + recreate_duration;
|
|
let overall_test_duration = test_start_time.elapsed();
|
|
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - All performance assertions passed", test_start_time.elapsed());
|
|
|
|
println!("✅ Deep scan performance test completed successfully");
|
|
println!(" Created {} old directories in {:?}", num_old_dirs, create_duration);
|
|
println!(" Deleted {} directories in {:?}", num_old_dirs, delete_duration);
|
|
println!(" Created {} new directories in {:?}", num_new_dirs, recreate_duration);
|
|
println!(" Total deep scan simulation time: {:?}", total_duration);
|
|
println!(" Overall test duration: {:?}", overall_test_duration);
|
|
|
|
eprintln!("[DEEP_SCAN_TEST] {:?} - Test completed successfully!", test_start_time.elapsed());
|
|
}
|
|
} |