use crate::queue::{Message, MsgType, Queue}; use std::{ sync::mpsc::{channel, Receiver}, thread::spawn, }; use uuid::Uuid; const RESPONDS_TO: [MsgType; 1] = [MsgType::SessionValidate]; pub struct Session { queue: Queue, rx: Receiver, } impl Session { fn new(queue: Queue, rx: Receiver) -> Self { Self { queue: queue, rx: rx, } } pub fn start(queue: Queue) { let (tx, rx) = channel(); let session = Session::new(queue, rx); session.queue.add(tx, RESPONDS_TO.to_vec()); spawn(move || { session.listen(); }); } fn listen(&self) { loop { let msg = self.rx.recv().unwrap(); self.validate(msg); } } fn validate(&self, msg: Message) { let mut reply = msg.reply(MsgType::Session); match msg.get_data("sess_id") { Some(id) => reply.add_data("sess_id", id.clone()), None => reply.add_data("sess_id", Uuid::new_v4()), } self.queue.send(reply); } } #[cfg(test)] mod sessions { use super::*; use crate::queue::{Message, MsgType}; use std::{sync::mpsc::channel, time::Duration}; static TIMEOUT: Duration = Duration::from_millis(500); fn setup_session(listen_for: Vec) -> (Queue, Receiver) { let queue = Queue::new(); let (tx, rx) = channel(); queue.add(tx, listen_for); Session::start(queue.clone()); (queue, rx) } #[test] fn get_new_session() { let listen_for = [MsgType::Session]; let (queue, rx) = setup_session(listen_for.to_vec()); let msg = Message::new(MsgType::SessionValidate); queue.send(msg.clone()); let result = rx.recv_timeout(TIMEOUT).unwrap(); match result.get_class() { MsgType::Session => {} _ => unreachable!( "received {:?}, should have been a session", result.get_class() ), } assert_eq!(result.get_id(), msg.get_id()); } #[test] fn session_id_is_unique() { let listen_for = [MsgType::Session]; let (queue, rx) = setup_session(listen_for.to_vec()); let msg = Message::new(MsgType::SessionValidate); let mut ids: Vec = Vec::new(); for _ in 0..10 { queue.send(msg.clone()); let result = rx.recv().unwrap(); let id = result.get_data("sess_id").unwrap().to_uuid().unwrap(); assert!(!ids.contains(&id), "{} is a duplicate id", id); ids.push(id); } } #[test] fn existing_id_are_returned() { let listen_for = [MsgType::Session]; let (queue, rx) = setup_session(listen_for.to_vec()); let mut msg = Message::new(MsgType::SessionValidate); queue.send(msg.clone()); let holder = rx.recv().unwrap(); let id = holder.get_data("sess_id").unwrap().to_uuid().unwrap(); msg.add_data("sess_id", id.clone()); queue.send(msg); let result = rx.recv().unwrap(); let output = result.get_data("sess_id").unwrap().to_uuid().unwrap(); assert_eq!(output, id); } }