windjammer_runtime/
mock.rs1use std::sync::{Arc, Mutex};
7
8pub struct MockTracker {
20 #[allow(clippy::type_complexity)]
21 calls: Arc<Mutex<Vec<(String, Vec<String>)>>>,
22}
23
24impl MockTracker {
25 pub fn new() -> Self {
27 Self {
28 calls: Arc::new(Mutex::new(Vec::new())),
29 }
30 }
31
32 pub fn record_call(&self, function: &str, args: Vec<String>) {
34 let mut calls = self.calls.lock().unwrap();
35 calls.push((function.to_string(), args));
36 }
37
38 pub fn was_called(&self, function: &str) -> bool {
40 let calls = self.calls.lock().unwrap();
41 calls.iter().any(|(name, _)| name == function)
42 }
43
44 pub fn call_count(&self, function: &str) -> usize {
46 let calls = self.calls.lock().unwrap();
47 calls.iter().filter(|(name, _)| name == function).count()
48 }
49
50 pub fn get_calls(&self, function: &str) -> Vec<Vec<String>> {
52 let calls = self.calls.lock().unwrap();
53 calls
54 .iter()
55 .filter(|(name, _)| name == function)
56 .map(|(_, args)| args.clone())
57 .collect()
58 }
59
60 pub fn reset(&self) {
62 let mut calls = self.calls.lock().unwrap();
63 calls.clear();
64 }
65
66 pub fn verify_call_count(&self, function: &str, expected: usize) {
68 let actual = self.call_count(function);
69 if actual != expected {
70 panic!(
71 "Mock verification failed: expected {} to be called {} time(s), but was called {} time(s)",
72 function, expected, actual
73 );
74 }
75 }
76
77 pub fn verify_called(&self, function: &str) {
79 if !self.was_called(function) {
80 panic!(
81 "Mock verification failed: expected {} to be called at least once",
82 function
83 );
84 }
85 }
86
87 pub fn verify_not_called(&self, function: &str) {
89 if self.was_called(function) {
90 panic!(
91 "Mock verification failed: expected {} to never be called, but was called {} time(s)",
92 function,
93 self.call_count(function)
94 );
95 }
96 }
97}
98
99impl Default for MockTracker {
100 fn default() -> Self {
101 Self::new()
102 }
103}
104
105pub struct MockReturn<T> {
107 values: Arc<Mutex<Vec<T>>>,
108 index: Arc<Mutex<usize>>,
109}
110
111impl<T: Clone> MockReturn<T> {
112 pub fn new(values: Vec<T>) -> Self {
114 Self {
115 values: Arc::new(Mutex::new(values)),
116 index: Arc::new(Mutex::new(0)),
117 }
118 }
119
120 pub fn next(&self) -> Option<T> {
122 let mut index = self.index.lock().unwrap();
123 let values = self.values.lock().unwrap();
124
125 if *index < values.len() {
126 let value = values[*index].clone();
127 *index += 1;
128 Some(value)
129 } else {
130 None
131 }
132 }
133
134 pub fn reset(&self) {
136 let mut index = self.index.lock().unwrap();
137 *index = 0;
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn test_mock_tracker_basic() {
147 let tracker = MockTracker::new();
148
149 tracker.record_call("foo", vec!["arg1".to_string()]);
150
151 assert!(tracker.was_called("foo"));
152 assert!(!tracker.was_called("bar"));
153 assert_eq!(tracker.call_count("foo"), 1);
154 assert_eq!(tracker.call_count("bar"), 0);
155 }
156
157 #[test]
158 fn test_mock_tracker_multiple_calls() {
159 let tracker = MockTracker::new();
160
161 tracker.record_call("foo", vec!["1".to_string()]);
162 tracker.record_call("foo", vec!["2".to_string()]);
163 tracker.record_call("bar", vec!["3".to_string()]);
164
165 assert_eq!(tracker.call_count("foo"), 2);
166 assert_eq!(tracker.call_count("bar"), 1);
167
168 let foo_calls = tracker.get_calls("foo");
169 assert_eq!(foo_calls.len(), 2);
170 assert_eq!(foo_calls[0], vec!["1".to_string()]);
171 assert_eq!(foo_calls[1], vec!["2".to_string()]);
172 }
173
174 #[test]
175 fn test_mock_tracker_reset() {
176 let tracker = MockTracker::new();
177
178 tracker.record_call("foo", vec![]);
179 assert_eq!(tracker.call_count("foo"), 1);
180
181 tracker.reset();
182 assert_eq!(tracker.call_count("foo"), 0);
183 }
184
185 #[test]
186 fn test_mock_tracker_verify_called() {
187 let tracker = MockTracker::new();
188 tracker.record_call("foo", vec![]);
189 tracker.verify_called("foo");
190 }
191
192 #[test]
193 #[should_panic(expected = "Mock verification failed")]
194 fn test_mock_tracker_verify_called_fails() {
195 let tracker = MockTracker::new();
196 tracker.verify_called("foo");
197 }
198
199 #[test]
200 fn test_mock_tracker_verify_not_called() {
201 let tracker = MockTracker::new();
202 tracker.verify_not_called("foo");
203 }
204
205 #[test]
206 #[should_panic(expected = "Mock verification failed")]
207 fn test_mock_tracker_verify_not_called_fails() {
208 let tracker = MockTracker::new();
209 tracker.record_call("foo", vec![]);
210 tracker.verify_not_called("foo");
211 }
212
213 #[test]
214 fn test_mock_return() {
215 let mock = MockReturn::new(vec![1, 2, 3]);
216
217 assert_eq!(mock.next(), Some(1));
218 assert_eq!(mock.next(), Some(2));
219 assert_eq!(mock.next(), Some(3));
220 assert_eq!(mock.next(), None);
221
222 mock.reset();
223 assert_eq!(mock.next(), Some(1));
224 }
225}