mod common;
use common::{delete_remote_db, fresh_remote_db};
use rouchdb::Database;
#[tokio::test]
#[ignore]
async fn data_nested_objects_roundtrip() {
let url = fresh_remote_db("data_nested").await;
let local = Database::memory("local");
let remote = Database::http(&url);
let data = serde_json::json!({
"address": {
"street": "123 Main St",
"city": "New York",
"geo": { "lat": 40.7128, "lng": -74.0060 }
},
"contacts": {
"email": "alice@example.com",
"phones": { "home": "555-0100", "work": "555-0200" }
}
});
local.put("doc1", data.clone()).await.unwrap();
local.replicate_to(&remote).await.unwrap();
let doc = remote.get("doc1").await.unwrap();
assert_eq!(doc.data["address"]["city"], "New York");
assert_eq!(doc.data["address"]["geo"]["lat"], 40.7128);
assert_eq!(doc.data["contacts"]["phones"]["work"], "555-0200");
let local2 = Database::memory("local2");
local2.replicate_from(&remote).await.unwrap();
let doc2 = local2.get("doc1").await.unwrap();
assert_eq!(doc2.data["address"]["geo"]["lng"], -74.006);
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn data_arrays_roundtrip() {
let url = fresh_remote_db("data_arrays").await;
let local = Database::memory("local");
let remote = Database::http(&url);
let data = serde_json::json!({
"tags": ["rust", "database", "sync"],
"matrix": [[1, 2, 3], [4, 5, 6]],
"nested": [{"name": "a"}, {"name": "b"}]
});
local.put("doc1", data).await.unwrap();
local.replicate_to(&remote).await.unwrap();
let doc = remote.get("doc1").await.unwrap();
assert_eq!(doc.data["tags"][0], "rust");
assert_eq!(doc.data["tags"][2], "sync");
assert_eq!(doc.data["matrix"][1][2], 6);
assert_eq!(doc.data["nested"][0]["name"], "a");
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn data_null_and_bool_roundtrip() {
let url = fresh_remote_db("data_nullbool").await;
let local = Database::memory("local");
let remote = Database::http(&url);
let data = serde_json::json!({
"optional": null,
"nested_null": {"inner": null},
"active": true,
"deleted": false,
"flags": [true, false, null]
});
local.put("doc1", data).await.unwrap();
local.replicate_to(&remote).await.unwrap();
let doc = remote.get("doc1").await.unwrap();
assert!(doc.data["optional"].is_null());
assert!(doc.data["nested_null"]["inner"].is_null());
assert_eq!(doc.data["active"], true);
assert_eq!(doc.data["deleted"], false);
assert!(doc.data["flags"][2].is_null());
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn data_numeric_types_roundtrip() {
let url = fresh_remote_db("data_nums").await;
let local = Database::memory("local");
let remote = Database::http(&url);
let data = serde_json::json!({
"integer": 42,
"negative": -7,
"zero": 0,
"float": 3.14160,
"small_float": 0.001,
"negative_float": -273.15,
"big": 9999999999_i64
});
local.put("doc1", data).await.unwrap();
local.replicate_to(&remote).await.unwrap();
let doc = remote.get("doc1").await.unwrap();
assert_eq!(doc.data["integer"], 42);
assert_eq!(doc.data["negative"], -7);
assert_eq!(doc.data["zero"], 0);
assert!((doc.data["float"].as_f64().unwrap() - 3.14160).abs() < 1e-10);
assert_eq!(doc.data["small_float"], 0.001);
assert_eq!(doc.data["negative_float"], -273.15);
assert_eq!(doc.data["big"], 9999999999_i64);
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn data_empty_structures_roundtrip() {
let url = fresh_remote_db("data_empty").await;
let local = Database::memory("local");
let remote = Database::http(&url);
let data = serde_json::json!({
"empty_arr": [],
"empty_obj": {},
"empty_str": "",
"nested_empty": {"a": [], "b": {}}
});
local.put("doc1", data).await.unwrap();
local.replicate_to(&remote).await.unwrap();
let doc = remote.get("doc1").await.unwrap();
assert_eq!(doc.data["empty_arr"].as_array().unwrap().len(), 0);
assert_eq!(doc.data["empty_obj"].as_object().unwrap().len(), 0);
assert_eq!(doc.data["empty_str"], "");
assert_eq!(doc.data["nested_empty"]["a"].as_array().unwrap().len(), 0);
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn data_mixed_type_array_roundtrip() {
let url = fresh_remote_db("data_mixed").await;
let local = Database::memory("local");
let remote = Database::http(&url);
let data = serde_json::json!({
"mix": [1, "two", true, null, {"nested": 5}, [6, 7]]
});
local.put("doc1", data).await.unwrap();
local.replicate_to(&remote).await.unwrap();
let doc = remote.get("doc1").await.unwrap();
let mix = doc.data["mix"].as_array().unwrap();
assert_eq!(mix[0], 1);
assert_eq!(mix[1], "two");
assert_eq!(mix[2], true);
assert!(mix[3].is_null());
assert_eq!(mix[4]["nested"], 5);
assert_eq!(mix[5][1], 7);
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn data_unicode_roundtrip() {
let url = fresh_remote_db("data_unicode").await;
let local = Database::memory("local");
let remote = Database::http(&url);
let data = serde_json::json!({
"emoji": "\u{1F980}\u{1F389}",
"japanese": "\u{6771}\u{4EAC}",
"chinese": "\u{4F60}\u{597D}\u{4E16}\u{754C}",
"korean": "\u{C548}\u{B155}\u{D558}\u{C138}\u{C694}",
"arabic": "\u{0645}\u{0631}\u{062D}\u{0628}\u{0627}",
"accented": "caf\u{00E9} na\u{00EF}ve r\u{00E9}sum\u{00E9}",
"special_chars": "line1\nline2\ttab\\backslash"
});
local.put("doc1", data).await.unwrap();
local.replicate_to(&remote).await.unwrap();
let doc = remote.get("doc1").await.unwrap();
assert_eq!(doc.data["emoji"], "\u{1F980}\u{1F389}");
assert_eq!(doc.data["japanese"], "\u{6771}\u{4EAC}");
assert_eq!(
doc.data["accented"],
"caf\u{00E9} na\u{00EF}ve r\u{00E9}sum\u{00E9}"
);
assert_eq!(doc.data["special_chars"], "line1\nline2\ttab\\backslash");
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn data_large_document() {
let url = fresh_remote_db("data_large").await;
let local = Database::memory("local");
let remote = Database::http(&url);
let mut obj = serde_json::Map::new();
for i in 0..100 {
obj.insert(
format!("field_{}", i),
serde_json::json!({
"index": i,
"value": format!("value_{}", i),
"nested": {"depth": 1, "data": [i, i*2, i*3]}
}),
);
}
let data = serde_json::Value::Object(obj);
local.put("big_doc", data).await.unwrap();
local.replicate_to(&remote).await.unwrap();
let doc = remote.get("big_doc").await.unwrap();
assert_eq!(doc.data["field_0"]["index"], 0);
assert_eq!(doc.data["field_99"]["value"], "value_99");
assert_eq!(doc.data["field_50"]["nested"]["data"][2], 150);
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn special_id_with_spaces() {
let url = fresh_remote_db("id_spaces").await;
let db = Database::http(&url);
db.put("my document", serde_json::json!({"v": 1}))
.await
.unwrap();
let doc = db.get("my document").await.unwrap();
assert_eq!(doc.data["v"], 1);
assert_eq!(doc.id, "my document");
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn special_id_with_unicode() {
let url = fresh_remote_db("id_unicode").await;
let db = Database::http(&url);
db.put("doc_\u{00E9}\u{00E8}\u{00EA}", serde_json::json!({"v": 1}))
.await
.unwrap();
let doc = db.get("doc_\u{00E9}\u{00E8}\u{00EA}").await.unwrap();
assert_eq!(doc.data["v"], 1);
delete_remote_db(&url).await;
}
#[tokio::test]
#[ignore]
async fn special_id_replicate_roundtrip() {
let url = fresh_remote_db("id_repl").await;
let local = Database::memory("local");
let remote = Database::http(&url);
local
.put("has spaces", serde_json::json!({"t": "spaces"}))
.await
.unwrap();
local
.put("has/slash", serde_json::json!({"t": "slash"}))
.await
.unwrap();
local
.put("has+plus", serde_json::json!({"t": "plus"}))
.await
.unwrap();
local
.put("has?question", serde_json::json!({"t": "question"}))
.await
.unwrap();
local.replicate_to(&remote).await.unwrap();
let doc = remote.get("has spaces").await.unwrap();
assert_eq!(doc.data["t"], "spaces");
let doc = remote.get("has+plus").await.unwrap();
assert_eq!(doc.data["t"], "plus");
delete_remote_db(&url).await;
}