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