about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-04-24 11:31:22 -0700
committerbors <bors@rust-lang.org>2014-04-24 11:31:22 -0700
commit3485d90728fe8dc076c6362211bf1f62830c97d8 (patch)
tree8cac8759d29cf01750f1e81c8463096b372ec2b9
parent22e4e6adaff9d1424e8e715f209cffccfa121df0 (diff)
parent65f68dcf700a140a64bdd868d5d86b187326e088 (diff)
downloadrust-3485d90728fe8dc076c6362211bf1f62830c97d8.tar.gz
rust-3485d90728fe8dc076c6362211bf1f62830c97d8.zip
auto merge of #13706 : alexcrichton/rust/test-nocapture, r=brson
A new flag to the test runner, --nocapture, can be passed to instruct that the
output of tests should not be captured by default. The behavior can also be
triggered via a RUST_TEST_NOCAPTURE environment variable being set.

Closes #13374
-rw-r--r--src/compiletest/compiletest.rs3
-rw-r--r--src/compiletest/runtest.rs4
-rw-r--r--src/libtest/lib.rs93
3 files changed, 62 insertions, 38 deletions
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index cae6c2b656d..2e287135dc2 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -267,7 +267,8 @@ pub fn test_opts(config: &config) -> test::TestOpts {
         ratchet_metrics: config.ratchet_metrics.clone(),
         ratchet_noise_percent: config.ratchet_noise_percent.clone(),
         save_metrics: config.save_metrics.clone(),
-        test_shard: config.test_shard.clone()
+        test_shard: config.test_shard.clone(),
+        nocapture: false,
     }
 }
 
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index dd246cf6114..9ce81c5bae5 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -955,6 +955,7 @@ fn fatal(err: ~str) -> ! { error(err); fail!(); }
 fn fatal_ProcRes(err: ~str, proc_res: &ProcRes) -> ! {
     print!("\n\
 error: {}\n\
+status: {}\n\
 command: {}\n\
 stdout:\n\
 ------------------------------------------\n\
@@ -965,7 +966,8 @@ stderr:\n\
 {}\n\
 ------------------------------------------\n\
 \n",
-             err, proc_res.cmdline, proc_res.stdout, proc_res.stderr);
+             err, proc_res.status, proc_res.cmdline, proc_res.stdout,
+             proc_res.stderr);
     fail!();
 }
 
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 145fea18cb2..6a1b7b4d073 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -257,7 +257,26 @@ pub struct TestOpts {
     pub ratchet_noise_percent: Option<f64>,
     pub save_metrics: Option<Path>,
     pub test_shard: Option<(uint,uint)>,
-    pub logfile: Option<Path>
+    pub logfile: Option<Path>,
+    pub nocapture: bool,
+}
+
+impl TestOpts {
+    #[cfg(test)]
+    fn new() -> TestOpts {
+        TestOpts {
+            filter: None,
+            run_ignored: false,
+            run_tests: false,
+            run_benchmarks: false,
+            ratchet_metrics: None,
+            ratchet_noise_percent: None,
+            save_metrics: None,
+            test_shard: None,
+            logfile: None,
+            nocapture: false,
+        }
+    }
 }
 
 /// Result of parsing the options.
