1use parking_lot::RwLock;
7use std::sync::Arc;
8use wae_types::{WaeError, WaeErrorKind, WaeResult as TestingResult};
9
10#[cfg(feature = "mockall")]
11pub use mockall::{self, __mock_MockObject, __mock_MockStatic, automock, mock, predicate, sequence};
12
13#[derive(Debug, Clone)]
15pub struct MockCall {
16 pub args: Vec<String>,
18 pub timestamp: std::time::Instant,
20}
21
22#[derive(Debug)]
24pub enum MockResult<T> {
25 Return(T),
27 Error(String),
29 Sequence(Vec<T>),
31}
32
33impl<T: Clone> MockResult<T> {
34 pub fn return_value(value: T) -> Self {
36 MockResult::Return(value)
37 }
38
39 pub fn error(msg: impl Into<String>) -> Self {
41 MockResult::Error(msg.into())
42 }
43
44 pub fn sequence(values: Vec<T>) -> Self {
46 MockResult::Sequence(values)
47 }
48}
49
50impl<T: Clone> Clone for MockResult<T> {
51 fn clone(&self) -> Self {
52 match self {
53 MockResult::Return(v) => MockResult::Return(v.clone()),
54 MockResult::Error(e) => MockResult::Error(e.clone()),
55 MockResult::Sequence(v) => MockResult::Sequence(v.clone()),
56 }
57 }
58}
59
60#[derive(Debug, Default)]
62pub struct MockExpectation {
63 pub expected_calls: Option<usize>,
65 pub description: Option<String>,
67}
68
69impl MockExpectation {
70 pub fn new() -> Self {
72 Self::default()
73 }
74
75 pub fn times(mut self, count: usize) -> Self {
77 self.expected_calls = Some(count);
78 self
79 }
80
81 pub fn description(mut self, desc: impl Into<String>) -> Self {
83 self.description = Some(desc.into());
84 self
85 }
86}
87
88pub trait Mock: Send + Sync {
90 fn calls(&self) -> Vec<MockCall>;
92
93 fn call_count(&self) -> usize;
95
96 fn verify(&self) -> TestingResult<()>;
98
99 fn reset(&self);
101}
102
103pub trait AsyncMock: Mock {
105 async fn verify_async(&self) -> TestingResult<()>;
107}
108
109pub struct MockBuilder<T> {
111 result: Option<MockResult<T>>,
112 expectation: MockExpectation,
113 calls: Arc<RwLock<Vec<MockCall>>>,
114}
115
116impl<T: Clone + Send + Sync + 'static> MockBuilder<T> {
117 pub fn new() -> Self {
119 Self { result: None, expectation: MockExpectation::default(), calls: Arc::new(RwLock::new(Vec::new())) }
120 }
121
122 pub fn return_value(mut self, value: T) -> Self {
124 self.result = Some(MockResult::return_value(value));
125 self
126 }
127
128 pub fn error(mut self, msg: impl Into<String>) -> Self {
130 self.result = Some(MockResult::error(msg));
131 self
132 }
133
134 pub fn sequence(mut self, values: Vec<T>) -> Self {
136 self.result = Some(MockResult::sequence(values));
137 self
138 }
139
140 pub fn expect(mut self, expectation: MockExpectation) -> Self {
142 self.expectation = expectation;
143 self
144 }
145
146 pub fn build(self) -> MockFn<T> {
148 MockFn {
149 result: self.result,
150 expectation: self.expectation,
151 calls: self.calls,
152 sequence_index: Arc::new(RwLock::new(0)),
153 }
154 }
155}
156
157impl<T: Clone + Send + Sync + 'static> Default for MockBuilder<T> {
158 fn default() -> Self {
159 Self::new()
160 }
161}
162
163pub struct MockFn<T> {
165 result: Option<MockResult<T>>,
166 expectation: MockExpectation,
167 calls: Arc<RwLock<Vec<MockCall>>>,
168 sequence_index: Arc<RwLock<usize>>,
169}
170
171impl<T: Clone + Send + Sync + 'static> MockFn<T> {
172 pub fn call(&self, args: Vec<String>) -> TestingResult<T> {
174 {
175 let mut calls = self.calls.write();
176 calls.push(MockCall { args, timestamp: std::time::Instant::now() });
177 }
178
179 match &self.result {
180 Some(MockResult::Return(v)) => Ok(v.clone()),
181 Some(MockResult::Error(e)) => Err(WaeError::new(WaeErrorKind::MockError { reason: e.clone() })),
182 Some(MockResult::Sequence(values)) => {
183 let mut idx = self.sequence_index.write();
184 if *idx < values.len() {
185 let value = values[*idx].clone();
186 *idx += 1;
187 Ok(value)
188 }
189 else {
190 Err(WaeError::new(WaeErrorKind::MockError { reason: "Mock sequence exhausted".to_string() }))
191 }
192 }
193 None => Err(WaeError::new(WaeErrorKind::MockError { reason: "No mock result configured".to_string() })),
194 }
195 }
196
197 pub async fn call_async(&self, args: Vec<String>) -> TestingResult<T> {
199 self.call(args)
200 }
201}
202
203impl<T: Clone + Send + Sync + 'static> Mock for MockFn<T> {
204 fn calls(&self) -> Vec<MockCall> {
205 self.calls.read().clone()
206 }
207
208 fn call_count(&self) -> usize {
209 self.calls.read().len()
210 }
211
212 fn verify(&self) -> TestingResult<()> {
213 let actual_calls = self.call_count();
214
215 if let Some(expected) = self.expectation.expected_calls
216 && actual_calls != expected
217 {
218 return Err(WaeError::new(WaeErrorKind::AssertionFailed {
219 message: format!("Expected {} calls, but got {}", expected, actual_calls),
220 }));
221 }
222
223 Ok(())
224 }
225
226 fn reset(&self) {
227 let mut calls = self.calls.write();
228 calls.clear();
229 let mut idx = self.sequence_index.write();
230 *idx = 0;
231 }
232}
233
234impl<T: Clone + Send + Sync + 'static> AsyncMock for MockFn<T> {
235 async fn verify_async(&self) -> TestingResult<()> {
236 self.verify()
237 }
238}
239
240pub fn verify<M: Mock>(mock: &M) -> TestingResult<()> {
242 mock.verify()
243}
244
245pub async fn verify_async<M: AsyncMock>(mock: &M) -> TestingResult<()> {
247 mock.verify_async().await
248}