#[cfg(test)]
mod tests {
use datastack::{DataStack, increment, array_union};
use serde_json::json;
use std::fs;
async fn setup_db(path: &str) -> DataStack {
let _ = fs::remove_dir_all(path);
DataStack::new(path).await.expect("Failed to create DataStack")
}
#[tokio::test]
async fn test_basic_crud() {
let db = setup_db("./test_db_basic").await;
let user = json!({"name": "Alice", "age": 25});
db.add("users", "u1", &user).await.unwrap();
let fetched = db.get("users", "u1").await.unwrap().unwrap();
assert_eq!(fetched["name"], "Alice");
db.delete("users", "u1").await.unwrap();
let after_delete = db.get("users", "u1").await.unwrap();
assert!(after_delete.is_none());
}
#[tokio::test]
async fn test_complex_updates() {
let db = setup_db("./test_db_updates").await;
db.add("users", "u1", &json!({
"balance": 100,
"profile": { "points": 10 },
"tags": ["rust"]
})).await.unwrap();
db.update("users", "u1", &json!({
"balance": increment(50), "profile.points": increment(-5), "tags": array_union(json!(["db"])), "active": true })).await.unwrap();
let updated = db.get("users", "u1").await.unwrap().unwrap();
assert_eq!(updated["balance"].as_f64().unwrap(), 150.0);
assert_eq!(updated["profile"]["points"].as_f64().unwrap(), 5.0);
assert!(updated["tags"].as_array().unwrap().contains(&json!("db")));
assert_eq!(updated["active"], true);
}
#[tokio::test]
async fn test_subcollections_and_scanning() {
let db = setup_db("./test_db_scan").await;
db.add("users:u1:inbox", "m1", &json!({"msg": "first"})).await.unwrap();
db.add("users:u1:inbox", "m2", &json!({"msg": "second"})).await.unwrap();
db.add("users:u1:inbox", "m3", &json!({"msg": "third"})).await.unwrap();
let scan_res = db.scan("users:u1:inbox", 2, "", "a").await.unwrap();
let obj = scan_res.as_object().unwrap();
assert_eq!(obj.len(), 2);
assert!(obj.contains_key("m1"));
assert!(obj.contains_key("m2"));
let scan_desc = db.scan("users:u1:inbox", 10, "m3", "d").await.unwrap();
let obj_desc = scan_desc.as_object().unwrap();
assert!(obj_desc.contains_key("m3"));
assert!(obj_desc.contains_key("m2"));
}
#[tokio::test]
async fn test_batch_operations() {
let db = setup_db("./test_db_add_get_delete.redb").await;
let batch_data = json!({
"tx1": { "amount": 100 },
"tx2": { "amount": 200 },
"tx3": { "amount": 300 }
});
db.batch_add("ledger", &batch_data).await.unwrap();
let tx2 = db.get("ledger", "tx2").await.unwrap().unwrap();
assert_eq!(tx2["amount"], 200);
let ids = json!(["tx1", "tx3"]);
let docs = db.batch_get("ledger", &ids).await.unwrap();
assert_eq!(docs["tx1"]["amount"], 100);
assert_eq!(docs["tx3"]["amount"], 300);
assert!(docs.get("tx2").is_none());
db.batch_delete("ledger", &ids).await.unwrap();
assert!(db.get("ledger", "tx1").await.unwrap().is_none());
assert!(db.get("ledger", "tx3").await.unwrap().is_none());
let tx2_after = db.get("ledger", "tx2").await.unwrap().unwrap();
assert_eq!(tx2_after["amount"], 200);
}
}