nushell/crates/nu-test-support/src/playground/director.rs
Stefan Holderbach e5d38dcff6
Address lints from clippy for beta/nightly (#5709)
* Fix clippy lints in tests

* Replace `format!` in `.push_str()` with `write!`

Stylistically that might be a bit rough but elides an allocation.

Fallibility of allocation is more explicit, but ignored with `let _ =`
like in the clippy example:

https://rust-lang.github.io/rust-clippy/master/index.html#format_push_string

* Remove unused lifetime

* Fix macro crate relative import

* Derive `Eq` for `PartialEq` with `Eq` members

https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

* Remove unnnecessary `.to_string()` for Cow<str>

* Remove `.to_string()` for `tendril::Tendril`

Implements `Deref<Target = str>`
2022-06-04 18:47:36 +12:00

163 lines
4.7 KiB
Rust

use super::nu_process::*;
use super::EnvironmentVariable;
use std::ffi::OsString;
use std::fmt;
use std::fmt::Write;
#[derive(Default, Debug)]
pub struct Director {
pub cwd: Option<OsString>,
pub environment_vars: Vec<EnvironmentVariable>,
pub config: Option<OsString>,
pub pipeline: Option<Vec<String>>,
pub executable: Option<NuProcess>,
}
impl Director {
pub fn cococo(&self, arg: &str) -> Self {
let mut process = NuProcess {
environment_vars: self.environment_vars.clone(),
..Default::default()
};
process.args(&["--testbin", "cococo", arg]);
Director {
config: self.config.clone(),
executable: Some(process),
environment_vars: self.environment_vars.clone(),
..Default::default()
}
}
pub fn and_then(&mut self, commands: &str) -> &mut Self {
let commands = commands.to_string();
if let Some(ref mut pipeline) = self.pipeline {
pipeline.push(commands);
} else {
self.pipeline = Some(vec![commands]);
}
self
}
pub fn pipeline(&self, commands: &str) -> Self {
let mut director = Director {
pipeline: if commands.is_empty() {
None
} else {
Some(vec![commands.to_string()])
},
..Default::default()
};
let mut process = NuProcess {
environment_vars: self.environment_vars.clone(),
..Default::default()
};
if let Some(working_directory) = &self.cwd {
process.cwd(working_directory);
}
process.arg("--skip-plugins");
process.arg("--no-history");
if let Some(config_file) = self.config.as_ref() {
process.args(&[
"--config-file",
config_file.to_str().expect("failed to convert."),
]);
}
process.arg("--perf");
director.executable = Some(process);
director
}
pub fn executable(&self) -> Option<&NuProcess> {
if let Some(binary) = &self.executable {
Some(binary)
} else {
None
}
}
}
impl Executable for Director {
fn execute(&mut self) -> NuResult {
use std::process::Stdio;
match self.executable() {
Some(binary) => {
let mut commands = String::new();
if let Some(pipelines) = &self.pipeline {
for pipeline in pipelines {
if !commands.is_empty() {
commands.push_str("| ");
}
let _ = writeln!(commands, "{}", pipeline);
}
}
let process = match binary
.construct()
.stdout(Stdio::piped())
// .stdin(Stdio::piped())
.stderr(Stdio::piped())
.arg(format!("-c '{}'", commands))
.spawn()
{
Ok(child) => child,
Err(why) => panic!("Can't run test {}", why),
};
process
.wait_with_output()
.map_err(|_| {
let reason = format!(
"could not execute process {} ({})",
binary, "No execution took place"
);
NuError {
desc: reason,
exit: None,
output: None,
}
})
.and_then(|process| {
let out =
Outcome::new(&read_std(&process.stdout), &read_std(&process.stderr));
match process.status.success() {
true => Ok(out),
false => Err(NuError {
desc: String::new(),
exit: Some(process.status),
output: Some(out),
}),
}
})
}
None => Err(NuError {
desc: String::from("err"),
exit: None,
output: None,
}),
}
}
}
impl fmt::Display for Director {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "director")
}
}
fn read_std(std: &[u8]) -> Vec<u8> {
let out = String::from_utf8_lossy(std);
let out = out.lines().collect::<Vec<_>>().join("\n");
let out = out.replace("\r\n", "");
out.replace('\n', "").into_bytes()
}