From 67b265b3d540466fa5a529040246f1ef538f5e09 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 16 Dec 2022 16:24:42 -0800 Subject: [PATCH] Add failing integration test for resharing projects on reconnect --- crates/collab/src/integration_tests.rs | 94 +++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index 4d08205b81..eeb9015876 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -15,7 +15,7 @@ use editor::{ self, ConfirmCodeAction, ConfirmCompletion, ConfirmRename, Editor, ExcerptRange, MultiBuffer, Redo, Rename, ToOffset, ToggleCodeActions, Undo, }; -use fs::{FakeFs, Fs as _, HomeDir, LineEnding}; +use fs::{FakeFs, Fs as _, HomeDir, LineEnding, RemoveOptions}; use futures::{channel::oneshot, StreamExt as _}; use gpui::{ executor::Deterministic, geometry::vector::vec2f, test::EmptyView, ModelHandle, Task, @@ -1306,6 +1306,98 @@ async fn test_host_disconnect( project_a.read_with(cx_a, |project, _| assert!(!project.is_shared())); } +#[gpui::test(iterations = 10)] +async fn test_host_reconnect( + deterministic: Arc, + cx_a: &mut TestAppContext, + cx_b: &mut TestAppContext, +) { + cx_b.update(editor::init); + deterministic.forbid_parking(); + let mut server = TestServer::start(&deterministic).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; + server + .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)]) + .await; + + client_a + .fs + .insert_tree( + "/root", + json!({ + "dir1": { + "a.txt": "a-contents", + "b.txt": "b-contents", + "subdir1": { + "c.txt": "c-contents", + "d.txt": "d-contents", + "e.txt": "e-contents", + } + }, + "dir2": { + "x.txt": "x-contents", + }, + }), + ) + .await; + + let active_call_a = cx_a.read(ActiveCall::global); + let (project_a, _) = client_a.build_local_project("/root/dir1", cx_a).await; + let worktree_a = project_a.read_with(cx_a, |project, cx| project.worktrees(cx).next().unwrap()); + let project_id = active_call_a + .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx)) + .await + .unwrap(); + + let project_b = client_b.build_remote_project(project_id, cx_b).await; + assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared())); + + // Drop client A's connection. + server.forbid_connections(); + server.disconnect_client(client_a.peer_id().unwrap()); + deterministic.advance_clock(RECEIVE_TIMEOUT); + project_a.read_with(cx_a, |project, _| { + assert!(project.collaborators().is_empty()) + }); + project_a.read_with(cx_a, |project, _| assert!(!project.is_shared())); + project_b.read_with(cx_b, |project, _| assert!(project.is_read_only())); + worktree_a.read_with(cx_a, |tree, _| { + assert!(!tree.as_local().unwrap().is_shared()) + }); + + // While disconnected, add and remove files from the client A's project. + client_a + .fs + .insert_tree( + "/root/dir1/subdir2", + json!({ + "f.txt": "f-contents", + "g.txt": "g-contents", + "h.txt": "h-contents", + "i.txt": "i-contents", + }), + ) + .await; + client_a + .fs + .remove_dir( + "/root/dir1/subdir1".as_ref(), + RemoveOptions { + recursive: true, + ..Default::default() + }, + ) + .await + .unwrap(); + + // Client A reconnects. Their project is re-shared, and client B re-joins it. + server.allow_connections(); + deterministic.advance_clock(RECEIVE_TIMEOUT); + project_a.read_with(cx_a, |project, _| assert!(project.is_shared())); + project_b.read_with(cx_b, |project, _| assert!(!project.is_read_only())); +} + #[gpui::test(iterations = 10)] async fn test_active_call_events( deterministic: Arc,