1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
pub mod service; pub mod status; pub mod manager; pub mod utils; pub use service::Service; pub use status::*; pub use manager::ServiceManager; #[allow(unused_must_use)] #[cfg(test)] mod tests { use super::*; use std::{time::{Duration, Instant}, thread}; use crossbeam_channel::{Sender, bounded}; struct ExampleService { id: String, pub delay: Duration, sender: Sender<String>, flag: ServiceStatusFlag } impl ExampleService { fn new(id: String, delay: Duration, sender: Sender<String>) -> ExampleService { ExampleService { id, delay, sender, flag: ServiceStatusFlag::default() } } } impl Service for ExampleService { fn start(&mut self) { self.flag.starting(); let id = self.id.clone(); let delay = self.delay.clone(); let sender = self.sender.clone(); let flag = self.flag.clone(); thread::spawn(move || { thread::sleep(delay); sender.send(format!("Service {} STARTED", id).to_string()); flag.started(); }); } fn await_started(&mut self) { while !self.flag.is_started() {} } fn stop(&mut self) { self.flag.stopping(); let id = self.id.clone(); let delay = self.delay.clone(); let sender = self.sender.clone(); let flag = self.flag.clone(); thread::spawn(move || { thread::sleep(delay); sender.send(format!("Service {} STOPPED", id).to_string()); flag.stopped(); }); } fn await_stopped(&mut self) { while !self.flag.is_stopped() {} } } #[test] fn should_start_then_stop() { let (sender, receiver) = bounded(2); let mut sm = ServiceManager::new(); let sa_delay = 1000; let sb_delay = 2000; sm.register(Box::new(ExampleService::new("SA".to_string(), Duration::from_millis(sa_delay), sender.clone()))); sm.register(Box::new(ExampleService::new("SB".to_string(), Duration::from_millis(sb_delay), sender.clone()))); let now = Instant::now(); sm.start(); sm.await_started(); let start_time = now.elapsed().as_millis(); assert!(start_time >= sb_delay as u128); assert!(start_time < (sb_delay + sa_delay) as u128); assert_eq!("Service SA STARTED", receiver.recv().unwrap()); assert_eq!("Service SB STARTED", receiver.recv().unwrap()); let now = Instant::now(); sm.stop(); sm.await_stopped(); let stop_time = now.elapsed().as_millis(); assert!(stop_time >= sb_delay as u128); assert!(start_time < (sb_delay + sa_delay) as u128); assert_eq!("Service SA STOPPED", receiver.recv().unwrap()); assert_eq!("Service SB STOPPED", receiver.recv().unwrap()); } #[test] fn should_start_and_await_then_stop_and_await() { let (sender, receiver) = bounded(2); let mut sm = ServiceManager::new(); let sa_delay = 1000; let sb_delay = 2000; sm.register(Box::new(ExampleService::new("SA".to_string(), Duration::from_millis(sa_delay), sender.clone()))); sm.register(Box::new(ExampleService::new("SB".to_string(), Duration::from_millis(sb_delay), sender.clone()))); let now = Instant::now(); sm.start_and_await(); assert!(now.elapsed().as_millis() >= (sa_delay + sb_delay) as u128); assert_eq!("Service SA STARTED", receiver.recv().unwrap()); assert_eq!("Service SB STARTED", receiver.recv().unwrap()); let now = Instant::now(); sm.stop_and_await(); assert!(now.elapsed().as_millis() >= (sa_delay + sb_delay) as u128); assert_eq!("Service SB STOPPED", receiver.recv().unwrap()); assert_eq!("Service SA STOPPED", receiver.recv().unwrap()); } }