//! Integration tests for the library system use sd_core::Core; use tempfile::TempDir; #[tokio::test] async fn test_library_lifecycle() { // Create temporary directory for test let temp_dir = TempDir::new().unwrap(); // Initialize core with custom data directory let core = Core::new(temp_dir.path().to_path_buf()).await.unwrap(); // Create library (will be created in the libraries directory) let library = core .libraries .create_library("Test Library", None, core.context.clone()) .await .unwrap(); assert_eq!(library.name().await, "Test Library"); // Verify directory structure let lib_path = library.path(); assert!(lib_path.exists()); assert!(lib_path.join("library.json").exists()); assert!(lib_path.join("database.db").exists()); assert!(lib_path.join("thumbnails").exists()); assert!(lib_path.join("thumbnails/metadata.json").exists()); // Test thumbnail operations // let cas_id = "test123"; // let thumb_data = b"test thumbnail data"; // library.save_thumbnail(cas_id, thumb_data).await.unwrap(); // assert!(library.has_thumbnail(cas_id).await); // let retrieved = library.get_thumbnail(cas_id).await.unwrap(); // assert_eq!(retrieved, thumb_data); // Test configuration update library .update_config(|config| { config.description = Some("Test description".to_string()); config.settings.thumbnail_quality = 90; }) .await .unwrap(); let config = library.config().await; assert_eq!(config.description, Some("Test description".to_string())); assert_eq!(config.settings.thumbnail_quality, 90); // Close library let lib_id = library.id(); let lib_path = library.path().to_path_buf(); core.libraries.close_library(lib_id).await.unwrap(); // Drop the library reference to release the lock drop(library); // Verify can't close again assert!(core.libraries.close_library(lib_id).await.is_err()); // Re-open library let reopened = core .libraries .open_library(&lib_path, core.context.clone()) .await .unwrap(); assert_eq!(reopened.id(), lib_id); assert_eq!(reopened.name().await, "Test Library"); // Verify data persisted // assert!(reopened.has_thumbnail(cas_id).await); let config = reopened.config().await; assert_eq!(config.description, Some("Test description".to_string())); } #[tokio::test] async fn test_library_locking() { let temp_dir = TempDir::new().unwrap(); let core = Core::new(temp_dir.path().to_path_buf()).await.unwrap(); // Create library let library = core .libraries .create_library("Lock Test", None, core.context.clone()) .await .unwrap(); let lib_path = library.path().to_path_buf(); // Try to open same library again - should fail let result = core .libraries .open_library(&lib_path, core.context.clone()) .await; assert!(result.is_err()); // Close library let lib_id = library.id(); core.libraries.close_library(lib_id).await.unwrap(); // Drop the library reference to release the lock drop(library); // Now should be able to open let reopened = core .libraries .open_library(&lib_path, core.context.clone()) .await .unwrap(); assert_eq!(reopened.name().await, "Lock Test"); } #[tokio::test] async fn test_library_discovery() { let temp_dir = TempDir::new().unwrap(); let core = Core::new(temp_dir.path().to_path_buf()).await.unwrap(); // Create multiple libraries let lib1 = core .libraries .create_library("Library 1", None, core.context.clone()) .await .unwrap(); let lib2 = core .libraries .create_library("Library 2", None, core.context.clone()) .await .unwrap(); // Close both let lib1_id = lib1.id(); let lib2_id = lib2.id(); core.libraries.close_library(lib1_id).await.unwrap(); core.libraries.close_library(lib2_id).await.unwrap(); // Drop library references to release locks drop(lib1); drop(lib2); // Test auto-loading - reload all libraries let loaded_count = core.libraries.load_all(core.context.clone()).await.unwrap(); assert!(loaded_count >= 2); // Verify libraries were loaded let open_libraries = core.libraries.list().await; let names: Vec = futures::future::join_all(open_libraries.iter().map(|lib| lib.name())).await; assert!(names.iter().any(|n| n == "Library 1")); assert!(names.iter().any(|n| n == "Library 2")); } #[tokio::test] async fn test_library_name_sanitization() { let temp_dir = TempDir::new().unwrap(); let core = Core::new(temp_dir.path().to_path_buf()).await.unwrap(); // Create library with problematic name let library = core .libraries .create_library("My/Library:Name*", None, core.context.clone()) .await .unwrap(); // Verify directory name was sanitized let dir_name = library.path().file_name().unwrap().to_str().unwrap(); assert!(dir_name.ends_with(".sdlibrary")); assert!(!dir_name.contains('/')); assert!(!dir_name.contains(':')); assert!(!dir_name.contains('*')); } #[tokio::test] async fn test_default_library_creation() { let temp_dir = TempDir::new().unwrap(); // Initialize core with fresh temporary directory (no existing libraries) let core = Core::new(temp_dir.path().to_path_buf()).await.unwrap(); // Check that a default library was created automatically let open_libraries = core.libraries.list().await; assert_eq!( open_libraries.len(), 1, "Expected exactly one default library to be created" ); let default_library = &open_libraries[0]; assert_eq!( default_library.name().await, "My Library", "Default library should be named 'My Library'" ); // Verify directory structure exists let lib_path = default_library.path(); assert!(lib_path.exists()); assert!(lib_path.join("library.json").exists()); assert!(lib_path.join("database.db").exists()); assert!(lib_path.join("thumbnails").exists()); }