use crate::queue::{Message, MsgType, Queue}; use chrono::prelude::*; use std::{ thread::{sleep, spawn}, time::Duration, }; const SLEEP_FOR: Duration = Duration::from_millis(1000); pub struct Clock { queue: Queue, } impl Clock { fn new(queue: Queue) -> Self { Self { queue: queue } } pub fn start(queue: Queue) { let clock = Clock::new(queue); spawn(move || { clock.listen(); }); } fn listen(&self) { loop { let mut msg = Message::new(MsgType::Time); msg.add_data("time", Utc::now()); match self.queue.send(msg) { Ok(_) => {} Err(_) => {} }; sleep(SLEEP_FOR); } } } #[cfg(test)] mod clocks { use super::*; use std::{ sync::mpsc::{channel, Receiver}, time::{Duration, Instant}, }; static TIMEOUT: Duration = Duration::from_millis(500); fn start_clock(listen_for: Vec) -> Receiver { let queue = Queue::new(); let (tx, rx) = channel(); queue.add(tx, listen_for); Clock::start(queue); rx } #[test] fn sends_timestamp() { let rx = start_clock([MsgType::Time].to_vec()); let msg = rx.recv_timeout(TIMEOUT).unwrap(); match msg.get_class() { MsgType::Time => { msg.get_data("time").unwrap().to_datetime().unwrap(); } _ => unreachable!("should have been a time message"), } } #[test] fn continues_to_send_time() { let start = Instant::now(); let rx = start_clock([MsgType::Time].to_vec()); let msg1 = rx.recv_timeout(TIMEOUT).unwrap(); let msg2 = rx.recv().unwrap(); assert!( start.elapsed() >= SLEEP_FOR, "did not pause long enough betwee sends" ); assert!( msg2.get_data("time").unwrap().to_datetime().unwrap() > msg1.get_data("time").unwrap().to_datetime().unwrap(), "shoould present the latest time" ); } #[test] fn does_not_panic_without_listeners() { let rx = start_clock([MsgType::SessionValidate].to_vec()); assert!(rx.recv_timeout(TIMEOUT).is_err(), "should timeout"); } }