diff options
| author | Igor Aleksanov <popzxc@yandex.ru> | 2019-10-17 17:38:16 +0300 |
|---|---|---|
| committer | Igor Aleksanov <popzxc@yandex.ru> | 2019-10-17 17:47:03 +0300 |
| commit | 12397e9dd5a97460d76c884d449ca1c2d26da8ed (patch) | |
| tree | b7d194c34c3ba67579303f34e5d5a1879f5755d5 | |
| parent | c951882c7364c672fe127f61d25b458e810572ff (diff) | |
| download | rust-12397e9dd5a97460d76c884d449ca1c2d26da8ed.tar.gz rust-12397e9dd5a97460d76c884d449ca1c2d26da8ed.zip | |
Make enum usage explicit and fix tests
| -rw-r--r-- | src/libtest/bench.rs | 16 | ||||
| -rw-r--r-- | src/libtest/console.rs | 18 | ||||
| -rw-r--r-- | src/libtest/event.rs | 25 | ||||
| -rw-r--r-- | src/libtest/formatters/json.rs | 31 | ||||
| -rw-r--r-- | src/libtest/formatters/mod.rs | 13 | ||||
| -rw-r--r-- | src/libtest/formatters/pretty.rs | 27 | ||||
| -rw-r--r-- | src/libtest/formatters/terse.rs | 31 | ||||
| -rw-r--r-- | src/libtest/helpers/exit_code.rs | 20 | ||||
| -rw-r--r-- | src/libtest/helpers/mod.rs | 2 | ||||
| -rw-r--r-- | src/libtest/helpers/sink.rs | 24 | ||||
| -rw-r--r-- | src/libtest/lib.rs | 184 | ||||
| -rw-r--r-- | src/libtest/stats/tests.rs | 2 | ||||
| -rw-r--r-- | src/libtest/tests.rs | 55 | ||||
| -rw-r--r-- | src/libtest/time.rs | 2 |
14 files changed, 289 insertions, 161 deletions
diff --git a/src/libtest/bench.rs b/src/libtest/bench.rs index 055a74f691c..bb5b0d1da53 100644 --- a/src/libtest/bench.rs +++ b/src/libtest/bench.rs @@ -1,6 +1,11 @@ //! Benchmarking module. use super::{ - BenchMode, MonitorMsg, Sender, Sink, TestDesc, TestResult + event::CompletedTest, + helpers::sink::Sink, + options::BenchMode, + types::TestDesc, + test_result::TestResult, + Sender, }; use crate::stats; @@ -182,7 +187,7 @@ where } } -pub fn benchmark<F>(desc: TestDesc, monitor_ch: Sender<MonitorMsg>, nocapture: bool, f: F) +pub fn benchmark<F>(desc: TestDesc, monitor_ch: Sender<CompletedTest>, nocapture: bool, f: F) where F: FnMut(&mut Bencher), { @@ -195,8 +200,8 @@ where let data = Arc::new(Mutex::new(Vec::new())); let oldio = if !nocapture { Some(( - io::set_print(Some(Box::new(Sink(data.clone())))), - io::set_panic(Some(Box::new(Sink(data.clone())))), + io::set_print(Some(Sink::new_boxed(&data))), + io::set_panic(Some(Sink::new_boxed(&data))), )) } else { None @@ -235,7 +240,8 @@ where }; let stdout = data.lock().unwrap().to_vec(); - monitor_ch.send((desc, test_result, None, stdout)).unwrap(); + let message = CompletedTest::new(desc, test_result, None, stdout); + monitor_ch.send(message).unwrap(); } pub fn run_once<F>(f: F) diff --git a/src/libtest/console.rs b/src/libtest/console.rs index 851c0389ff3..2c14e9a1591 100644 --- a/src/libtest/console.rs +++ b/src/libtest/console.rs @@ -1,7 +1,7 @@ //! Module providing interface for running tests in the console. use std::fs::File; -use std::io::prelude::*; +use std::io::prelude::Write; use std::io; use term; @@ -192,7 +192,8 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res // A simple console test runner pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<bool> { - fn callback( + // A callback handling events that occure during test execution. + fn on_test_event( event: &TestEvent, st: &mut ConsoleTestState, out: &mut dyn OutputFormatter, @@ -205,9 +206,14 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu TestEvent::TeFilteredOut(filtered_out) => Ok(st.filtered_out = filtered_out), TestEvent::TeWait(ref test) => out.write_test_start(test), TestEvent::TeTimeout(ref test) => out.write_timeout(test), - TestEvent::TeResult(test, result, exec_time, stdout) => { - st.write_log_result(&test, &result, exec_time.as_ref())?; - out.write_result(&test, &result, exec_time.as_ref(), &*stdout, &st)?; + TestEvent::TeResult(completed_test) => { + let test = completed_test.desc; + let result = &completed_test.result; + let exec_time = &completed_test.exec_time; + let stdout = completed_test.stdout; + + st.write_log_result(&test, result, exec_time.as_ref())?; + out.write_result(&test, result, exec_time.as_ref(), &*stdout, st)?; match result { TestResult::TrOk => { st.passed += 1; @@ -280,7 +286,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu } } - run_tests(opts, tests, |x| callback(&x, &mut st, &mut *out))?; + run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?; assert!(st.current_test_count() == st.total); diff --git a/src/libtest/event.rs b/src/libtest/event.rs index b84551826c6..e1b606149c5 100644 --- a/src/libtest/event.rs +++ b/src/libtest/event.rs @@ -5,11 +5,32 @@ use super::types::TestDesc; use super::test_result::TestResult; use super::time::TestExecTime; -#[derive(Clone)] +#[derive(Debug, Clone)] +pub struct CompletedTest { + pub desc: TestDesc, + pub result: TestResult, + pub exec_time: Option<TestExecTime>, + pub stdout: Vec<u8>, +} + +impl CompletedTest { + pub fn new(desc: TestDesc, result: TestResult, exec_time: Option<TestExecTime>, stdout: Vec<u8>) -> Self { + Self { + desc, + result, + exec_time, + stdout, + } + } +} + +unsafe impl Send for CompletedTest {} + +#[derive(Debug, Clone)] pub enum TestEvent { TeFiltered(Vec<TestDesc>), TeWait(TestDesc), - TeResult(TestDesc, TestResult, Option<TestExecTime>, Vec<u8>), + TeResult(CompletedTest), TeTimeout(TestDesc), TeFilteredOut(usize), } diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs index 41a293195cc..fc677036dab 100644 --- a/src/libtest/formatters/json.rs +++ b/src/libtest/formatters/json.rs @@ -1,5 +1,16 @@ -use super::*; -use super::console::{ConsoleTestState, OutputLocation}; +use std::{ + io, + io::prelude::Write, + borrow::Cow, +}; + +use crate::{ + types::TestDesc, + time, + test_result::TestResult, + console::{ConsoleTestState, OutputLocation}, +}; +use super::OutputFormatter; pub(crate) struct JsonFormatter<T> { out: OutputLocation<T>, @@ -81,21 +92,21 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> { stdout: &[u8], state: &ConsoleTestState, ) -> io::Result<()> { - let stdout = if (state.options.display_output || *result != TrOk) && stdout.len() > 0 { + let stdout = if (state.options.display_output || *result != TestResult::TrOk) && stdout.len() > 0 { Some(String::from_utf8_lossy(stdout)) } else { None }; match *result { - TrOk => { + TestResult::TrOk => { self.write_event("test", desc.name.as_slice(), "ok", exec_time, stdout, None) } - TrFailed => { + TestResult::TrFailed => { self.write_event("test", desc.name.as_slice(), "failed", exec_time, stdout, None) } - TrTimedFail => self.write_event( + TestResult::TrTimedFail => self.write_event( "test", desc.name.as_slice(), "failed", @@ -104,7 +115,7 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> { Some(r#""reason": "time limit exceeded""#), ), - TrFailedMsg(ref m) => self.write_event( + TestResult::TrFailedMsg(ref m) => self.write_event( "test", desc.name.as_slice(), "failed", @@ -113,11 +124,11 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> { Some(&*format!(r#""message": "{}""#, EscapedString(m))), ), - TrIgnored => { + TestResult::TrIgnored => { self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None) } - TrAllowedFail => self.write_event( + TestResult::TrAllowedFail => self.write_event( "test", desc.name.as_slice(), "allowed_failure", @@ -126,7 +137,7 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> { None, ), - TrBench(ref bs) => { + TestResult::TrBench(ref bs) => { let median = bs.ns_iter_summ.median as usize; let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize; diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs index 4f3ffdafe3f..b6649a3effc 100644 --- a/src/libtest/formatters/mod.rs +++ b/src/libtest/formatters/mod.rs @@ -1,5 +1,14 @@ -use super::*; -use super::console::ConsoleTestState; +use std::{ + io, + io::prelude::Write, +}; + +use crate::{ + types::{TestDesc, TestName}, + time, + test_result::TestResult, + console::{ConsoleTestState}, +}; mod pretty; mod json; diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs index 6f2c56bdf45..2fdbc63d513 100644 --- a/src/libtest/formatters/pretty.rs +++ b/src/libtest/formatters/pretty.rs @@ -1,5 +1,16 @@ -use super::*; -use super::console::{ConsoleTestState, OutputLocation}; +use std::{ + io, + io::prelude::Write, +}; + +use crate::{ + types::TestDesc, + time, + test_result::TestResult, + console::{ConsoleTestState, OutputLocation}, + bench::fmt_bench_samples, +}; +use super::OutputFormatter; pub(crate) struct PrettyFormatter<T> { out: OutputLocation<T>, @@ -204,15 +215,15 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> { } match *result { - TrOk => self.write_ok()?, - TrFailed | TrFailedMsg(_) => self.write_failed()?, - TrIgnored => self.write_ignored()?, - TrAllowedFail => self.write_allowed_fail()?, - TrBench(ref bs) => { + TestResult::TrOk => self.write_ok()?, + TestResult::TrFailed | TestResult::TrFailedMsg(_) => self.write_failed()?, + TestResult::TrIgnored => self.write_ignored()?, + TestResult::TrAllowedFail => self.write_allowed_fail()?, + TestResult::TrBench(ref bs) => { self.write_bench()?; self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?; } - TrTimedFail => self.write_time_failed()?, + TestResult::TrTimedFail => self.write_time_failed()?, } self.write_time(desc, exec_time)?; diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs index 96203d5ea42..90eb62251fb 100644 --- a/src/libtest/formatters/terse.rs +++ b/src/libtest/formatters/terse.rs @@ -1,5 +1,20 @@ -use super::*; -use super::console::{ConsoleTestState, OutputLocation}; +use std::{ + io, + io::prelude::Write, +}; + +use crate::{ + types::TestDesc, + time, + test_result::TestResult, + types::NamePadding, + console::{ConsoleTestState, OutputLocation}, + bench::fmt_bench_samples, +}; +use super::OutputFormatter; + +// insert a '\n' after 100 tests in quiet mode +const QUIET_MODE_MAX_COLUMN: usize = 100; pub(crate) struct TerseFormatter<T> { out: OutputLocation<T>, @@ -164,7 +179,7 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> { // in order to indicate benchmarks. // When running benchmarks, terse-mode should still print their name as if // it is the Pretty formatter. - if !self.is_multithreaded && desc.name.padding() == PadOnRight { + if !self.is_multithreaded && desc.name.padding() == NamePadding::PadOnRight { self.write_test_name(desc)?; } @@ -180,11 +195,11 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> { _: &ConsoleTestState, ) -> io::Result<()> { match *result { - TrOk => self.write_ok(), - TrFailed | TrFailedMsg(_) | TrTimedFail => self.write_failed(), - TrIgnored => self.write_ignored(), - TrAllowedFail => self.write_allowed_fail(), - TrBench(ref bs) => { + TestResult::TrOk => self.write_ok(), + TestResult::TrFailed | TestResult::TrFailedMsg(_) | TestResult::TrTimedFail => self.write_failed(), + TestResult::TrIgnored => self.write_ignored(), + TestResult::TrAllowedFail => self.write_allowed_fail(), + TestResult::TrBench(ref bs) => { if self.is_multithreaded { self.write_test_name(desc)?; } diff --git a/src/libtest/helpers/exit_code.rs b/src/libtest/helpers/exit_code.rs new file mode 100644 index 00000000000..831bef3b118 --- /dev/null +++ b/src/libtest/helpers/exit_code.rs @@ -0,0 +1,20 @@ +//! Helper module to detect subprocess exit code. + +use std::process::ExitStatus; + +#[cfg(not(unix))] +pub fn get_exit_code(status: ExitStatus) -> Result<i32, String> { + status.code().ok_or("received no exit code from child process".into()) +} + +#[cfg(unix)] +pub fn get_exit_code(status: ExitStatus) -> Result<i32, String> { + use std::os::unix::process::ExitStatusExt; + match status.code() { + Some(code) => Ok(code), + None => match status.signal() { + Some(signal) => Err(format!("child process exited with signal {}", signal)), + None => Err("child process exited with unknown signal".into()), + } + } +} diff --git a/src/libtest/helpers/mod.rs b/src/libtest/helpers/mod.rs index 0bbe77b1c50..6a2ef6086cb 100644 --- a/src/libtest/helpers/mod.rs +++ b/src/libtest/helpers/mod.rs @@ -4,3 +4,5 @@ pub mod concurrency; pub mod isatty; pub mod metrics; +pub mod sink; +pub mod exit_code; diff --git a/src/libtest/helpers/sink.rs b/src/libtest/helpers/sink.rs new file mode 100644 index 00000000000..aa7fe248773 --- /dev/null +++ b/src/libtest/helpers/sink.rs @@ -0,0 +1,24 @@ +//! Module providing a helper structure to capture output in subprocesses. + +use std::{ + io, + io::prelude::Write, + sync::{Arc, Mutex}, +}; + +pub struct Sink(Arc<Mutex<Vec<u8>>>); + +impl Sink { + pub fn new_boxed(data: &Arc<Mutex<Vec<u8>>>) -> Box<Self> { + Box::new(Self(data.clone())) + } +} + +impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 6221140f606..31da97b736a 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -30,30 +30,13 @@ #![feature(termination_trait_lib)] #![feature(test)] +// Public reexports pub use self::ColorConfig::*; -use self::event::TestEvent::*; +pub use self::types::*; pub use self::types::TestName::*; +pub use self::options::{Options, ShouldPanic}; -use std::borrow::Cow; -use std::env; -use std::io; -use std::io::prelude::*; -use std::panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo}; -use std::process; -use std::process::{ExitStatus, Command, Termination}; -use std::sync::mpsc::{channel, Sender}; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::{Duration, Instant}; - -#[cfg(test)] -mod tests; - -const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in quiet mode - -const SECONDARY_TEST_INVOKER_VAR: &'static str = "__RUST_TEST_INVOKE"; - -// to be used by rustc to compile tests in libtest +// Module to be used by rustc to compile tests in libtest pub mod test { pub use crate::{ bench::Bencher, @@ -61,7 +44,7 @@ pub mod test { helpers::metrics::{Metric, MetricMap}, options::{ShouldPanic, Options, RunIgnored, RunStrategy}, test_result::{TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk}, - time::TestTimeOptions, + time::{TestTimeOptions, TestExecTime}, types::{ DynTestFn, DynTestName, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, TestType, @@ -70,18 +53,21 @@ pub mod test { }; } -use bench::*; -use test_result::*; -use types::*; -use options::*; -use cli::*; -use event::*; - -use helpers::concurrency::get_concurrency; +use std::{ + env, + io, + io::prelude::Write, + panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo}, + process, + process::{Command, Termination}, + sync::mpsc::{channel, Sender}, + sync::{Arc, Mutex}, + thread, + time::{Duration, Instant}, +}; -mod formatters; pub mod stats; - +mod formatters; mod cli; mod console; mod event; @@ -92,14 +78,31 @@ mod options; mod bench; mod test_result; +#[cfg(test)] +mod tests; + +use test_result::*; +use time::TestExecTime; +use options::{RunStrategy, Concurrent, RunIgnored, ColorConfig}; +use event::{CompletedTest, TestEvent}; +use cli::TestOpts; +use helpers::sink::Sink; +use helpers::concurrency::get_concurrency; +use helpers::exit_code::get_exit_code; + +// Process exit code to be used to indicate test failures. +const ERROR_EXIT_CODE: i32 = 101; + +const SECONDARY_TEST_INVOKER_VAR: &'static str = "__RUST_TEST_INVOKE"; + // The default console test runner. It accepts the command line // arguments and a vector of test_descs. pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Option<Options>) { - let mut opts = match parse_opts(args) { + let mut opts = match cli::parse_opts(args) { Some(Ok(o)) => o, Some(Err(msg)) => { eprintln!("error: {}", msg); - process::exit(101); + process::exit(ERROR_EXIT_CODE); } None => return, }; @@ -109,15 +112,15 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Option<Opt if opts.list { if let Err(e) = console::list_tests_console(&opts, tests) { eprintln!("error: io error when listing tests: {:?}", e); - process::exit(101); + process::exit(ERROR_EXIT_CODE); } } else { match console::run_tests_console(&opts, tests) { Ok(true) => {} - Ok(false) => process::exit(101), + Ok(false) => process::exit(ERROR_EXIT_CODE), Err(e) => { eprintln!("error: io error when listing tests: {:?}", e); - process::exit(101); + process::exit(ERROR_EXIT_CODE); } } } @@ -196,19 +199,7 @@ pub fn assert_test_result<T: Termination>(result: T) { ); } -pub type MonitorMsg = (TestDesc, TestResult, Option<time::TestExecTime>, Vec<u8>); - -struct Sink(Arc<Mutex<Vec<u8>>>); -impl Write for Sink { - fn write(&mut self, data: &[u8]) -> io::Result<usize> { - Write::write(&mut *self.0.lock().unwrap(), data) - } - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -pub fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) -> io::Result<()> +pub fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut notify_about_test_event: F) -> io::Result<()> where F: FnMut(TestEvent) -> io::Result<()>, { @@ -236,11 +227,13 @@ where }; let filtered_out = tests_len - filtered_tests.len(); - callback(TeFilteredOut(filtered_out))?; + let event = TestEvent::TeFilteredOut(filtered_out); + notify_about_test_event(event)?; let filtered_descs = filtered_tests.iter().map(|t| t.desc.clone()).collect(); - callback(TeFiltered(filtered_descs))?; + let event = TestEvent::TeFiltered(filtered_descs); + notify_about_test_event(event)?; let (filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests.into_iter().partition(|e| match e.testfn { @@ -254,7 +247,7 @@ where remaining.reverse(); let mut pending = 0; - let (tx, rx) = channel::<MonitorMsg>(); + let (tx, rx) = channel::<CompletedTest>(); let run_strategy = if opts.options.panic_abort { RunStrategy::SpawnPrimary } else { @@ -295,10 +288,13 @@ where if concurrency == 1 { while !remaining.is_empty() { let test = remaining.pop().unwrap(); - callback(TeWait(test.desc.clone()))?; + let event = TestEvent::TeWait(test.desc.clone()); + notify_about_test_event(event)?; run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::No); - let (test, result, exec_time, stdout) = rx.recv().unwrap(); - callback(TeResult(test, result, exec_time, stdout))?; + let completed_test = rx.recv().unwrap(); + + let event = TestEvent::TeResult(completed_test); + notify_about_test_event(event)?; } } else { while pending > 0 || !remaining.is_empty() { @@ -306,7 +302,9 @@ where let test = remaining.pop().unwrap(); let timeout = time::get_default_test_timeout(); running_tests.insert(test.desc.clone(), timeout); - callback(TeWait(test.desc.clone()))?; //here no pad + + let event = TestEvent::TeWait(test.desc.clone()); + notify_about_test_event(event)?; //here no pad run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::Yes); pending += 1; } @@ -316,10 +314,18 @@ where if let Some(timeout) = calc_timeout(&running_tests) { res = rx.recv_timeout(timeout); for test in get_timed_out_tests(&mut running_tests) { - callback(TeTimeout(test))?; + let event = TestEvent::TeTimeout(test); + notify_about_test_event(event)?; } - if res != Err(RecvTimeoutError::Timeout) { - break; + + match res { + Err(RecvTimeoutError::Timeout) => { + // Result is not yet ready, continue waiting. + } + _ => { + // We've got a result, stop the loop. + break; + } } } else { res = rx.recv().map_err(|_| RecvTimeoutError::Disconnected); @@ -327,10 +333,11 @@ where } } - let (desc, result, exec_time, stdout) = res.unwrap(); - running_tests.remove(&desc); + let completed_test = res.unwrap(); + running_tests.remove(&completed_test.desc); - callback(TeResult(desc, result, exec_time, stdout))?; + let event = TestEvent::TeResult(completed_test); + notify_about_test_event(event)?; pending -= 1; } } @@ -338,10 +345,13 @@ where if opts.bench_benchmarks { // All benchmarks run at the end, in serial. for b in filtered_benchs { - callback(TeWait(b.desc.clone()))?; + let event = TestEvent::TeWait(b.desc.clone()); + notify_about_test_event(event)?; run_test(opts, false, b, run_strategy, tx.clone(), Concurrent::No); - let (test, result, exec_time, stdout) = rx.recv().unwrap(); - callback(TeResult(test, result, exec_time, stdout))?; + let completed_test = rx.recv().unwrap(); + + let event = TestEvent::TeResult(completed_test); + notify_about_test_event(event)?; } } Ok(()) @@ -420,7 +430,7 @@ pub fn run_test( force_ignore: bool, test: TestDescAndFn, strategy: RunStrategy, - monitor_ch: Sender<MonitorMsg>, + monitor_ch: Sender<CompletedTest>, concurrency: Concurrent, ) { let TestDescAndFn { desc, testfn } = test; @@ -430,7 +440,8 @@ pub fn run_test( && (cfg!(target_arch = "wasm32") || cfg!(target_os = "emscripten")); if force_ignore || desc.ignore || ignore_because_no_process_support { - monitor_ch.send((desc, TrIgnored, None, Vec::new())).unwrap(); + let message = CompletedTest::new(desc, TrIgnored, None, Vec::new()); + monitor_ch.send(message).unwrap(); return; } @@ -443,7 +454,7 @@ pub fn run_test( fn run_test_inner( desc: TestDesc, - monitor_ch: Sender<MonitorMsg>, + monitor_ch: Sender<CompletedTest>, testfn: Box<dyn FnOnce() + Send>, opts: TestRunOpts, ) { @@ -530,7 +541,7 @@ fn run_test_in_process( nocapture: bool, report_time: bool, testfn: Box<dyn FnOnce() + Send>, - monitor_ch: Sender<MonitorMsg>, + monitor_ch: Sender<CompletedTest>, time_opts: Option<time::TestTimeOptions>, ) { // Buffer for capturing standard I/O @@ -538,8 +549,8 @@ fn run_test_in_process( let oldio = if !nocapture { Some(( - io::set_print(Some(Box::new(Sink(data.clone())))), - io::set_panic(Some(Box::new(Sink(data.clone())))), + io::set_print(Some(Sink::new_boxed(&data))), + io::set_panic(Some(Sink::new_boxed(&data))), )) } else { None @@ -553,7 +564,7 @@ fn run_test_in_process( let result = catch_unwind(AssertUnwindSafe(testfn)); let exec_time = start.map(|start| { let duration = start.elapsed(); - time::TestExecTime(duration) + TestExecTime(duration) }); if let Some((printio, panicio)) = oldio { @@ -566,13 +577,14 @@ fn run_test_in_process( Err(e) => calc_result(&desc, Err(e.as_ref()), &time_opts, &exec_time), }; let stdout = data.lock().unwrap().to_vec(); - monitor_ch.send((desc.clone(), test_result, exec_time, stdout)).unwrap(); + let message = CompletedTest::new(desc.clone(), test_result, exec_time, stdout); + monitor_ch.send(message).unwrap(); } fn spawn_test_subprocess( desc: TestDesc, report_time: bool, - monitor_ch: Sender<MonitorMsg>, + monitor_ch: Sender<CompletedTest>, time_opts: Option<time::TestTimeOptions>, ) { let (result, test_output, exec_time) = (|| { @@ -595,7 +607,7 @@ fn spawn_test_subprocess( }; let exec_time = start.map(|start| { let duration = start.elapsed(); - time::TestExecTime(duration) + TestExecTime(duration) }); let std::process::Output { stdout, stderr, status } = output; @@ -617,7 +629,8 @@ fn spawn_test_subprocess( (result, test_output, exec_time) })(); - monitor_ch.send((desc.clone(), result, exec_time, test_output)).unwrap(); + let message = CompletedTest::new(desc.clone(), result, exec_time, test_output); + monitor_ch.send(message).unwrap(); } fn run_test_in_spawned_subprocess( @@ -653,20 +666,3 @@ fn run_test_in_spawned_subprocess( record_result(None); unreachable!("panic=abort callback should have exited the process") } - -#[cfg(not(unix))] -fn get_exit_code(status: ExitStatus) -> Result<i32, String> { - status.code().ok_or("received no exit code from child process".into()) -} - -#[cfg(unix)] -fn get_exit_code(status: ExitStatus) -> Result<i32, String> { - use std::os::unix::process::ExitStatusExt; - match status.code() { - Some(code) => Ok(code), - None => match status.signal() { - Some(signal) => Err(format!("child process exited with signal {}", signal)), - None => Err("child process exited with unknown signal".into()), - } - } -} diff --git a/src/libtest/stats/tests.rs b/src/libtest/stats/tests.rs index 7d1d635186f..eaf41bc9e22 100644 --- a/src/libtest/stats/tests.rs +++ b/src/libtest/stats/tests.rs @@ -4,7 +4,7 @@ extern crate test; use std::f64; use std::io::prelude::*; use std::io; -use self::test::Bencher; +use self::test::test::Bencher; // Test vectors generated from R, using the script src/etc/stat-test-vectors.r. diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs index 5f7150a8eeb..f6470b40a39 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -1,11 +1,18 @@ use super::*; -use crate::test::{ - filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, RunStrategy, - // ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TestTimeOptions, - // TestType, TrFailedMsg, TrIgnored, TrOk, - ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, - TrIgnored, TrOk, +use crate::{ + bench::Bencher, + console::OutputLocation, + options::OutputFormat, + time::{TimeThreshold, TestTimeOptions}, + formatters::PrettyFormatter, + test::{ + filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, RunStrategy, + // ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TestTimeOptions, + // TestType, TrFailedMsg, TrIgnored, TrOk, + ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, + TrIgnored, TrOk, + }, }; use std::sync::mpsc::channel; use std::time::Duration; @@ -74,8 +81,8 @@ pub fn do_not_run_ignored_tests() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let (_, res, _, _) = rx.recv().unwrap(); - assert!(res != TrOk); + let result = rx.recv().unwrap().result; + assert!(result != TrOk); } #[test] @@ -93,8 +100,8 @@ pub fn ignored_tests_result_in_ignored() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let (_, res, _, _) = rx.recv().unwrap(); - assert!(res == TrIgnored); + let result = rx.recv().unwrap().result; + assert!(result == TrIgnored); } // FIXME: Re-enable emscripten once it can catch panics again @@ -116,8 +123,8 @@ fn test_should_panic() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let (_, res, _, _) = rx.recv().unwrap(); - assert!(res == TrOk); + let result = rx.recv().unwrap().result; + assert!(result == TrOk); } // FIXME: Re-enable emscripten once it can catch panics again @@ -139,8 +146,8 @@ fn test_should_panic_good_message() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let (_, res, _, _) = rx.recv().unwrap(); - assert!(res == TrOk); + let result = rx.recv().unwrap().result; + assert!(result == TrOk); } // FIXME: Re-enable emscripten once it can catch panics again @@ -165,8 +172,8 @@ fn test_should_panic_bad_message() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let (_, res, _, _) = rx.recv().unwrap(); - assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); + let result = rx.recv().unwrap().result; + assert!(result == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); } // FIXME: Re-enable emscripten once it can catch panics again @@ -186,8 +193,8 @@ fn test_should_panic_but_succeeds() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let (_, res, _, _) = rx.recv().unwrap(); - assert!(res == TrFailedMsg("test did not panic as expected".to_string())); + let result = rx.recv().unwrap().result; + assert!(result == TrFailedMsg("test did not panic as expected".to_string())); } fn report_time_test_template(report_time: bool) -> Option<TestExecTime> { @@ -214,7 +221,7 @@ fn report_time_test_template(report_time: bool) -> Option<TestExecTime> { }; let (tx, rx) = channel(); run_test(&test_opts, false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let (_, _, exec_time, _) = rx.recv().unwrap(); + let exec_time = rx.recv().unwrap().exec_time; exec_time } @@ -252,7 +259,7 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { }; let (tx, rx) = channel(); run_test(&test_opts, false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let (_, result, _, _) = rx.recv().unwrap(); + let result = rx.recv().unwrap().result; result } @@ -658,9 +665,9 @@ fn should_sort_failures_before_printing_them() { test_type: TestType::Unknown, }; - let mut out = PrettyFormatter::new(Raw(Vec::new()), false, 10, false, None); + let mut out = PrettyFormatter::new(OutputLocation::Raw(Vec::new()), false, 10, false, None); - let st = ConsoleTestState { + let st = console::ConsoleTestState { log_out: None, total: 0, passed: 0, @@ -678,8 +685,8 @@ fn should_sort_failures_before_printing_them() { out.write_failures(&st).unwrap(); let s = match out.output_location() { - &Raw(ref m) => String::from_utf8_lossy(&m[..]), - &Pretty(_) => unreachable!(), + &OutputLocation::Raw(ref m) => String::from_utf8_lossy(&m[..]), + &OutputLocation::Pretty(_) => unreachable!(), }; let apos = s.find("a").unwrap(); diff --git a/src/libtest/time.rs b/src/libtest/time.rs index b7ce764505b..83a545470ef 100644 --- a/src/libtest/time.rs +++ b/src/libtest/time.rs @@ -61,7 +61,7 @@ pub fn get_default_test_timeout() -> Instant { } /// The meassured execution time of a unit test. -#[derive(Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub struct TestExecTime(pub Duration); impl fmt::Display for TestExecTime { |
