Remove 2 suffix for collab, rope, settings, menu
Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
@@ -5,7 +5,7 @@ mod feature_flag_tests;
|
||||
mod message_tests;
|
||||
|
||||
use super::*;
|
||||
use gpui::executor::Background;
|
||||
use gpui::BackgroundExecutor;
|
||||
use parking_lot::Mutex;
|
||||
use sea_orm::ConnectionTrait;
|
||||
use sqlx::migrate::MigrateDatabase;
|
||||
@@ -22,7 +22,7 @@ pub struct TestDb {
|
||||
}
|
||||
|
||||
impl TestDb {
|
||||
pub fn sqlite(background: Arc<Background>) -> Self {
|
||||
pub fn sqlite(background: BackgroundExecutor) -> Self {
|
||||
let url = format!("sqlite::memory:");
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_io()
|
||||
@@ -59,7 +59,7 @@ impl TestDb {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn postgres(background: Arc<Background>) -> Self {
|
||||
pub fn postgres(background: BackgroundExecutor) -> Self {
|
||||
static LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
let _guard = LOCK.lock();
|
||||
@@ -108,17 +108,14 @@ impl TestDb {
|
||||
macro_rules! test_both_dbs {
|
||||
($test_name:ident, $postgres_test_name:ident, $sqlite_test_name:ident) => {
|
||||
#[gpui::test]
|
||||
async fn $postgres_test_name() {
|
||||
let test_db = crate::db::TestDb::postgres(
|
||||
gpui::executor::Deterministic::new(0).build_background(),
|
||||
);
|
||||
async fn $postgres_test_name(cx: &mut gpui::TestAppContext) {
|
||||
let test_db = crate::db::TestDb::postgres(cx.executor().clone());
|
||||
$test_name(test_db.db()).await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn $sqlite_test_name() {
|
||||
let test_db =
|
||||
crate::db::TestDb::sqlite(gpui::executor::Deterministic::new(0).build_background());
|
||||
async fn $sqlite_test_name(cx: &mut gpui::TestAppContext) {
|
||||
let test_db = crate::db::TestDb::sqlite(cx.executor().clone());
|
||||
$test_name(test_db.db()).await;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -420,8 +420,6 @@ async fn test_db_channel_moving_bugs(db: &Arc<Database>) {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Dag is: zed - projects - livestreaming
|
||||
|
||||
// Move to same parent should be a no-op
|
||||
assert!(db
|
||||
.move_channel(projects_id, Some(zed_id), user_id)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
use crate::test_both_dbs;
|
||||
use gpui::executor::{Background, Deterministic};
|
||||
use gpui::TestAppContext;
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
use std::sync::Arc;
|
||||
use tests::TestDb;
|
||||
@@ -509,8 +509,8 @@ fn test_fuzzy_like_string() {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_fuzzy_search_users() {
|
||||
let test_db = TestDb::postgres(build_background_executor());
|
||||
async fn test_fuzzy_search_users(cx: &mut TestAppContext) {
|
||||
let test_db = TestDb::postgres(cx.executor());
|
||||
let db = test_db.db();
|
||||
for (i, github_login) in [
|
||||
"California",
|
||||
@@ -631,7 +631,3 @@ async fn test_non_matching_release_channels(db: &Arc<Database>) {
|
||||
|
||||
assert!(result.is_ok())
|
||||
}
|
||||
|
||||
fn build_background_executor() -> Arc<Background> {
|
||||
Deterministic::new(0).build_background()
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
use std::{future::Future, time::Duration};
|
||||
|
||||
#[cfg(test)]
|
||||
use gpui::BackgroundExecutor;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Executor {
|
||||
Production,
|
||||
#[cfg(test)]
|
||||
Deterministic(std::sync::Arc<gpui::executor::Background>),
|
||||
Deterministic(BackgroundExecutor),
|
||||
}
|
||||
|
||||
impl Executor {
|
||||
@@ -33,12 +36,4 @@ impl Executor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_backtrace(&self) {
|
||||
match self {
|
||||
Executor::Production => {}
|
||||
#[cfg(test)]
|
||||
Executor::Deterministic(background) => background.record_backtrace(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ struct Session {
|
||||
peer: Arc<Peer>,
|
||||
connection_pool: Arc<parking_lot::Mutex<ConnectionPool>>,
|
||||
live_kit_client: Option<Arc<dyn live_kit_server::api::Client>>,
|
||||
executor: Executor,
|
||||
_executor: Executor,
|
||||
}
|
||||
|
||||
impl Session {
|
||||
@@ -612,7 +612,7 @@ impl Server {
|
||||
peer: this.peer.clone(),
|
||||
connection_pool: this.connection_pool.clone(),
|
||||
live_kit_client: this.app_state.live_kit_client.clone(),
|
||||
executor: executor.clone(),
|
||||
_executor: executor.clone()
|
||||
};
|
||||
update_user_contacts(user_id, &session).await?;
|
||||
|
||||
@@ -1723,7 +1723,6 @@ async fn update_language_server(
|
||||
request: proto::UpdateLanguageServer,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
session.executor.record_backtrace();
|
||||
let project_id = ProjectId::from_proto(request.project_id);
|
||||
let project_connection_ids = session
|
||||
.db()
|
||||
@@ -1750,7 +1749,6 @@ async fn forward_project_request<T>(
|
||||
where
|
||||
T: EntityMessage + RequestMessage,
|
||||
{
|
||||
session.executor.record_backtrace();
|
||||
let project_id = ProjectId::from_proto(request.remote_entity_id());
|
||||
let host_connection_id = {
|
||||
let collaborators = session
|
||||
@@ -1778,7 +1776,6 @@ async fn create_buffer_for_peer(
|
||||
request: proto::CreateBufferForPeer,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
session.executor.record_backtrace();
|
||||
let peer_id = request.peer_id.ok_or_else(|| anyhow!("invalid peer id"))?;
|
||||
session
|
||||
.peer
|
||||
@@ -1791,7 +1788,6 @@ async fn update_buffer(
|
||||
response: Response<proto::UpdateBuffer>,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
session.executor.record_backtrace();
|
||||
let project_id = ProjectId::from_proto(request.project_id);
|
||||
let mut guest_connection_ids;
|
||||
let mut host_connection_id = None;
|
||||
@@ -1812,7 +1808,6 @@ async fn update_buffer(
|
||||
}
|
||||
let host_connection_id = host_connection_id.ok_or_else(|| anyhow!("host not found"))?;
|
||||
|
||||
session.executor.record_backtrace();
|
||||
broadcast(
|
||||
Some(session.connection_id),
|
||||
guest_connection_ids,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use call::Room;
|
||||
use gpui::{ModelHandle, TestAppContext};
|
||||
use gpui::{Model, TestAppContext};
|
||||
|
||||
mod channel_buffer_tests;
|
||||
mod channel_message_tests;
|
||||
mod channel_tests;
|
||||
mod editor_tests;
|
||||
mod following_tests;
|
||||
mod integration_tests;
|
||||
mod notification_tests;
|
||||
@@ -23,7 +24,7 @@ struct RoomParticipants {
|
||||
pending: Vec<String>,
|
||||
}
|
||||
|
||||
fn room_participants(room: &ModelHandle<Room>, cx: &mut TestAppContext) -> RoomParticipants {
|
||||
fn room_participants(room: &Model<Room>, cx: &mut TestAppContext) -> RoomParticipants {
|
||||
room.read_with(cx, |room, _| {
|
||||
let mut remote = room
|
||||
.remote_participants()
|
||||
@@ -41,6 +42,6 @@ fn room_participants(room: &ModelHandle<Room>, cx: &mut TestAppContext) -> RoomP
|
||||
})
|
||||
}
|
||||
|
||||
fn channel_id(room: &ModelHandle<Room>, cx: &mut TestAppContext) -> Option<u64> {
|
||||
fn channel_id(room: &Model<Room>, cx: &mut TestAppContext) -> Option<u64> {
|
||||
cx.read(|cx| room.read(cx).channel_id())
|
||||
}
|
||||
|
||||
@@ -4,25 +4,23 @@ use crate::{
|
||||
};
|
||||
use call::ActiveCall;
|
||||
use channel::ACKNOWLEDGE_DEBOUNCE_INTERVAL;
|
||||
use client::ParticipantIndex;
|
||||
use client::{Collaborator, UserId};
|
||||
use client::{Collaborator, ParticipantIndex, UserId};
|
||||
use collab_ui::channel_view::ChannelView;
|
||||
use collections::HashMap;
|
||||
use editor::{Anchor, Editor, ToOffset};
|
||||
use futures::future;
|
||||
use gpui::{executor::Deterministic, ModelHandle, TestAppContext, ViewContext};
|
||||
use gpui::{BackgroundExecutor, Model, TestAppContext, ViewContext};
|
||||
use rpc::{proto::PeerId, RECEIVE_TIMEOUT};
|
||||
use serde_json::json;
|
||||
use std::{ops::Range, sync::Arc};
|
||||
use std::ops::Range;
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_core_channel_buffers(
|
||||
deterministic: Arc<Deterministic>,
|
||||
executor: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(executor.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
@@ -50,7 +48,7 @@ async fn test_core_channel_buffers(
|
||||
});
|
||||
buffer_a.update(cx_a, |buffer, cx| buffer.undo(cx));
|
||||
assert_eq!(buffer_text(&buffer_a, cx_a), "hello, cruel world");
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
|
||||
// Client B joins the channel buffer
|
||||
let channel_buffer_b = client_b
|
||||
@@ -77,13 +75,13 @@ async fn test_core_channel_buffers(
|
||||
});
|
||||
|
||||
// Both A and B see the new edit
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
assert_eq!(buffer_text(&buffer_a, cx_a), "hello, beautiful world");
|
||||
assert_eq!(buffer_text(&buffer_b, cx_b), "hello, beautiful world");
|
||||
|
||||
// Client A closes the channel buffer.
|
||||
cx_a.update(|_| drop(channel_buffer_a));
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
|
||||
// Client B sees that client A is gone from the channel buffer.
|
||||
channel_buffer_b.read_with(cx_b, |buffer, _| {
|
||||
@@ -96,7 +94,7 @@ async fn test_core_channel_buffers(
|
||||
.update(cx_a, |store, cx| store.open_channel_buffer(channel_id, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
|
||||
// Sanity test, make sure we saw A rejoining
|
||||
channel_buffer_b.read_with(cx_b, |buffer, _| {
|
||||
@@ -109,7 +107,7 @@ async fn test_core_channel_buffers(
|
||||
// Client A loses connection.
|
||||
server.forbid_connections();
|
||||
server.disconnect_client(client_a.peer_id().unwrap());
|
||||
deterministic.advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);
|
||||
executor.advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);
|
||||
|
||||
// Client B observes A disconnect
|
||||
channel_buffer_b.read_with(cx_b, |buffer, _| {
|
||||
@@ -123,13 +121,12 @@ async fn test_core_channel_buffers(
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_channel_notes_participant_indices(
|
||||
deterministic: Arc<Deterministic>,
|
||||
mut cx_a: &mut TestAppContext,
|
||||
mut cx_b: &mut TestAppContext,
|
||||
executor: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
cx_c: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(executor.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
let client_c = server.create_client(cx_c, "user_c").await;
|
||||
@@ -157,9 +154,10 @@ async fn test_channel_notes_participant_indices(
|
||||
let (project_a, worktree_id_a) = client_a.build_local_project("/root", cx_a).await;
|
||||
let project_b = client_b.build_empty_local_project(cx_b);
|
||||
let project_c = client_c.build_empty_local_project(cx_c);
|
||||
let workspace_a = client_a.build_workspace(&project_a, cx_a).root(cx_a);
|
||||
let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
|
||||
let workspace_c = client_c.build_workspace(&project_c, cx_c).root(cx_c);
|
||||
|
||||
let (workspace_a, mut cx_a) = client_a.build_workspace(&project_a, cx_a);
|
||||
let (workspace_b, mut cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||
let (workspace_c, cx_c) = client_c.build_workspace(&project_c, cx_c);
|
||||
|
||||
// Clients A, B, and C open the channel notes
|
||||
let channel_view_a = cx_a
|
||||
@@ -184,7 +182,7 @@ async fn test_channel_notes_participant_indices(
|
||||
});
|
||||
});
|
||||
});
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
channel_view_b.update(cx_b, |notes, cx| {
|
||||
notes.editor.update(cx, |editor, cx| {
|
||||
editor.move_down(&Default::default(), cx);
|
||||
@@ -194,7 +192,7 @@ async fn test_channel_notes_participant_indices(
|
||||
});
|
||||
});
|
||||
});
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
channel_view_c.update(cx_c, |notes, cx| {
|
||||
notes.editor.update(cx, |editor, cx| {
|
||||
editor.move_down(&Default::default(), cx);
|
||||
@@ -207,7 +205,7 @@ async fn test_channel_notes_participant_indices(
|
||||
|
||||
// Client A sees clients B and C without assigned colors, because they aren't
|
||||
// in a call together.
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
channel_view_a.update(cx_a, |notes, cx| {
|
||||
notes.editor.update(cx, |editor, cx| {
|
||||
assert_remote_selections(editor, &[(None, 1..2), (None, 2..3)], cx);
|
||||
@@ -223,7 +221,7 @@ async fn test_channel_notes_participant_indices(
|
||||
|
||||
// Clients A and B see each other with two different assigned colors. Client C
|
||||
// still doesn't have a color.
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
channel_view_a.update(cx_a, |notes, cx| {
|
||||
notes.editor.update(cx, |editor, cx| {
|
||||
assert_remote_selections(
|
||||
@@ -249,7 +247,7 @@ async fn test_channel_notes_participant_indices(
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
|
||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||
|
||||
// Clients A and B open the same file.
|
||||
let editor_a = workspace_a
|
||||
@@ -279,7 +277,7 @@ async fn test_channel_notes_participant_indices(
|
||||
selections.select_ranges(vec![2..3]);
|
||||
});
|
||||
});
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
|
||||
// Clients A and B see each other with the same colors as in the channel notes.
|
||||
editor_a.update(cx_a, |editor, cx| {
|
||||
@@ -314,11 +312,10 @@ fn assert_remote_selections(
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_multiple_handles_to_channel_buffer(
|
||||
deterministic: Arc<Deterministic>,
|
||||
deterministic: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(deterministic.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
|
||||
let channel_id = server
|
||||
@@ -340,7 +337,7 @@ async fn test_multiple_handles_to_channel_buffer(
|
||||
future::try_join3(channel_buffer_1, channel_buffer_2, channel_buffer_3)
|
||||
.await
|
||||
.unwrap();
|
||||
let channel_buffer_model_id = channel_buffer.id();
|
||||
let channel_buffer_model_id = channel_buffer.entity_id();
|
||||
assert_eq!(channel_buffer, channel_buffer_2);
|
||||
assert_eq!(channel_buffer, channel_buffer_3);
|
||||
|
||||
@@ -364,7 +361,7 @@ async fn test_multiple_handles_to_channel_buffer(
|
||||
.update(cx_a, |store, cx| store.open_channel_buffer(channel_id, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
assert_ne!(channel_buffer.id(), channel_buffer_model_id);
|
||||
assert_ne!(channel_buffer.entity_id(), channel_buffer_model_id);
|
||||
channel_buffer.update(cx_a, |buffer, cx| {
|
||||
buffer.buffer().update(cx, |buffer, _| {
|
||||
assert_eq!(buffer.text(), "hello");
|
||||
@@ -374,12 +371,11 @@ async fn test_multiple_handles_to_channel_buffer(
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_channel_buffer_disconnect(
|
||||
deterministic: Arc<Deterministic>,
|
||||
deterministic: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(deterministic.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
@@ -397,6 +393,7 @@ async fn test_channel_buffer_disconnect(
|
||||
.update(cx_a, |store, cx| store.open_channel_buffer(channel_id, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let channel_buffer_b = client_b
|
||||
.channel_store()
|
||||
.update(cx_b, |store, cx| store.open_channel_buffer(channel_id, cx))
|
||||
@@ -437,12 +434,11 @@ async fn test_channel_buffer_disconnect(
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_rejoin_channel_buffer(
|
||||
deterministic: Arc<Deterministic>,
|
||||
deterministic: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(deterministic.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
@@ -518,13 +514,12 @@ async fn test_rejoin_channel_buffer(
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_channel_buffers_and_server_restarts(
|
||||
deterministic: Arc<Deterministic>,
|
||||
deterministic: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
cx_c: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(deterministic.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
let client_c = server.create_client(cx_c, "user_c").await;
|
||||
@@ -606,13 +601,12 @@ async fn test_channel_buffers_and_server_restarts(
|
||||
|
||||
#[gpui::test(iterations = 10)]
|
||||
async fn test_following_to_channel_notes_without_a_shared_project(
|
||||
deterministic: Arc<Deterministic>,
|
||||
deterministic: BackgroundExecutor,
|
||||
mut cx_a: &mut TestAppContext,
|
||||
mut cx_b: &mut TestAppContext,
|
||||
mut cx_c: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(deterministic.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
@@ -664,9 +658,9 @@ async fn test_following_to_channel_notes_without_a_shared_project(
|
||||
let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
|
||||
let (project_b, _) = client_b.build_local_project("/b", cx_b).await;
|
||||
let (project_c, _) = client_b.build_local_project("/c", cx_c).await;
|
||||
let workspace_a = client_a.build_workspace(&project_a, cx_a).root(cx_a);
|
||||
let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
|
||||
let _workspace_c = client_c.build_workspace(&project_c, cx_c).root(cx_c);
|
||||
let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
|
||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||
let (_workspace_c, _cx_c) = client_c.build_workspace(&project_c, cx_c);
|
||||
|
||||
active_call_a
|
||||
.update(cx_a, |call, cx| call.set_location(Some(&project_a), cx))
|
||||
@@ -691,7 +685,9 @@ async fn test_following_to_channel_notes_without_a_shared_project(
|
||||
// Client B follows client A.
|
||||
workspace_b
|
||||
.update(cx_b, |workspace, cx| {
|
||||
workspace.follow(client_a.peer_id().unwrap(), cx).unwrap()
|
||||
workspace
|
||||
.start_following(client_a.peer_id().unwrap(), cx)
|
||||
.unwrap()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -699,7 +695,7 @@ async fn test_following_to_channel_notes_without_a_shared_project(
|
||||
// Client B is taken to the notes for channel 1, with the same
|
||||
// text selected as client A.
|
||||
deterministic.run_until_parked();
|
||||
let channel_view_1_b = workspace_b.read_with(cx_b, |workspace, cx| {
|
||||
let channel_view_1_b = workspace_b.update(cx_b, |workspace, cx| {
|
||||
assert_eq!(
|
||||
workspace.leader_for_pane(workspace.active_pane()),
|
||||
Some(client_a.peer_id().unwrap())
|
||||
@@ -710,7 +706,7 @@ async fn test_following_to_channel_notes_without_a_shared_project(
|
||||
.downcast::<ChannelView>()
|
||||
.expect("active item is not a channel view")
|
||||
});
|
||||
channel_view_1_b.read_with(cx_b, |notes, cx| {
|
||||
channel_view_1_b.update(cx_b, |notes, cx| {
|
||||
assert_eq!(notes.channel(cx).unwrap().name, "channel-1");
|
||||
let editor = notes.editor.read(cx);
|
||||
assert_eq!(editor.text(cx), "Hello from A.");
|
||||
@@ -718,17 +714,22 @@ async fn test_following_to_channel_notes_without_a_shared_project(
|
||||
});
|
||||
|
||||
// Client A opens the notes for channel 2.
|
||||
eprintln!("opening -------------------->");
|
||||
|
||||
let channel_view_2_a = cx_a
|
||||
.update(|cx| ChannelView::open(channel_2_id, workspace_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
channel_view_2_a.read_with(cx_a, |notes, cx| {
|
||||
channel_view_2_a.update(cx_a, |notes, cx| {
|
||||
assert_eq!(notes.channel(cx).unwrap().name, "channel-2");
|
||||
});
|
||||
|
||||
// Client B is taken to the notes for channel 2.
|
||||
deterministic.run_until_parked();
|
||||
let channel_view_2_b = workspace_b.read_with(cx_b, |workspace, cx| {
|
||||
|
||||
eprintln!("opening <--------------------");
|
||||
|
||||
let channel_view_2_b = workspace_b.update(cx_b, |workspace, cx| {
|
||||
assert_eq!(
|
||||
workspace.leader_for_pane(workspace.active_pane()),
|
||||
Some(client_a.peer_id().unwrap())
|
||||
@@ -739,19 +740,18 @@ async fn test_following_to_channel_notes_without_a_shared_project(
|
||||
.downcast::<ChannelView>()
|
||||
.expect("active item is not a channel view")
|
||||
});
|
||||
channel_view_2_b.read_with(cx_b, |notes, cx| {
|
||||
channel_view_2_b.update(cx_b, |notes, cx| {
|
||||
assert_eq!(notes.channel(cx).unwrap().name, "channel-2");
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_channel_buffer_changes(
|
||||
deterministic: Arc<Deterministic>,
|
||||
deterministic: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(deterministic.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
@@ -778,7 +778,7 @@ async fn test_channel_buffer_changes(
|
||||
});
|
||||
deterministic.run_until_parked();
|
||||
|
||||
let has_buffer_changed = cx_b.read(|cx| {
|
||||
let has_buffer_changed = cx_b.update(|cx| {
|
||||
client_b
|
||||
.channel_store()
|
||||
.read(cx)
|
||||
@@ -789,14 +789,14 @@ async fn test_channel_buffer_changes(
|
||||
|
||||
// Opening the buffer should clear the changed flag.
|
||||
let project_b = client_b.build_empty_local_project(cx_b);
|
||||
let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
|
||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||
let channel_view_b = cx_b
|
||||
.update(|cx| ChannelView::open(channel_id, workspace_b.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
deterministic.run_until_parked();
|
||||
|
||||
let has_buffer_changed = cx_b.read(|cx| {
|
||||
let has_buffer_changed = cx_b.update(|cx| {
|
||||
client_b
|
||||
.channel_store()
|
||||
.read(cx)
|
||||
@@ -826,7 +826,8 @@ async fn test_channel_buffer_changes(
|
||||
|
||||
// Test that the server is tracking things correctly, and we retain our 'not changed'
|
||||
// state across a disconnect
|
||||
server.simulate_long_connection_interruption(client_b.peer_id().unwrap(), &deterministic);
|
||||
server
|
||||
.simulate_long_connection_interruption(client_b.peer_id().unwrap(), deterministic.clone());
|
||||
let has_buffer_changed = cx_b.read(|cx| {
|
||||
client_b
|
||||
.channel_store()
|
||||
@@ -877,6 +878,6 @@ fn assert_collaborators(collaborators: &HashMap<PeerId, Collaborator>, ids: &[Op
|
||||
);
|
||||
}
|
||||
|
||||
fn buffer_text(channel_buffer: &ModelHandle<language::Buffer>, cx: &mut TestAppContext) -> String {
|
||||
fn buffer_text(channel_buffer: &Model<language::Buffer>, cx: &mut TestAppContext) -> String {
|
||||
channel_buffer.read_with(cx, |buffer, _| buffer.text())
|
||||
}
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer};
|
||||
use channel::{ChannelChat, ChannelMessageId, MessageParams};
|
||||
use collab_ui::chat_panel::ChatPanel;
|
||||
use gpui::{executor::Deterministic, BorrowAppContext, ModelHandle, TestAppContext};
|
||||
use gpui::{BackgroundExecutor, Model, TestAppContext};
|
||||
use rpc::Notification;
|
||||
use std::sync::Arc;
|
||||
use workspace::dock::Panel;
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_basic_channel_messages(
|
||||
deterministic: Arc<Deterministic>,
|
||||
executor: BackgroundExecutor,
|
||||
mut cx_a: &mut TestAppContext,
|
||||
mut cx_b: &mut TestAppContext,
|
||||
mut cx_c: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(executor.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
let client_c = server.create_client(cx_c, "user_c").await;
|
||||
@@ -57,13 +53,13 @@ async fn test_basic_channel_messages(
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
channel_chat_b
|
||||
.update(cx_b, |c, cx| c.send_message("three".into(), cx).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
|
||||
let channel_chat_c = client_c
|
||||
.channel_store()
|
||||
@@ -117,12 +113,11 @@ async fn test_basic_channel_messages(
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_rejoin_channel_chat(
|
||||
deterministic: Arc<Deterministic>,
|
||||
executor: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(executor.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
@@ -178,7 +173,7 @@ async fn test_rejoin_channel_chat(
|
||||
|
||||
// Client A reconnects.
|
||||
server.allow_connections();
|
||||
deterministic.advance_clock(RECONNECT_TIMEOUT);
|
||||
executor.advance_clock(RECONNECT_TIMEOUT);
|
||||
|
||||
// Client A fetches the messages that were sent while they were disconnected
|
||||
// and resends their own messages which failed to send.
|
||||
@@ -189,13 +184,12 @@ async fn test_rejoin_channel_chat(
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_remove_channel_message(
|
||||
deterministic: Arc<Deterministic>,
|
||||
executor: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
cx_c: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(executor.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
let client_c = server.create_client(cx_c, "user_c").await;
|
||||
@@ -235,7 +229,7 @@ async fn test_remove_channel_message(
|
||||
.unwrap();
|
||||
|
||||
// Clients A and B see all of the messages.
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
let expected_messages = &["one", "two", "three"];
|
||||
assert_messages(&channel_chat_a, expected_messages, cx_a);
|
||||
assert_messages(&channel_chat_b, expected_messages, cx_b);
|
||||
@@ -252,7 +246,7 @@ async fn test_remove_channel_message(
|
||||
.unwrap();
|
||||
|
||||
// Client B sees that the message is gone.
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
let expected_messages = &["one", "three"];
|
||||
assert_messages(&channel_chat_a, expected_messages, cx_a);
|
||||
assert_messages(&channel_chat_b, expected_messages, cx_b);
|
||||
@@ -267,146 +261,148 @@ async fn test_remove_channel_message(
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn assert_messages(chat: &ModelHandle<ChannelChat>, messages: &[&str], cx: &mut TestAppContext) {
|
||||
fn assert_messages(chat: &Model<ChannelChat>, messages: &[&str], cx: &mut TestAppContext) {
|
||||
// todo!(don't directly borrow here)
|
||||
assert_eq!(
|
||||
chat.read_with(cx, |chat, _| chat
|
||||
.messages()
|
||||
.iter()
|
||||
.map(|m| m.body.clone())
|
||||
.collect::<Vec<_>>(),),
|
||||
chat.read_with(cx, |chat, _| {
|
||||
chat.messages()
|
||||
.iter()
|
||||
.map(|m| m.body.clone())
|
||||
.collect::<Vec<_>>()
|
||||
}),
|
||||
messages
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_channel_message_changes(
|
||||
deterministic: Arc<Deterministic>,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
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;
|
||||
//todo!(collab_ui)
|
||||
// #[gpui::test]
|
||||
// async fn test_channel_message_changes(
|
||||
// executor: BackgroundExecutor,
|
||||
// cx_a: &mut TestAppContext,
|
||||
// cx_b: &mut TestAppContext,
|
||||
// ) {
|
||||
// let mut server = TestServer::start(&executor).await;
|
||||
// let client_a = server.create_client(cx_a, "user_a").await;
|
||||
// let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
let channel_id = server
|
||||
.make_channel(
|
||||
"the-channel",
|
||||
None,
|
||||
(&client_a, cx_a),
|
||||
&mut [(&client_b, cx_b)],
|
||||
)
|
||||
.await;
|
||||
// let channel_id = server
|
||||
// .make_channel(
|
||||
// "the-channel",
|
||||
// None,
|
||||
// (&client_a, cx_a),
|
||||
// &mut [(&client_b, cx_b)],
|
||||
// )
|
||||
// .await;
|
||||
|
||||
// Client A sends a message, client B should see that there is a new message.
|
||||
let channel_chat_a = client_a
|
||||
.channel_store()
|
||||
.update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
// // Client A sends a message, client B should see that there is a new message.
|
||||
// let channel_chat_a = client_a
|
||||
// .channel_store()
|
||||
// .update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx))
|
||||
// .await
|
||||
// .unwrap();
|
||||
|
||||
channel_chat_a
|
||||
.update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
// channel_chat_a
|
||||
// .update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap())
|
||||
// .await
|
||||
// .unwrap();
|
||||
|
||||
deterministic.run_until_parked();
|
||||
// executor.run_until_parked();
|
||||
|
||||
let b_has_messages = cx_b.read_with(|cx| {
|
||||
client_b
|
||||
.channel_store()
|
||||
.read(cx)
|
||||
.has_new_messages(channel_id)
|
||||
.unwrap()
|
||||
});
|
||||
// let b_has_messages = cx_b.read_with(|cx| {
|
||||
// client_b
|
||||
// .channel_store()
|
||||
// .read(cx)
|
||||
// .has_new_messages(channel_id)
|
||||
// .unwrap()
|
||||
// });
|
||||
|
||||
assert!(b_has_messages);
|
||||
// assert!(b_has_messages);
|
||||
|
||||
// Opening the chat should clear the changed flag.
|
||||
cx_b.update(|cx| {
|
||||
collab_ui::init(&client_b.app_state, cx);
|
||||
});
|
||||
let project_b = client_b.build_empty_local_project(cx_b);
|
||||
let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
|
||||
let chat_panel_b = workspace_b.update(cx_b, |workspace, cx| ChatPanel::new(workspace, cx));
|
||||
chat_panel_b
|
||||
.update(cx_b, |chat_panel, cx| {
|
||||
chat_panel.set_active(true, cx);
|
||||
chat_panel.select_channel(channel_id, None, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
// // Opening the chat should clear the changed flag.
|
||||
// cx_b.update(|cx| {
|
||||
// collab_ui::init(&client_b.app_state, cx);
|
||||
// });
|
||||
// let project_b = client_b.build_empty_local_project(cx_b);
|
||||
// let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
|
||||
// let chat_panel_b = workspace_b.update(cx_b, |workspace, cx| ChatPanel::new(workspace, cx));
|
||||
// chat_panel_b
|
||||
// .update(cx_b, |chat_panel, cx| {
|
||||
// chat_panel.set_active(true, cx);
|
||||
// chat_panel.select_channel(channel_id, None, cx)
|
||||
// })
|
||||
// .await
|
||||
// .unwrap();
|
||||
|
||||
deterministic.run_until_parked();
|
||||
// executor.run_until_parked();
|
||||
|
||||
let b_has_messages = cx_b.read_with(|cx| {
|
||||
client_b
|
||||
.channel_store()
|
||||
.read(cx)
|
||||
.has_new_messages(channel_id)
|
||||
.unwrap()
|
||||
});
|
||||
// let b_has_messages = cx_b.read_with(|cx| {
|
||||
// client_b
|
||||
// .channel_store()
|
||||
// .read(cx)
|
||||
// .has_new_messages(channel_id)
|
||||
// .unwrap()
|
||||
// });
|
||||
|
||||
assert!(!b_has_messages);
|
||||
// assert!(!b_has_messages);
|
||||
|
||||
// Sending a message while the chat is open should not change the flag.
|
||||
channel_chat_a
|
||||
.update(cx_a, |c, cx| c.send_message("two".into(), cx).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
// // Sending a message while the chat is open should not change the flag.
|
||||
// channel_chat_a
|
||||
// .update(cx_a, |c, cx| c.send_message("two".into(), cx).unwrap())
|
||||
// .await
|
||||
// .unwrap();
|
||||
|
||||
deterministic.run_until_parked();
|
||||
// executor.run_until_parked();
|
||||
|
||||
let b_has_messages = cx_b.read_with(|cx| {
|
||||
client_b
|
||||
.channel_store()
|
||||
.read(cx)
|
||||
.has_new_messages(channel_id)
|
||||
.unwrap()
|
||||
});
|
||||
// let b_has_messages = cx_b.read_with(|cx| {
|
||||
// client_b
|
||||
// .channel_store()
|
||||
// .read(cx)
|
||||
// .has_new_messages(channel_id)
|
||||
// .unwrap()
|
||||
// });
|
||||
|
||||
assert!(!b_has_messages);
|
||||
// assert!(!b_has_messages);
|
||||
|
||||
// Sending a message while the chat is closed should change the flag.
|
||||
chat_panel_b.update(cx_b, |chat_panel, cx| {
|
||||
chat_panel.set_active(false, cx);
|
||||
});
|
||||
// // Sending a message while the chat is closed should change the flag.
|
||||
// chat_panel_b.update(cx_b, |chat_panel, cx| {
|
||||
// chat_panel.set_active(false, cx);
|
||||
// });
|
||||
|
||||
// Sending a message while the chat is open should not change the flag.
|
||||
channel_chat_a
|
||||
.update(cx_a, |c, cx| c.send_message("three".into(), cx).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
// // Sending a message while the chat is open should not change the flag.
|
||||
// channel_chat_a
|
||||
// .update(cx_a, |c, cx| c.send_message("three".into(), cx).unwrap())
|
||||
// .await
|
||||
// .unwrap();
|
||||
|
||||
deterministic.run_until_parked();
|
||||
// executor.run_until_parked();
|
||||
|
||||
let b_has_messages = cx_b.read_with(|cx| {
|
||||
client_b
|
||||
.channel_store()
|
||||
.read(cx)
|
||||
.has_new_messages(channel_id)
|
||||
.unwrap()
|
||||
});
|
||||
// let b_has_messages = cx_b.read_with(|cx| {
|
||||
// client_b
|
||||
// .channel_store()
|
||||
// .read(cx)
|
||||
// .has_new_messages(channel_id)
|
||||
// .unwrap()
|
||||
// });
|
||||
|
||||
assert!(b_has_messages);
|
||||
// assert!(b_has_messages);
|
||||
|
||||
// Closing the chat should re-enable change tracking
|
||||
cx_b.update(|_| drop(chat_panel_b));
|
||||
// // Closing the chat should re-enable change tracking
|
||||
// cx_b.update(|_| drop(chat_panel_b));
|
||||
|
||||
channel_chat_a
|
||||
.update(cx_a, |c, cx| c.send_message("four".into(), cx).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
// channel_chat_a
|
||||
// .update(cx_a, |c, cx| c.send_message("four".into(), cx).unwrap())
|
||||
// .await
|
||||
// .unwrap();
|
||||
|
||||
deterministic.run_until_parked();
|
||||
// executor.run_until_parked();
|
||||
|
||||
let b_has_messages = cx_b.read_with(|cx| {
|
||||
client_b
|
||||
.channel_store()
|
||||
.read(cx)
|
||||
.has_new_messages(channel_id)
|
||||
.unwrap()
|
||||
});
|
||||
// let b_has_messages = cx_b.read_with(|cx| {
|
||||
// client_b
|
||||
// .channel_store()
|
||||
// .read(cx)
|
||||
// .has_new_messages(channel_id)
|
||||
// .unwrap()
|
||||
// });
|
||||
|
||||
assert!(b_has_messages);
|
||||
}
|
||||
// assert!(b_has_messages);
|
||||
// }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1890
-1820
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,19 @@
|
||||
use crate::tests::TestServer;
|
||||
use gpui::{executor::Deterministic, TestAppContext};
|
||||
use std::sync::Arc;
|
||||
|
||||
use gpui::{BackgroundExecutor, TestAppContext};
|
||||
use notifications::NotificationEvent;
|
||||
use parking_lot::Mutex;
|
||||
use rpc::{proto, Notification};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::tests::TestServer;
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_notifications(
|
||||
deterministic: Arc<Deterministic>,
|
||||
executor: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(executor.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
@@ -42,7 +43,7 @@ async fn test_notifications(
|
||||
|
||||
// Client B receives a contact request notification and responds to the
|
||||
// request, accepting it.
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
client_b.notification_store().update(cx_b, |store, cx| {
|
||||
assert_eq!(store.notification_count(), 1);
|
||||
assert_eq!(store.unread_notification_count(), 1);
|
||||
@@ -72,7 +73,7 @@ async fn test_notifications(
|
||||
});
|
||||
|
||||
// Client B sees the notification is now read, and that they responded.
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
client_b.notification_store().read_with(cx_b, |store, _| {
|
||||
assert_eq!(store.notification_count(), 1);
|
||||
assert_eq!(store.unread_notification_count(), 0);
|
||||
@@ -127,7 +128,7 @@ async fn test_notifications(
|
||||
|
||||
// Client B receives a channel invitation notification and responds to the
|
||||
// invitation, accepting it.
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
client_b.notification_store().update(cx_b, |store, cx| {
|
||||
assert_eq!(store.notification_count(), 2);
|
||||
assert_eq!(store.unread_notification_count(), 1);
|
||||
@@ -147,7 +148,7 @@ async fn test_notifications(
|
||||
});
|
||||
|
||||
// Client B sees the notification is now read, and that they responded.
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
client_b.notification_store().read_with(cx_b, |store, _| {
|
||||
assert_eq!(store.notification_count(), 2);
|
||||
assert_eq!(store.unread_notification_count(), 0);
|
||||
|
||||
@@ -3,10 +3,14 @@ use crate::db::ChannelRole;
|
||||
use super::{run_randomized_test, RandomizedTest, TestClient, TestError, TestServer, UserTestPlan};
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use gpui::{executor::Deterministic, TestAppContext};
|
||||
use gpui::{BackgroundExecutor, SharedString, TestAppContext};
|
||||
use rand::prelude::*;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{ops::Range, rc::Rc, sync::Arc};
|
||||
use std::{
|
||||
ops::{Deref, DerefMut, Range},
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
};
|
||||
use text::Bias;
|
||||
|
||||
#[gpui::test(
|
||||
@@ -15,10 +19,10 @@ use text::Bias;
|
||||
)]
|
||||
async fn test_random_channel_buffers(
|
||||
cx: &mut TestAppContext,
|
||||
deterministic: Arc<Deterministic>,
|
||||
executor: BackgroundExecutor,
|
||||
rng: StdRng,
|
||||
) {
|
||||
run_randomized_test::<RandomChannelBufferTest>(cx, deterministic, rng).await;
|
||||
run_randomized_test::<RandomChannelBufferTest>(cx, executor, rng).await;
|
||||
}
|
||||
|
||||
struct RandomChannelBufferTest;
|
||||
@@ -26,13 +30,13 @@ struct RandomChannelBufferTest;
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
enum ChannelBufferOperation {
|
||||
JoinChannelNotes {
|
||||
channel_name: String,
|
||||
channel_name: SharedString,
|
||||
},
|
||||
LeaveChannelNotes {
|
||||
channel_name: String,
|
||||
channel_name: SharedString,
|
||||
},
|
||||
EditChannelNotes {
|
||||
channel_name: String,
|
||||
channel_name: SharedString,
|
||||
edits: Vec<(Range<usize>, Arc<str>)>,
|
||||
},
|
||||
Noop,
|
||||
@@ -69,11 +73,11 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||
cx: &TestAppContext,
|
||||
) -> ChannelBufferOperation {
|
||||
let channel_store = client.channel_store().clone();
|
||||
let channel_buffers = client.channel_buffers();
|
||||
let mut channel_buffers = client.channel_buffers();
|
||||
|
||||
// When signed out, we can't do anything unless a channel buffer is
|
||||
// already open.
|
||||
if channel_buffers.is_empty()
|
||||
if channel_buffers.deref_mut().is_empty()
|
||||
&& channel_store.read_with(cx, |store, _| store.channel_count() == 0)
|
||||
{
|
||||
return ChannelBufferOperation::Noop;
|
||||
@@ -97,7 +101,7 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||
}
|
||||
|
||||
30..=40 => {
|
||||
if let Some(buffer) = channel_buffers.iter().choose(rng) {
|
||||
if let Some(buffer) = channel_buffers.deref().iter().choose(rng) {
|
||||
let channel_name =
|
||||
buffer.read_with(cx, |b, cx| b.channel(cx).unwrap().name.clone());
|
||||
break ChannelBufferOperation::LeaveChannelNotes { channel_name };
|
||||
@@ -105,7 +109,7 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||
}
|
||||
|
||||
_ => {
|
||||
if let Some(buffer) = channel_buffers.iter().choose(rng) {
|
||||
if let Some(buffer) = channel_buffers.deref().iter().choose(rng) {
|
||||
break buffer.read_with(cx, |b, cx| {
|
||||
let channel_name = b.channel(cx).unwrap().name.clone();
|
||||
let edits = b
|
||||
@@ -147,13 +151,13 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||
"{}: opening notes for channel {channel_name}",
|
||||
client.username
|
||||
);
|
||||
client.channel_buffers().insert(buffer.await?);
|
||||
client.channel_buffers().deref_mut().insert(buffer.await?);
|
||||
}
|
||||
|
||||
ChannelBufferOperation::LeaveChannelNotes { channel_name } => {
|
||||
let buffer = cx.update(|cx| {
|
||||
let mut left_buffer = Err(TestError::Inapplicable);
|
||||
client.channel_buffers().retain(|buffer| {
|
||||
client.channel_buffers().deref_mut().retain(|buffer| {
|
||||
if buffer.read(cx).channel(cx).unwrap().name == channel_name {
|
||||
left_buffer = Ok(buffer.clone());
|
||||
false
|
||||
@@ -179,6 +183,7 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||
.read(|cx| {
|
||||
client
|
||||
.channel_buffers()
|
||||
.deref()
|
||||
.iter()
|
||||
.find(|buffer| {
|
||||
buffer.read(cx).channel(cx).unwrap().name == channel_name
|
||||
@@ -215,13 +220,6 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn on_client_added(client: &Rc<TestClient>, cx: &mut TestAppContext) {
|
||||
let channel_store = client.channel_store();
|
||||
while channel_store.read_with(cx, |store, _| store.channel_count() == 0) {
|
||||
channel_store.next_notification(cx).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn on_quiesce(server: &mut TestServer, clients: &mut [(Rc<TestClient>, TestAppContext)]) {
|
||||
let channels = server.app_state.db.all_channels().await.unwrap();
|
||||
|
||||
@@ -229,6 +227,7 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||
client_cx.update(|cx| {
|
||||
client
|
||||
.channel_buffers()
|
||||
.deref_mut()
|
||||
.retain(|b| b.read(cx).is_connected());
|
||||
});
|
||||
}
|
||||
@@ -252,6 +251,7 @@ impl RandomizedTest for RandomChannelBufferTest {
|
||||
client_cx.read(|cx| {
|
||||
if let Some(channel_buffer) = client
|
||||
.channel_buffers()
|
||||
.deref()
|
||||
.iter()
|
||||
.find(|b| b.read(cx).channel_id == channel_id.to_proto())
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{run_randomized_test, RandomizedTest, TestClient, TestError, TestServer, UserTestPlan};
|
||||
use crate::db::UserId;
|
||||
use super::{RandomizedTest, TestClient, TestError, TestServer, UserTestPlan};
|
||||
use crate::{db::UserId, tests::run_randomized_test};
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use call::ActiveCall;
|
||||
@@ -7,7 +7,7 @@ use collections::{BTreeMap, HashMap};
|
||||
use editor::Bias;
|
||||
use fs::{repository::GitFileStatus, FakeFs, Fs as _};
|
||||
use futures::StreamExt;
|
||||
use gpui::{executor::Deterministic, ModelHandle, TestAppContext};
|
||||
use gpui::{BackgroundExecutor, Model, TestAppContext};
|
||||
use language::{range_to_lsp, FakeLspAdapter, Language, LanguageConfig, PointUtf16};
|
||||
use lsp::FakeLanguageServer;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -18,7 +18,7 @@ use rand::{
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
ops::Range,
|
||||
ops::{Deref, Range},
|
||||
path::{Path, PathBuf},
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
@@ -31,10 +31,10 @@ use util::ResultExt;
|
||||
)]
|
||||
async fn test_random_project_collaboration(
|
||||
cx: &mut TestAppContext,
|
||||
deterministic: Arc<Deterministic>,
|
||||
executor: BackgroundExecutor,
|
||||
rng: StdRng,
|
||||
) {
|
||||
run_randomized_test::<ProjectCollaborationTest>(cx, deterministic, rng).await;
|
||||
run_randomized_test::<ProjectCollaborationTest>(cx, executor, rng).await;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@@ -295,7 +295,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
let is_local = project.read_with(cx, |project, _| project.is_local());
|
||||
let worktree = project.read_with(cx, |project, cx| {
|
||||
project
|
||||
.worktrees(cx)
|
||||
.worktrees()
|
||||
.filter(|worktree| {
|
||||
let worktree = worktree.read(cx);
|
||||
worktree.is_visible()
|
||||
@@ -417,7 +417,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
81.. => {
|
||||
let worktree = project.read_with(cx, |project, cx| {
|
||||
project
|
||||
.worktrees(cx)
|
||||
.worktrees()
|
||||
.filter(|worktree| {
|
||||
let worktree = worktree.read(cx);
|
||||
worktree.is_visible()
|
||||
@@ -624,7 +624,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
room.join_project(
|
||||
project_id,
|
||||
client.language_registry().clone(),
|
||||
FakeFs::new(cx.background().clone()),
|
||||
FakeFs::new(cx.background_executor().clone()),
|
||||
cx,
|
||||
)
|
||||
}))
|
||||
@@ -782,6 +782,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
.map_err(|err| anyhow!("save request failed: {:?}", err))?;
|
||||
assert!(buffer
|
||||
.read_with(&cx, |buffer, _| { buffer.saved_version().to_owned() })
|
||||
.expect("App should not be dropped")
|
||||
.observed_all(&requested_version));
|
||||
anyhow::Ok(())
|
||||
});
|
||||
@@ -817,30 +818,30 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
|
||||
use futures::{FutureExt as _, TryFutureExt as _};
|
||||
let offset = buffer.read_with(cx, |b, _| b.clip_offset(offset, Bias::Left));
|
||||
let request = cx.foreground().spawn(project.update(cx, |project, cx| {
|
||||
match kind {
|
||||
LspRequestKind::Rename => project
|
||||
.prepare_rename(buffer, offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
LspRequestKind::Completion => project
|
||||
.completions(&buffer, offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
LspRequestKind::CodeAction => project
|
||||
.code_actions(&buffer, offset..offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
LspRequestKind::Definition => project
|
||||
.definition(&buffer, offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
LspRequestKind::Highlights => project
|
||||
.document_highlights(&buffer, offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
}
|
||||
}));
|
||||
|
||||
let process_lsp_request = project.update(cx, |project, cx| match kind {
|
||||
LspRequestKind::Rename => project
|
||||
.prepare_rename(buffer, offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
LspRequestKind::Completion => project
|
||||
.completions(&buffer, offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
LspRequestKind::CodeAction => project
|
||||
.code_actions(&buffer, offset..offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
LspRequestKind::Definition => project
|
||||
.definition(&buffer, offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
LspRequestKind::Highlights => project
|
||||
.document_highlights(&buffer, offset, cx)
|
||||
.map_ok(|_| ())
|
||||
.boxed(),
|
||||
});
|
||||
let request = cx.foreground_executor().spawn(process_lsp_request);
|
||||
if detach {
|
||||
request.detach();
|
||||
} else {
|
||||
@@ -874,7 +875,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
)
|
||||
});
|
||||
drop(project);
|
||||
let search = cx.background().spawn(async move {
|
||||
let search = cx.executor().spawn(async move {
|
||||
let mut results = HashMap::default();
|
||||
while let Some((buffer, ranges)) = search.next().await {
|
||||
results.entry(buffer).or_insert(ranges);
|
||||
@@ -1075,12 +1076,12 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
fake_server.handle_request::<lsp::request::GotoDefinition, _, _>({
|
||||
let fs = fs.clone();
|
||||
move |_, cx| {
|
||||
let background = cx.background();
|
||||
let background = cx.background_executor();
|
||||
let mut rng = background.rng();
|
||||
let count = rng.gen_range::<usize, _>(1..3);
|
||||
let files = fs.as_fake().files();
|
||||
let files = (0..count)
|
||||
.map(|_| files.choose(&mut *rng).unwrap().clone())
|
||||
.map(|_| files.choose(&mut rng).unwrap().clone())
|
||||
.collect::<Vec<_>>();
|
||||
async move {
|
||||
log::info!("LSP: Returning definitions in files {:?}", &files);
|
||||
@@ -1100,7 +1101,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
fake_server.handle_request::<lsp::request::DocumentHighlightRequest, _, _>(
|
||||
move |_, cx| {
|
||||
let mut highlights = Vec::new();
|
||||
let background = cx.background();
|
||||
let background = cx.background_executor();
|
||||
let mut rng = background.rng();
|
||||
|
||||
let highlight_count = rng.gen_range(1..=5);
|
||||
@@ -1153,7 +1154,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
let host_worktree_snapshots =
|
||||
host_project.read_with(host_cx, |host_project, cx| {
|
||||
host_project
|
||||
.worktrees(cx)
|
||||
.worktrees()
|
||||
.map(|worktree| {
|
||||
let worktree = worktree.read(cx);
|
||||
(worktree.id(), worktree.snapshot())
|
||||
@@ -1161,7 +1162,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
.collect::<BTreeMap<_, _>>()
|
||||
});
|
||||
let guest_worktree_snapshots = guest_project
|
||||
.worktrees(cx)
|
||||
.worktrees()
|
||||
.map(|worktree| {
|
||||
let worktree = worktree.read(cx);
|
||||
(worktree.id(), worktree.snapshot())
|
||||
@@ -1218,7 +1219,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
}
|
||||
}
|
||||
|
||||
for buffer in guest_project.opened_buffers(cx) {
|
||||
for buffer in guest_project.opened_buffers() {
|
||||
let buffer = buffer.read(cx);
|
||||
assert_eq!(
|
||||
buffer.deferred_ops_len(),
|
||||
@@ -1268,8 +1269,8 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
for guest_buffer in guest_buffers {
|
||||
let buffer_id =
|
||||
guest_buffer.read_with(client_cx, |buffer, _| buffer.remote_id());
|
||||
let host_buffer = host_project.read_with(host_cx, |project, cx| {
|
||||
project.buffer_for_id(buffer_id, cx).unwrap_or_else(|| {
|
||||
let host_buffer = host_project.read_with(host_cx, |project, _| {
|
||||
project.buffer_for_id(buffer_id).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"host does not have buffer for guest:{}, peer:{:?}, id:{}",
|
||||
client.username,
|
||||
@@ -1457,10 +1458,10 @@ fn generate_git_operation(rng: &mut StdRng, client: &TestClient) -> GitOperation
|
||||
|
||||
fn buffer_for_full_path(
|
||||
client: &TestClient,
|
||||
project: &ModelHandle<Project>,
|
||||
project: &Model<Project>,
|
||||
full_path: &PathBuf,
|
||||
cx: &TestAppContext,
|
||||
) -> Option<ModelHandle<language::Buffer>> {
|
||||
) -> Option<Model<language::Buffer>> {
|
||||
client
|
||||
.buffers_for_project(project)
|
||||
.iter()
|
||||
@@ -1476,18 +1477,18 @@ fn project_for_root_name(
|
||||
client: &TestClient,
|
||||
root_name: &str,
|
||||
cx: &TestAppContext,
|
||||
) -> Option<ModelHandle<Project>> {
|
||||
if let Some(ix) = project_ix_for_root_name(&*client.local_projects(), root_name, cx) {
|
||||
) -> Option<Model<Project>> {
|
||||
if let Some(ix) = project_ix_for_root_name(&*client.local_projects().deref(), root_name, cx) {
|
||||
return Some(client.local_projects()[ix].clone());
|
||||
}
|
||||
if let Some(ix) = project_ix_for_root_name(&*client.remote_projects(), root_name, cx) {
|
||||
if let Some(ix) = project_ix_for_root_name(&*client.remote_projects().deref(), root_name, cx) {
|
||||
return Some(client.remote_projects()[ix].clone());
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn project_ix_for_root_name(
|
||||
projects: &[ModelHandle<Project>],
|
||||
projects: &[Model<Project>],
|
||||
root_name: &str,
|
||||
cx: &TestAppContext,
|
||||
) -> Option<usize> {
|
||||
@@ -1499,7 +1500,7 @@ fn project_ix_for_root_name(
|
||||
})
|
||||
}
|
||||
|
||||
fn root_name_for_project(project: &ModelHandle<Project>, cx: &TestAppContext) -> String {
|
||||
fn root_name_for_project(project: &Model<Project>, cx: &TestAppContext) -> String {
|
||||
project.read_with(cx, |project, cx| {
|
||||
project
|
||||
.visible_worktrees(cx)
|
||||
@@ -1512,7 +1513,7 @@ fn root_name_for_project(project: &ModelHandle<Project>, cx: &TestAppContext) ->
|
||||
}
|
||||
|
||||
fn project_path_for_full_path(
|
||||
project: &ModelHandle<Project>,
|
||||
project: &Model<Project>,
|
||||
full_path: &Path,
|
||||
cx: &TestAppContext,
|
||||
) -> Option<ProjectPath> {
|
||||
@@ -1520,7 +1521,7 @@ fn project_path_for_full_path(
|
||||
let root_name = components.next().unwrap().as_os_str().to_str().unwrap();
|
||||
let path = components.as_path().into();
|
||||
let worktree_id = project.read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).find_map(|worktree| {
|
||||
project.worktrees().find_map(|worktree| {
|
||||
let worktree = worktree.read(cx);
|
||||
if worktree.root_name() == root_name {
|
||||
Some(worktree.id())
|
||||
@@ -1533,7 +1534,7 @@ fn project_path_for_full_path(
|
||||
}
|
||||
|
||||
async fn ensure_project_shared(
|
||||
project: &ModelHandle<Project>,
|
||||
project: &Model<Project>,
|
||||
client: &TestClient,
|
||||
cx: &mut TestAppContext,
|
||||
) {
|
||||
@@ -1566,9 +1567,10 @@ async fn ensure_project_shared(
|
||||
}
|
||||
}
|
||||
|
||||
fn choose_random_project(client: &TestClient, rng: &mut StdRng) -> Option<ModelHandle<Project>> {
|
||||
fn choose_random_project(client: &TestClient, rng: &mut StdRng) -> Option<Model<Project>> {
|
||||
client
|
||||
.local_projects()
|
||||
.deref()
|
||||
.iter()
|
||||
.chain(client.remote_projects().iter())
|
||||
.choose(rng)
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use futures::StreamExt;
|
||||
use gpui::{executor::Deterministic, Task, TestAppContext};
|
||||
use gpui::{BackgroundExecutor, Task, TestAppContext};
|
||||
use parking_lot::Mutex;
|
||||
use rand::prelude::*;
|
||||
use rpc::RECEIVE_TIMEOUT;
|
||||
@@ -115,18 +115,17 @@ pub trait RandomizedTest: 'static + Sized {
|
||||
|
||||
async fn initialize(server: &mut TestServer, users: &[UserTestPlan]);
|
||||
|
||||
async fn on_client_added(client: &Rc<TestClient>, cx: &mut TestAppContext);
|
||||
async fn on_client_added(_client: &Rc<TestClient>, _cx: &mut TestAppContext) {}
|
||||
|
||||
async fn on_quiesce(server: &mut TestServer, client: &mut [(Rc<TestClient>, TestAppContext)]);
|
||||
}
|
||||
|
||||
pub async fn run_randomized_test<T: RandomizedTest>(
|
||||
cx: &mut TestAppContext,
|
||||
deterministic: Arc<Deterministic>,
|
||||
executor: BackgroundExecutor,
|
||||
rng: StdRng,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
let mut server = TestServer::start(executor.clone()).await;
|
||||
let plan = TestPlan::<T>::new(&mut server, rng).await;
|
||||
|
||||
LAST_PLAN.lock().replace({
|
||||
@@ -144,7 +143,7 @@ pub async fn run_randomized_test<T: RandomizedTest>(
|
||||
applied.store(true, SeqCst);
|
||||
let did_apply = TestPlan::apply_server_operation(
|
||||
plan.clone(),
|
||||
deterministic.clone(),
|
||||
executor.clone(),
|
||||
&mut server,
|
||||
&mut clients,
|
||||
&mut client_tasks,
|
||||
@@ -159,14 +158,14 @@ pub async fn run_randomized_test<T: RandomizedTest>(
|
||||
}
|
||||
|
||||
drop(operation_channels);
|
||||
deterministic.start_waiting();
|
||||
executor.start_waiting();
|
||||
futures::future::join_all(client_tasks).await;
|
||||
deterministic.finish_waiting();
|
||||
executor.finish_waiting();
|
||||
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
T::on_quiesce(&mut server, &mut clients).await;
|
||||
|
||||
for (client, mut cx) in clients {
|
||||
for (client, cx) in clients {
|
||||
cx.update(|cx| {
|
||||
let store = cx.remove_global::<SettingsStore>();
|
||||
cx.clear_globals();
|
||||
@@ -174,7 +173,7 @@ pub async fn run_randomized_test<T: RandomizedTest>(
|
||||
drop(client);
|
||||
});
|
||||
}
|
||||
deterministic.run_until_parked();
|
||||
executor.run_until_parked();
|
||||
|
||||
if let Some(path) = &*PLAN_SAVE_PATH {
|
||||
eprintln!("saved test plan to path {:?}", path);
|
||||
@@ -450,7 +449,7 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||
|
||||
async fn apply_server_operation(
|
||||
plan: Arc<Mutex<Self>>,
|
||||
deterministic: Arc<Deterministic>,
|
||||
deterministic: BackgroundExecutor,
|
||||
server: &mut TestServer,
|
||||
clients: &mut Vec<(Rc<TestClient>, TestAppContext)>,
|
||||
client_tasks: &mut Vec<Task<()>>,
|
||||
@@ -471,28 +470,18 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||
username = user.username.clone();
|
||||
};
|
||||
log::info!("adding new connection for {}", username);
|
||||
let next_entity_id = (user_id.0 * 10_000) as usize;
|
||||
let mut client_cx = TestAppContext::new(
|
||||
cx.foreground_platform(),
|
||||
cx.platform(),
|
||||
deterministic.build_foreground(user_id.0 as usize),
|
||||
deterministic.build_background(),
|
||||
cx.font_cache(),
|
||||
cx.leak_detector(),
|
||||
next_entity_id,
|
||||
cx.function_name.clone(),
|
||||
);
|
||||
|
||||
let mut client_cx = cx.new_app();
|
||||
|
||||
let (operation_tx, operation_rx) = futures::channel::mpsc::unbounded();
|
||||
let client = Rc::new(server.create_client(&mut client_cx, &username).await);
|
||||
operation_channels.push(operation_tx);
|
||||
clients.push((client.clone(), client_cx.clone()));
|
||||
client_tasks.push(client_cx.foreground().spawn(Self::simulate_client(
|
||||
plan.clone(),
|
||||
client,
|
||||
operation_rx,
|
||||
client_cx,
|
||||
)));
|
||||
|
||||
let foreground_executor = client_cx.foreground_executor().clone();
|
||||
let simulate_client =
|
||||
Self::simulate_client(plan.clone(), client, operation_rx, client_cx);
|
||||
client_tasks.push(foreground_executor.spawn(simulate_client));
|
||||
|
||||
log::info!("added connection for {}", username);
|
||||
}
|
||||
@@ -514,7 +503,7 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(user_connection_ids.len(), 1);
|
||||
let removed_peer_id = user_connection_ids[0].into();
|
||||
let (client, mut client_cx) = clients.remove(client_ix);
|
||||
let (client, client_cx) = clients.remove(client_ix);
|
||||
let client_task = client_tasks.remove(client_ix);
|
||||
operation_channels.remove(client_ix);
|
||||
server.forbid_connections();
|
||||
@@ -647,7 +636,7 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||
log::error!("{} error: {}", client.username, error);
|
||||
}
|
||||
}
|
||||
cx.background().simulate_random_delay().await;
|
||||
cx.executor().simulate_random_delay().await;
|
||||
}
|
||||
log::info!("{}: done", client.username);
|
||||
}
|
||||
|
||||
@@ -13,9 +13,10 @@ use client::{
|
||||
use collections::{HashMap, HashSet};
|
||||
use fs::FakeFs;
|
||||
use futures::{channel::oneshot, StreamExt as _};
|
||||
use gpui::{executor::Deterministic, ModelHandle, Task, TestAppContext, WindowHandle};
|
||||
use gpui::{BackgroundExecutor, Context, Model, TestAppContext, View, VisualTestContext};
|
||||
use language::LanguageRegistry;
|
||||
use node_runtime::FakeNodeRuntime;
|
||||
|
||||
use notifications::NotificationStore;
|
||||
use parking_lot::Mutex;
|
||||
use project::{Project, WorktreeId};
|
||||
@@ -46,17 +47,17 @@ pub struct TestServer {
|
||||
pub struct TestClient {
|
||||
pub username: String,
|
||||
pub app_state: Arc<workspace::AppState>,
|
||||
channel_store: ModelHandle<ChannelStore>,
|
||||
notification_store: ModelHandle<NotificationStore>,
|
||||
channel_store: Model<ChannelStore>,
|
||||
notification_store: Model<NotificationStore>,
|
||||
state: RefCell<TestClientState>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TestClientState {
|
||||
local_projects: Vec<ModelHandle<Project>>,
|
||||
remote_projects: Vec<ModelHandle<Project>>,
|
||||
buffers: HashMap<ModelHandle<Project>, HashSet<ModelHandle<language::Buffer>>>,
|
||||
channel_buffers: HashSet<ModelHandle<ChannelBuffer>>,
|
||||
local_projects: Vec<Model<Project>>,
|
||||
remote_projects: Vec<Model<Project>>,
|
||||
buffers: HashMap<Model<Project>, HashSet<Model<language::Buffer>>>,
|
||||
channel_buffers: HashSet<Model<ChannelBuffer>>,
|
||||
}
|
||||
|
||||
pub struct ContactsSummary {
|
||||
@@ -66,22 +67,22 @@ pub struct ContactsSummary {
|
||||
}
|
||||
|
||||
impl TestServer {
|
||||
pub async fn start(deterministic: &Arc<Deterministic>) -> Self {
|
||||
pub async fn start(deterministic: BackgroundExecutor) -> Self {
|
||||
static NEXT_LIVE_KIT_SERVER_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
let use_postgres = env::var("USE_POSTGRES").ok();
|
||||
let use_postgres = use_postgres.as_deref();
|
||||
let test_db = if use_postgres == Some("true") || use_postgres == Some("1") {
|
||||
TestDb::postgres(deterministic.build_background())
|
||||
TestDb::postgres(deterministic.clone())
|
||||
} else {
|
||||
TestDb::sqlite(deterministic.build_background())
|
||||
TestDb::sqlite(deterministic.clone())
|
||||
};
|
||||
let live_kit_server_id = NEXT_LIVE_KIT_SERVER_ID.fetch_add(1, SeqCst);
|
||||
let live_kit_server = live_kit_client::TestServer::create(
|
||||
format!("http://livekit.{}.test", live_kit_server_id),
|
||||
format!("devkey-{}", live_kit_server_id),
|
||||
format!("secret-{}", live_kit_server_id),
|
||||
deterministic.build_background(),
|
||||
deterministic.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
let app_state = Self::build_app_state(&test_db, &live_kit_server).await;
|
||||
@@ -93,7 +94,7 @@ impl TestServer {
|
||||
let server = Server::new(
|
||||
epoch,
|
||||
app_state.clone(),
|
||||
Executor::Deterministic(deterministic.build_background()),
|
||||
Executor::Deterministic(deterministic.clone()),
|
||||
);
|
||||
server.start().await.unwrap();
|
||||
// Advance clock to ensure the server's cleanup task is finished.
|
||||
@@ -124,8 +125,8 @@ impl TestServer {
|
||||
if cx.has_global::<SettingsStore>() {
|
||||
panic!("Same cx used to create two test clients")
|
||||
}
|
||||
|
||||
cx.set_global(SettingsStore::test(cx));
|
||||
let settings = SettingsStore::test(cx);
|
||||
cx.set_global(settings);
|
||||
});
|
||||
|
||||
let http = FakeHttpClient::with_404_response();
|
||||
@@ -148,7 +149,7 @@ impl TestServer {
|
||||
.user_id
|
||||
};
|
||||
let client_name = name.to_string();
|
||||
let mut client = cx.read(|cx| Client::new(http.clone(), cx));
|
||||
let mut client = cx.update(|cx| Client::new(http.clone(), cx));
|
||||
let server = self.server.clone();
|
||||
let db = self.app_state.db.clone();
|
||||
let connection_killers = self.connection_killers.clone();
|
||||
@@ -182,20 +183,20 @@ impl TestServer {
|
||||
)))
|
||||
} else {
|
||||
let (client_conn, server_conn, killed) =
|
||||
Connection::in_memory(cx.background());
|
||||
Connection::in_memory(cx.background_executor().clone());
|
||||
let (connection_id_tx, connection_id_rx) = oneshot::channel();
|
||||
let user = db
|
||||
.get_user_by_id(user_id)
|
||||
.await
|
||||
.expect("retrieving user failed")
|
||||
.unwrap();
|
||||
cx.background()
|
||||
cx.background_executor()
|
||||
.spawn(server.handle_connection(
|
||||
server_conn,
|
||||
client_name,
|
||||
user,
|
||||
Some(connection_id_tx),
|
||||
Executor::Deterministic(cx.background()),
|
||||
Executor::Deterministic(cx.background_executor().clone()),
|
||||
))
|
||||
.detach();
|
||||
let connection_id = connection_id_rx.await.unwrap();
|
||||
@@ -207,11 +208,11 @@ impl TestServer {
|
||||
})
|
||||
});
|
||||
|
||||
let fs = FakeFs::new(cx.background());
|
||||
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
|
||||
let workspace_store = cx.add_model(|cx| WorkspaceStore::new(client.clone(), cx));
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
|
||||
let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
|
||||
let mut language_registry = LanguageRegistry::test();
|
||||
language_registry.set_executor(cx.background());
|
||||
language_registry.set_executor(cx.executor());
|
||||
let app_state = Arc::new(workspace::AppState {
|
||||
client: client.clone(),
|
||||
user_store: user_store.clone(),
|
||||
@@ -219,13 +220,11 @@ impl TestServer {
|
||||
languages: Arc::new(language_registry),
|
||||
fs: fs.clone(),
|
||||
build_window_options: |_, _, _| Default::default(),
|
||||
initialize_workspace: |_, _, _, _| Task::ready(Ok(())),
|
||||
background_actions: || &[],
|
||||
node_runtime: FakeNodeRuntime::new(),
|
||||
});
|
||||
|
||||
cx.update(|cx| {
|
||||
theme::init((), cx);
|
||||
theme::init(theme::LoadThemes::JustBase, cx);
|
||||
Project::init(&client, cx);
|
||||
client::init(&client, cx);
|
||||
language::init(cx);
|
||||
@@ -264,7 +263,7 @@ impl TestServer {
|
||||
pub fn simulate_long_connection_interruption(
|
||||
&self,
|
||||
peer_id: PeerId,
|
||||
deterministic: &Arc<Deterministic>,
|
||||
deterministic: BackgroundExecutor,
|
||||
) {
|
||||
self.forbid_connections();
|
||||
self.disconnect_client(peer_id);
|
||||
@@ -295,7 +294,7 @@ impl TestServer {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx_a.foreground().run_until_parked();
|
||||
cx_a.executor().run_until_parked();
|
||||
client_b
|
||||
.app_state
|
||||
.user_store
|
||||
@@ -338,7 +337,7 @@ impl TestServer {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
admin_cx.foreground().run_until_parked();
|
||||
admin_cx.executor().run_until_parked();
|
||||
|
||||
member_cx
|
||||
.read(ChannelStore::global)
|
||||
@@ -399,7 +398,7 @@ impl TestServer {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx_b.foreground().run_until_parked();
|
||||
cx_b.executor().run_until_parked();
|
||||
let active_call_b = cx_b.read(ActiveCall::global);
|
||||
active_call_b
|
||||
.update(*cx_b, |call, cx| call.accept_incoming(cx))
|
||||
@@ -448,15 +447,15 @@ impl TestClient {
|
||||
self.app_state.fs.as_fake()
|
||||
}
|
||||
|
||||
pub fn channel_store(&self) -> &ModelHandle<ChannelStore> {
|
||||
pub fn channel_store(&self) -> &Model<ChannelStore> {
|
||||
&self.channel_store
|
||||
}
|
||||
|
||||
pub fn notification_store(&self) -> &ModelHandle<NotificationStore> {
|
||||
pub fn notification_store(&self) -> &Model<NotificationStore> {
|
||||
&self.notification_store
|
||||
}
|
||||
|
||||
pub fn user_store(&self) -> &ModelHandle<UserStore> {
|
||||
pub fn user_store(&self) -> &Model<UserStore> {
|
||||
&self.app_state.user_store
|
||||
}
|
||||
|
||||
@@ -491,30 +490,26 @@ impl TestClient {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub fn local_projects<'a>(&'a self) -> impl Deref<Target = Vec<ModelHandle<Project>>> + 'a {
|
||||
pub fn local_projects<'a>(&'a self) -> impl Deref<Target = Vec<Model<Project>>> + 'a {
|
||||
Ref::map(self.state.borrow(), |state| &state.local_projects)
|
||||
}
|
||||
|
||||
pub fn remote_projects<'a>(&'a self) -> impl Deref<Target = Vec<ModelHandle<Project>>> + 'a {
|
||||
pub fn remote_projects<'a>(&'a self) -> impl Deref<Target = Vec<Model<Project>>> + 'a {
|
||||
Ref::map(self.state.borrow(), |state| &state.remote_projects)
|
||||
}
|
||||
|
||||
pub fn local_projects_mut<'a>(
|
||||
&'a self,
|
||||
) -> impl DerefMut<Target = Vec<ModelHandle<Project>>> + 'a {
|
||||
pub fn local_projects_mut<'a>(&'a self) -> impl DerefMut<Target = Vec<Model<Project>>> + 'a {
|
||||
RefMut::map(self.state.borrow_mut(), |state| &mut state.local_projects)
|
||||
}
|
||||
|
||||
pub fn remote_projects_mut<'a>(
|
||||
&'a self,
|
||||
) -> impl DerefMut<Target = Vec<ModelHandle<Project>>> + 'a {
|
||||
pub fn remote_projects_mut<'a>(&'a self) -> impl DerefMut<Target = Vec<Model<Project>>> + 'a {
|
||||
RefMut::map(self.state.borrow_mut(), |state| &mut state.remote_projects)
|
||||
}
|
||||
|
||||
pub fn buffers_for_project<'a>(
|
||||
&'a self,
|
||||
project: &ModelHandle<Project>,
|
||||
) -> impl DerefMut<Target = HashSet<ModelHandle<language::Buffer>>> + 'a {
|
||||
project: &Model<Project>,
|
||||
) -> impl DerefMut<Target = HashSet<Model<language::Buffer>>> + 'a {
|
||||
RefMut::map(self.state.borrow_mut(), |state| {
|
||||
state.buffers.entry(project.clone()).or_default()
|
||||
})
|
||||
@@ -522,14 +517,14 @@ impl TestClient {
|
||||
|
||||
pub fn buffers<'a>(
|
||||
&'a self,
|
||||
) -> impl DerefMut<Target = HashMap<ModelHandle<Project>, HashSet<ModelHandle<language::Buffer>>>> + 'a
|
||||
) -> impl DerefMut<Target = HashMap<Model<Project>, HashSet<Model<language::Buffer>>>> + 'a
|
||||
{
|
||||
RefMut::map(self.state.borrow_mut(), |state| &mut state.buffers)
|
||||
}
|
||||
|
||||
pub fn channel_buffers<'a>(
|
||||
&'a self,
|
||||
) -> impl DerefMut<Target = HashSet<ModelHandle<ChannelBuffer>>> + 'a {
|
||||
) -> impl DerefMut<Target = HashSet<Model<ChannelBuffer>>> + 'a {
|
||||
RefMut::map(self.state.borrow_mut(), |state| &mut state.channel_buffers)
|
||||
}
|
||||
|
||||
@@ -559,7 +554,7 @@ impl TestClient {
|
||||
&self,
|
||||
root_path: impl AsRef<Path>,
|
||||
cx: &mut TestAppContext,
|
||||
) -> (ModelHandle<Project>, WorktreeId) {
|
||||
) -> (Model<Project>, WorktreeId) {
|
||||
let project = self.build_empty_local_project(cx);
|
||||
let (worktree, _) = project
|
||||
.update(cx, |p, cx| {
|
||||
@@ -573,7 +568,7 @@ impl TestClient {
|
||||
(project, worktree.read_with(cx, |tree, _| tree.id()))
|
||||
}
|
||||
|
||||
pub fn build_empty_local_project(&self, cx: &mut TestAppContext) -> ModelHandle<Project> {
|
||||
pub fn build_empty_local_project(&self, cx: &mut TestAppContext) -> Model<Project> {
|
||||
cx.update(|cx| {
|
||||
Project::local(
|
||||
self.client().clone(),
|
||||
@@ -590,7 +585,7 @@ impl TestClient {
|
||||
&self,
|
||||
host_project_id: u64,
|
||||
guest_cx: &mut TestAppContext,
|
||||
) -> ModelHandle<Project> {
|
||||
) -> Model<Project> {
|
||||
let active_call = guest_cx.read(ActiveCall::global);
|
||||
let room = active_call.read_with(guest_cx, |call, _| call.room().unwrap().clone());
|
||||
room.update(guest_cx, |room, cx| {
|
||||
@@ -605,12 +600,12 @@ impl TestClient {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn build_workspace(
|
||||
&self,
|
||||
project: &ModelHandle<Project>,
|
||||
cx: &mut TestAppContext,
|
||||
) -> WindowHandle<Workspace> {
|
||||
cx.add_window(|cx| Workspace::new(0, project.clone(), self.app_state.clone(), cx))
|
||||
pub fn build_workspace<'a>(
|
||||
&'a self,
|
||||
project: &Model<Project>,
|
||||
cx: &'a mut TestAppContext,
|
||||
) -> (View<Workspace>, &'a mut VisualTestContext) {
|
||||
cx.add_window_view(|cx| Workspace::new(0, project.clone(), self.app_state.clone(), cx))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user