pub struct FakeProcessRunner { /* private fields */ }Expand description
A process runner that returns pre-configured results for specific commands.
This is useful for testing code that depends on ProcessRunner without
actually spawning processes. Results can be configured per-command or
using a fallback.
§Thread Safety
All configuration methods are &self (not &mut self), making it safe
to share a single instance across multiple threads in tests.
§Example
use perfgate_fake::FakeProcessRunner;
use perfgate_adapters::{ProcessRunner, CommandSpec, RunResult};
let runner = FakeProcessRunner::new();
// Configure a result for a specific command
runner.set_result(
&["echo", "hello"],
RunResult {
wall_ms: 50,
exit_code: 0,
timed_out: false,
cpu_ms: Some(10),
page_faults: None,
ctx_switches: None,
max_rss_kb: Some(1024),
io_read_bytes: None,
io_write_bytes: None,
network_packets: None,
energy_uj: None,
binary_bytes: None,
stdout: b"hello\n".to_vec(),
stderr: vec![],
},
);
// Get the history of executed commands
assert!(runner.history().is_empty());Implementations§
Source§impl FakeProcessRunner
impl FakeProcessRunner
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new FakeProcessRunner with no configured results.
Examples found in repository?
8fn main() {
9 println!("=== perfgate-fake Basic Example ===\n");
10
11 println!("1. Creating a fake process runner:");
12 let runner = FakeProcessRunner::new();
13 println!(" Created empty FakeProcessRunner");
14
15 println!("\n2. Configuring mock results with MockProcessBuilder:");
16 let success_result = MockProcessBuilder::new()
17 .exit_code(0)
18 .wall_ms(100)
19 .stdout(b"hello world".to_vec())
20 .stderr(b"".to_vec())
21 .build();
22
23 runner.set_result(&["echo", "hello"], success_result);
24 println!(" Configured: echo hello -> exit 0, 100ms, stdout='hello world'");
25
26 let slow_result = MockProcessBuilder::new()
27 .exit_code(0)
28 .wall_ms(500)
29 .stdout(b"slow output".to_vec())
30 .build();
31
32 runner.set_result(&["slow", "command"], slow_result);
33 println!(" Configured: slow command -> exit 0, 500ms");
34
35 let failure_result = MockProcessBuilder::new()
36 .exit_code(1)
37 .wall_ms(50)
38 .stderr(b"error: something went wrong".to_vec())
39 .build();
40
41 runner.set_result(&["failing", "cmd"], failure_result);
42 println!(" Configured: failing cmd -> exit 1, 50ms");
43
44 println!("\n3. Running commands with the fake runner:");
45 let spec1 = CommandSpec {
46 name: "echo-hello".to_string(),
47 argv: vec!["echo".to_string(), "hello".to_string()],
48 cwd: None,
49 env: vec![],
50 timeout: None,
51 output_cap_bytes: 1024,
52 };
53
54 match runner.run(&spec1) {
55 Ok(result) => {
56 println!(" echo hello:");
57 println!(" Exit code: {}", result.exit_code);
58 println!(" Wall time: {} ms", result.wall_ms);
59 println!(" Stdout: {:?}", String::from_utf8_lossy(&result.stdout));
60 }
61 Err(e) => println!(" Error: {}", e),
62 }
63
64 let spec2 = CommandSpec {
65 name: "failing-cmd".to_string(),
66 argv: vec!["failing".to_string(), "cmd".to_string()],
67 cwd: None,
68 env: vec![],
69 timeout: None,
70 output_cap_bytes: 1024,
71 };
72
73 match runner.run(&spec2) {
74 Ok(result) => {
75 println!(" failing cmd:");
76 println!(" Exit code: {}", result.exit_code);
77 println!(" Stderr: {:?}", String::from_utf8_lossy(&result.stderr));
78 }
79 Err(e) => println!(" Error: {}", e),
80 }
81
82 println!("\n4. Testing deterministic behavior:");
83 let spec3 = CommandSpec {
84 name: "slow-command".to_string(),
85 argv: vec!["slow".to_string(), "command".to_string()],
86 cwd: None,
87 env: vec![],
88 timeout: None,
89 output_cap_bytes: 1024,
90 };
91
92 let r1 = runner.run(&spec3).unwrap();
93 let r2 = runner.run(&spec3).unwrap();
94 println!(" First run: {} ms", r1.wall_ms);
95 println!(" Second run: {} ms", r2.wall_ms);
96 println!(" Same result: {}", r1.wall_ms == r2.wall_ms);
97
98 println!("\n5. Default behavior for unconfigured commands:");
99 let unknown_spec = CommandSpec {
100 name: "unknown-command".to_string(),
101 argv: vec!["unknown".to_string(), "command".to_string()],
102 cwd: None,
103 env: vec![],
104 timeout: None,
105 output_cap_bytes: 1024,
106 };
107
108 match runner.run(&unknown_spec) {
109 Ok(result) => {
110 println!(" Unknown command returned default:");
111 println!(" Exit code: {}", result.exit_code);
112 println!(" Wall time: {} ms", result.wall_ms);
113 }
114 Err(e) => println!(" Error: {}", e),
115 }
116
117 println!("\n6. Setting fallback result for all unconfigured commands:");
118 let fallback_result = MockProcessBuilder::new()
119 .exit_code(127)
120 .wall_ms(1)
121 .stderr(b"command not found".to_vec())
122 .build();
123
124 runner.set_fallback(fallback_result);
125 println!(" Set fallback: exit 127, 1ms, stderr='command not found'");
126
127 let another_unknown = CommandSpec {
128 name: "another-unknown".to_string(),
129 argv: vec!["another".to_string(), "unknown".to_string()],
130 cwd: None,
131 env: vec![],
132 timeout: None,
133 output_cap_bytes: 1024,
134 };
135
136 match runner.run(&another_unknown) {
137 Ok(result) => {
138 println!(" Another unknown:");
139 println!(" Exit code: {}", result.exit_code);
140 println!(" Stderr: {:?}", String::from_utf8_lossy(&result.stderr));
141 }
142 Err(e) => println!(" Error: {}", e),
143 }
144
145 println!("\n7. Configuring with CPU and memory metrics:");
146 let detailed_result = MockProcessBuilder::new()
147 .exit_code(0)
148 .wall_ms(250)
149 .cpu_ms(200)
150 .max_rss_kb(4096)
151 .stdout(b"detailed output".to_vec())
152 .build();
153
154 runner.set_result(&["detailed"], detailed_result);
155
156 let detailed_spec = CommandSpec {
157 name: "detailed".to_string(),
158 argv: vec!["detailed".to_string()],
159 cwd: None,
160 env: vec![],
161 timeout: None,
162 output_cap_bytes: 1024,
163 };
164
165 if let Ok(result) = runner.run(&detailed_spec) {
166 println!(" Detailed result:");
167 println!(" Wall time: {} ms", result.wall_ms);
168 println!(" CPU time: {:?} ms", result.cpu_ms);
169 println!(" Max RSS: {:?} KB", result.max_rss_kb);
170 }
171
172 println!("\n=== Example complete ===");
173}Sourcepub fn set_result(&self, argv: &[&str], result: RunResult)
pub fn set_result(&self, argv: &[&str], result: RunResult)
Configure a result for a specific command argv.
The argv is joined with spaces to create a lookup key. When a matching command is run, the configured result is returned.
Examples found in repository?
8fn main() {
9 println!("=== perfgate-fake Basic Example ===\n");
10
11 println!("1. Creating a fake process runner:");
12 let runner = FakeProcessRunner::new();
13 println!(" Created empty FakeProcessRunner");
14
15 println!("\n2. Configuring mock results with MockProcessBuilder:");
16 let success_result = MockProcessBuilder::new()
17 .exit_code(0)
18 .wall_ms(100)
19 .stdout(b"hello world".to_vec())
20 .stderr(b"".to_vec())
21 .build();
22
23 runner.set_result(&["echo", "hello"], success_result);
24 println!(" Configured: echo hello -> exit 0, 100ms, stdout='hello world'");
25
26 let slow_result = MockProcessBuilder::new()
27 .exit_code(0)
28 .wall_ms(500)
29 .stdout(b"slow output".to_vec())
30 .build();
31
32 runner.set_result(&["slow", "command"], slow_result);
33 println!(" Configured: slow command -> exit 0, 500ms");
34
35 let failure_result = MockProcessBuilder::new()
36 .exit_code(1)
37 .wall_ms(50)
38 .stderr(b"error: something went wrong".to_vec())
39 .build();
40
41 runner.set_result(&["failing", "cmd"], failure_result);
42 println!(" Configured: failing cmd -> exit 1, 50ms");
43
44 println!("\n3. Running commands with the fake runner:");
45 let spec1 = CommandSpec {
46 name: "echo-hello".to_string(),
47 argv: vec!["echo".to_string(), "hello".to_string()],
48 cwd: None,
49 env: vec![],
50 timeout: None,
51 output_cap_bytes: 1024,
52 };
53
54 match runner.run(&spec1) {
55 Ok(result) => {
56 println!(" echo hello:");
57 println!(" Exit code: {}", result.exit_code);
58 println!(" Wall time: {} ms", result.wall_ms);
59 println!(" Stdout: {:?}", String::from_utf8_lossy(&result.stdout));
60 }
61 Err(e) => println!(" Error: {}", e),
62 }
63
64 let spec2 = CommandSpec {
65 name: "failing-cmd".to_string(),
66 argv: vec!["failing".to_string(), "cmd".to_string()],
67 cwd: None,
68 env: vec![],
69 timeout: None,
70 output_cap_bytes: 1024,
71 };
72
73 match runner.run(&spec2) {
74 Ok(result) => {
75 println!(" failing cmd:");
76 println!(" Exit code: {}", result.exit_code);
77 println!(" Stderr: {:?}", String::from_utf8_lossy(&result.stderr));
78 }
79 Err(e) => println!(" Error: {}", e),
80 }
81
82 println!("\n4. Testing deterministic behavior:");
83 let spec3 = CommandSpec {
84 name: "slow-command".to_string(),
85 argv: vec!["slow".to_string(), "command".to_string()],
86 cwd: None,
87 env: vec![],
88 timeout: None,
89 output_cap_bytes: 1024,
90 };
91
92 let r1 = runner.run(&spec3).unwrap();
93 let r2 = runner.run(&spec3).unwrap();
94 println!(" First run: {} ms", r1.wall_ms);
95 println!(" Second run: {} ms", r2.wall_ms);
96 println!(" Same result: {}", r1.wall_ms == r2.wall_ms);
97
98 println!("\n5. Default behavior for unconfigured commands:");
99 let unknown_spec = CommandSpec {
100 name: "unknown-command".to_string(),
101 argv: vec!["unknown".to_string(), "command".to_string()],
102 cwd: None,
103 env: vec![],
104 timeout: None,
105 output_cap_bytes: 1024,
106 };
107
108 match runner.run(&unknown_spec) {
109 Ok(result) => {
110 println!(" Unknown command returned default:");
111 println!(" Exit code: {}", result.exit_code);
112 println!(" Wall time: {} ms", result.wall_ms);
113 }
114 Err(e) => println!(" Error: {}", e),
115 }
116
117 println!("\n6. Setting fallback result for all unconfigured commands:");
118 let fallback_result = MockProcessBuilder::new()
119 .exit_code(127)
120 .wall_ms(1)
121 .stderr(b"command not found".to_vec())
122 .build();
123
124 runner.set_fallback(fallback_result);
125 println!(" Set fallback: exit 127, 1ms, stderr='command not found'");
126
127 let another_unknown = CommandSpec {
128 name: "another-unknown".to_string(),
129 argv: vec!["another".to_string(), "unknown".to_string()],
130 cwd: None,
131 env: vec![],
132 timeout: None,
133 output_cap_bytes: 1024,
134 };
135
136 match runner.run(&another_unknown) {
137 Ok(result) => {
138 println!(" Another unknown:");
139 println!(" Exit code: {}", result.exit_code);
140 println!(" Stderr: {:?}", String::from_utf8_lossy(&result.stderr));
141 }
142 Err(e) => println!(" Error: {}", e),
143 }
144
145 println!("\n7. Configuring with CPU and memory metrics:");
146 let detailed_result = MockProcessBuilder::new()
147 .exit_code(0)
148 .wall_ms(250)
149 .cpu_ms(200)
150 .max_rss_kb(4096)
151 .stdout(b"detailed output".to_vec())
152 .build();
153
154 runner.set_result(&["detailed"], detailed_result);
155
156 let detailed_spec = CommandSpec {
157 name: "detailed".to_string(),
158 argv: vec!["detailed".to_string()],
159 cwd: None,
160 env: vec![],
161 timeout: None,
162 output_cap_bytes: 1024,
163 };
164
165 if let Ok(result) = runner.run(&detailed_spec) {
166 println!(" Detailed result:");
167 println!(" Wall time: {} ms", result.wall_ms);
168 println!(" CPU time: {:?} ms", result.cpu_ms);
169 println!(" Max RSS: {:?} KB", result.max_rss_kb);
170 }
171
172 println!("\n=== Example complete ===");
173}Sourcepub fn set_fallback(&self, result: RunResult)
pub fn set_fallback(&self, result: RunResult)
Configure a fallback result for any command without a specific result.
This is useful for tests that don’t care about the exact command but need some default behavior.
Examples found in repository?
8fn main() {
9 println!("=== perfgate-fake Basic Example ===\n");
10
11 println!("1. Creating a fake process runner:");
12 let runner = FakeProcessRunner::new();
13 println!(" Created empty FakeProcessRunner");
14
15 println!("\n2. Configuring mock results with MockProcessBuilder:");
16 let success_result = MockProcessBuilder::new()
17 .exit_code(0)
18 .wall_ms(100)
19 .stdout(b"hello world".to_vec())
20 .stderr(b"".to_vec())
21 .build();
22
23 runner.set_result(&["echo", "hello"], success_result);
24 println!(" Configured: echo hello -> exit 0, 100ms, stdout='hello world'");
25
26 let slow_result = MockProcessBuilder::new()
27 .exit_code(0)
28 .wall_ms(500)
29 .stdout(b"slow output".to_vec())
30 .build();
31
32 runner.set_result(&["slow", "command"], slow_result);
33 println!(" Configured: slow command -> exit 0, 500ms");
34
35 let failure_result = MockProcessBuilder::new()
36 .exit_code(1)
37 .wall_ms(50)
38 .stderr(b"error: something went wrong".to_vec())
39 .build();
40
41 runner.set_result(&["failing", "cmd"], failure_result);
42 println!(" Configured: failing cmd -> exit 1, 50ms");
43
44 println!("\n3. Running commands with the fake runner:");
45 let spec1 = CommandSpec {
46 name: "echo-hello".to_string(),
47 argv: vec!["echo".to_string(), "hello".to_string()],
48 cwd: None,
49 env: vec![],
50 timeout: None,
51 output_cap_bytes: 1024,
52 };
53
54 match runner.run(&spec1) {
55 Ok(result) => {
56 println!(" echo hello:");
57 println!(" Exit code: {}", result.exit_code);
58 println!(" Wall time: {} ms", result.wall_ms);
59 println!(" Stdout: {:?}", String::from_utf8_lossy(&result.stdout));
60 }
61 Err(e) => println!(" Error: {}", e),
62 }
63
64 let spec2 = CommandSpec {
65 name: "failing-cmd".to_string(),
66 argv: vec!["failing".to_string(), "cmd".to_string()],
67 cwd: None,
68 env: vec![],
69 timeout: None,
70 output_cap_bytes: 1024,
71 };
72
73 match runner.run(&spec2) {
74 Ok(result) => {
75 println!(" failing cmd:");
76 println!(" Exit code: {}", result.exit_code);
77 println!(" Stderr: {:?}", String::from_utf8_lossy(&result.stderr));
78 }
79 Err(e) => println!(" Error: {}", e),
80 }
81
82 println!("\n4. Testing deterministic behavior:");
83 let spec3 = CommandSpec {
84 name: "slow-command".to_string(),
85 argv: vec!["slow".to_string(), "command".to_string()],
86 cwd: None,
87 env: vec![],
88 timeout: None,
89 output_cap_bytes: 1024,
90 };
91
92 let r1 = runner.run(&spec3).unwrap();
93 let r2 = runner.run(&spec3).unwrap();
94 println!(" First run: {} ms", r1.wall_ms);
95 println!(" Second run: {} ms", r2.wall_ms);
96 println!(" Same result: {}", r1.wall_ms == r2.wall_ms);
97
98 println!("\n5. Default behavior for unconfigured commands:");
99 let unknown_spec = CommandSpec {
100 name: "unknown-command".to_string(),
101 argv: vec!["unknown".to_string(), "command".to_string()],
102 cwd: None,
103 env: vec![],
104 timeout: None,
105 output_cap_bytes: 1024,
106 };
107
108 match runner.run(&unknown_spec) {
109 Ok(result) => {
110 println!(" Unknown command returned default:");
111 println!(" Exit code: {}", result.exit_code);
112 println!(" Wall time: {} ms", result.wall_ms);
113 }
114 Err(e) => println!(" Error: {}", e),
115 }
116
117 println!("\n6. Setting fallback result for all unconfigured commands:");
118 let fallback_result = MockProcessBuilder::new()
119 .exit_code(127)
120 .wall_ms(1)
121 .stderr(b"command not found".to_vec())
122 .build();
123
124 runner.set_fallback(fallback_result);
125 println!(" Set fallback: exit 127, 1ms, stderr='command not found'");
126
127 let another_unknown = CommandSpec {
128 name: "another-unknown".to_string(),
129 argv: vec!["another".to_string(), "unknown".to_string()],
130 cwd: None,
131 env: vec![],
132 timeout: None,
133 output_cap_bytes: 1024,
134 };
135
136 match runner.run(&another_unknown) {
137 Ok(result) => {
138 println!(" Another unknown:");
139 println!(" Exit code: {}", result.exit_code);
140 println!(" Stderr: {:?}", String::from_utf8_lossy(&result.stderr));
141 }
142 Err(e) => println!(" Error: {}", e),
143 }
144
145 println!("\n7. Configuring with CPU and memory metrics:");
146 let detailed_result = MockProcessBuilder::new()
147 .exit_code(0)
148 .wall_ms(250)
149 .cpu_ms(200)
150 .max_rss_kb(4096)
151 .stdout(b"detailed output".to_vec())
152 .build();
153
154 runner.set_result(&["detailed"], detailed_result);
155
156 let detailed_spec = CommandSpec {
157 name: "detailed".to_string(),
158 argv: vec!["detailed".to_string()],
159 cwd: None,
160 env: vec![],
161 timeout: None,
162 output_cap_bytes: 1024,
163 };
164
165 if let Ok(result) = runner.run(&detailed_spec) {
166 println!(" Detailed result:");
167 println!(" Wall time: {} ms", result.wall_ms);
168 println!(" CPU time: {:?} ms", result.cpu_ms);
169 println!(" Max RSS: {:?} KB", result.max_rss_kb);
170 }
171
172 println!("\n=== Example complete ===");
173}Sourcepub fn history(&self) -> Vec<CommandSpec>
pub fn history(&self) -> Vec<CommandSpec>
Get the history of executed commands.
Commands are recorded in the order they were run.
Sourcepub fn call_count(&self) -> usize
pub fn call_count(&self) -> usize
Get the number of times any command has been run.
Sourcepub fn nth_call(&self, n: usize) -> Option<CommandSpec>
pub fn nth_call(&self, n: usize) -> Option<CommandSpec>
Get the nth command that was run (0-indexed).
Trait Implementations§
Source§impl Clone for FakeProcessRunner
impl Clone for FakeProcessRunner
Source§fn clone(&self) -> FakeProcessRunner
fn clone(&self) -> FakeProcessRunner
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for FakeProcessRunner
impl Debug for FakeProcessRunner
Source§impl Default for FakeProcessRunner
impl Default for FakeProcessRunner
Source§fn default() -> FakeProcessRunner
fn default() -> FakeProcessRunner
Source§impl ProcessRunner for FakeProcessRunner
impl ProcessRunner for FakeProcessRunner
fn run(&self, spec: &CommandSpec) -> Result<RunResult, AdapterError>
Auto Trait Implementations§
impl Freeze for FakeProcessRunner
impl RefUnwindSafe for FakeProcessRunner
impl Send for FakeProcessRunner
impl Sync for FakeProcessRunner
impl Unpin for FakeProcessRunner
impl UnsafeUnpin for FakeProcessRunner
impl UnwindSafe for FakeProcessRunner
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more