use communitas_core::doc_replicator::{DocReplicator, DocReplicatorConfig, StorageMode};
use std::sync::Arc;
async fn create_test_replicator() -> Arc<DocReplicator> {
let config = DocReplicatorConfig {
files_storage_enabled: true,
web_storage_enabled: true,
};
Arc::new(
DocReplicator::new(config)
.await
.expect("replicator creation"),
)
}
async fn create_replicator_with_config(
files_enabled: bool,
web_enabled: bool,
) -> Arc<DocReplicator> {
let config = DocReplicatorConfig {
files_storage_enabled: files_enabled,
web_storage_enabled: web_enabled,
};
Arc::new(
DocReplicator::new(config)
.await
.expect("replicator creation"),
)
}
#[tokio::test]
async fn test_create_document_files_storage() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("test-doc", StorageMode::Files)
.await
.expect("create document");
assert!(!doc_id.is_empty());
let doc = replicator
.get_document(&doc_id)
.await
.expect("get document");
assert!(doc.is_some());
let exists_files = replicator
.document_exists_in_files(&doc_id)
.await
.expect("check files");
assert!(exists_files);
let exists_web = replicator
.document_exists_in_web(&doc_id)
.await
.expect("check web");
assert!(!exists_web);
}
#[tokio::test]
async fn test_create_document_web_storage() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("public-doc", StorageMode::Web)
.await
.expect("create document");
let doc = replicator
.get_document(&doc_id)
.await
.expect("get document");
assert!(doc.is_some());
let exists_web = replicator
.document_exists_in_web(&doc_id)
.await
.expect("check web");
assert!(exists_web);
let exists_files = replicator
.document_exists_in_files(&doc_id)
.await
.expect("check files");
assert!(!exists_files);
}
#[tokio::test]
async fn test_create_document_dual_storage() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("dual-doc", StorageMode::Both)
.await
.expect("create document");
let doc = replicator
.get_document(&doc_id)
.await
.expect("get document");
assert!(doc.is_some());
let exists_files = replicator
.document_exists_in_files(&doc_id)
.await
.expect("check files");
let exists_web = replicator
.document_exists_in_web(&doc_id)
.await
.expect("check web");
assert!(exists_files, "Document should exist in Files storage");
assert!(exists_web, "Document should exist in Web storage");
}
#[tokio::test]
async fn test_create_document_with_custom_key() {
let replicator = create_test_replicator().await;
let custom_key = [42u8; 32];
let doc_id = replicator
.create_document_with_key("keyed-doc", StorageMode::Files, &custom_key)
.await
.expect("create with key");
let doc = replicator
.get_document(&doc_id)
.await
.expect("get document");
assert!(doc.is_some());
let retrieved_key = replicator
.get_encryption_key(&doc_id)
.await
.expect("get key");
assert_eq!(retrieved_key, custom_key);
}
#[tokio::test]
async fn test_insert_text() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("text-doc", StorageMode::Files)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Hello, ")
.await
.expect("insert 1");
replicator
.insert_text(&doc_id, 7, "World!")
.await
.expect("insert 2");
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, "Hello, World!");
}
#[tokio::test]
async fn test_delete_text() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("delete-doc", StorageMode::Files)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Hello, World!")
.await
.expect("insert");
replicator.delete_text(&doc_id, 7, 5).await.expect("delete");
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, "Hello, !");
}
#[tokio::test]
async fn test_insert_and_delete_operations() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("ops-doc", StorageMode::Files)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "The quick brown fox")
.await
.expect("insert 1");
replicator
.insert_text(&doc_id, 19, " jumps over the lazy dog")
.await
.expect("insert 2");
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, "The quick brown fox jumps over the lazy dog");
replicator
.delete_text(&doc_id, 10, 6)
.await
.expect("delete");
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, "The quick fox jumps over the lazy dog");
}
#[tokio::test]
async fn test_empty_document() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("empty-doc", StorageMode::Files)
.await
.expect("create");
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, "");
}
#[tokio::test]
async fn test_delete_beyond_length() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("bounds-doc", StorageMode::Files)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Short")
.await
.expect("insert");
let result = replicator.delete_text(&doc_id, 0, 100).await;
assert!(result.is_ok());
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, "");
}
#[tokio::test]
async fn test_delete_at_invalid_position() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("invalid-doc", StorageMode::Files)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Test")
.await
.expect("insert");
let result = replicator.delete_text(&doc_id, 100, 5).await;
assert!(result.is_ok());
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, "Test"); }
#[tokio::test]
async fn test_files_storage_is_encrypted() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("encrypted-doc", StorageMode::Files)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Secret data")
.await
.expect("insert");
let encrypted_blob = replicator
.get_files_blob(&doc_id)
.await
.expect("get blob")
.expect("blob exists");
let plaintext = "Secret data";
assert!(
!encrypted_blob
.windows(plaintext.len())
.any(|window| { window == plaintext.as_bytes() }),
"Encrypted blob should not contain plaintext"
);
}
#[tokio::test]
async fn test_decrypt_with_correct_key() {
let replicator = create_test_replicator().await;
let custom_key = [99u8; 32];
let doc_id = replicator
.create_document_with_key("decrypt-doc", StorageMode::Files, &custom_key)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Test content")
.await
.expect("insert");
let decrypted = replicator
.decrypt_with_key(&doc_id, &custom_key)
.await
.expect("decrypt");
assert!(!decrypted.is_empty());
}
#[tokio::test]
async fn test_decrypt_with_wrong_key() {
let replicator = create_test_replicator().await;
let correct_key = [99u8; 32];
let wrong_key = [55u8; 32];
let doc_id = replicator
.create_document_with_key("wrong-key-doc", StorageMode::Files, &correct_key)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Test content")
.await
.expect("insert");
let result = replicator.decrypt_with_key(&doc_id, &wrong_key).await;
assert!(result.is_err(), "Decryption with wrong key should fail");
}
#[tokio::test]
async fn test_web_document_has_no_encryption_key() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("web-doc", StorageMode::Web)
.await
.expect("create");
let result = replicator.get_encryption_key(&doc_id).await;
assert!(
result.is_err(),
"Web documents should not have encryption keys"
);
}
#[tokio::test]
async fn test_web_storage_is_unencrypted() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("public-doc", StorageMode::Web)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Public data")
.await
.expect("insert");
let web_blob = replicator
.get_web_blob(&doc_id)
.await
.expect("get blob")
.expect("blob exists");
assert!(!web_blob.is_empty());
}
#[tokio::test]
async fn test_web_storage_accessible_without_key() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("accessible-doc", StorageMode::Web)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Open content")
.await
.expect("insert");
let web_blob = replicator.get_web_blob(&doc_id).await.expect("get blob");
assert!(web_blob.is_some());
}
#[tokio::test]
async fn test_dual_storage_both_updated() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("dual-sync", StorageMode::Both)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Sync test")
.await
.expect("insert");
let files_blob = replicator
.get_files_blob(&doc_id)
.await
.expect("get files")
.expect("files exists");
let web_blob = replicator
.get_web_blob(&doc_id)
.await
.expect("get web")
.expect("web exists");
assert!(!files_blob.is_empty());
assert!(!web_blob.is_empty());
}
#[tokio::test]
async fn test_dual_storage_files_encrypted_web_not() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("dual-enc", StorageMode::Both)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Dual content")
.await
.expect("insert");
let key_result = replicator.get_encryption_key(&doc_id).await;
assert!(key_result.is_ok(), "Files storage should have key");
let files_blob = replicator
.get_files_blob(&doc_id)
.await
.expect("get files")
.expect("files exists");
let web_blob = replicator
.get_web_blob(&doc_id)
.await
.expect("get web")
.expect("web exists");
assert_ne!(files_blob, web_blob);
}
#[tokio::test]
async fn test_get_crdt_update() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("update-doc", StorageMode::Files)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Update test")
.await
.expect("insert");
let update = replicator
.get_crdt_update(&doc_id)
.await
.expect("get update");
assert!(!update.is_empty());
}
#[tokio::test]
async fn test_apply_crdt_update() {
let replicator1 = create_test_replicator().await;
let replicator2 = create_test_replicator().await;
let doc_id = "shared-sync-doc";
replicator1
.create_document_with_key(doc_id, StorageMode::Files, &[1u8; 32])
.await
.expect("create 1");
replicator2
.create_document_with_key(doc_id, StorageMode::Files, &[1u8; 32])
.await
.expect("create 2");
replicator1
.insert_text(doc_id, 0, "Sync content")
.await
.expect("insert");
let update = replicator1
.get_crdt_update(doc_id)
.await
.expect("get update");
replicator2
.apply_crdt_update(doc_id, &update)
.await
.expect("apply update");
let text = replicator2.get_text(doc_id).await.expect("get text");
assert_eq!(text, "Sync content");
}
#[tokio::test]
async fn test_crdt_convergence() {
let replicator1 = create_test_replicator().await;
let replicator2 = create_test_replicator().await;
let doc_id = "convergence-doc";
replicator1
.create_document_with_key(doc_id, StorageMode::Files, &[2u8; 32])
.await
.expect("create 1");
replicator2
.create_document_with_key(doc_id, StorageMode::Files, &[2u8; 32])
.await
.expect("create 2");
replicator1
.insert_text(doc_id, 0, "A")
.await
.expect("insert 1");
replicator2
.insert_text(doc_id, 0, "B")
.await
.expect("insert 2");
let update1 = replicator1.get_crdt_update(doc_id).await.expect("update 1");
let update2 = replicator2.get_crdt_update(doc_id).await.expect("update 2");
replicator1
.apply_crdt_update(doc_id, &update2)
.await
.expect("apply 2");
replicator2
.apply_crdt_update(doc_id, &update1)
.await
.expect("apply 1");
let text1 = replicator1.get_text(doc_id).await.expect("text 1");
let text2 = replicator2.get_text(doc_id).await.expect("text 2");
assert_eq!(text1, text2, "CRDT should converge");
assert!(!text1.is_empty(), "Merged text should not be empty");
}
#[tokio::test]
async fn test_get_nonexistent_document() {
let replicator = create_test_replicator().await;
let result = replicator
.get_document("nonexistent-id")
.await
.expect("query should succeed");
assert!(result.is_none());
}
#[tokio::test]
async fn test_insert_text_nonexistent_document() {
let replicator = create_test_replicator().await;
let result = replicator.insert_text("nonexistent-id", 0, "test").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_get_text_nonexistent_document() {
let replicator = create_test_replicator().await;
let result = replicator.get_text("nonexistent-id").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_get_encryption_key_nonexistent_document() {
let replicator = create_test_replicator().await;
let result = replicator.get_encryption_key("nonexistent-id").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_files_storage_disabled() {
let replicator = create_replicator_with_config(false, true).await;
let doc_id = replicator
.create_document("files-disabled", StorageMode::Files)
.await
.expect("create");
let _exists = replicator
.document_exists_in_files(&doc_id)
.await
.expect("check");
}
#[tokio::test]
async fn test_web_storage_disabled() {
let replicator = create_replicator_with_config(true, false).await;
let doc_id = replicator
.create_document("web-disabled", StorageMode::Web)
.await
.expect("create");
let _exists = replicator
.document_exists_in_web(&doc_id)
.await
.expect("check");
}
#[tokio::test]
async fn test_unicode_text() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("unicode-doc", StorageMode::Files)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "Hello δΈη! ππ")
.await
.expect("insert");
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, "Hello δΈη! ππ");
}
#[tokio::test]
async fn test_emoji_text() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("emoji-doc", StorageMode::Files)
.await
.expect("create");
replicator
.insert_text(&doc_id, 0, "ππππ")
.await
.expect("insert");
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, "ππππ");
}
#[tokio::test]
async fn test_newlines_and_special_chars() {
let replicator = create_test_replicator().await;
let doc_id = replicator
.create_document("special-doc", StorageMode::Files)
.await
.expect("create");
let content = "Line 1\nLine 2\n\tTabbed\r\nWindows line";
replicator
.insert_text(&doc_id, 0, content)
.await
.expect("insert");
let text = replicator.get_text(&doc_id).await.expect("get text");
assert_eq!(text, content);
}