use anyhow::Context as AnyhowContext; use solstice_proto::server; use crate::context::Context; use crate::control; use crate::message_handler::MessageHandler; use crate::room::Message as RoomMessage; #[derive(Debug, Default)] pub struct RoomMessageResponseHandler; impl MessageHandler for RoomMessageResponseHandler { type Message = server::RoomMessageResponse; fn run( self, context: &mut Context, response: &server::RoomMessageResponse, ) -> anyhow::Result<()> { let room = context .state .rooms .get_mut_strict(&response.room_name) .context("looking up room")?; let message = RoomMessage { received_at: context.system_clock.now(), user_name: response.user_name.clone(), message: response.message.clone(), }; room.messages.insert(message.clone()); context .control_response_tx .blocking_send(control::Response::RoomMessageResponse( control::RoomMessageResponse { room_name: response.room_name.clone(), message, }, )) .context("sending control response")?; Ok(()) } fn name() -> String { "RoomMessageResponseHandler".to_string() } } #[cfg(test)] mod tests { use std::time::{Duration, SystemTime}; use solstice_proto::server; use crate::clock::SimulatedSystemClock; use crate::context::{ContextBundle, ContextOptions}; use crate::control; use crate::message_handler::MessageHandler; use crate::room::{Message, Room, Visibility}; use super::RoomMessageResponseHandler; fn system_time_from_secs(seconds: u64) -> SystemTime { SystemTime::UNIX_EPOCH + Duration::from_secs(seconds) } #[test] fn run_forwards_response() { let mut options = ContextOptions::default(); options .initial_state .rooms .insert("apple".to_string(), Room::new(Visibility::Public, 1)); options.simulated_clock = Some(SimulatedSystemClock::new(system_time_from_secs(42))); let mut bundle = ContextBundle::new(options); RoomMessageResponseHandler::default() .run( &mut bundle.context, &server::RoomMessageResponse { room_name: "apple".to_string(), user_name: "shruti".to_string(), message: "yo!".to_string(), }, ) .expect("running handler"); let response = bundle .control_response_rx .blocking_recv() .expect("receiving control response"); assert_eq!( response, control::Response::RoomMessageResponse(control::RoomMessageResponse { room_name: "apple".to_string(), message: Message { user_name: "shruti".to_string(), message: "yo!".to_string(), received_at: SystemTime::UNIX_EPOCH + Duration::from_secs(42), }, }) ); } #[test] fn run_stores_message() { let mut room = Room::new(Visibility::Public, 42); room.messages.insert(Message { received_at: system_time_from_secs(42), user_name: "karandeep".to_string(), message: "namaste!".to_string(), }); let mut options = ContextOptions::default(); options .initial_state .rooms .insert("apple".to_string(), room.clone()); options.simulated_clock = Some(SimulatedSystemClock::new(system_time_from_secs(43))); let mut bundle = ContextBundle::new(options); RoomMessageResponseHandler::default() .run( &mut bundle.context, &server::RoomMessageResponse { room_name: "apple".to_string(), user_name: "shruti".to_string(), message: "yo!".to_string(), }, ) .expect("running handler"); let room = bundle .context .state .rooms .get_strict("apple") .expect("looking up room"); assert_eq!( room.messages.to_vec(), vec![ Message { received_at: system_time_from_secs(42), user_name: "karandeep".to_string(), message: "namaste!".to_string(), }, Message { received_at: system_time_from_secs(43), user_name: "shruti".to_string(), message: "yo!".to_string(), }, ] ); } }