summaryrefslogtreecommitdiff
path: root/src/libtest/console.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtest/console.rs')
-rw-r--r--src/libtest/console.rs293
1 files changed, 0 insertions, 293 deletions
diff --git a/src/libtest/console.rs b/src/libtest/console.rs
deleted file mode 100644
index ff741e3bd53..00000000000
--- a/src/libtest/console.rs
+++ /dev/null
@@ -1,293 +0,0 @@
-//! Module providing interface for running tests in the console.
-
-use std::fs::File;
-use std::io;
-use std::io::prelude::Write;
-
-use super::{
- bench::fmt_bench_samples,
- cli::TestOpts,
- event::{CompletedTest, TestEvent},
- filter_tests,
- formatters::{JsonFormatter, OutputFormatter, PrettyFormatter, TerseFormatter},
- helpers::{concurrency::get_concurrency, metrics::MetricMap},
- options::{Options, OutputFormat},
- run_tests,
- test_result::TestResult,
- time::TestExecTime,
- types::{NamePadding, TestDesc, TestDescAndFn},
-};
-
-/// Generic wrapper over stdout.
-pub enum OutputLocation<T> {
- Pretty(Box<term::StdoutTerminal>),
- Raw(T),
-}
-
-impl<T: Write> Write for OutputLocation<T> {
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- match *self {
- OutputLocation::Pretty(ref mut term) => term.write(buf),
- OutputLocation::Raw(ref mut stdout) => stdout.write(buf),
- }
- }
-
- fn flush(&mut self) -> io::Result<()> {
- match *self {
- OutputLocation::Pretty(ref mut term) => term.flush(),
- OutputLocation::Raw(ref mut stdout) => stdout.flush(),
- }
- }
-}
-
-pub struct ConsoleTestState {
- pub log_out: Option<File>,
- pub total: usize,
- pub passed: usize,
- pub failed: usize,
- pub ignored: usize,
- pub allowed_fail: usize,
- pub filtered_out: usize,
- pub measured: usize,
- pub metrics: MetricMap,
- pub failures: Vec<(TestDesc, Vec<u8>)>,
- pub not_failures: Vec<(TestDesc, Vec<u8>)>,
- pub time_failures: Vec<(TestDesc, Vec<u8>)>,
- pub options: Options,
-}
-
-impl ConsoleTestState {
- pub fn new(opts: &TestOpts) -> io::Result<ConsoleTestState> {
- let log_out = match opts.logfile {
- Some(ref path) => Some(File::create(path)?),
- None => None,
- };
-
- Ok(ConsoleTestState {
- log_out,
- total: 0,
- passed: 0,
- failed: 0,
- ignored: 0,
- allowed_fail: 0,
- filtered_out: 0,
- measured: 0,
- metrics: MetricMap::new(),
- failures: Vec::new(),
- not_failures: Vec::new(),
- time_failures: Vec::new(),
- options: opts.options,
- })
- }
-
- pub fn write_log<F, S>(&mut self, msg: F) -> io::Result<()>
- where
- S: AsRef<str>,
- F: FnOnce() -> S,
- {
- match self.log_out {
- None => Ok(()),
- Some(ref mut o) => {
- let msg = msg();
- let msg = msg.as_ref();
- o.write_all(msg.as_bytes())
- }
- }
- }
-
- pub fn write_log_result(
- &mut self,
- test: &TestDesc,
- result: &TestResult,
- exec_time: Option<&TestExecTime>,
- ) -> io::Result<()> {
- self.write_log(|| {
- format!(
- "{} {}",
- match *result {
- TestResult::TrOk => "ok".to_owned(),
- TestResult::TrFailed => "failed".to_owned(),
- TestResult::TrFailedMsg(ref msg) => format!("failed: {}", msg),
- TestResult::TrIgnored => "ignored".to_owned(),
- TestResult::TrAllowedFail => "failed (allowed)".to_owned(),
- TestResult::TrBench(ref bs) => fmt_bench_samples(bs),
- TestResult::TrTimedFail => "failed (time limit exceeded)".to_owned(),
- },
- test.name,
- )
- })?;
- if let Some(exec_time) = exec_time {
- self.write_log(|| format!(" <{}>", exec_time))?;
- }
- self.write_log(|| "\n")
- }
-
- fn current_test_count(&self) -> usize {
- self.passed + self.failed + self.ignored + self.measured + self.allowed_fail
- }
-}
-
-// List the tests to console, and optionally to logfile. Filters are honored.
-pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<()> {
- let mut output = match term::stdout() {
- None => OutputLocation::Raw(io::stdout()),
- Some(t) => OutputLocation::Pretty(t),
- };
-
- let quiet = opts.format == OutputFormat::Terse;
- let mut st = ConsoleTestState::new(opts)?;
-
- let mut ntest = 0;
- let mut nbench = 0;
-
- for test in filter_tests(&opts, tests) {
- use crate::TestFn::*;
-
- let TestDescAndFn { desc: TestDesc { name, .. }, testfn } = test;
-
- let fntype = match testfn {
- StaticTestFn(..) | DynTestFn(..) => {
- ntest += 1;
- "test"
- }
- StaticBenchFn(..) | DynBenchFn(..) => {
- nbench += 1;
- "benchmark"
- }
- };
-
- writeln!(output, "{}: {}", name, fntype)?;
- st.write_log(|| format!("{} {}\n", fntype, name))?;
- }
-
- fn plural(count: u32, s: &str) -> String {
- match count {
- 1 => format!("{} {}", 1, s),
- n => format!("{} {}s", n, s),
- }
- }
-
- if !quiet {
- if ntest != 0 || nbench != 0 {
- writeln!(output)?;
- }
-
- writeln!(output, "{}, {}", plural(ntest, "test"), plural(nbench, "benchmark"))?;
- }
-
- Ok(())
-}
-
-// Updates `ConsoleTestState` depending on result of the test execution.
-fn handle_test_result(st: &mut ConsoleTestState, completed_test: CompletedTest) {
- let test = completed_test.desc;
- let stdout = completed_test.stdout;
- match completed_test.result {
- TestResult::TrOk => {
- st.passed += 1;
- st.not_failures.push((test, stdout));
- }
- TestResult::TrIgnored => st.ignored += 1,
- TestResult::TrAllowedFail => st.allowed_fail += 1,
- TestResult::TrBench(bs) => {
- st.metrics.insert_metric(
- test.name.as_slice(),
- bs.ns_iter_summ.median,
- bs.ns_iter_summ.max - bs.ns_iter_summ.min,
- );
- st.measured += 1
- }
- TestResult::TrFailed => {
- st.failed += 1;
- st.failures.push((test, stdout));
- }
- TestResult::TrFailedMsg(msg) => {
- st.failed += 1;
- let mut stdout = stdout;
- stdout.extend_from_slice(format!("note: {}", msg).as_bytes());
- st.failures.push((test, stdout));
- }
- TestResult::TrTimedFail => {
- st.failed += 1;
- st.time_failures.push((test, stdout));
- }
- }
-}
-
-// Handler for events that occur during test execution.
-// It is provided as a callback to the `run_tests` function.
-fn on_test_event(
- event: &TestEvent,
- st: &mut ConsoleTestState,
- out: &mut dyn OutputFormatter,
-) -> io::Result<()> {
- match (*event).clone() {
- TestEvent::TeFiltered(ref filtered_tests) => {
- st.total = filtered_tests.len();
- out.write_run_start(filtered_tests.len())?;
- }
- TestEvent::TeFilteredOut(filtered_out) => {
- st.filtered_out = filtered_out;
- }
- TestEvent::TeWait(ref test) => out.write_test_start(test)?,
- TestEvent::TeTimeout(ref test) => out.write_timeout(test)?,
- 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)?;
- handle_test_result(st, completed_test);
- }
- }
-
- Ok(())
-}
-
-/// A simple console test runner.
-/// Runs provided tests reporting process and results to the stdout.
-pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<bool> {
- let output = match term::stdout() {
- None => OutputLocation::Raw(io::stdout()),
- Some(t) => OutputLocation::Pretty(t),
- };
-
- let max_name_len = tests
- .iter()
- .max_by_key(|t| len_if_padded(*t))
- .map(|t| t.desc.name.as_slice().len())
- .unwrap_or(0);
-
- let is_multithreaded = opts.test_threads.unwrap_or_else(get_concurrency) > 1;
-
- let mut out: Box<dyn OutputFormatter> = match opts.format {
- OutputFormat::Pretty => Box::new(PrettyFormatter::new(
- output,
- opts.use_color(),
- max_name_len,
- is_multithreaded,
- opts.time_options,
- )),
- OutputFormat::Terse => {
- Box::new(TerseFormatter::new(output, opts.use_color(), max_name_len, is_multithreaded))
- }
- OutputFormat::Json => Box::new(JsonFormatter::new(output)),
- };
- let mut st = ConsoleTestState::new(opts)?;
-
- run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?;
-
- assert!(st.current_test_count() == st.total);
-
- out.write_run_finish(&st)
-}
-
-// Calculates padding for given test description.
-fn len_if_padded(t: &TestDescAndFn) -> usize {
- match t.testfn.padding() {
- NamePadding::PadNone => 0,
- NamePadding::PadOnRight => t.desc.name.as_slice().len(),
- }
-}