Skip to main content

meerkat_mobkit/
mocks.rs

1//! Test doubles and mock implementations for development and testing.
2
3use std::sync::Arc;
4use std::sync::atomic::{AtomicU32, Ordering};
5use std::time::{Duration, Instant};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum MockProcessError {
9    LaunchFailed,
10    Timeout,
11}
12
13#[derive(Debug, Clone)]
14enum MockBehavior {
15    FailThenSucceed { failures_before_success: u32 },
16    NeverResponds,
17}
18
19#[derive(Debug, Clone)]
20pub struct MockModuleProcess {
21    behavior: MockBehavior,
22    attempts: Arc<AtomicU32>,
23}
24
25impl MockModuleProcess {
26    pub fn fail_then_succeed(failures_before_success: u32) -> Self {
27        Self {
28            behavior: MockBehavior::FailThenSucceed {
29                failures_before_success,
30            },
31            attempts: Arc::new(AtomicU32::new(0)),
32        }
33    }
34
35    pub fn never_responds() -> Self {
36        Self {
37            behavior: MockBehavior::NeverResponds,
38            attempts: Arc::new(AtomicU32::new(0)),
39        }
40    }
41
42    pub fn invoke_json_line_with_timeout(
43        &self,
44        timeout: Duration,
45        success_line: &str,
46    ) -> Result<String, MockProcessError> {
47        match self.behavior {
48            MockBehavior::FailThenSucceed {
49                failures_before_success,
50            } => {
51                let attempt = self.attempts.fetch_add(1, Ordering::SeqCst);
52                if attempt < failures_before_success {
53                    return Err(MockProcessError::LaunchFailed);
54                }
55                Ok(success_line.to_string())
56            }
57            MockBehavior::NeverResponds => {
58                let started = Instant::now();
59                while started.elapsed() < timeout {
60                    std::thread::yield_now();
61                }
62                Err(MockProcessError::Timeout)
63            }
64        }
65    }
66
67    pub fn attempts(&self) -> u32 {
68        self.attempts.load(Ordering::SeqCst)
69    }
70}