openkeyv 0.1.4

Async Key-Value Store - A pluggable interface for KV Stores
Documentation
use openkeyv::protocol::{
    AsyncDestroyCollection, AsyncDestroyStore, AsyncEnumerateCollections, AsyncEnumerateKeys,
    AsyncKeyValue,
};
use serde_json::Value;
use std::collections::HashMap;

fn sample_value(msg: &str) -> HashMap<String, Value> {
    let mut m = HashMap::new();
    m.insert("message".to_string(), Value::String(msg.to_string()));
    m
}

// ---------------------------------------------------------------------------
// MemoryStore
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_memory_store_basic_crud() {
    use openkeyv::store::memory::MemoryStore;

    let store = MemoryStore::new();
    let value = sample_value("hello");

    store.put("key1", value.clone(), None, None).await.unwrap();
    let got = store.get("key1", None).await.unwrap();
    assert_eq!(got, Some(value.clone()));

    let ttl = store.ttl("key1", None).await.unwrap();
    assert!(ttl.is_some());

    let deleted = store.delete("key1", None).await.unwrap();
    assert!(deleted);
    let got = store.get("key1", None).await.unwrap();
    assert!(got.is_none());
}

#[tokio::test]
async fn test_memory_store_batch_and_enum() {
    use openkeyv::store::memory::MemoryStore;

    let store = MemoryStore::new();
    let keys = vec!["a".to_string(), "b".to_string()];
    let values = vec![sample_value("1"), sample_value("2")];

    store
        .put_many(&keys, &values, Some("coll"), None)
        .await
        .unwrap();

    let got = store.get_many(&keys, Some("coll")).await.unwrap();
    assert_eq!(got.len(), 2);
    assert!(got[0].is_some());
    assert!(got[1].is_some());

    let ks = store.keys(Some("coll"), None).await.unwrap();
    assert_eq!(ks.len(), 2);

    let cols = store.collections(None).await.unwrap();
    assert!(cols.contains(&"coll".to_string()));
}

#[tokio::test]
async fn test_memory_store_destroy() {
    use openkeyv::store::memory::MemoryStore;

    let store = MemoryStore::new();
    store.put("k", sample_value("x"), None, None).await.unwrap();
    assert!(store.destroy().await.unwrap());
    assert!(store.get("k", None).await.unwrap().is_none());
}

// ---------------------------------------------------------------------------
// SimpleStore
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_simple_store_basic_crud() {
    use openkeyv::store::simple::SimpleStore;

    let store = SimpleStore::new();
    let value = sample_value("simple");

    store.put("key1", value.clone(), None, None).await.unwrap();
    let got = store.get("key1", None).await.unwrap();
    assert_eq!(got, Some(value.clone()));

    let deleted = store.delete("key1", None).await.unwrap();
    assert!(deleted);
    assert!(store.get("key1", None).await.unwrap().is_none());
}

#[tokio::test]
async fn test_simple_store_batch_and_enum() {
    use openkeyv::store::simple::SimpleStore;

    let store = SimpleStore::new();
    let keys = vec!["a".to_string(), "b".to_string()];
    let values = vec![sample_value("1"), sample_value("2")];

    store
        .put_many(&keys, &values, Some("coll"), None)
        .await
        .unwrap();

    let got = store.get_many(&keys, Some("coll")).await.unwrap();
    assert_eq!(got.len(), 2);

    let ks = store.keys(Some("coll"), None).await.unwrap();
    assert_eq!(ks.len(), 2);

    let cols = store.collections(None).await.unwrap();
    assert!(cols.contains(&"coll".to_string()));
}

// ---------------------------------------------------------------------------
// FileTreeStore
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_filetree_store_basic_crud() {
    use openkeyv::store::filetree::store::FileTreeStore;

    let tmp = tempfile::tempdir().unwrap();
    let store = FileTreeStore::new(tmp.path());
    let value = sample_value("tree");

    store.put("key1", value.clone(), None, None).await.unwrap();
    let got = store.get("key1", None).await.unwrap();
    assert_eq!(got, Some(value.clone()));

    let deleted = store.delete("key1", None).await.unwrap();
    assert!(deleted);
    assert!(store.get("key1", None).await.unwrap().is_none());
}

#[tokio::test]
async fn test_filetree_store_batch_and_enum() {
    use openkeyv::store::filetree::store::FileTreeStore;

    let tmp = tempfile::tempdir().unwrap();
    let store = FileTreeStore::new(tmp.path());
    let keys = vec!["a".to_string(), "b".to_string()];
    let values = vec![sample_value("1"), sample_value("2")];

    store
        .put_many(&keys, &values, Some("coll"), None)
        .await
        .unwrap();

    let got = store.get_many(&keys, Some("coll")).await.unwrap();
    assert_eq!(got.len(), 2);

    let ks = store.keys(Some("coll"), None).await.unwrap();
    assert_eq!(ks.len(), 2);

    let cols = store.collections(None).await.unwrap();
    assert!(cols.contains(&"coll".to_string()));
}

#[tokio::test]
async fn test_filetree_store_destroy_collection() {
    use openkeyv::store::filetree::store::FileTreeStore;

    let tmp = tempfile::tempdir().unwrap();
    let store = FileTreeStore::new(tmp.path());
    store
        .put("k", sample_value("x"), Some("c1"), None)
        .await
        .unwrap();
    assert!(store.destroy_collection("c1").await.unwrap());
    assert!(!store.destroy_collection("c1").await.unwrap());
}

// ---------------------------------------------------------------------------
// DiskStore (sled)
// ---------------------------------------------------------------------------
#[cfg(feature = "disk")]
#[tokio::test]
async fn test_disk_store_basic_crud() {
    use openkeyv::store::disk::DiskStore;

    let tmp = tempfile::tempdir().unwrap();
    let store = DiskStore::new(tmp.path()).unwrap();
    let value = sample_value("disk");

    store.put("key1", value.clone(), None, None).await.unwrap();
    let got = store.get("key1", None).await.unwrap();
    assert_eq!(got, Some(value.clone()));

    let deleted = store.delete("key1", None).await.unwrap();
    assert!(deleted);
    assert!(store.get("key1", None).await.unwrap().is_none());
}

#[cfg(feature = "disk")]
#[tokio::test]
async fn test_disk_store_batch_and_enum() {
    use openkeyv::store::disk::DiskStore;

    let tmp = tempfile::tempdir().unwrap();
    let store = DiskStore::new(tmp.path()).unwrap();
    let keys = vec!["a".to_string(), "b".to_string()];
    let values = vec![sample_value("1"), sample_value("2")];

    store
        .put_many(&keys, &values, Some("coll"), None)
        .await
        .unwrap();

    let got = store.get_many(&keys, Some("coll")).await.unwrap();
    assert_eq!(got.len(), 2);

    let ks = store.keys(Some("coll"), None).await.unwrap();
    assert_eq!(ks.len(), 2);

    let cols = store.collections(None).await.unwrap();
    assert!(cols.contains(&"coll".to_string()));
}

#[cfg(feature = "disk")]
#[tokio::test]
async fn test_disk_store_destroy_collection() {
    use openkeyv::store::disk::DiskStore;

    let tmp = tempfile::tempdir().unwrap();
    let store = DiskStore::new(tmp.path()).unwrap();
    store
        .put("k", sample_value("x"), Some("c1"), None)
        .await
        .unwrap();
    assert!(store.destroy_collection("c1").await.unwrap());
    assert!(store.get("k", Some("c1")).await.unwrap().is_none());
}