hojicha_runtime/testing/
test_runner.rs1use crate::program::{Program, ProgramOptions};
4use hojicha_core::{
5 core::Model,
6 error::Result,
7 event::Event,
8};
9use std::sync::{mpsc, Arc, Mutex};
10use std::time::Duration;
11
12pub struct TestRunner<M: Model> {
14 program: crate::program::Program<M>,
15 timeout: Option<Duration>,
16 message_log: Arc<Mutex<Vec<Event<M::Message>>>>,
17}
18
19impl<M: Model> TestRunner<M>
20where
21 M::Message: Clone + Send + 'static,
22{
23 pub fn new(model: M) -> Result<Self> {
25 Self::with_options(model, ProgramOptions::default().headless())
26 }
27
28 pub fn with_options(model: M, options: ProgramOptions) -> Result<Self> {
30 let program = Program::with_options(model, options)?;
31 Ok(Self {
32 program,
33 timeout: Some(Duration::from_secs(5)), message_log: Arc::new(Mutex::new(Vec::new())),
35 })
36 }
37
38 pub fn with_timeout(mut self, timeout: Duration) -> Self {
40 self.timeout = Some(timeout);
41 self
42 }
43
44 pub fn without_timeout(mut self) -> Self {
46 self.timeout = None;
47 self
48 }
49
50 pub fn init_async_bridge(&mut self) -> mpsc::SyncSender<Event<M::Message>> {
52 self.program.init_async_bridge()
53 }
54
55 pub fn sender(&self) -> Option<mpsc::SyncSender<Event<M::Message>>> {
57 self.program.sender()
58 }
59
60 pub fn send_message(&self, msg: M::Message) -> Result<()> {
62 self.program.send_message(msg)
63 }
64
65 pub fn run(self) -> Result<()> {
67 match self.timeout {
68 Some(timeout) => self.program.run_with_timeout(timeout),
69 None => self.program.run(),
70 }
71 }
72
73 pub fn run_until<F>(self, condition: F) -> Result<()>
75 where
76 F: FnMut(&M) -> bool + 'static,
77 {
78 self.program.run_until(condition)
79 }
80
81 pub fn run_for_updates(self, count: usize) -> Result<()> {
83 let counter = Arc::new(Mutex::new(0));
84 let target = count;
85
86 self.program.run_until(move |_| {
87 let mut c = counter.lock().unwrap();
88 *c += 1;
89 *c >= target
90 })
91 }
92}
93
94#[macro_export]
96macro_rules! test_runner {
97 ($model:expr) => {
98 $crate::testing::TestRunner::new($model).unwrap()
99 };
100 ($model:expr, $timeout:expr) => {
101 $crate::testing::TestRunner::new($model)
102 .unwrap()
103 .with_timeout($timeout)
104 };
105}