Add a helper method to show stdout/err in tests
authorAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 15 Mar 2018 07:40:26 +0000 (10:40 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 15 Mar 2018 07:52:42 +0000 (10:52 +0300)
ARCHITECTURE.md
tests/testsuite/cargotest/support/mod.rs

index 11e3e121872e9df27460ca62d8b5b859fef976ae..68ce7e6cf82bee08dddce5b488b71982718b6c53 100644 (file)
@@ -7,13 +7,10 @@ interested in the inner workings of Cargo.
 
 ## Subcommands
 
-Cargo is organized as a set of subcommands. All subcommands live in
-`src/bin` directory. However, only `src/bin/cargo.rs` file produces an
-executable, other files inside the `bin` directory are submodules. See
-`src/bin/cargo.rs` for how these subcommands get wired up with the
-main executable.
+Cargo is organized as a set of `clap` subcommands. All subcommands live in
+`src/bin/commands` directory. `src/bin/cargo.rs` is the entry point.
 
-A typical subcommand, such as `src/bin/build.rs`, parses command line
+A typical subcommand, such as `src/bin/commands/build.rs`, parses command line
 options, reads the configuration files, discovers the Cargo project in
 the current directory and delegates the actual implementation to one
 of the functions in `src/cargo/ops/mod.rs`. This short file is a good
@@ -88,3 +85,21 @@ verified against the expected output. To simplify testing, several
 macros of the form `[MACRO]` are used in the expected output. For
 example, `[..]` matches any string and `[/]` matches `/` on Unixes and
 `\` on windows.
+
+To see stdout and stderr streams of the subordinate process, add `.stream()` 
+call to `execs()`:
+
+```rust
+// Before
+assert_that(
+    p.cargo("run"),
+    execs().with_status(0)
+);
+
+// After
+assert_that(
+    p.cargo("run"),
+    execs().stream().with_status(0)
+);
+
+```
index d15ddc5a7681775f3a22f0d080bb5357df6a9e70..a2d5d59576e7d62e1244085b7a0c3c1e878fd4b8 100644 (file)
@@ -365,6 +365,7 @@ pub struct Execs {
     expect_stderr_not_contains: Vec<String>,
     expect_neither_contains: Vec<String>,
     expect_json: Option<Vec<Value>>,
+    stream_output: bool,
 }
 
 impl Execs {
@@ -428,6 +429,14 @@ impl Execs {
         self
     }
 
+    /// Forward subordinate process stdout/stderr to the terminal.
+    /// Useful for prtintf debugging of the tests.
+    #[allow(unused)]
+    pub fn stream(mut self) -> Execs {
+        self.stream_output = true;
+        self
+    }
+
     fn match_output(&self, actual: &Output) -> ham::MatchResult {
         self.match_status(actual)
             .and(self.match_stdout(actual))
@@ -855,7 +864,18 @@ impl ham::Matcher<ProcessBuilder> for Execs {
 impl<'a> ham::Matcher<&'a mut ProcessBuilder> for Execs {
     fn matches(&self, process: &'a mut ProcessBuilder) -> ham::MatchResult {
         println!("running {}", process);
-        let res = process.exec_with_output();
+        let res = if self.stream_output {
+            if env::var("CI").is_ok() {
+                panic!("`.stream()` is for local debugging")
+            }
+            process.exec_with_streaming(
+                &mut |out| Ok(println!("{}", out)),
+                &mut |err| Ok(eprintln!("{}", err)),
+                false,
+            )
+        } else {
+            process.exec_with_output()
+        };
 
         match res {
             Ok(out) => self.match_output(&out),
@@ -898,6 +918,7 @@ pub fn execs() -> Execs {
         expect_stderr_not_contains: Vec::new(),
         expect_neither_contains: Vec::new(),
         expect_json: None,
+        stream_output: false,
     }
 }