use crate::{ rpc::{CLEANUP_TIMEOUT, RECONNECT_TIMEOUT}, tests::{ channel_id, following_tests::join_channel, room_participants, rust_lang, RoomParticipants, TestClient, TestServer, },};use anyhow::{anyhow, Result};use assistant::ContextStore;use assistant_slash_command::SlashCommandWorkingSet;use assistant_tool::ToolWorkingSet;use call::{room, ActiveCall, ParticipantLocation, Room};use client::{User, RECEIVE_TIMEOUT};use collections::{HashMap, HashSet};use fs::{FakeFs, Fs as _, RemoveOptions};use futures::{channel::mpsc, StreamExt as _};use prompt_library::PromptBuilder; use git::status::{FileStatus, StatusCode, TrackedStatus, UnmergedStatus, UnmergedStatusCode};use gpui::{ px, size, AppContext, BackgroundExecutor, Model, Modifiers, MouseButton, MouseDownEvent, TestAppContext, UpdateGlobal,};use language::{ language_settings::{ AllLanguageSettings, Formatter, FormatterList, PrettierSettings, SelectedFormatter, }, tree_sitter_rust, tree_sitter_typescript, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher, LineEnding, OffsetRangeExt, Point, Rope,};use lsp::LanguageServerId;use parking_lot::Mutex;use project::{ lsp_store::{FormatTrigger, LspFormatTarget}, search::{SearchQuery, SearchResult}, DiagnosticSummary, HoverBlockKind, Project, ProjectPath,};use rand::prelude::*;use serde_json::json;use settings::SettingsStore;use std::{ cell::{Cell, RefCell}, env, future, mem, path::{Path, PathBuf}, rc::Rc, sync::{ atomic::{AtomicBool, Ordering::SeqCst}, Arc, }, time::Duration,};use unindent::Unindent as _;use workspace::Pane; #[ctor::ctor]fn init_logger() { if std::env::var("RUST_LOG").is_ok() { env_logger::init(); }} #[gpui::test(iterations = 10)]async fn test_basic_calls( executor: BackgroundExecutor, cx_a: &mut TestAppContext, cx_b: &mut TestAppContext, cx_b2: &mut TestAppContext, cx_c: &mut TestAppContext,) { 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; server .make_contacts(&mut [(&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c)]) .await; let active_call_a = cx_a.read(ActiveCall::global); let active_call_b = cx_b.read(ActiveCall::global); let active_call_c = cx_c.read(ActiveCall::global); // Call user B from client A. active_call_a .update(cx_a, |call, cx| { call.invite(client_b.user_id().unwrap(), None, cx) }) .await .unwrap(); let room_a = active_call_a.read_with(cx_a, |call, _| call.room().unwrap().clone()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: vec!["user_b".to_string()] } ); // User B receives the call. let mut incoming_call_b = active_call_b.read_with(cx_b, |call, _| call.incoming()); let call_b = incoming_call_b.next().await.unwrap().unwrap(); assert_eq!(call_b.calling_user.github_login, "user_a"); // User B connects via another client and also receives a ring on the newly-connected client. let _client_b2 = server.create_client(cx_b2, "user_b").await; let active_call_b2 = cx_b2.read(ActiveCall::global); let mut incoming_call_b2 = active_call_b2.read_with(cx_b2, |call, _| call.incoming()); executor.run_until_parked(); let call_b2 = incoming_call_b2.next().await.unwrap().unwrap(); assert_eq!(call_b2.calling_user.github_login, "user_a"); // User B joins the room using the first client. active_call_b .update(cx_b, |call, cx| call.accept_incoming(cx)) .await .unwrap(); let room_b = active_call_b.read_with(cx_b, |call, _| call.room().unwrap().clone()); assert!(incoming_call_b.next().await.unwrap().is_none()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string()], pending: Default::default() } ); // Call user C from client B. let mut incoming_call_c = active_call_c.read_with(cx_c, |call, _| call.incoming()); active_call_b .update(cx_b, |call, cx| { call.invite(client_c.user_id().unwrap(), None, cx) }) .await .unwrap(); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string()], pending: vec!["user_c".to_string()] } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string()], pending: vec!["user_c".to_string()] } ); // User C receives the call, but declines it. let call_c = incoming_call_c.next().await.unwrap().unwrap(); assert_eq!(call_c.calling_user.github_login, "user_b"); active_call_c.update(cx_c, |call, cx| call.decline_incoming(cx).unwrap()); assert!(incoming_call_c.next().await.unwrap().is_none()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string()], pending: Default::default() } ); // Call user C again from user A. active_call_a .update(cx_a, |call, cx| { call.invite(client_c.user_id().unwrap(), None, cx) }) .await .unwrap(); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string()], pending: vec!["user_c".to_string()] } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string()], pending: vec!["user_c".to_string()] } ); // User C accepts the call. let call_c = incoming_call_c.next().await.unwrap().unwrap(); assert_eq!(call_c.calling_user.github_login, "user_a"); active_call_c .update(cx_c, |call, cx| call.accept_incoming(cx)) .await .unwrap(); assert!(incoming_call_c.next().await.unwrap().is_none()); let room_c = active_call_c.read_with(cx_c, |call, _| call.room().unwrap().clone()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string(), "user_c".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string(), "user_c".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_c, cx_c), RoomParticipants { remote: vec!["user_a".to_string(), "user_b".to_string()], pending: Default::default() } ); // TODO: Re-enable this test once we can replace our swift Livekit SDK with the rust SDK #[cfg(not(target_os = "macos"))] { // User A shares their screen let display = gpui::TestScreenCaptureSource::new(); let events_b = active_call_events(cx_b); let events_c = active_call_events(cx_c); cx_a.set_screen_capture_sources(vec![display]); active_call_a .update(cx_a, |call, cx| { call.room() .unwrap() .update(cx, |room, cx| room.share_screen(cx)) }) .await .unwrap(); executor.run_until_parked(); // User B observes the remote screen sharing track. assert_eq!(events_b.borrow().len(), 1); let event_b = events_b.borrow().first().unwrap().clone(); if let call::room::Event::RemoteVideoTracksChanged { participant_id } = event_b { assert_eq!(participant_id, client_a.peer_id().unwrap()); room_b.read_with(cx_b, |room, _| { assert_eq!( room.remote_participants()[&client_a.user_id().unwrap()] .video_tracks .len(), 1 ); }); } else { panic!("unexpected event") } // User C observes the remote screen sharing track. assert_eq!(events_c.borrow().len(), 1); let event_c = events_c.borrow().first().unwrap().clone(); if let call::room::Event::RemoteVideoTracksChanged { participant_id } = event_c { assert_eq!(participant_id, client_a.peer_id().unwrap()); room_c.read_with(cx_c, |room, _| { assert_eq!( room.remote_participants()[&client_a.user_id().unwrap()] .video_tracks .len(), 1 ); }); } else { panic!("unexpected event") } } // User A leaves the room. active_call_a .update(cx_a, |call, cx| { let hang_up = call.hang_up(cx); assert!(call.room().is_none()); hang_up }) .await .unwrap(); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_c".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_c, cx_c), RoomParticipants { remote: vec!["user_b".to_string()], pending: Default::default() } ); // User B gets disconnected from the LiveKit server, which causes them // to automatically leave the room. User C leaves the room as well because // nobody else is in there. server .test_livekit_server .disconnect_client(client_b.user_id().unwrap().to_string()) .await; executor.run_until_parked(); active_call_b.read_with(cx_b, |call, _| assert!(call.room().is_none())); active_call_c.read_with(cx_c, |call, _| assert!(call.room().is_none())); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: Default::default(), pending: Default::default() } ); assert_eq!( room_participants(&room_c, cx_c), RoomParticipants { remote: Default::default(), pending: Default::default() } );} #[gpui::test(iterations = 10)]async fn test_calling_multiple_users_simultaneously( executor: BackgroundExecutor, cx_a: &mut TestAppContext, cx_b: &mut TestAppContext, cx_c: &mut TestAppContext, cx_d: &mut TestAppContext,) { 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; let client_d = server.create_client(cx_d, "user_d").await; server .make_contacts(&mut [ (&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c), (&client_d, cx_d), ]) .await; let active_call_a = cx_a.read(ActiveCall::global); let active_call_b = cx_b.read(ActiveCall::global); let active_call_c = cx_c.read(ActiveCall::global); let active_call_d = cx_d.read(ActiveCall::global); // Simultaneously call user B and user C from client A. let b_invite = active_call_a.update(cx_a, |call, cx| { call.invite(client_b.user_id().unwrap(), None, cx) }); let c_invite = active_call_a.update(cx_a, |call, cx| { call.invite(client_c.user_id().unwrap(), None, cx) }); b_invite.await.unwrap(); c_invite.await.unwrap(); let room_a = active_call_a.read_with(cx_a, |call, _| call.room().unwrap().clone()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: vec!["user_b".to_string(), "user_c".to_string()] } ); // Call client D from client A. active_call_a .update(cx_a, |call, cx| { call.invite(client_d.user_id().unwrap(), None, cx) }) .await .unwrap(); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: vec![ "user_b".to_string(), "user_c".to_string(), "user_d".to_string() ] } ); // Accept the call on all clients simultaneously. let accept_b = active_call_b.update(cx_b, |call, cx| call.accept_incoming(cx)); let accept_c = active_call_c.update(cx_c, |call, cx| call.accept_incoming(cx)); let accept_d = active_call_d.update(cx_d, |call, cx| call.accept_incoming(cx)); accept_b.await.unwrap(); accept_c.await.unwrap(); accept_d.await.unwrap(); executor.run_until_parked(); let room_b = active_call_b.read_with(cx_b, |call, _| call.room().unwrap().clone()); let room_c = active_call_c.read_with(cx_c, |call, _| call.room().unwrap().clone()); let room_d = active_call_d.read_with(cx_d, |call, _| call.room().unwrap().clone()); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec![ "user_b".to_string(), "user_c".to_string(), "user_d".to_string(), ], pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec![ "user_a".to_string(), "user_c".to_string(), "user_d".to_string(), ], pending: Default::default() } ); assert_eq!( room_participants(&room_c, cx_c), RoomParticipants { remote: vec![ "user_a".to_string(), "user_b".to_string(), "user_d".to_string(), ], pending: Default::default() } ); assert_eq!( room_participants(&room_d, cx_d), RoomParticipants { remote: vec![ "user_a".to_string(), "user_b".to_string(), "user_c".to_string(), ], pending: Default::default() } );} #[gpui::test(iterations = 10)]async fn test_joining_channels_and_calling_multiple_users_simultaneously( executor: BackgroundExecutor,Lines 1–500 of 6737. Load more
use crate::{ rpc::{CLEANUP_TIMEOUT, RECONNECT_TIMEOUT}, tests::{ channel_id, following_tests::join_channel, room_participants, rust_lang, RoomParticipants, TestClient, TestServer, }, }; use anyhow::{anyhow, Result}; use assistant::ContextStore; use assistant_slash_command::SlashCommandWorkingSet; use assistant_tool::ToolWorkingSet; use call::{room, ActiveCall, ParticipantLocation, Room}; use client::{User, RECEIVE_TIMEOUT}; use collections::{HashMap, HashSet}; use fs::{FakeFs, Fs as _, RemoveOptions}; use futures::{channel::mpsc, StreamExt as _}; use prompt_library::PromptBuilder; use git::status::{FileStatus, StatusCode, TrackedStatus, UnmergedStatus, UnmergedStatusCode}; use gpui::{ px, size, AppContext, BackgroundExecutor, Model, Modifiers, MouseButton, MouseDownEvent, TestAppContext, UpdateGlobal, }; use language::{ language_settings::{ AllLanguageSettings, Formatter, FormatterList, PrettierSettings, SelectedFormatter, }, tree_sitter_rust, tree_sitter_typescript, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher, LineEnding, OffsetRangeExt, Point, Rope, }; use lsp::LanguageServerId; use parking_lot::Mutex; use project::{ lsp_store::{FormatTrigger, LspFormatTarget}, search::{SearchQuery, SearchResult}, DiagnosticSummary, HoverBlockKind, Project, ProjectPath, }; use rand::prelude::*; use serde_json::json; use settings::SettingsStore; use std::{ cell::{Cell, RefCell}, env, future, mem, path::{Path, PathBuf}, rc::Rc, sync::{ atomic::{AtomicBool, Ordering::SeqCst}, Arc, }, time::Duration, }; use unindent::Unindent as _; use workspace::Pane; #[ctor::ctor] fn init_logger() { if std::env::var("RUST_LOG").is_ok() { env_logger::init(); } } #[gpui::test(iterations = 10)] async fn test_basic_calls( executor: BackgroundExecutor, cx_a: &mut TestAppContext, cx_b: &mut TestAppContext, cx_b2: &mut TestAppContext, cx_c: &mut TestAppContext, ) { 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; server .make_contacts(&mut [(&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c)]) .await; let active_call_a = cx_a.read(ActiveCall::global); let active_call_b = cx_b.read(ActiveCall::global); let active_call_c = cx_c.read(ActiveCall::global); // Call user B from client A. active_call_a .update(cx_a, |call, cx| { call.invite(client_b.user_id().unwrap(), None, cx) }) .await .unwrap(); let room_a = active_call_a.read_with(cx_a, |call, _| call.room().unwrap().clone()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: vec!["user_b".to_string()] } ); // User B receives the call. let mut incoming_call_b = active_call_b.read_with(cx_b, |call, _| call.incoming()); let call_b = incoming_call_b.next().await.unwrap().unwrap(); assert_eq!(call_b.calling_user.github_login, "user_a"); // User B connects via another client and also receives a ring on the newly-connected client. let _client_b2 = server.create_client(cx_b2, "user_b").await; let active_call_b2 = cx_b2.read(ActiveCall::global); let mut incoming_call_b2 = active_call_b2.read_with(cx_b2, |call, _| call.incoming()); executor.run_until_parked(); let call_b2 = incoming_call_b2.next().await.unwrap().unwrap(); assert_eq!(call_b2.calling_user.github_login, "user_a"); // User B joins the room using the first client. active_call_b .update(cx_b, |call, cx| call.accept_incoming(cx)) .await .unwrap(); let room_b = active_call_b.read_with(cx_b, |call, _| call.room().unwrap().clone()); assert!(incoming_call_b.next().await.unwrap().is_none()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string()], pending: Default::default() } ); // Call user C from client B. let mut incoming_call_c = active_call_c.read_with(cx_c, |call, _| call.incoming()); active_call_b .update(cx_b, |call, cx| { call.invite(client_c.user_id().unwrap(), None, cx) }) .await .unwrap(); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string()], pending: vec!["user_c".to_string()] } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string()], pending: vec!["user_c".to_string()] } ); // User C receives the call, but declines it. let call_c = incoming_call_c.next().await.unwrap().unwrap(); assert_eq!(call_c.calling_user.github_login, "user_b"); active_call_c.update(cx_c, |call, cx| call.decline_incoming(cx).unwrap()); assert!(incoming_call_c.next().await.unwrap().is_none()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string()], pending: Default::default() } ); // Call user C again from user A. active_call_a .update(cx_a, |call, cx| { call.invite(client_c.user_id().unwrap(), None, cx) }) .await .unwrap(); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string()], pending: vec!["user_c".to_string()] } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string()], pending: vec!["user_c".to_string()] } ); // User C accepts the call. let call_c = incoming_call_c.next().await.unwrap().unwrap(); assert_eq!(call_c.calling_user.github_login, "user_a"); active_call_c .update(cx_c, |call, cx| call.accept_incoming(cx)) .await .unwrap(); assert!(incoming_call_c.next().await.unwrap().is_none()); let room_c = active_call_c.read_with(cx_c, |call, _| call.room().unwrap().clone()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec!["user_b".to_string(), "user_c".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_a".to_string(), "user_c".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_c, cx_c), RoomParticipants { remote: vec!["user_a".to_string(), "user_b".to_string()], pending: Default::default() } ); // TODO: Re-enable this test once we can replace our swift Livekit SDK with the rust SDK #[cfg(not(target_os = "macos"))] { // User A shares their screen let display = gpui::TestScreenCaptureSource::new(); let events_b = active_call_events(cx_b); let events_c = active_call_events(cx_c); cx_a.set_screen_capture_sources(vec![display]); active_call_a .update(cx_a, |call, cx| { call.room() .unwrap() .update(cx, |room, cx| room.share_screen(cx)) }) .await .unwrap(); executor.run_until_parked(); // User B observes the remote screen sharing track. assert_eq!(events_b.borrow().len(), 1); let event_b = events_b.borrow().first().unwrap().clone(); if let call::room::Event::RemoteVideoTracksChanged { participant_id } = event_b { assert_eq!(participant_id, client_a.peer_id().unwrap()); room_b.read_with(cx_b, |room, _| { assert_eq!( room.remote_participants()[&client_a.user_id().unwrap()] .video_tracks .len(), 1 ); }); } else { panic!("unexpected event") } // User C observes the remote screen sharing track. assert_eq!(events_c.borrow().len(), 1); let event_c = events_c.borrow().first().unwrap().clone(); if let call::room::Event::RemoteVideoTracksChanged { participant_id } = event_c { assert_eq!(participant_id, client_a.peer_id().unwrap()); room_c.read_with(cx_c, |room, _| { assert_eq!( room.remote_participants()[&client_a.user_id().unwrap()] .video_tracks .len(), 1 ); }); } else { panic!("unexpected event") } } // User A leaves the room. active_call_a .update(cx_a, |call, cx| { let hang_up = call.hang_up(cx); assert!(call.room().is_none()); hang_up }) .await .unwrap(); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec!["user_c".to_string()], pending: Default::default() } ); assert_eq!( room_participants(&room_c, cx_c), RoomParticipants { remote: vec!["user_b".to_string()], pending: Default::default() } ); // User B gets disconnected from the LiveKit server, which causes them // to automatically leave the room. User C leaves the room as well because // nobody else is in there. server .test_livekit_server .disconnect_client(client_b.user_id().unwrap().to_string()) .await; executor.run_until_parked(); active_call_b.read_with(cx_b, |call, _| assert!(call.room().is_none())); active_call_c.read_with(cx_c, |call, _| assert!(call.room().is_none())); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: Default::default(), pending: Default::default() } ); assert_eq!( room_participants(&room_c, cx_c), RoomParticipants { remote: Default::default(), pending: Default::default() } ); } #[gpui::test(iterations = 10)] async fn test_calling_multiple_users_simultaneously( executor: BackgroundExecutor, cx_a: &mut TestAppContext, cx_b: &mut TestAppContext, cx_c: &mut TestAppContext, cx_d: &mut TestAppContext, ) { 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; let client_d = server.create_client(cx_d, "user_d").await; server .make_contacts(&mut [ (&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c), (&client_d, cx_d), ]) .await; let active_call_a = cx_a.read(ActiveCall::global); let active_call_b = cx_b.read(ActiveCall::global); let active_call_c = cx_c.read(ActiveCall::global); let active_call_d = cx_d.read(ActiveCall::global); // Simultaneously call user B and user C from client A. let b_invite = active_call_a.update(cx_a, |call, cx| { call.invite(client_b.user_id().unwrap(), None, cx) }); let c_invite = active_call_a.update(cx_a, |call, cx| { call.invite(client_c.user_id().unwrap(), None, cx) }); b_invite.await.unwrap(); c_invite.await.unwrap(); let room_a = active_call_a.read_with(cx_a, |call, _| call.room().unwrap().clone()); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: vec!["user_b".to_string(), "user_c".to_string()] } ); // Call client D from client A. active_call_a .update(cx_a, |call, cx| { call.invite(client_d.user_id().unwrap(), None, cx) }) .await .unwrap(); executor.run_until_parked(); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: Default::default(), pending: vec![ "user_b".to_string(), "user_c".to_string(), "user_d".to_string() ] } ); // Accept the call on all clients simultaneously. let accept_b = active_call_b.update(cx_b, |call, cx| call.accept_incoming(cx)); let accept_c = active_call_c.update(cx_c, |call, cx| call.accept_incoming(cx)); let accept_d = active_call_d.update(cx_d, |call, cx| call.accept_incoming(cx)); accept_b.await.unwrap(); accept_c.await.unwrap(); accept_d.await.unwrap(); executor.run_until_parked(); let room_b = active_call_b.read_with(cx_b, |call, _| call.room().unwrap().clone()); let room_c = active_call_c.read_with(cx_c, |call, _| call.room().unwrap().clone()); let room_d = active_call_d.read_with(cx_d, |call, _| call.room().unwrap().clone()); assert_eq!( room_participants(&room_a, cx_a), RoomParticipants { remote: vec![ "user_b".to_string(), "user_c".to_string(), "user_d".to_string(), ], pending: Default::default() } ); assert_eq!( room_participants(&room_b, cx_b), RoomParticipants { remote: vec![ "user_a".to_string(), "user_c".to_string(), "user_d".to_string(), ], pending: Default::default() } ); assert_eq!( room_participants(&room_c, cx_c), RoomParticipants { remote: vec![ "user_a".to_string(), "user_b".to_string(), "user_d".to_string(), ], pending: Default::default() } ); assert_eq!( room_participants(&room_d, cx_d), RoomParticipants { remote: vec![ "user_a".to_string(), "user_b".to_string(), "user_c".to_string(), ], pending: Default::default() } ); } #[gpui::test(iterations = 10)] async fn test_joining_channels_and_calling_multiple_users_simultaneously( executor: BackgroundExecutor,