123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- //! Basic tests for real-time collaboration.
- use std::time::Duration;
- use anyhow::Result;
- use common::*;
- use log::info;
- use operational_transform::OperationSeq;
- use rustpad_server::{server, ServerConfig};
- use serde_json::json;
- use tokio::time;
- pub mod common;
- #[tokio::test]
- async fn test_single_operation() -> Result<()> {
- pretty_env_logger::try_init().ok();
- let filter = server(ServerConfig::default());
- expect_text(&filter, "foobar", "").await;
- let mut client = connect(&filter, "foobar").await?;
- let msg = client.recv().await?;
- assert_eq!(msg, json!({ "Identity": 0 }));
- let mut operation = OperationSeq::default();
- operation.insert("hello");
- let msg = json!({
- "Edit": {
- "revision": 0,
- "operation": operation
- }
- });
- info!("sending ClientMsg {}", msg);
- client.send(&msg).await;
- let msg = client.recv().await?;
- assert_eq!(
- msg,
- json!({
- "History": {
- "start": 0,
- "operations": [
- { "id": 0, "operation": ["hello"] }
- ]
- }
- })
- );
- expect_text(&filter, "foobar", "hello").await;
- Ok(())
- }
- #[tokio::test]
- async fn test_invalid_operation() -> Result<()> {
- pretty_env_logger::try_init().ok();
- let filter = server(ServerConfig::default());
- expect_text(&filter, "foobar", "").await;
- let mut client = connect(&filter, "foobar").await?;
- let msg = client.recv().await?;
- assert_eq!(msg, json!({ "Identity": 0 }));
- let mut operation = OperationSeq::default();
- operation.insert("hello");
- let msg = json!({
- "Edit": {
- "revision": 1,
- "operation": operation
- }
- });
- info!("sending ClientMsg {}", msg);
- client.send(&msg).await;
- client.recv_closed().await?;
- Ok(())
- }
- #[tokio::test]
- async fn test_concurrent_transform() -> Result<()> {
- pretty_env_logger::try_init().ok();
- let filter = server(ServerConfig::default());
- // Connect the first client
- let mut client = connect(&filter, "foobar").await?;
- let msg = client.recv().await?;
- assert_eq!(msg, json!({ "Identity": 0 }));
- // Insert the first operation
- let mut operation = OperationSeq::default();
- operation.insert("hello");
- let msg = json!({
- "Edit": {
- "revision": 0,
- "operation": operation
- }
- });
- info!("sending ClientMsg {}", msg);
- client.send(&msg).await;
- let msg = client.recv().await?;
- assert_eq!(
- msg,
- json!({
- "History": {
- "start": 0,
- "operations": [
- { "id": 0, "operation": ["hello"] }
- ]
- }
- })
- );
- // Insert the second operation
- let mut operation = OperationSeq::default();
- operation.retain(2);
- operation.delete(1);
- operation.insert("n");
- operation.retain(2);
- let msg = json!({
- "Edit": {
- "revision": 1,
- "operation": operation
- }
- });
- info!("sending ClientMsg {}", msg);
- client.send(&msg).await;
- let msg = client.recv().await?;
- assert_eq!(
- msg,
- json!({
- "History": {
- "start": 1,
- "operations": [
- { "id": 0, "operation": [2, "n", -1, 2] }
- ]
- }
- })
- );
- expect_text(&filter, "foobar", "henlo").await;
- // Connect the second client
- let mut client2 = connect(&filter, "foobar").await?;
- let msg = client2.recv().await?;
- assert_eq!(msg, json!({ "Identity": 1 }));
- // Insert a concurrent operation before seeing the existing history
- time::sleep(Duration::from_millis(50)).await;
- let mut operation = OperationSeq::default();
- operation.insert("~rust~");
- let msg = json!({
- "Edit": {
- "revision": 0,
- "operation": operation
- }
- });
- info!("sending ClientMsg {}", msg);
- client2.send(&msg).await;
- // Receive the existing history
- let msg = client2.recv().await?;
- assert_eq!(
- msg,
- json!({
- "History": {
- "start": 0,
- "operations": [
- { "id": 0, "operation": ["hello"] },
- { "id": 0, "operation": [2, "n", -1, 2] }
- ]
- }
- })
- );
- // Expect to receive a transformed operation
- let transformed_op = json!({
- "History": {
- "start": 2,
- "operations": [
- { "id": 1, "operation": ["~rust~", 5] },
- ]
- }
- });
- // ... in the first client
- let msg = client.recv().await?;
- assert_eq!(msg, transformed_op);
- // ... and in the second client
- let msg = client2.recv().await?;
- assert_eq!(msg, transformed_op);
- expect_text(&filter, "foobar", "~rust~henlo").await;
- Ok(())
- }
- #[tokio::test]
- async fn test_set_language() -> Result<()> {
- pretty_env_logger::try_init().ok();
- let filter = server(ServerConfig::default());
- let mut client = connect(&filter, "foobar").await?;
- let msg = client.recv().await?;
- assert_eq!(msg, json!({ "Identity": 0 }));
- let msg = json!({ "SetLanguage": "javascript" });
- client.send(&msg).await;
- let msg = client.recv().await?;
- assert_eq!(msg, json!({ "Language": "javascript" }));
- let mut client2 = connect(&filter, "foobar").await?;
- let msg = client2.recv().await?;
- assert_eq!(msg, json!({ "Identity": 1 }));
- let msg = client2.recv().await?;
- assert_eq!(msg, json!({ "Language": "javascript" }));
- let msg = json!({ "SetLanguage": "python" });
- client2.send(&msg).await;
- let msg = client.recv().await?;
- assert_eq!(msg, json!({ "Language": "python" }));
- let msg = client2.recv().await?;
- assert_eq!(msg, json!({ "Language": "python" }));
- expect_text(&filter, "foobar", "").await;
- Ok(())
- }
|