1use crate::RunResult;
4
5#[derive(Debug, Clone, Default)]
43pub struct MockProcessBuilder {
44 wall_ms: u64,
45 exit_code: i32,
46 timed_out: bool,
47 cpu_ms: Option<u64>,
48 page_faults: Option<u64>,
49 ctx_switches: Option<u64>,
50 max_rss_kb: Option<u64>,
51 binary_bytes: Option<u64>,
52 stdout: Vec<u8>,
53 stderr: Vec<u8>,
54}
55
56impl MockProcessBuilder {
57 pub fn new() -> Self {
59 Self::default()
60 }
61
62 pub fn success() -> Self {
66 Self::new().exit_code(0)
67 }
68
69 pub fn failure() -> Self {
73 Self::new().exit_code(1)
74 }
75
76 pub fn timeout() -> Self {
80 Self::new().exit_code(-1).timed_out(true)
81 }
82
83 pub fn wall_ms(mut self, ms: u64) -> Self {
85 self.wall_ms = ms;
86 self
87 }
88
89 pub fn exit_code(mut self, code: i32) -> Self {
91 self.exit_code = code;
92 self
93 }
94
95 pub fn timed_out(mut self, timed_out: bool) -> Self {
97 self.timed_out = timed_out;
98 self
99 }
100
101 pub fn cpu_ms(mut self, ms: u64) -> Self {
103 self.cpu_ms = Some(ms);
104 self
105 }
106
107 pub fn page_faults(mut self, faults: u64) -> Self {
109 self.page_faults = Some(faults);
110 self
111 }
112
113 pub fn ctx_switches(mut self, switches: u64) -> Self {
115 self.ctx_switches = Some(switches);
116 self
117 }
118
119 pub fn max_rss_kb(mut self, kb: u64) -> Self {
121 self.max_rss_kb = Some(kb);
122 self
123 }
124
125 pub fn binary_bytes(mut self, bytes: u64) -> Self {
127 self.binary_bytes = Some(bytes);
128 self
129 }
130
131 pub fn stdout(mut self, output: Vec<u8>) -> Self {
133 self.stdout = output;
134 self
135 }
136
137 pub fn stdout_str(mut self, output: &str) -> Self {
139 self.stdout = output.as_bytes().to_vec();
140 self
141 }
142
143 pub fn stderr(mut self, output: Vec<u8>) -> Self {
145 self.stderr = output;
146 self
147 }
148
149 pub fn stderr_str(mut self, output: &str) -> Self {
151 self.stderr = output.as_bytes().to_vec();
152 self
153 }
154
155 pub fn build(self) -> RunResult {
157 RunResult {
158 wall_ms: self.wall_ms,
159 exit_code: self.exit_code,
160 timed_out: self.timed_out,
161 cpu_ms: self.cpu_ms,
162 page_faults: self.page_faults,
163 ctx_switches: self.ctx_switches,
164 max_rss_kb: self.max_rss_kb,
165 io_read_bytes: None,
166 io_write_bytes: None,
167 network_packets: None,
168 energy_uj: None,
169 binary_bytes: self.binary_bytes,
170 stdout: self.stdout,
171 stderr: self.stderr,
172 }
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn new_builder_has_defaults() {
182 let result = MockProcessBuilder::new().build();
183
184 assert_eq!(result.wall_ms, 0);
185 assert_eq!(result.exit_code, 0);
186 assert!(!result.timed_out);
187 assert!(result.cpu_ms.is_none());
188 assert!(result.page_faults.is_none());
189 assert!(result.ctx_switches.is_none());
190 assert!(result.max_rss_kb.is_none());
191 assert!(result.binary_bytes.is_none());
192 assert!(result.stdout.is_empty());
193 assert!(result.stderr.is_empty());
194 }
195
196 #[test]
197 fn success_preset() {
198 let result = MockProcessBuilder::success().build();
199 assert_eq!(result.exit_code, 0);
200 }
201
202 #[test]
203 fn failure_preset() {
204 let result = MockProcessBuilder::failure().build();
205 assert_eq!(result.exit_code, 1);
206 }
207
208 #[test]
209 fn timeout_preset() {
210 let result = MockProcessBuilder::timeout().build();
211 assert_eq!(result.exit_code, -1);
212 assert!(result.timed_out);
213 }
214
215 #[test]
216 fn fluent_configuration() {
217 let result = MockProcessBuilder::new()
218 .wall_ms(500)
219 .exit_code(42)
220 .timed_out(false)
221 .cpu_ms(200)
222 .page_faults(100)
223 .ctx_switches(50)
224 .max_rss_kb(4096)
225 .binary_bytes(8192)
226 .stdout(b"out".to_vec())
227 .stderr(b"err".to_vec())
228 .build();
229
230 assert_eq!(result.wall_ms, 500);
231 assert_eq!(result.exit_code, 42);
232 assert!(!result.timed_out);
233 assert_eq!(result.cpu_ms, Some(200));
234 assert_eq!(result.page_faults, Some(100));
235 assert_eq!(result.ctx_switches, Some(50));
236 assert_eq!(result.max_rss_kb, Some(4096));
237 assert_eq!(result.binary_bytes, Some(8192));
238 assert_eq!(result.stdout, b"out");
239 assert_eq!(result.stderr, b"err");
240 }
241
242 #[test]
243 fn stdout_str_and_stderr_str() {
244 let result = MockProcessBuilder::new()
245 .stdout_str("hello\n")
246 .stderr_str("warning\n")
247 .build();
248
249 assert_eq!(result.stdout, b"hello\n");
250 assert_eq!(result.stderr, b"warning\n");
251 }
252
253 #[test]
254 fn builder_can_be_reused() {
255 let base = MockProcessBuilder::new().wall_ms(100);
256
257 let result1 = base.clone().exit_code(0).build();
258 let result2 = base.exit_code(1).build();
259
260 assert_eq!(result1.wall_ms, 100);
261 assert_eq!(result1.exit_code, 0);
262 assert_eq!(result2.wall_ms, 100);
263 assert_eq!(result2.exit_code, 1);
264 }
265}