use super::*; #[test] fn builder_ephemeral_succeeds() { let db = TidalDb::builder().ephemeral().open(); assert!(db.is_ok()); } #[test] fn builder_default_is_ephemeral() { let db = TidalDb::builder().open(); assert!(db.is_ok()); } #[test] fn builder_persistent_requires_data_dir() { // Construct a persistent-mode builder without calling with_data_dir // by manually setting mode. let builder = TidalDbBuilder { config: Config { mode: StorageMode::Persistent, data_dir: None, wal_dir: None, cache_dir: None, cluster: Default::default(), }, metrics_addr: None, schema: None, rate_limiter_config: None, }; let result = builder.validate(); assert!(result.is_err()); let err = result.expect_err("should fail"); assert!( matches!(err, ConfigError::MissingDataDir), "expected MissingDataDir, got: {err}" ); } #[test] fn builder_persistent_missing_dir() { let result = TidalDb::builder() .with_data_dir("/nonexistent/path/that/does/not/exist") .open(); assert!(result.is_err()); let err_msg = result.expect_err("should fail").to_string(); assert!( err_msg.contains("does not exist"), "expected DirectoryNotFound, got: {err_msg}" ); } #[test] fn builder_persistent_existing_dir() { let tmp = tempfile::tempdir().expect("failed to create tempdir"); let result = TidalDb::builder().with_data_dir(tmp.path()).open(); assert!(result.is_ok(), "open with valid tempdir should succeed"); } #[test] fn health_check_ok() { let db = TidalDb::builder().ephemeral().open().expect("open failed"); assert!(db.health_check().is_ok()); } #[test] fn close_ok() { let db = TidalDb::builder().ephemeral().open().expect("open failed"); assert!(db.close().is_ok()); } #[test] fn builder_with_wal_and_cache_dir() { let tmp = tempfile::tempdir().expect("failed to create tempdir"); let wal = tmp.path().join("wal"); let cache = tmp.path().join("cache"); std::fs::create_dir_all(&wal).expect("mkdir wal"); std::fs::create_dir_all(&cache).expect("mkdir cache"); let result = TidalDb::builder() .with_data_dir(tmp.path()) .wal_dir(&wal) .cache_dir(&cache) .open(); assert!( result.is_ok(), "open with explicit wal/cache dirs should succeed" ); } #[test] fn builder_ephemeral_resets_dirs() { let builder = TidalDb::builder() .with_data_dir("/some/path") .wal_dir("/some/wal") .cache_dir("/some/cache") .ephemeral(); assert_eq!(builder.config.mode, StorageMode::Ephemeral); assert!(builder.config.data_dir.is_none()); assert!(builder.config.wal_dir.is_none()); assert!(builder.config.cache_dir.is_none()); } #[test] fn builder_wal_dir_nonexistent() { let tmp = tempfile::tempdir().expect("failed to create tempdir"); let result = TidalDb::builder() .with_data_dir(tmp.path()) .wal_dir("/nonexistent/wal") .open(); assert!(result.is_err()); let err_msg = result.expect_err("should fail").to_string(); assert!(err_msg.contains("does not exist")); } #[test] fn resolve_defaults_sets_wal_and_cache() { let tmp = tempfile::tempdir().expect("failed to create tempdir"); let mut builder = TidalDb::builder().with_data_dir(tmp.path()); assert!(builder.config.wal_dir.is_none()); assert!(builder.config.cache_dir.is_none()); builder.resolve_defaults(); let paths = Paths::new(tmp.path()); assert_eq!(builder.config.wal_dir.as_ref(), Some(&paths.wal_dir())); assert_eq!(builder.config.cache_dir.as_ref(), Some(&paths.cache_dir())); } #[test] fn resolve_defaults_preserves_explicit_overrides() { let tmp = tempfile::tempdir().expect("failed to create tempdir"); let custom_wal = tmp.path().join("custom_wal"); let custom_cache = tmp.path().join("custom_cache"); let mut builder = TidalDb::builder() .with_data_dir(tmp.path()) .wal_dir(&custom_wal) .cache_dir(&custom_cache); builder.resolve_defaults(); assert_eq!(builder.config.wal_dir.as_ref(), Some(&custom_wal)); assert_eq!(builder.config.cache_dir.as_ref(), Some(&custom_cache)); } #[test] fn resolve_defaults_noop_for_ephemeral() { let mut builder = TidalDb::builder().ephemeral(); builder.resolve_defaults(); assert!(builder.config.wal_dir.is_none()); assert!(builder.config.cache_dir.is_none()); } // ── Fix A: Directory lock tests ───────────────────────────────────── #[test] fn dual_open_same_directory_fails() { let dir = tempfile::tempdir().expect("tempdir"); // First open succeeds (no schema -- M0 mode, but still persistent). let _db1 = TidalDb::builder() .with_data_dir(dir.path().to_path_buf()) .open() .expect("first open should succeed"); // Second open on the same directory must fail with DataDirLocked. let result = TidalDb::builder() .with_data_dir(dir.path().to_path_buf()) .open(); assert!(result.is_err(), "expected error for dual open"); let err_msg = result.expect_err("should fail").to_string(); assert!( err_msg.contains("already open"), "expected DataDirLocked, got: {err_msg}" ); } #[test] fn lock_released_after_close() { let dir = tempfile::tempdir().expect("tempdir"); { let db = TidalDb::builder() .with_data_dir(dir.path().to_path_buf()) .open() .expect("open"); db.close().expect("close"); } // After close (and drop), the lock should be released. let db2 = TidalDb::builder() .with_data_dir(dir.path().to_path_buf()) .open(); assert!( db2.is_ok(), "second open after close should succeed: {:?}", db2.err() ); } #[test] fn ephemeral_mode_skips_lock() { // Two ephemeral databases should both succeed (no lock file). let _db1 = TidalDb::builder().ephemeral().open().expect("open 1"); let _db2 = TidalDb::builder().ephemeral().open().expect("open 2"); }