pub struct RecordingRunner<R: ProcessRunner = ScriptedRunner> { /* private fields */ }Expand description
Wraps another ProcessRunner, recording every Invocation before
delegating, so tests can assert exactly what was run.
Implementations§
Source§impl<R: ProcessRunner> RecordingRunner<R>
impl<R: ProcessRunner> RecordingRunner<R>
Sourcepub fn calls(&self) -> Vec<Invocation>
pub fn calls(&self) -> Vec<Invocation>
A snapshot of every recorded invocation, in order.
§Panics
Panics if the recorder’s internal mutex is poisoned — which happens only if a prior recording panicked while holding it (a crate bug), never from any caller input.
Sourcepub fn only_call(&self) -> Invocation
pub fn only_call(&self) -> Invocation
Trait Implementations§
Source§impl<R: ProcessRunner> Debug for RecordingRunner<R>
impl<R: ProcessRunner> Debug for RecordingRunner<R>
Source§impl<R: ProcessRunner> ProcessRunner for RecordingRunner<R>
impl<R: ProcessRunner> ProcessRunner for RecordingRunner<R>
Source§fn output_string<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn output_string<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run
command to completion, capturing stdout/stderr and the exit code.
A non-zero exit is reported in the result, not raised.Source§fn start<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<RunningProcess>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn start<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<RunningProcess>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Start
command and return a live RunningProcess for streaming,
readiness probes, or incremental consumption. Read moreSource§fn output_bytes<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<Vec<u8>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn output_bytes<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<Vec<u8>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run
command to completion, capturing stdout as raw bytes (output_string
captures it as lossy-UTF-8 text); stderr is still text. For binary tools
— git cat-file, tar -c, an image transcoder — whose stdout is not
UTF-8. Read moreAuto Trait Implementations§
impl<R = ScriptedRunner> !Freeze for RecordingRunner<R>
impl<R> RefUnwindSafe for RecordingRunner<R>where
R: RefUnwindSafe,
impl<R> Send for RecordingRunner<R>
impl<R> Sync for RecordingRunner<R>
impl<R> Unpin for RecordingRunner<R>where
R: Unpin,
impl<R> UnsafeUnpin for RecordingRunner<R>where
R: UnsafeUnpin,
impl<R> UnwindSafe for RecordingRunner<R>where
R: UnwindSafe,
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
Mutably borrows from an owned value. Read more
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> ProcessRunnerExt for Twhere
T: ProcessRunner + ?Sized,
impl<T> ProcessRunnerExt for Twhere
T: ProcessRunner + ?Sized,
Source§fn run<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn run<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run, require an accepted exit, and return trimmed stdout. Accepted is
0 by default, widened by Command::ok_codes;
any other code is Error::Exit.Source§fn run_unit<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn run_unit<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run for the side effect: require an accepted exit (
0, or any code in
Command::ok_codes), discard the output.Source§fn exit_code<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<i32>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn exit_code<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<i32>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run and return just the exit code. A run that produced no code surfaces as
an error — a timeout as
Error::Timeout, a
signal-kill as Error::Signalled — rather than a
synthetic sentinel, mirroring
ensure_success.Source§fn probe<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn probe<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run a predicate command and read its exit code as a boolean: exit
0 →
Ok(true), exit 1 → Ok(false), anything else → Err (other code as
Error::Exit, timeout as
Error::Timeout, signal-kill as
Error::Signalled). For
commands whose exit code is the answer — git diff --quiet, grep -q, …Source§fn checked<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn checked<'life0, 'life1, 'async_trait>(
&'life0 self,
command: &'life1 Command,
) -> Pin<Box<dyn Future<Output = Result<ProcessResult<String>>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Run, require an accepted exit (
0 by default, widened by
Command::ok_codes), and return the full
captured result (untrimmed stdout). The building block for the
parse/try_parse helpers — use it when you need the whole
ProcessResult after success-checking, rather than just trimmed stdout
(run) or the raw result (output_string). Read moreSource§fn parse<'life0, 'life1, 'async_trait, T, F>(
&'life0 self,
command: &'life1 Command,
parse: F,
) -> Pin<Box<dyn Future<Output = Result<T>> + Send + 'async_trait>>
fn parse<'life0, 'life1, 'async_trait, T, F>( &'life0 self, command: &'life1 Command, parse: F, ) -> Pin<Box<dyn Future<Output = Result<T>> + Send + 'async_trait>>
Run (requiring an accepted exit) and feed the captured stdout to an
infallible
parse closure — the shape of struct-returning CLI
commands (git/jj --format output). Built on checked,
but unlike it, fails loud on a bounded-buffer truncation so the
parser never silently sees a clipped tail; returns the parsed value. Read moreSource§fn try_parse<'life0, 'life1, 'async_trait, T, F>(
&'life0 self,
command: &'life1 Command,
parse: F,
) -> Pin<Box<dyn Future<Output = Result<T>> + Send + 'async_trait>>
fn try_parse<'life0, 'life1, 'async_trait, T, F>( &'life0 self, command: &'life1 Command, parse: F, ) -> Pin<Box<dyn Future<Output = Result<T>> + Send + 'async_trait>>
Run (requiring an accepted exit) and feed the captured stdout to a
fallible
parse closure — the shape of JSON deserialization, where a
parse failure becomes Error::Parse (or whatever
error the closure returns). Like parse it is built on
checked, fails loud on truncation, and — being generic
over F — cannot be dispatched through a dyn ProcessRunnerExt object
(the trait isn’t object-safe), though it is callable on a
&dyn ProcessRunner. The Command::try_parse /
CliClient::try_parse wrappers are the
ergonomic path.Source§fn first_line<'life0, 'life1, 'async_trait, F>(
&'life0 self,
command: &'life1 Command,
predicate: F,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>
fn first_line<'life0, 'life1, 'async_trait, F>( &'life0 self, command: &'life1 Command, predicate: F, ) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>
Stream
command’s stdout and return the first line matching predicate
(None if the stream ends first), bounded by the command’s
timeout: a Some deadline surfaces as
Error::Timeout and tears the process down. On an
own-group runner (JobRunner, the default) that teardown covers the
whole tree; on a shared ProcessGroup it reaches
the run’s direct child by pid — a forking child’s grandchildren (and, on the
Linux cgroup mechanism, a direct child that catches the graceful signal and
closes stdout but keeps running) may outlive the probe until the group is
dropped. Bound such a run with a whole-chain owner instead. Read more