run-make-support: introduce macro for common methods to avoid repetition
Add a helper macro for adding common methods to command wrappers. Common methods include helpers that delegate to `Command` and running methods. - `arg` and `args` (delegates to `Command`) - `env`, `env_remove` and `env_clear` (delegates to `Command`) - `output`, `run` and `run_fail` This helps to avoid needing to copy-pasta / reimplement these common methods on a new command wrapper, which hopefully reduces the friction for run-make test writers wanting to introduce new command wrappers.
This commit is contained in:
parent
e994534242
commit
b22099d4e0
@ -129,3 +129,127 @@ pub fn set_host_rpath(cmd: &mut Command) {
|
|||||||
env::join_paths(paths.iter()).unwrap()
|
env::join_paths(paths.iter()).unwrap()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
|
||||||
|
/// containing a `cmd: Command` field. The provided helpers are:
|
||||||
|
///
|
||||||
|
/// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
|
||||||
|
/// to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
|
||||||
|
/// new specific helper methods over relying on these generic argument providers.
|
||||||
|
/// 2. Environment manipulation methods: `env`, `env_remove` and `env_clear`: these delegate to
|
||||||
|
/// methods of the same name on [`Command`].
|
||||||
|
/// 3. Output and execution: `output`, `run` and `run_fail` are provided. `output` waits for the
|
||||||
|
/// command to finish running and returns the process's [`Output`]. `run` and `run_fail` are
|
||||||
|
/// higher-level convenience methods which waits for the command to finish running and assert
|
||||||
|
/// that the command successfully ran or failed as expected. Prefer `run` and `run_fail` when
|
||||||
|
/// possible.
|
||||||
|
///
|
||||||
|
/// Example usage:
|
||||||
|
///
|
||||||
|
/// ```ignore (illustrative)
|
||||||
|
/// struct CommandWrapper { cmd: Command }
|
||||||
|
///
|
||||||
|
/// crate::impl_common_helpers!(CommandWrapper);
|
||||||
|
///
|
||||||
|
/// impl CommandWrapper {
|
||||||
|
/// // ... additional specific helper methods
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`Command`]: ::std::process::Command
|
||||||
|
/// [`Output`]: ::std::process::Output
|
||||||
|
macro_rules! impl_common_helpers {
|
||||||
|
($wrapper: ident) => {
|
||||||
|
impl $wrapper {
|
||||||
|
/// Specify an environment variable.
|
||||||
|
pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Self
|
||||||
|
where
|
||||||
|
K: AsRef<::std::ffi::OsStr>,
|
||||||
|
V: AsRef<::std::ffi::OsStr>,
|
||||||
|
{
|
||||||
|
self.cmd.env(key, value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove an environmental variable.
|
||||||
|
pub fn env_remove<K>(&mut self, key: K) -> &mut Self
|
||||||
|
where
|
||||||
|
K: AsRef<::std::ffi::OsStr>,
|
||||||
|
{
|
||||||
|
self.cmd.env_remove(key);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear all environmental variables.
|
||||||
|
pub fn env_var(&mut self) -> &mut Self {
|
||||||
|
self.cmd.env_clear();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic command argument provider. Prefer specific helper methods if possible.
|
||||||
|
/// Note that for some executables, arguments might be platform specific. For C/C++
|
||||||
|
/// compilers, arguments might be platform *and* compiler specific.
|
||||||
|
pub fn arg<S>(&mut self, arg: S) -> &mut Self
|
||||||
|
where
|
||||||
|
S: AsRef<::std::ffi::OsStr>,
|
||||||
|
{
|
||||||
|
self.cmd.arg(arg);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic command arguments provider. Prefer specific helper methods if possible.
|
||||||
|
/// Note that for some executables, arguments might be platform specific. For C/C++
|
||||||
|
/// compilers, arguments might be platform *and* compiler specific.
|
||||||
|
pub fn args<S>(&mut self, args: &[S]) -> &mut Self
|
||||||
|
where
|
||||||
|
S: AsRef<::std::ffi::OsStr>,
|
||||||
|
{
|
||||||
|
self.cmd.args(args);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inspect what the underlying [`Command`][::std::process::Command] is up to the
|
||||||
|
/// current construction.
|
||||||
|
pub fn inspect<I>(&mut self, inspector: I) -> &mut Self
|
||||||
|
where
|
||||||
|
I: FnOnce(&::std::process::Command),
|
||||||
|
{
|
||||||
|
inspector(&self.cmd);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the [`Output`][::std::process::Output] of the finished process.
|
||||||
|
pub fn output(&mut self) -> ::std::process::Output {
|
||||||
|
self.cmd.output().expect("failed to get output of finished process")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the constructed command and assert that it is successfully run.
|
||||||
|
#[track_caller]
|
||||||
|
pub fn run(&mut self) -> ::std::process::Output {
|
||||||
|
let caller_location = ::std::panic::Location::caller();
|
||||||
|
let caller_line_number = caller_location.line();
|
||||||
|
|
||||||
|
let output = self.cmd.output().unwrap();
|
||||||
|
if !output.status.success() {
|
||||||
|
handle_failed_output(&self.cmd, output, caller_line_number);
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the constructed command and assert that it does not successfully run.
|
||||||
|
#[track_caller]
|
||||||
|
pub fn run_fail(&mut self) -> ::std::process::Output {
|
||||||
|
let caller_location = ::std::panic::Location::caller();
|
||||||
|
let caller_line_number = caller_location.line();
|
||||||
|
|
||||||
|
let output = self.cmd.output().unwrap();
|
||||||
|
if output.status.success() {
|
||||||
|
handle_failed_output(&self.cmd, output, caller_line_number);
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use impl_common_helpers;
|
||||||
|
Loading…
Reference in New Issue
Block a user