mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
more ergonomic testing
This commit is contained in:
parent
aafd20d565
commit
5e764ecf6e
5 changed files with 97 additions and 34 deletions
|
@ -27,6 +27,7 @@ static FIXTURES_DIR: &'static str = "tests/fixtures";
|
|||
static ALREADY_RUN: &'static str = " you have already run this UCommand, if you want to run \
|
||||
another command in the same test, use TestSet::new instead of \
|
||||
testing();";
|
||||
static MULTIPLE_STDIN_MEANINGLESS: &'static str = "Ucommand is designed around a typical use case of: provide args and input stream -> spawn process -> block until completion -> return output streams. For verifying that a particular section of the input stream is what causes a particular behavior, use the Command type directly.";
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_empty_stderr(
|
||||
|
@ -53,6 +54,44 @@ pub struct CmdResult {
|
|||
pub stderr: String,
|
||||
}
|
||||
|
||||
impl CmdResult {
|
||||
pub fn success(&self) -> Box<&CmdResult> {
|
||||
assert!(self.success);
|
||||
Box::new(self)
|
||||
}
|
||||
pub fn failure(&self) -> Box<&CmdResult> {
|
||||
assert!(!self.success);
|
||||
Box::new(self)
|
||||
}
|
||||
pub fn no_stderr(&self) -> Box<&CmdResult> {
|
||||
assert!(self.stderr.len() == 0);
|
||||
Box::new(self)
|
||||
}
|
||||
pub fn no_stdout(&self) -> Box<&CmdResult> {
|
||||
assert!(self.stdout.len() == 0);
|
||||
Box::new(self)
|
||||
}
|
||||
pub fn stdout_is<T: AsRef<str>>(&self, msg: T) -> Box<&CmdResult> {
|
||||
assert!(self.stdout.trim_right() == String::from(msg.as_ref()).trim_right());
|
||||
Box::new(self)
|
||||
}
|
||||
pub fn stderr_is<T: AsRef<str>>(&self, msg: T) -> Box<&CmdResult> {
|
||||
assert!(self.stderr.trim_right() == String::from(msg.as_ref()).trim_right());
|
||||
Box::new(self)
|
||||
}
|
||||
pub fn stdout_only<T: AsRef<str>>(&self, msg: T) -> Box<&CmdResult> {
|
||||
self.stdout_is(msg).no_stderr()
|
||||
}
|
||||
pub fn stderr_only<T: AsRef<str>>(&self, msg: T) -> Box<&CmdResult> {
|
||||
self.stderr_is(msg).no_stdout()
|
||||
}
|
||||
pub fn fails_silently(&self) -> Box<&CmdResult> {
|
||||
assert!(!self.success);
|
||||
assert!(self.stderr.len() == 0);
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn log_info<T: AsRef<str>, U: AsRef<str>>(msg: T, par: U) {
|
||||
println!("{}: {}", msg.as_ref(), par.as_ref());
|
||||
}
|
||||
|
@ -272,6 +311,7 @@ pub struct UCommand {
|
|||
comm_string: String,
|
||||
tmpd: Option<Rc<TempDir>>,
|
||||
has_run: bool,
|
||||
stdin: Option<Vec<u8>>
|
||||
}
|
||||
impl UCommand {
|
||||
pub fn new<T: AsRef<OsStr>, U: AsRef<OsStr>>(arg: T, curdir: U, env_clear: bool) -> UCommand {
|
||||
|
@ -299,6 +339,7 @@ impl UCommand {
|
|||
cmd
|
||||
},
|
||||
comm_string: String::from(arg.as_ref().to_str().unwrap()),
|
||||
stdin: None
|
||||
}
|
||||
}
|
||||
pub fn new_from_tmp<T: AsRef<OsStr>>(arg: T, tmpd: Rc<TempDir>, env_clear: bool) -> UCommand {
|
||||
|
@ -319,7 +360,7 @@ impl UCommand {
|
|||
|
||||
pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> Box<&mut UCommand> {
|
||||
if self.has_run {
|
||||
panic!(ALREADY_RUN);
|
||||
panic!(MULTIPLE_STDIN_MEANINGLESS);
|
||||
}
|
||||
for s in args {
|
||||
self.comm_string.push_str(" ");
|
||||
|
@ -339,37 +380,59 @@ impl UCommand {
|
|||
}
|
||||
|
||||
pub fn run(&mut self) -> CmdResult {
|
||||
if self.has_run {
|
||||
panic!(ALREADY_RUN);
|
||||
}
|
||||
self.has_run = true;
|
||||
log_info("run", &self.comm_string);
|
||||
let prog = self.raw.output().unwrap();
|
||||
let prog = match self.stdin {
|
||||
Some(ref input) => {
|
||||
let mut result = self.raw
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
|
||||
result.stdin
|
||||
.take()
|
||||
.unwrap_or_else(
|
||||
|| panic!(
|
||||
"Could not take child process stdin"))
|
||||
.write_all(&input)
|
||||
.unwrap_or_else(|e| panic!("{}", e));
|
||||
|
||||
result.wait_with_output().unwrap()
|
||||
}
|
||||
None => {
|
||||
self.raw.output().unwrap()
|
||||
}
|
||||
};
|
||||
CmdResult {
|
||||
success: prog.status.success(),
|
||||
stdout: from_utf8(&prog.stdout).unwrap().to_string(),
|
||||
stderr: from_utf8(&prog.stderr).unwrap().to_string(),
|
||||
}
|
||||
}
|
||||
pub fn run_piped_stdin<T: AsRef<[u8]>>(&mut self, input: T) -> CmdResult {
|
||||
self.has_run = true;
|
||||
log_info("run_piped_stdin", &self.comm_string);
|
||||
let mut result = self.raw
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
|
||||
result.stdin
|
||||
.take()
|
||||
.unwrap_or_else(|| panic!("Could not take child process stdin"))
|
||||
.write_all(input.as_ref())
|
||||
.unwrap_or_else(|e| panic!("{}", e));
|
||||
|
||||
let prog = result.wait_with_output().unwrap();
|
||||
CmdResult {
|
||||
success: prog.status.success(),
|
||||
stdout: from_utf8(&prog.stdout).unwrap().to_string(),
|
||||
stderr: from_utf8(&prog.stderr).unwrap().to_string(),
|
||||
pub fn pipe_in<T: Into<Vec<u8>>>(&mut self, input: T) -> Box<&mut UCommand> {
|
||||
if self.stdin.is_some() {
|
||||
panic!(MULTIPLE_STDIN_MEANINGLESS);
|
||||
}
|
||||
self.stdin = Some(input.into());
|
||||
Box::new(self)
|
||||
}
|
||||
pub fn run_piped_stdin<T: Into<Vec<u8>>>(&mut self, input: T) -> CmdResult {
|
||||
self.pipe_in(input).run()
|
||||
}
|
||||
pub fn succeeds(&mut self) -> CmdResult {
|
||||
let cmd_result = self.run();
|
||||
cmd_result.success();
|
||||
cmd_result
|
||||
}
|
||||
pub fn fails(&mut self) -> CmdResult {
|
||||
let cmd_result = self.run();
|
||||
cmd_result.failure();
|
||||
cmd_result
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ fn test_symlink_interactive() {
|
|||
|
||||
let result1 = ts.util_cmd()
|
||||
.args(&["-i", "-s", file, link])
|
||||
.run_piped_stdin(b"n");
|
||||
.run_piped_stdin("n");
|
||||
|
||||
assert_empty_stderr!(result1);
|
||||
assert!(result1.success);
|
||||
|
@ -136,7 +136,7 @@ fn test_symlink_interactive() {
|
|||
|
||||
let result2 = ts.util_cmd()
|
||||
.args(&["-i", "-s", file, link])
|
||||
.run_piped_stdin(b"Yesh");
|
||||
.run_piped_stdin("Yesh");
|
||||
|
||||
assert_empty_stderr!(result2);
|
||||
assert!(result2.success);
|
||||
|
|
|
@ -131,7 +131,7 @@ fn test_mv_interactive() {
|
|||
at.touch(file_b);
|
||||
|
||||
|
||||
let result1 = ts.util_cmd().arg("-i").arg(file_a).arg(file_b).run_piped_stdin(b"n");
|
||||
let result1 = ts.util_cmd().arg("-i").arg(file_a).arg(file_b).run_piped_stdin("n");
|
||||
|
||||
assert_empty_stderr!(result1);
|
||||
assert!(result1.success);
|
||||
|
@ -140,7 +140,7 @@ fn test_mv_interactive() {
|
|||
assert!(at.file_exists(file_b));
|
||||
|
||||
|
||||
let result2 = ts.util_cmd().arg("-i").arg(file_a).arg(file_b).run_piped_stdin(b"Yesh");
|
||||
let result2 = ts.util_cmd().arg("-i").arg(file_a).arg(file_b).run_piped_stdin("Yesh");
|
||||
|
||||
assert_empty_stderr!(result2);
|
||||
assert!(result2.success);
|
||||
|
|
|
@ -51,7 +51,7 @@ fn test_rm_interactive() {
|
|||
.arg("-i")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.run_piped_stdin(b"n");
|
||||
.run_piped_stdin("n");
|
||||
|
||||
assert!(result1.success);
|
||||
|
||||
|
@ -62,7 +62,7 @@ fn test_rm_interactive() {
|
|||
.arg("-i")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.run_piped_stdin(b"Yesh");
|
||||
.run_piped_stdin("Yesh");
|
||||
|
||||
assert!(result2.success);
|
||||
|
||||
|
|
|
@ -10,14 +10,14 @@ static UTIL_NAME: &'static str = "tr";
|
|||
#[test]
|
||||
fn test_toupper() {
|
||||
let (_, mut ucmd) = testing(UTIL_NAME);
|
||||
let result = ucmd.args(&["a-z", "A-Z"]).run_piped_stdin(b"!abcd!");
|
||||
let result = ucmd.args(&["a-z", "A-Z"]).run_piped_stdin("!abcd!");
|
||||
assert_eq!(result.stdout, "!ABCD!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_small_set2() {
|
||||
let (_, mut ucmd) = testing(UTIL_NAME);
|
||||
let result = ucmd.args(&["0-9", "X"]).run_piped_stdin(b"@0123456789");
|
||||
let result = ucmd.args(&["0-9", "X"]).run_piped_stdin("@0123456789");
|
||||
assert_eq!(result.stdout, "@XXXXXXXXXX");
|
||||
}
|
||||
|
||||
|
@ -32,13 +32,13 @@ fn test_unicode() {
|
|||
#[test]
|
||||
fn test_delete() {
|
||||
let (_, mut ucmd) = testing(UTIL_NAME);
|
||||
let result = ucmd.args(&["-d", "a-z"]).run_piped_stdin(b"aBcD");
|
||||
let result = ucmd.args(&["-d", "a-z"]).run_piped_stdin("aBcD");
|
||||
assert_eq!(result.stdout, "BD");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_complement() {
|
||||
let (_, mut ucmd) = testing(UTIL_NAME);
|
||||
let result = ucmd.args(&["-d", "-c", "a-z"]).run_piped_stdin(b"aBcD");
|
||||
let result = ucmd.args(&["-d", "-c", "a-z"]).run_piped_stdin("aBcD");
|
||||
assert_eq!(result.stdout, "ac");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue