1460 lines · 40.1 KB · Rust
RawDownload
use crate::{    db::{self, UserId},    rpc::RECONNECT_TIMEOUT,    tests::{room_participants, RoomParticipants, TestServer},};use call::ActiveCall;use channel::{ChannelMembership, ChannelStore};use client::{ChannelId, User};use futures::future::try_join_all;use gpui::{BackgroundExecutor, Entity, SharedString, TestAppContext};use rpc::{    proto::{self, ChannelRole},    RECEIVE_TIMEOUT,};use std::sync::Arc; #[gpui::test]async fn test_core_channels(    executor: BackgroundExecutor,    cx_a: &mut TestAppContext,    cx_b: &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 channel_a_id = client_a        .channel_store()        .update(cx_a, |channel_store, cx| {            channel_store.create_channel("channel-a", None, cx)        })        .await        .unwrap();    let channel_b_id = client_a        .channel_store()        .update(cx_a, |channel_store, cx| {            channel_store.create_channel("channel-b", Some(channel_a_id), cx)        })        .await        .unwrap();     executor.run_until_parked();    assert_channels(        client_a.channel_store(),        cx_a,        &[            ExpectedChannel {                id: channel_a_id,                name: "channel-a".into(),                depth: 0,            },            ExpectedChannel {                id: channel_b_id,                name: "channel-b".into(),                depth: 1,            },        ],    );     cx_b.read(|cx| {        client_b.channel_store().read_with(cx, |channels, _| {            assert!(channels.ordered_channels().collect::<Vec<_>>().is_empty())        })    });     // Invite client B to channel A as client A.    client_a        .channel_store()        .update(cx_a, |store, cx| {            assert!(!store.has_pending_channel_invite(channel_a_id, client_b.user_id().unwrap()));             let invite = store.invite_member(                channel_a_id,                client_b.user_id().unwrap(),                proto::ChannelRole::Member,                cx,            );             // Make sure we're synchronously storing the pending invite            assert!(store.has_pending_channel_invite(channel_a_id, client_b.user_id().unwrap()));            invite        })        .await        .unwrap();     // Client A sees that B has been invited.    executor.run_until_parked();    assert_channel_invitations(        client_b.channel_store(),        cx_b,        &[ExpectedChannel {            id: channel_a_id,            name: "channel-a".into(),            depth: 0,        }],    );     let members = client_a        .channel_store()        .update(cx_a, |store, cx| {            assert!(!store.has_pending_channel_invite(channel_a_id, client_b.user_id().unwrap()));            store.fuzzy_search_members(channel_a_id, "".to_string(), 10, cx)        })        .await        .unwrap();    assert_members_eq(        &members,        &[            (                client_a.user_id().unwrap(),                proto::ChannelRole::Admin,                proto::channel_member::Kind::Member,            ),            (                client_b.user_id().unwrap(),                proto::ChannelRole::Member,                proto::channel_member::Kind::Invitee,            ),        ],    );     // Client B accepts the invitation.    client_b        .channel_store()        .update(cx_b, |channels, cx| {            channels.respond_to_channel_invite(channel_a_id, true, cx)        })        .await        .unwrap();    executor.run_until_parked();     // Client B now sees that they are a member of channel A and its existing subchannels.    assert_channel_invitations(client_b.channel_store(), cx_b, &[]);    assert_channels(        client_b.channel_store(),        cx_b,        &[            ExpectedChannel {                id: channel_a_id,                name: "channel-a".into(),                depth: 0,            },            ExpectedChannel {                id: channel_b_id,                name: "channel-b".into(),                depth: 1,            },        ],    );     let channel_c_id = client_a        .channel_store()        .update(cx_a, |channel_store, cx| {            channel_store.create_channel("channel-c", Some(channel_b_id), cx)        })        .await        .unwrap();     executor.run_until_parked();    assert_channels(        client_b.channel_store(),        cx_b,        &[            ExpectedChannel {                id: channel_a_id,                name: "channel-a".into(),                depth: 0,            },            ExpectedChannel {                id: channel_b_id,                name: "channel-b".into(),                depth: 1,            },            ExpectedChannel {                id: channel_c_id,                name: "channel-c".into(),                depth: 2,            },        ],    );     // Update client B's membership to channel A to be an admin.    client_a        .channel_store()        .update(cx_a, |store, cx| {            store.set_member_role(                channel_a_id,                client_b.user_id().unwrap(),                proto::ChannelRole::Admin,                cx,            )        })        .await        .unwrap();    executor.run_until_parked();     // Observe that client B is now an admin of channel A, and that    // their admin privileges extend to subchannels of channel A.    assert_channel_invitations(client_b.channel_store(), cx_b, &[]);    assert_channels(        client_b.channel_store(),        cx_b,        &[            ExpectedChannel {                id: channel_a_id,                name: "channel-a".into(),                depth: 0,            },            ExpectedChannel {                id: channel_b_id,                name: "channel-b".into(),                depth: 1,            },            ExpectedChannel {                id: channel_c_id,                name: "channel-c".into(),                depth: 2,            },        ],    );     // Client A deletes the channel, deletion also deletes subchannels.    client_a        .channel_store()        .update(cx_a, |channel_store, _| {            channel_store.remove_channel(channel_b_id)        })        .await        .unwrap();     executor.run_until_parked();    assert_channels(        client_a.channel_store(),        cx_a,        &[ExpectedChannel {            id: channel_a_id,            name: "channel-a".into(),            depth: 0,        }],    );    assert_channels(        client_b.channel_store(),        cx_b,        &[ExpectedChannel {            id: channel_a_id,            name: "channel-a".into(),            depth: 0,        }],    );     // Remove client B    client_a        .channel_store()        .update(cx_a, |channel_store, cx| {            channel_store.remove_member(channel_a_id, client_b.user_id().unwrap(), cx)        })        .await        .unwrap();     executor.run_until_parked();     // Client A still has their channel    assert_channels(        client_a.channel_store(),        cx_a,        &[ExpectedChannel {            id: channel_a_id,            name: "channel-a".into(),            depth: 0,        }],    );     // Client B no longer has access to the channel    assert_channels(client_b.channel_store(), cx_b, &[]);     server.forbid_connections();    server.disconnect_client(client_a.peer_id().unwrap());    executor.advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);     server        .app_state        .db        .rename_channel(            db::ChannelId::from_proto(channel_a_id.0),            UserId::from_proto(client_a.id()),            "channel-a-renamed",        )        .await        .unwrap();     server.allow_connections();    executor.advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);    assert_channels(        client_a.channel_store(),        cx_a,        &[ExpectedChannel {            id: channel_a_id,            name: "channel-a-renamed".into(),            depth: 0,        }],    );} #[track_caller]fn assert_participants_eq(participants: &[Arc<User>], expected_partitipants: &[u64]) {    assert_eq!(        participants.iter().map(|p| p.id).collect::<Vec<_>>(),        expected_partitipants    );} #[track_caller]fn assert_members_eq(    members: &[ChannelMembership],    expected_members: &[(u64, proto::ChannelRole, proto::channel_member::Kind)],) {    assert_eq!(        members            .iter()            .map(|member| (member.user.id, member.role, member.kind))            .collect::<Vec<_>>(),        expected_members    );} #[gpui::test]async fn test_joining_channel_ancestor_member(    executor: BackgroundExecutor,    cx_a: &mut TestAppContext,    cx_b: &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 parent_id = server        .make_channel("parent", None, (&client_a, cx_a), &mut [(&client_b, cx_b)])        .await;     let sub_id = client_a        .channel_store()        .update(cx_a, |channel_store, cx| {            channel_store.create_channel("sub_channel", Some(parent_id), cx)        })        .await        .unwrap();     let active_call_b = cx_b.read(ActiveCall::global);     assert!(active_call_b        .update(cx_b, |active_call, cx| active_call.join_channel(sub_id, cx))        .await        .is_ok());} #[gpui::test]async fn test_channel_room(    executor: BackgroundExecutor,    cx_a: &mut TestAppContext,    cx_b: &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;     let zed_id = server        .make_channel(            "zed",            None,            (&client_a, cx_a),            &mut [(&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);     active_call_a        .update(cx_a, |active_call, cx| active_call.join_channel(zed_id, cx))        .await        .unwrap();     // Give everyone a chance to observe user A joining    executor.run_until_parked();    let room_a =        cx_a.read(|cx| active_call_a.read_with(cx, |call, _| call.room().unwrap().clone()));    cx_a.read(|cx| room_a.read_with(cx, |room, _| assert!(room.is_connected())));     cx_a.read(|cx| {        client_a.channel_store().read_with(cx, |channels, _| {            assert_participants_eq(                channels.channel_participants(zed_id),                &[client_a.user_id().unwrap()],            );        })    });     assert_channels(        client_b.channel_store(),        cx_b,        &[ExpectedChannel {            id: zed_id,            name: "zed".into(),            depth: 0,        }],    );    cx_b.read(|cx| {        client_b.channel_store().read_with(cx, |channels, _| {            assert_participants_eq(                channels.channel_participants(zed_id),                &[client_a.user_id().unwrap()],            );        })    });     cx_c.read(|cx| {        client_c.channel_store().read_with(cx, |channels, _| {            assert_participants_eq(                channels.channel_participants(zed_id),                &[client_a.user_id().unwrap()],            );        })    });     active_call_b        .update(cx_b, |active_call, cx| active_call.join_channel(zed_id, cx))        .await        .unwrap();     executor.run_until_parked();     cx_a.read(|cx| {        client_a.channel_store().read_with(cx, |channels, _| {            assert_participants_eq(                channels.channel_participants(zed_id),                &[client_a.user_id().unwrap(), client_b.user_id().unwrap()],            );        })    });     cx_b.read(|cx| {        client_b.channel_store().read_with(cx, |channels, _| {            assert_participants_eq(                channels.channel_participants(zed_id),                &[client_a.user_id().unwrap(), client_b.user_id().unwrap()],            );        })    });     cx_c.read(|cx| {        client_c.channel_store().read_with(cx, |channels, _| {            assert_participants_eq(                channels.channel_participants(zed_id),                &[client_a.user_id().unwrap(), client_b.user_id().unwrap()],            );        })    });     let room_a =        cx_a.read(|cx| active_call_a.read_with(cx, |call, _| call.room().unwrap().clone()));    cx_a.read(|cx| room_a.read_with(cx, |room, _| assert!(room.is_connected())));    assert_eq!(        room_participants(&room_a, cx_a),        RoomParticipants {            remote: vec!["user_b".to_string()],            pending: vec![]        }    );     let room_b =        cx_b.read(|cx| active_call_b.read_with(cx, |call, _| call.room().unwrap().clone()));    cx_b.read(|cx| room_b.read_with(cx, |room, _| assert!(room.is_connected())));    assert_eq!(        room_participants(&room_b, cx_b),        RoomParticipants {            remote: vec!["user_a".to_string()],            pending: vec![]        }    );     // Make sure that leaving and rejoining works     active_call_a        .update(cx_a, |active_call, cx| active_call.hang_up(cx))        .await        .unwrap();     executor.run_until_parked();     cx_a.read(|cx| {        client_a.channel_store().read_with(cx, |channels, _| {            assert_participants_eq(                channels.channel_participants(zed_id),                &[client_b.user_id().unwrap()],            );        })    });

Lines 1–500 of 1460.