@@ -280,7 +299,9 @@ fn optgroups() -> Vec<getopts::OptGroup> {
       getopts::optopt("", "logfile", "Write logs to the specified file instead \
                           of stdout", "PATH"),
       getopts::optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite",
-                     "A.B"))
+                     "A.B"),
+      getopts::optflag("", "nocapture", "don't capture stdout/stderr of each \
+                                         task, allow printing directly"))
 }
 
 fn usage(binary: &str, helpstr: &str) {
@@ -295,6 +316,10 @@ have a substring match, only those tests are run.
 By default, all tests are run in parallel. This can be altered with the
 RUST_TEST_TASKS environment variable when running tests (set it to 1).
 
+All tests have their standard output and standard error captured by default.
+This can be overridden with the --nocapture flag or the RUST_TEST_NOCAPTURE=1
+environment variable. Logging is not captured by default.
+
 Test Attributes:
 
     #[test]        - Indicates a function is a test to be run. This function
@@ -351,6 +376,11 @@ pub fn parse_opts(args: &[~str]) -> Option<OptRes> {
     let test_shard = matches.opt_str("test-shard");
     let test_shard = opt_shard(test_shard);
 
+    let mut nocapture = matches.opt_present("nocapture");
+    if !nocapture {
+        nocapture = os::getenv("RUST_TEST_NOCAPTURE").is_some();
+    }
+
     let test_opts = TestOpts {
         filter: filter,
         run_ignored: run_ignored,
@@ -360,7 +390,8 @@ pub fn parse_opts(args: &[~str]) -> Option<OptRes> {
         ratchet_noise_percent: ratchet_noise_percent,
         save_metrics: save_metrics,
         test_shard: test_shard,
-        logfile: logfile
+        logfile: logfile,
+        nocapture: nocapture,
     };
 
     Some(Ok(test_opts))
@@ -843,7 +874,7 @@ fn run_tests(opts: &TestOpts,
                 // that hang forever.
                 try!(callback(TeWait(test.desc.clone(), test.testfn.padding())));
             }
-            run_test(!opts.run_tests, test, tx.clone());
+            run_test(opts, !opts.run_tests, test, tx.clone());
             pending += 1;
         }
 
@@ -859,7 +890,7 @@ fn run_tests(opts: &TestOpts,
     // (this includes metric fns)
     for b in filtered_benchs_and_metrics.move_iter() {
         try!(callback(TeWait(b.desc.clone(), b.testfn.padding())));
-        run_test(!opts.run_benchmarks, b, tx.clone());
+        run_test(opts, !opts.run_benchmarks, b, tx.clone());
         let (test, result, stdout) = rx.recv();
         try!(callback(TeResult(test, result, stdout)));
     }
@@ -941,7 +972,8 @@ pub fn filter_tests(
     }
 }
 
-pub fn run_test(force_ignore: bool,
+pub fn run_test(opts: &TestOpts,
+                force_ignore: bool,
                 test: TestDescAndFn,
                 monitor_ch: Sender<MonitorMsg>) {
 
@@ -955,6 +987,7 @@ pub fn run_test(force_ignore: bool,
     #[allow(deprecated_owned_vector)]
     fn run_test_inner(desc: TestDesc,
                       monitor_ch: Sender<MonitorMsg>,
+                      nocapture: bool,
                       testfn: proc():Send) {
         spawn(proc() {
             let (tx, rx) = channel();
@@ -965,8 +998,12 @@ pub fn run_test(force_ignore: bool,
                 DynTestName(ref name) => name.clone().into_maybe_owned(),
                 StaticTestName(name) => name.into_maybe_owned(),
             });
-            task.opts.stdout = Some(~stdout as ~Writer:Send);
-            task.opts.stderr = Some(~stderr as ~Writer:Send);
+            if nocapture {
+                drop((stdout, stderr));
+            } else {
+                task.opts.stdout = Some(~stdout as ~Writer:Send);
+                task.opts.stderr = Some(~stderr as ~Writer:Send);
+            }
             let result_future = task.future_result();
             task.spawn(testfn);
 
@@ -1000,8 +1037,9 @@ pub fn run_test(force_ignore: bool,
             monitor_ch.send((desc, TrMetrics(mm), Vec::new()));
             return;
         }
-        DynTestFn(f) => run_test_inner(desc, monitor_ch, f),
-        StaticTestFn(f) => run_test_inner(desc, monitor_ch, proc() f())
+        DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f),
+        StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture,
+                                          proc() f())
     }
 }
 
@@ -1320,7 +1358,7 @@ mod tests {
             testfn: DynTestFn(proc() f()),
         };
         let (tx, rx) = channel();
-        run_test(false, desc, tx);
+        run_test(&TestOpts::new(), false, desc, tx);
         let (_, res, _) = rx.recv();
         assert!(res != TrOk);
     }
@@ -1337,7 +1375,7 @@ mod tests {
             testfn: DynTestFn(proc() f()),
         };
         let (tx, rx) = channel();
-        run_test(false, desc, tx);
+        run_test(&TestOpts::new(), false, desc, tx);
         let (_, res, _) = rx.recv();
         assert!(res == TrIgnored);
     }
@@ -1354,7 +1392,7 @@ mod tests {
             testfn: DynTestFn(proc() f()),
         };
         let (tx, rx) = channel();
-        run_test(false, desc, tx);
+        run_test(&TestOpts::new(), false, desc, tx);
         let (_, res, _) = rx.recv();
         assert!(res == TrOk);
     }
@@ -1371,7 +1409,7 @@ mod tests {
             testfn: DynTestFn(proc() f()),
         };
         let (tx, rx) = channel();
-        run_test(false, desc, tx);
+        run_test(&TestOpts::new(), false, desc, tx);
         let (_, res, _) = rx.recv();
         assert!(res == TrFailed);
     }
@@ -1401,17 +1439,9 @@ mod tests {
         // When we run ignored tests the test filter should filter out all the
         // unignored tests and flip the ignore flag on the rest to false
 
-        let opts = TestOpts {
-            filter: None,
-            run_ignored: true,
-            logfile: None,
-            run_tests: true,
-            run_benchmarks: false,
-            ratchet_noise_percent: None,
-            ratchet_metrics: None,
-            save_metrics: None,
-            test_shard: None
-        };
+        let mut opts = TestOpts::new();
+        opts.run_tests = true;
+        opts.run_ignored = true;
 
         let tests = vec!(
             TestDescAndFn {
@@ -1439,17 +1469,8 @@ mod tests {
 
     #[test]
     pub fn sort_tests() {
-        let opts = TestOpts {
-            filter: None,
-            run_ignored: false,
-            logfile: None,
-            run_tests: true,
-            run_benchmarks: false,
-            ratchet_noise_percent: None,
-            ratchet_metrics: None,
-            save_metrics: None,
-            test_shard: None
-        };
+        let mut opts = TestOpts::new();
+        opts.run_tests = true;
 
         let names =
             vec!("sha1::test".to_owned(), "int::test_to_str".to_owned(), "int::test_pow".to_owned(),