From dcf3bcda83742c3825e96cc961e14f0e64e6cd94 Mon Sep 17 00:00:00 2001 From: Titouan Rigoudy Date: Wed, 18 Aug 2021 20:00:02 +0200 Subject: [PATCH] Handle RoomJoinRequest. --- client/src/handlers/mod.rs | 2 + .../src/handlers/room_join_request_handler.rs | 116 ++++++++++++++++++ client/src/room.rs | 2 +- 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 client/src/handlers/room_join_request_handler.rs diff --git a/client/src/handlers/mod.rs b/client/src/handlers/mod.rs index 68e95e7..f22b17a 100644 --- a/client/src/handlers/mod.rs +++ b/client/src/handlers/mod.rs @@ -1,8 +1,10 @@ +mod room_join_request_handler; mod room_list_request_handler; mod room_message_request_handler; mod set_privileged_users_handler; mod set_room_list_handler; +pub use room_join_request_handler::RoomJoinRequestHandler; pub use room_list_request_handler::RoomListRequestHandler; pub use room_message_request_handler::RoomMessageRequestHandler; pub use set_privileged_users_handler::SetPrivilegedUsersHandler; diff --git a/client/src/handlers/room_join_request_handler.rs b/client/src/handlers/room_join_request_handler.rs new file mode 100644 index 0000000..c5acccf --- /dev/null +++ b/client/src/handlers/room_join_request_handler.rs @@ -0,0 +1,116 @@ +use anyhow::Context as AnyhowContext; +use solstice_proto::server::RoomJoinRequest; +use solstice_proto::ServerRequest; + +use crate::context::Context; +use crate::message_handler::MessageHandler; + +#[derive(Debug, Default)] +pub struct RoomJoinRequestHandler; + +impl MessageHandler for RoomJoinRequestHandler { + type Message = String; + + fn run( + self, + context: &Context, + room_name: &Self::Message, + ) -> anyhow::Result<()> { + { + // TODO: Send response immediately if we already joined. + let mut guard = context.state.lock(); + guard + .rooms + .start_joining(room_name) + .context("joining room")?; + } + context + .server_request_tx + .blocking_send(ServerRequest::RoomJoinRequest(RoomJoinRequest { + room_name: room_name.clone(), + })) + .context("sending server request")?; + Ok(()) + } + + fn name() -> String { + "RoomJoinRequestHandler".to_string() + } +} + +#[cfg(test)] +mod tests { + use anyhow::Context; + use solstice_proto::server::{RoomJoinRequest, RoomListResponse}; + use solstice_proto::ServerRequest; + + use crate::context::ContextBundle; + use crate::message_handler::MessageHandler; + use crate::room::Membership; + + use super::RoomJoinRequestHandler; + + #[test] + fn run_failure() -> anyhow::Result<()> { + let mut bundle = ContextBundle::default(); + + RoomJoinRequestHandler::default() + .run(&bundle.context, &"bleep".to_string()) + .unwrap_err(); + + // Room state has not changed. + assert_eq!(bundle.context.state.lock().rooms.get_room_list(), vec![]); + + // Close the channel, so we can observe it was empty without hanging. + drop(bundle.context.server_request_tx); + assert_eq!(bundle.server_request_rx.blocking_recv(), None); + + Ok(()) + } + + #[test] + fn run_success() -> anyhow::Result<()> { + let mut bundle = ContextBundle::default(); + + bundle + .context + .state + .lock() + .rooms + .set_room_list(RoomListResponse { + rooms: vec![("bleep".to_string(), 3)], + owned_private_rooms: vec![], + other_private_rooms: vec![], + operated_private_room_names: vec![], + }); + + RoomJoinRequestHandler::default() + .run(&bundle.context, &"bleep".to_string()) + .context("running handler")?; + + let request = bundle.server_request_rx.blocking_recv().unwrap(); + + // Room state has been altered to reflect the request. + assert_eq!( + bundle + .context + .state + .lock() + .rooms + .get_strict("bleep") + .context("getting room")? + .membership, + Membership::Joining + ); + + // The request is forwarded onwards. + assert_eq!( + request, + ServerRequest::RoomJoinRequest(RoomJoinRequest { + room_name: "bleep".to_string(), + }) + ); + + Ok(()) + } +} diff --git a/client/src/room.rs b/client/src/room.rs index f7cfbe5..8746f1b 100644 --- a/client/src/room.rs +++ b/client/src/room.rs @@ -134,7 +134,7 @@ impl RoomMap { /// Looks up the given room name in the map, returning an immutable /// reference to the associated data if found, or an error if not found. #[cfg(test)] - fn get_strict(&self, room_name: &str) -> Result<&Room, Error> { + pub fn get_strict(&self, room_name: &str) -> Result<&Room, Error> { match self.map.get(room_name) { Some(room) => Ok(room), None => Err(Error::RoomNotFound(room_name.to_string())),