@@ -1390,6 +1390,52 @@ async fn test_leaving_worktree_while_opening_buffer(
.await;
}
+#[gpui::test(iterations = 10)]
+async fn test_canceling_buffer_opening(
+ deterministic: Arc<Deterministic>,
+ cx_a: &mut TestAppContext,
+ cx_b: &mut TestAppContext,
+) {
+ deterministic.forbid_parking();
+
+ let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
+ let client_a = server.create_client(cx_a, "user_a").await;
+ let client_b = server.create_client(cx_b, "user_b").await;
+ server
+ .make_contacts(vec![(&client_a, cx_a), (&client_b, cx_b)])
+ .await;
+
+ client_a
+ .fs
+ .insert_tree(
+ "/dir",
+ json!({
+ "a.txt": "abc",
+ }),
+ )
+ .await;
+ let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
+ let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
+
+ let buffer_a = project_a
+ .update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
+ .await
+ .unwrap();
+
+ // Open a buffer as client B but cancel after a random amount of time.
+ let buffer_b = project_b.update(cx_b, |p, cx| p.open_buffer_by_id(buffer_a.id() as u64, cx));
+ deterministic.simulate_random_delay().await;
+ drop(buffer_b);
+
+ // Try opening the same buffer again as client B, and ensure we can
+ // still do it despite the cancellation above.
+ let buffer_b = project_b
+ .update(cx_b, |p, cx| p.open_buffer_by_id(buffer_a.id() as u64, cx))
+ .await
+ .unwrap();
+ buffer_b.read_with(cx_b, |buf, _| assert_eq!(buf.text(), "abc"));
+}
+
#[gpui::test(iterations = 10)]
async fn test_leaving_project(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
cx_a.foreground().forbid_parking();
@@ -381,6 +381,17 @@ impl Deterministic {
state.forbid_parking = true;
state.rng = StdRng::seed_from_u64(state.seed);
}
+
+ pub async fn simulate_random_delay(&self) {
+ use rand::prelude::*;
+ use smol::future::yield_now;
+ if self.state.lock().rng.gen_bool(0.2) {
+ let yields = self.state.lock().rng.gen_range(1..=10);
+ for _ in 0..yields {
+ yield_now().await;
+ }
+ }
+ }
}
impl Drop for Timer {
@@ -662,17 +673,9 @@ impl Background {
#[cfg(any(test, feature = "test-support"))]
pub async fn simulate_random_delay(&self) {
- use rand::prelude::*;
- use smol::future::yield_now;
-
match self {
Self::Deterministic { executor, .. } => {
- if executor.state.lock().rng.gen_bool(0.2) {
- let yields = executor.state.lock().rng.gen_range(1..=10);
- for _ in 0..yields {
- yield_now().await;
- }
- }
+ executor.simulate_random_delay().await;
}
_ => {
panic!("this method can only be called on a deterministic executor")