| 1 | use docs_native_host::Host; |
| 2 | use serde_json::json; |
| 3 | #[test] |
| 4 | fn interpreter_executes_native_crdt_without_host_imports() { |
| 5 | let mut host = Host::new().unwrap(); |
| 6 | host.call(br#"{"op":"open","guid":"fixture","client":123}"#).unwrap(); |
| 7 | host.call(br#"{"op":"insert_element","at":0,"type":"paragraph"}"#).unwrap(); |
| 8 | let p: serde_json::Value = serde_json::from_slice(host.call(br#"{"op":"project"}"#).unwrap()).unwrap(); |
| 9 | assert_eq!(p["children"][0]["type"], "paragraph"); |
| 10 | let node = p["children"][0]["id"].as_str().unwrap(); |
| 11 | host.call(&serde_json::to_vec(&json!({"op":"insert_text","node":node,"at":0,"text":"Sandbox π"})).unwrap()).unwrap(); |
| 12 | let p: serde_json::Value = serde_json::from_slice(host.call(br#"{"op":"project"}"#).unwrap()).unwrap(); |
| 13 | assert_eq!(p["children"][0]["children"][0]["runs"][0]["insert"], "Sandbox π"); |
| 14 | } |
| 15 | #[test] |
| 16 | fn failed_replica_cannot_be_reused() { |
| 17 | let mut host = Host::new().unwrap(); |
| 18 | host.call(br#"{"op":"open","guid":"fixture","client":456}"#).unwrap(); |
| 19 | assert!(host.call(br#"{"op":"apply","bytes":[255,255,255]}"#).is_err()); |
| 20 | assert!(host.call(br#"{"op":"project"}"#).is_err()); |
| 21 | let mut clean = Host::new().unwrap(); |
| 22 | assert!(clean.call(br#"{"op":"open","guid":"fixture","client":789}"#).is_ok()); |
| 23 | } |
| 24 | |
| 25 | #[test] |
| 26 | fn selection_anchor_call_does_not_poison_source_interpreter() { |
| 27 | let mut host = Host::new().unwrap(); |
| 28 | host.call(br#"{"op":"open","guid":"anchor","client":4000000000}"#).unwrap(); |
| 29 | host.call(br#"{"op":"insert_element","at":0,"type":"paragraph"}"#).unwrap(); |
| 30 | host.call(br#"{"op":"display_edit","at":0,"length":0,"text":"N"}"#).unwrap(); |
| 31 | let anchored = host.call(br#"{"op":"anchor","at":1}"#); |
| 32 | assert!(anchored.is_ok(), "anchor must succeed: {:?}", anchored.err()); |
| 33 | assert!(host.call(br#"{"op":"snapshot"}"#).is_ok()); |
| 34 | assert!(host.call(br#"{"op":"display_edit","at":1,"length":0,"text":"a"}"#).is_ok()); |
| 35 | host.call("{\"op\":\"display_edit\",\"at\":2,\"length\":0,\"text\":\"π\"}".as_bytes()).unwrap(); |
| 36 | let anchor: serde_json::Value = serde_json::from_slice(host.call(br#"{"op":"anchor","at":4}"#).unwrap()).unwrap(); |
| 37 | let resolved = host.call(&serde_json::to_vec(&json!({"op":"resolve","anchor":anchor})).unwrap()).unwrap(); |
| 38 | assert_eq!(resolved,b"4"); |
| 39 | assert!(host.call(br#"{"op":"anchor","at":999}"#).is_ok()); |
| 40 | assert!(host.call(br#"{"op":"snapshot"}"#).is_ok()); |
| 41 | } |
| 42 | |
| 43 | #[test] |
| 44 | fn generated_source_delta_applies_to_authority_with_protocol_client_ids() { |
| 45 | let mut authority = Host::new().unwrap(); |
| 46 | authority.call(br#"{"op":"open","guid":"generation","client":3088656600}"#).unwrap(); |
| 47 | authority.call(br#"{"op":"insert_element","at":0,"type":"paragraph"}"#).unwrap(); |
| 48 | let snapshot = authority.call(br#"{"op":"snapshot"}"#).unwrap().to_vec(); |
| 49 | let mut source = Host::new().unwrap(); |
| 50 | source.call(br#"{"op":"open","guid":"generation","client":4088656600}"#).unwrap(); |
| 51 | let mut imported = vec![255]; imported.extend(snapshot); source.call(&imported).unwrap(); |
| 52 | let update = source.call(br#"{"op":"display_edit","at":0,"length":0,"text":"N"}"#).unwrap().to_vec(); |
| 53 | let mut applied = vec![254]; applied.extend(update); authority.call(&applied).unwrap(); |
| 54 | let p: serde_json::Value = serde_json::from_slice(authority.call(br#"{"op":"project"}"#).unwrap()).unwrap(); |
| 55 | assert_eq!(p["children"][0]["children"][0]["runs"][0]["insert"], "N"); |
| 56 | } |
| 57 | |
| 58 | #[test] |
| 59 | fn native_boundary_rejects_client_ids_that_v1_decoder_would_truncate() { |
| 60 | let mut host = Host::new().unwrap(); |
| 61 | assert!(host.call(br#"{"op":"open","guid":"generation","client":6088656600138213}"#).is_err()); |
| 62 | } |
| 63 | |