//! Integration tests for the zaz database module use crate::core::{DB, DBBuilder, SledDBResult, Storable, SledModel, SledDB}; use crate::zaz::models::user::User; use crate::zaz::models::company::{Company, BusinessType, CompanyStatus}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use std::fs; use std::path::Path; use tempfile::tempdir; use std::fmt::{Display, Formatter}; /// Test the basic database functionality #[test] fn test_basic_database_operations() { match run_comprehensive_test() { Ok(_) => println!("All tests passed successfully!"), Err(e) => panic!("Error running tests: {}", e), } } fn run_comprehensive_test() -> Result<(), Box> { // Create a temporary directory for testing let temp_dir = tempdir()?; println!("Using temporary directory: {:?}", temp_dir.path()); println!("\n--- Testing User operations ---"); test_user_operations(temp_dir.path())?; println!("\n--- Testing Company operations ---"); test_company_operations(temp_dir.path())?; println!("\n--- Testing Transaction Simulation ---"); test_transaction_simulation(temp_dir.path())?; // Clean up drop(temp_dir); println!("All comprehensive tests completed successfully!"); Ok(()) } fn test_user_operations(base_path: &Path) -> Result<(), Box> { // Open the user database let db = SledDB::::open(base_path.join("users"))?; println!("Opened user database at: {:?}", base_path.join("users")); // Create a test user let user = User::new( 100, "Test User".to_string(), "test@example.com".to_string(), "password123".to_string(), "Test Company".to_string(), "Admin".to_string(), ); // Insert the user db.insert(&user)?; println!("Inserted user: {}", user.name); // Retrieve the user let retrieved_user = db.get(&user.id.to_string())?; println!("Retrieved user: {}", retrieved_user.name); assert_eq!(user.name, retrieved_user.name); assert_eq!(user.email, retrieved_user.email); // Update the user let updated_user = User::new( 100, "Updated User".to_string(), "updated@example.com".to_string(), "newpassword".to_string(), "New Company".to_string(), "SuperAdmin".to_string(), ); db.insert(&updated_user)?; println!("Updated user: {}", updated_user.name); // Retrieve the updated user let retrieved_user = db.get(&user.id.to_string())?; println!("Retrieved updated user: {}", retrieved_user.name); assert_eq!(updated_user.name, retrieved_user.name); assert_eq!(updated_user.email, retrieved_user.email); // Delete the user db.delete(&user.id.to_string())?; println!("Deleted user: {}", user.name); // Try to retrieve the deleted user (should fail) let result = db.get(&user.id.to_string()); assert!(result.is_err(), "User should be deleted"); println!("Verified user was deleted"); Ok(()) } fn test_company_operations(base_path: &Path) -> Result<(), Box> { // Open the company database let db = SledDB::::open(base_path.join("companies"))?; println!("Opened company database at: {:?}", base_path.join("companies")); // Create a test company let company = Company::new( 100, "Test Corp".to_string(), "TEST123".to_string(), Utc::now(), "12-31".to_string(), "test@corp.com".to_string(), "123-456-7890".to_string(), "www.testcorp.com".to_string(), "123 Test St".to_string(), BusinessType::new(BusinessType::GLOBAL.to_string()) .unwrap_or_else(|e| { eprintln!("Warning: {}", e); BusinessType::new_unchecked(BusinessType::GLOBAL.to_string()) }), "Technology".to_string(), "A test company".to_string(), CompanyStatus::Active, ); // Insert the company db.insert(&company)?; println!("Inserted company: {}", company.name); // Retrieve the company let retrieved_company = db.get(&company.id.to_string())?; println!("Retrieved company: {}", retrieved_company.name); assert_eq!(company.name, retrieved_company.name); // List all companies let companies = db.list()?; println!("Found {} companies", companies.len()); assert_eq!(companies.len(), 1); // Delete the company db.delete(&company.id.to_string())?; println!("Deleted company: {}", company.name); // List companies again (should be empty) let companies = db.list()?; assert_eq!(companies.len(), 0); println!("Verified company was deleted"); Ok(()) } fn test_transaction_simulation(base_path: &Path) -> Result<(), Box> { // Create a DB instance with User model registered let mut db = DB::new(base_path.join("transaction"))?; db.register::()?; println!("Created DB with User model registered at: {:?}", base_path.join("transaction")); // Add a user outside of transaction let user = User::new( 200, "Transaction Test".to_string(), "tx@example.com".to_string(), "password".to_string(), "TX Corp".to_string(), "User".to_string(), ); // Add the user without a transaction db.set(&user)?; println!("Added initial user: {}", user.name); // Begin a transaction db.begin_transaction()?; println!("Transaction started"); // Update user in transaction let updated_user = User::new( 200, "Updated in TX".to_string(), "updated@example.com".to_string(), "newpass".to_string(), "New Corp".to_string(), "Admin".to_string(), ); db.set(&updated_user)?; println!("Updated user in transaction"); // Add new user in transaction let new_user = User::new( 201, "New in TX".to_string(), "new@example.com".to_string(), "password".to_string(), "New Corp".to_string(), "User".to_string(), ); db.set(&new_user)?; println!("Added new user in transaction"); // Verify transaction changes are visible within transaction let tx_user: User = db.get(&user.id.to_string())?; assert_eq!(tx_user.name, "Updated in TX"); println!("Verified transaction changes are visible"); // Commit the transaction db.commit_transaction()?; println!("Transaction committed"); // Verify changes persisted after commit let committed_user: User = db.get(&user.id.to_string())?; assert_eq!(committed_user.name, "Updated in TX"); println!("Verified changes persisted after commit"); // Test transaction rollback // Begin another transaction db.begin_transaction()?; println!("New transaction started"); // Make changes that will be rolled back let rollback_user = User::new( 200, "Will Be Rolled Back".to_string(), "rollback@example.com".to_string(), "temppass".to_string(), "Temp Corp".to_string(), "TempAdmin".to_string(), ); db.set(&rollback_user)?; println!("Updated user in transaction that will be rolled back"); // Rollback the transaction db.rollback_transaction()?; println!("Transaction rolled back"); // Verify original data is intact let after_rollback: User = db.get(&user.id.to_string())?; assert_eq!(after_rollback.name, "Updated in TX"); println!("Verified data is intact after rollback: {}", after_rollback.name); Ok(()) } #[test] fn test_simple_db() { // A simpler test that uses a basic DB setup // Test model #[derive(Debug, Clone, Serialize, Deserialize)] struct User { id: u32, name: String, email: String, } impl User { fn new(id: u32, name: String, email: String) -> Self { Self { id, name, email } } } impl Storable for User {} impl SledModel for User { fn get_id(&self) -> String { self.id.to_string() } fn db_prefix() -> &'static str { "test_simple_user" } } // Create a temporary directory for the test let dir = tempdir().expect("Failed to create temp dir"); // Create a DB with the builder let db = DBBuilder::new(dir.path()) .register_model::() .build() .expect("Failed to build DB"); // Create a test user let user = User::new(1, "Simple Test User".to_string(), "simple@example.com".to_string()); // Set the user db.set(&user).expect("Failed to set user"); // Get the user let retrieved: User = db.get(&user.id.to_string()).expect("Failed to get user"); // Check that it matches assert_eq!(user.name, retrieved.name); assert_eq!(user.email, retrieved.email); println!("Simple DB test passed!"); }