mindb 0.1.2

Lightweight embedded key–value store with write-ahead log and zstd compression.
Documentation
use std::time::Duration;

use mindb::config::{ConfigManager, DbConfig};

fn temp_config() -> DbConfig {
    DbConfig::new(std::env::temp_dir().join("mindb-tests"))
}

#[test]
fn default_configuration_is_valid() {
    let config = temp_config();
    assert!(config.validate().is_ok());
}

#[test]
fn invalid_cache_size_is_rejected() {
    let mut config = temp_config();
    config.cache_bytes = 1024;

    let result = config.validate();
    assert!(result.is_err(), "Expected validation error for tiny cache");
}

#[test]
fn invalid_wal_group_interval_is_rejected() {
    let mut config = temp_config();
    config.wal_group_interval_ms = 0;

    let result = config.validate();
    assert!(
        result
            .expect_err("validation should fail when wal_group_interval_ms is zero")
            .to_string()
            .contains("wal_group_interval_ms"),
        "error message should mention the offending field"
    );
}

#[test]
fn invalid_wal_max_batch_ops_is_rejected() {
    let mut config = temp_config();
    config.wal_max_batch_ops = 0;

    let result = config.validate();
    assert!(
        result.is_err(),
        "Expected validation error for wal_max_batch_ops"
    );
}

#[test]
fn wal_group_interval_has_lower_bound() {
    let mut config = temp_config();
    config.wal_group_interval_ms = 0;

    // Even without validation the accessor enforces the documented lower bound.
    assert_eq!(config.wal_group_interval(), Duration::from_millis(1));
}

#[test]
fn config_manager_notifies_on_reload() {
    let config = temp_config();
    let manager = ConfigManager::new(config.clone()).expect("initial config should validate");
    let receiver = manager.subscribe();

    // Initial snapshot is sent immediately.
    let initial = receiver.recv().expect("should receive initial config");
    assert_eq!(initial.cache_bytes, config.cache_bytes);

    manager
        .update(|cfg| cfg.cache_bytes *= 2)
        .expect("update should keep config valid");

    let updated = receiver
        .recv_timeout(Duration::from_millis(100))
        .expect("should receive updated configuration");
    assert_eq!(updated.cache_bytes, config.cache_bytes * 2);
}

#[test]
fn config_manager_allows_multiple_subscribers() {
    let config = temp_config();
    let manager = ConfigManager::new(config.clone()).expect("initial config should validate");
    let recv_a = manager.subscribe();
    let recv_b = manager.subscribe();

    // Drain the initial snapshots sent on subscription.
    recv_a.recv().expect("subscriber A should receive snapshot");
    recv_b.recv().expect("subscriber B should receive snapshot");

    manager
        .update(|cfg| cfg.wal_group_bytes *= 2)
        .expect("update should keep config valid");

    let updated_a = recv_a
        .recv_timeout(Duration::from_millis(100))
        .expect("subscriber A should receive update");
    let updated_b = recv_b
        .recv_timeout(Duration::from_millis(100))
        .expect("subscriber B should receive update");

    assert_eq!(updated_a.wal_group_bytes, config.wal_group_bytes * 2);
    assert_eq!(updated_b.wal_group_bytes, config.wal_group_bytes * 2);
}