From 5e764ecf6e745fc1bcf390c77e69a4e9aaf8e8bc Mon Sep 17 00:00:00 2001 From: Nathan Ross Date: Wed, 17 Feb 2016 00:03:52 -0500 Subject: [PATCH] more ergonomic testing --- tests/common/util.rs | 111 +++++++++++++++++++++++++++++++++---------- tests/ln.rs | 4 +- tests/mv.rs | 4 +- tests/rm.rs | 4 +- tests/tr.rs | 8 ++-- 5 files changed, 97 insertions(+), 34 deletions(-) diff --git a/tests/common/util.rs b/tests/common/util.rs index cf84a1abf..8225f921a 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -27,7 +27,8 @@ 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( ($cond:expr) => ( @@ -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>(&self, msg: T) -> Box<&CmdResult> { + assert!(self.stdout.trim_right() == String::from(msg.as_ref()).trim_right()); + Box::new(self) + } + pub fn stderr_is>(&self, msg: T) -> Box<&CmdResult> { + assert!(self.stderr.trim_right() == String::from(msg.as_ref()).trim_right()); + Box::new(self) + } + pub fn stdout_only>(&self, msg: T) -> Box<&CmdResult> { + self.stdout_is(msg).no_stderr() + } + pub fn stderr_only>(&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, U: AsRef>(msg: T, par: U) { println!("{}: {}", msg.as_ref(), par.as_ref()); } @@ -272,6 +311,7 @@ pub struct UCommand { comm_string: String, tmpd: Option>, has_run: bool, + stdin: Option> } impl UCommand { pub fn new, U: AsRef>(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>(arg: T, tmpd: Rc, env_clear: bool) -> UCommand { @@ -319,7 +360,7 @@ impl UCommand { pub fn args>(&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>(&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>>(&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>>(&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 } } diff --git a/tests/ln.rs b/tests/ln.rs index 761571da1..826ac0f29 100644 --- a/tests/ln.rs +++ b/tests/ln.rs @@ -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); diff --git a/tests/mv.rs b/tests/mv.rs index db39eed23..d07b9d444 100644 --- a/tests/mv.rs +++ b/tests/mv.rs @@ -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); diff --git a/tests/rm.rs b/tests/rm.rs index 91dba21ff..2a5cd353e 100644 --- a/tests/rm.rs +++ b/tests/rm.rs @@ -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); diff --git a/tests/tr.rs b/tests/tr.rs index 869a3c51c..f383aaa4a 100644 --- a/tests/tr.rs +++ b/tests/tr.rs @@ -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"); }