dittolive-ditto 5.0.3

Ditto is a peer to peer cross-platform database that allows mobile, web, IoT and server apps to sync with or without an internet connection.
//! Ensure `Ditto::open` gracefully handles incorrect system parameters.
mod common;

use std::{collections::HashMap, time::Duration};

use dittolive_ditto::{
    fs::TempRoot,
    prelude::{DatabaseId, Ditto, DittoConfig, DittoConfigConnect, DittoRoot},
};

fn make_config_with_invalid_system_parameter(root: &TempRoot) -> DittoConfig {
    let mut config = DittoConfig::new(
        DatabaseId::generate().to_string(),
        DittoConfigConnect::SmallPeersOnly { private_key: None },
    )
    .with_persistence_directory(root.root_path());
    config.system_parameters =
        HashMap::from([("not_a_real_parameter".into(), serde_json::json!("value"))]);
    config
}

/// Regression test for SDKS-3540
#[tokio::test]
async fn open_async_with_invalid_system_parameter_should_not_deadlock() {
    let root = TempRoot::new();
    let config = make_config_with_invalid_system_parameter(&root);

    let result = tokio::time::timeout(Duration::from_secs(10), Ditto::open(config)).await;

    // Should complete within timeout (not deadlock) and return an error
    let open_result = result.expect("Ditto::open() timed out after 10s");
    let err = match open_result {
        Err(e) => e,
        Ok(_) => panic!("invalid system parameter should cause an error, but open succeeded"),
    };
    let msg = err.to_string();
    assert!(
        msg.contains("unknown parameter") || msg.contains("not_a_real_parameter"),
        "error should mention the unknown parameter, got: {msg}",
    );

    drop(root);
}

/// Sanity check: the sync path should return an error without deadlocking.
#[test]
fn open_sync_with_invalid_system_parameter_returns_error() {
    let root = TempRoot::new();
    let config = make_config_with_invalid_system_parameter(&root);

    let err = match Ditto::open_sync(config) {
        Err(e) => e,
        Ok(_) => panic!("invalid system parameter should cause an error, but open succeeded"),
    };
    let msg = err.to_string();
    assert!(
        msg.contains("unknown parameter") || msg.contains("not_a_real_parameter"),
        "error should mention the unknown parameter, got: {msg}",
    );

    drop(root);
}