Remove 2 suffix for collab, rope, settings, menu
Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
parent
177e3028a9
commit
0cf65223ce
234 changed files with 3765 additions and 42229 deletions
|
@ -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
1889
crates/collab/src/tests/editor_tests.rs
Normal file
1889
crates/collab/src/tests/editor_tests.rs
Normal file
File diff suppressed because it is too large
Load diff
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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue