Implement process hamcrest matcher
authorCarl Lerche <me@carllerche.com>
Wed, 2 Apr 2014 23:34:19 +0000 (16:34 -0700)
committerCarl Lerche <me@carllerche.com>
Wed, 2 Apr 2014 23:34:19 +0000 (16:34 -0700)
src/cargo/util/process_builder.rs
tests/support.rs
tests/test_cargo_compile.rs

index 381b4d5c6525b026b3deb6138a1798f0db389fab..508065ab3e183f028a2cd7c65491b331ffcd9331 100644 (file)
@@ -4,6 +4,7 @@ use std::io::process::{Process,ProcessConfig,ProcessOutput};
 use ToCargoError;
 use CargoResult;
 
+#[deriving(Clone,Eq)]
 pub struct ProcessBuilder {
   program: ~str,
   args: ~[~str],
@@ -20,8 +21,9 @@ impl ProcessBuilder {
     self
   }
 
-  pub fn extra_path(mut self, path: &str) -> ProcessBuilder {
-    self.path.push(path.to_owned());
+  pub fn extra_path(mut self, path: Path) -> ProcessBuilder {
+    // For now, just convert to a string, but we should do something better
+    self.path.push(format!("{}", path.display()));
     self
   }
 
@@ -30,7 +32,7 @@ impl ProcessBuilder {
     self
   }
 
-  pub fn exec_with_output(self) -> CargoResult<ProcessOutput> {
+  pub fn exec_with_output(&self) -> CargoResult<ProcessOutput> {
     let mut config = ProcessConfig::new();
 
     println!("cwd: {}", self.cwd.display());
index dfe3497741a318dff65d9c4b93a2d8cc2b8475fc..79ea19f3ae77310d87936076b255f1a2fa5c8e40 100644 (file)
@@ -1,7 +1,10 @@
 // use std::io::fs::{mkdir_recursive,rmdir_recursive};
 use std::io::fs;
+use std::io::process::{ProcessOutput,ProcessExit};
 use std::os;
 use std::path::{Path};
+use std::str;
+use ham = hamcrest;
 use cargo::util::{process,ProcessBuilder};
 
 static CARGO_INTEGRATION_TEST_DIR : &'static str = "cargo-integration-tests";
@@ -136,10 +139,10 @@ impl<T, E> ErrMsg<T> for Result<T, E> {
 }
 
 // Path to cargo executables
-pub fn cargo_dir() -> ~str {
-  os::getenv("CARGO_BIN_PATH").unwrap_or_else(|| {
-    fail!("CARGO_BIN_PATH wasn't set. Cannot continue running test")
-  })
+pub fn cargo_dir() -> Path {
+  os::getenv("CARGO_BIN_PATH")
+    .map(|s| Path::new(s))
+    .unwrap_or_else(|| fail!("CARGO_BIN_PATH wasn't set. Cannot continue running test"))
 }
 
 /*
@@ -147,3 +150,73 @@ pub fn cargo_dir() -> ~str {
  * ===== Matchers =====
  *
  */
+
+#[deriving(Clone,Eq)]
+struct Execs {
+  expect_stdout: Option<~str>,
+  expect_stdin: Option<~str>,
+  expect_exit_code: Option<int>
+}
+
+impl Execs {
+
+  pub fn with_stdout(mut self, expected: &str) -> Execs {
+    self.expect_stdout = Some(expected.to_owned());
+    self
+  }
+
+  fn match_output(&self, actual: &ProcessOutput) -> ham::MatchResult {
+    self.match_status(actual.status)
+      .and(self.match_stdout(actual.output))
+  }
+
+  fn match_status(&self, actual: ProcessExit) -> ham::MatchResult {
+    match self.expect_exit_code {
+      None => ham::success(),
+      Some(code) => {
+        ham::expect(
+          actual.matches_exit_status(code),
+          format!("exited with {}", actual))
+      }
+    }
+  }
+
+  fn match_stdout(&self, actual: &[u8]) -> ham::MatchResult {
+    match self.expect_stdout.as_ref().map(|s| s.as_slice()) {
+      None => ham::success(),
+      Some(out) => {
+        match str::from_utf8(actual) {
+          None => Err(~"stdout was not utf8 encoded"),
+          Some(actual) => {
+            ham::expect(actual == out, format!("stdout was `{}`", actual))
+          }
+        }
+      }
+    }
+  }
+}
+
+impl ham::SelfDescribing for Execs {
+  fn describe(&self) -> ~str {
+    ~"execs"
+  }
+}
+
+impl ham::Matcher<ProcessBuilder> for Execs {
+  fn matches(&self, process: &ProcessBuilder) -> ham::MatchResult {
+    let res = process.exec_with_output();
+
+    match res {
+      Ok(out) => self.match_output(&out),
+      Err(_) => Err(~"could not exec process")
+    }
+  }
+}
+
+pub fn execs() -> Execs {
+  Execs {
+    expect_stdout: None,
+    expect_stdin: None,
+    expect_exit_code: None
+  }
+}
index c4769bd323a937b9cf9ed5860db962ead62ccac3..6f25ea270c82c9cbe9cf8e981c4485f112736bc5 100644 (file)
@@ -1,5 +1,5 @@
 use std;
-use support::project;
+use support::{project,execs};
 use hamcrest::{assert_that,existing_file};
 use cargo;
 
@@ -39,12 +39,9 @@ test!(cargo_compile_with_explicit_manifest_path {
 
     assert_that(&p.root().join("target/foo"), existing_file());
 
-    let o = cargo::util::process("foo")
-      .extra_path(format!("{}", p.root().join("target").display()))
-      .exec_with_output()
-      .unwrap();
-
-    assert_eq!(std::str::from_utf8(o.output).unwrap(), "i am foo\n");
+    assert_that(
+      &cargo::util::process("foo").extra_path(p.root().join("target")),
+      execs().with_stdout("i am foo\n"));
 })
 
 // test!(compiling_project_with_invalid_manifest)