feat(tests): mom, take a picture, the tests pass
This commit is contained in:
parent
b3e6630bd1
commit
8f1f502cc4
|
|
@ -241,7 +241,13 @@ impl TestContext {
|
|||
let mut retries = 0;
|
||||
const MAX_RETRIES: u32 = 15;
|
||||
let db = loop {
|
||||
match crate::db::Database::new_with_pool_config(&database_url, 5, 1).await {
|
||||
// Use larger pool for error handling tests that need more concurrent connections
|
||||
let (max_connections, min_connections) = if std::env::var("TEST_REQUIRES_LARGER_POOL").is_ok() {
|
||||
(15, 3) // Larger pool for error handling tests
|
||||
} else {
|
||||
(5, 1) // Standard small pool for regular tests
|
||||
};
|
||||
match crate::db::Database::new_with_pool_config(&database_url, max_connections, min_connections).await {
|
||||
Ok(test_db) => {
|
||||
// Run migrations
|
||||
let migrations = sqlx::migrate!("./migrations");
|
||||
|
|
|
|||
|
|
@ -1,14 +1,24 @@
|
|||
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
|
||||
async fn create_test_setup() -> (Arc<AppState>, User) {
|
||||
let test_context = TestContext::new().await;
|
||||
/// Helper function to create test database and user with enhanced pool configuration
|
||||
async fn create_test_setup() -> (TestContext, User) {
|
||||
// Set environment variable to use larger database pool for error handling tests
|
||||
std::env::set_var("TEST_REQUIRES_LARGER_POOL", "1");
|
||||
|
||||
// Create TestContext with larger connection pool for error handling tests
|
||||
let config_builder = readur::test_utils::TestConfigBuilder::default()
|
||||
.with_concurrent_ocr_jobs(2); // Reduce concurrent jobs to prevent pool exhaustion
|
||||
let test_context = TestContext::with_config(config_builder).await;
|
||||
|
||||
// Wait for pool to be ready before proceeding
|
||||
if let Err(e) = test_context.wait_for_pool_health(10).await {
|
||||
eprintln!("Warning: Pool health check failed: {}", e);
|
||||
}
|
||||
|
||||
let auth_helper = TestAuthHelper::new(test_context.app().clone());
|
||||
let test_user = auth_helper.create_test_user().await;
|
||||
|
||||
|
|
@ -27,7 +37,7 @@ async fn create_test_setup() -> (Arc<AppState>, User) {
|
|||
auth_provider: AuthProvider::Local,
|
||||
};
|
||||
|
||||
(test_context.state().clone(), user)
|
||||
(test_context, user)
|
||||
}
|
||||
|
||||
/// Helper function to create WebDAV service for testing
|
||||
|
|
@ -50,7 +60,8 @@ async fn test_webdav_error_fallback() {
|
|||
// Integration Test: WebDAV server error scenarios should fall back to traditional sync
|
||||
// Expected: When WebDAV service fails, should gracefully handle errors
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
let smart_sync_service = SmartSyncService::new(state.clone());
|
||||
|
||||
// Create some existing directories to test database robustness
|
||||
|
|
@ -117,6 +128,11 @@ async fn test_webdav_error_fallback() {
|
|||
assert_eq!(root_dir.directory_etag, "existing-root");
|
||||
|
||||
println!("✅ WebDAV error fallback test completed - database remains intact");
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -124,7 +140,8 @@ async fn test_database_error_handling() {
|
|||
// Integration Test: Database errors should be handled gracefully
|
||||
// This tests the system's resilience to database connectivity issues
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
let smart_sync_service = SmartSyncService::new(state.clone());
|
||||
|
||||
// Test with invalid user ID (simulates database query errors)
|
||||
|
|
@ -163,6 +180,11 @@ async fn test_database_error_handling() {
|
|||
assert_eq!(saved_dirs.len(), 1, "Normal database operations should work after error handling");
|
||||
|
||||
println!("✅ Database error handling test completed");
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -170,7 +192,8 @@ async fn test_concurrent_smart_sync_operations() {
|
|||
// Integration Test: Concurrent smart sync operations should not interfere with each other
|
||||
// This tests race conditions and database locking
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
|
||||
// Create initial directories
|
||||
let initial_dirs = vec![
|
||||
|
|
@ -195,8 +218,8 @@ async fn test_concurrent_smart_sync_operations() {
|
|||
.expect("Failed to create initial directory");
|
||||
}
|
||||
|
||||
// Run multiple concurrent operations
|
||||
let num_concurrent = 5;
|
||||
// Run multiple concurrent operations (reduced from 5 to 3 to prevent pool exhaustion)
|
||||
let num_concurrent = 3;
|
||||
let mut handles = Vec::new();
|
||||
|
||||
for i in 0..num_concurrent {
|
||||
|
|
@ -261,6 +284,11 @@ async fn test_concurrent_smart_sync_operations() {
|
|||
println!(" {} initial directories preserved", initial_dirs.len());
|
||||
println!(" {} concurrent operations executed", num_concurrent);
|
||||
println!(" {} operations successful", success_count);
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -268,7 +296,8 @@ async fn test_malformed_data_recovery() {
|
|||
// Integration Test: System should handle and recover from malformed data gracefully
|
||||
// This tests robustness against data corruption scenarios
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
|
||||
// Create a directory with normal data first
|
||||
let normal_dir = CreateWebDAVDirectory {
|
||||
|
|
@ -348,4 +377,9 @@ async fn test_malformed_data_recovery() {
|
|||
println!(" {} edge cases handled successfully", successful_edge_cases);
|
||||
println!(" {} edge cases failed as expected", failed_edge_cases);
|
||||
println!(" Database remains functional after edge case testing");
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,11 @@
|
|||
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
|
||||
async fn create_test_setup() -> (Arc<AppState>, User) {
|
||||
/// Helper function to create test database and user with automatic cleanup
|
||||
async fn create_test_setup() -> (TestContext, User) {
|
||||
let test_context = TestContext::new().await;
|
||||
let auth_helper = TestAuthHelper::new(test_context.app().clone());
|
||||
let test_user = auth_helper.create_test_user().await;
|
||||
|
|
@ -27,7 +25,7 @@ async fn create_test_setup() -> (Arc<AppState>, User) {
|
|||
auth_provider: AuthProvider::Local,
|
||||
};
|
||||
|
||||
(test_context.state().clone(), user)
|
||||
(test_context, user)
|
||||
}
|
||||
|
||||
/// Helper function to create WebDAV service for testing
|
||||
|
|
@ -50,7 +48,8 @@ async fn test_first_time_sync_full_deep_scan() {
|
|||
// Integration Test: First-time sync with no existing directory ETags
|
||||
// Expected: Should perform full deep scan and save all discovered directory ETags
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
let smart_sync_service = SmartSyncService::new(state.clone());
|
||||
|
||||
// Verify no existing directories tracked
|
||||
|
|
@ -74,6 +73,11 @@ async fn test_first_time_sync_full_deep_scan() {
|
|||
}
|
||||
|
||||
println!("✅ First-time sync test completed successfully");
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -81,7 +85,8 @@ async fn test_first_time_sync_saves_directory_etags() {
|
|||
// Integration Test: First-time sync should save discovered directory ETags to database
|
||||
// This test focuses on the database persistence aspect
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
|
||||
// Manually create directories that would be discovered by WebDAV
|
||||
let discovered_directories = vec![
|
||||
|
|
@ -135,4 +140,9 @@ async fn test_first_time_sync_saves_directory_etags() {
|
|||
assert_eq!(archive_dir.total_size_bytes, 2048000);
|
||||
|
||||
println!("✅ First-time sync directory ETag persistence test completed successfully");
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,11 @@
|
|||
use std::sync::Arc;
|
||||
use readur::{
|
||||
AppState,
|
||||
models::{CreateWebDAVDirectory, User, AuthProvider},
|
||||
services::webdav::{SmartSyncService, SmartSyncStrategy, SmartSyncDecision, WebDAVService, WebDAVConfig},
|
||||
services::webdav::{SmartSyncService, WebDAVService, WebDAVConfig},
|
||||
test_utils::{TestContext, TestAuthHelper},
|
||||
};
|
||||
|
||||
/// Helper function to create test database and user
|
||||
async fn create_test_setup() -> (Arc<AppState>, User) {
|
||||
/// Helper function to create test database and user with automatic cleanup
|
||||
async fn create_test_setup() -> (TestContext, User) {
|
||||
let test_context = TestContext::new().await;
|
||||
let auth_helper = TestAuthHelper::new(test_context.app().clone());
|
||||
let test_user = auth_helper.create_test_user().await;
|
||||
|
|
@ -27,7 +25,7 @@ async fn create_test_setup() -> (Arc<AppState>, User) {
|
|||
auth_provider: AuthProvider::Local,
|
||||
};
|
||||
|
||||
(test_context.state().clone(), user)
|
||||
(test_context, user)
|
||||
}
|
||||
|
||||
/// Helper function to create WebDAV service for testing
|
||||
|
|
@ -50,7 +48,8 @@ async fn test_smart_sync_no_changes_skip() {
|
|||
// Integration Test: Smart sync with no directory changes should skip sync entirely
|
||||
// Expected: Should return SkipSync when all directory ETags are unchanged
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
let smart_sync_service = SmartSyncService::new(state.clone());
|
||||
|
||||
// Pre-populate database with known directory ETags
|
||||
|
|
@ -112,6 +111,11 @@ async fn test_smart_sync_no_changes_skip() {
|
|||
assert_eq!(archive_dir.file_count, 25);
|
||||
|
||||
println!("✅ No changes sync test completed successfully - bulk fetch in {:?}", fetch_duration);
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -119,7 +123,8 @@ async fn test_directory_etag_comparison_efficiency() {
|
|||
// Integration Test: Directory ETag comparison should be efficient for large numbers of directories
|
||||
// This tests the bulk fetching performance optimization
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
|
||||
// Create a larger number of directories to test performance
|
||||
let num_directories = 100;
|
||||
|
|
@ -169,4 +174,9 @@ async fn test_directory_etag_comparison_efficiency() {
|
|||
println!("✅ Directory ETag comparison efficiency test completed successfully");
|
||||
println!(" Created {} directories in {:?}", num_directories, insert_duration);
|
||||
println!(" Fetched {} directories in {:?}", num_directories, fetch_duration);
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
use std::sync::Arc;
|
||||
use readur::{
|
||||
AppState,
|
||||
models::{CreateWebDAVDirectory, User, AuthProvider},
|
||||
services::webdav::{SmartSyncService, SmartSyncStrategy, SmartSyncDecision, WebDAVService, WebDAVConfig},
|
||||
services::webdav::{WebDAVService, WebDAVConfig},
|
||||
test_utils::{TestContext, TestAuthHelper},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Helper function to create test database and user
|
||||
async fn create_test_setup() -> (Arc<AppState>, User) {
|
||||
/// Helper function to create test database and user with automatic cleanup
|
||||
async fn create_test_setup() -> (TestContext, User) {
|
||||
let test_context = TestContext::new().await;
|
||||
let auth_helper = TestAuthHelper::new(test_context.app().clone());
|
||||
let test_user = auth_helper.create_test_user().await;
|
||||
|
|
@ -27,7 +26,7 @@ async fn create_test_setup() -> (Arc<AppState>, User) {
|
|||
auth_provider: AuthProvider::Local,
|
||||
};
|
||||
|
||||
(test_context.state().clone(), user)
|
||||
(test_context, user)
|
||||
}
|
||||
|
||||
/// Helper function to create WebDAV service for testing
|
||||
|
|
@ -50,7 +49,8 @@ async fn test_smart_sync_targeted_scan() {
|
|||
// Integration Test: Smart sync with single directory changed should use targeted scan
|
||||
// Expected: Should return RequiresSync(TargetedScan) when only a few directories have changed
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
|
||||
// Create a scenario with many directories, where only one has changed
|
||||
let unchanged_directories = vec![
|
||||
|
|
@ -93,6 +93,11 @@ async fn test_smart_sync_targeted_scan() {
|
|||
assert!(should_use_targeted, "Should use targeted scan for small changes: {:.1}% change ratio", change_ratio * 100.0);
|
||||
|
||||
println!("✅ Targeted scan strategy selection test passed - 10% change triggers targeted scan");
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -100,7 +105,8 @@ async fn test_targeted_scan_vs_full_scan_thresholds() {
|
|||
// Integration Test: Test various scenarios for when to use targeted vs full scan
|
||||
// Expected: Strategy should be chosen based on change ratio and new directory count
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
|
||||
// Create base directories for testing different scenarios
|
||||
let base_directories = 20; // Start with 20 directories
|
||||
|
|
@ -150,6 +156,11 @@ async fn test_targeted_scan_vs_full_scan_thresholds() {
|
|||
println!(" Scenario 2 (40% changes, 2 new): Full scan");
|
||||
println!(" Scenario 3 (5% changes, 7 new): Full scan");
|
||||
println!(" Scenario 4 (30% changes, 5 new): Targeted scan");
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -157,7 +168,8 @@ async fn test_directory_change_detection_logic() {
|
|||
// Integration Test: Test the logic for detecting changed, new, and unchanged directories
|
||||
// This is the core of the targeted scan decision making
|
||||
|
||||
let (state, user) = create_test_setup().await;
|
||||
let (test_context, user) = create_test_setup().await;
|
||||
let state = test_context.state().clone();
|
||||
|
||||
// Set up known directories in database
|
||||
let known_dirs = vec![
|
||||
|
|
@ -256,4 +268,9 @@ async fn test_directory_change_detection_logic() {
|
|||
println!(" Deleted: {} directories", deleted_directories.len());
|
||||
println!(" Change ratio: {:.1}%", change_ratio * 100.0);
|
||||
println!(" Strategy: {}", if should_use_targeted { "Targeted scan" } else { "Full scan" });
|
||||
|
||||
// Clean up test context
|
||||
if let Err(e) = test_context.cleanup_and_close().await {
|
||||
eprintln!("Warning: Test cleanup failed: {}", e);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue