Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libtest: Print the total time taken to execute a test suite #75752

Merged
merged 2 commits into from
Nov 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion library/test/src/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::fs::File;
use std::io;
use std::io::prelude::Write;
use std::time::Instant;

use super::{
bench::fmt_bench_samples,
Expand All @@ -14,7 +15,7 @@ use super::{
options::{Options, OutputFormat},
run_tests,
test_result::TestResult,
time::TestExecTime,
time::{TestExecTime, TestSuiteExecTime},
types::{NamePadding, TestDesc, TestDescAndFn},
};

Expand Down Expand Up @@ -49,6 +50,7 @@ pub struct ConsoleTestState {
pub allowed_fail: usize,
pub filtered_out: usize,
pub measured: usize,
pub exec_time: Option<TestSuiteExecTime>,
pub metrics: MetricMap,
pub failures: Vec<(TestDesc, Vec<u8>)>,
pub not_failures: Vec<(TestDesc, Vec<u8>)>,
Expand All @@ -72,6 +74,7 @@ impl ConsoleTestState {
allowed_fail: 0,
filtered_out: 0,
measured: 0,
exec_time: None,
metrics: MetricMap::new(),
failures: Vec::new(),
not_failures: Vec::new(),
Expand Down Expand Up @@ -277,7 +280,14 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
};
let mut st = ConsoleTestState::new(opts)?;

// Prevent the usage of `Instant` in some cases:
// - It's currently not supported for wasm targets.
// - We disable it for miri because it's not available when isolation is enabled.
let is_instant_supported = !cfg!(target_arch = "wasm32") && !cfg!(miri);

let start_time = is_instant_supported.then(Instant::now);
run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?;
st.exec_time = start_time.map(|t| TestSuiteExecTime(t.elapsed()));

assert!(st.current_test_count() == st.total);

Expand Down
15 changes: 11 additions & 4 deletions library/test/src/formatters/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl<T: Write> JsonFormatter<T> {
evt
))?;
if let Some(exec_time) = exec_time {
self.write_message(&*format!(r#", "exec_time": "{}""#, exec_time))?;
self.write_message(&*format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()))?;
}
if let Some(stdout) = stdout {
self.write_message(&*format!(r#", "stdout": "{}""#, EscapedString(stdout)))?;
Expand Down Expand Up @@ -162,24 +162,31 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
}

fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
self.writeln_message(&*format!(
self.write_message(&*format!(
"{{ \"type\": \"suite\", \
\"event\": \"{}\", \
\"passed\": {}, \
\"failed\": {}, \
\"allowed_fail\": {}, \
\"ignored\": {}, \
\"measured\": {}, \
\"filtered_out\": {} }}",
\"filtered_out\": {}",
if state.failed == 0 { "ok" } else { "failed" },
state.passed,
state.failed + state.allowed_fail,
state.allowed_fail,
state.ignored,
state.measured,
state.filtered_out
state.filtered_out,
))?;

if let Some(ref exec_time) = state.exec_time {
let time_str = format!(", \"exec_time\": {}", exec_time.0.as_secs_f64());
self.write_message(&time_str)?;
}

self.writeln_message(" }")?;

Ok(state.failed == 0)
}
}
Expand Down
11 changes: 9 additions & 2 deletions library/test/src/formatters/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {

let s = if state.allowed_fail > 0 {
format!(
". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n",
". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out",
state.passed,
state.failed + state.allowed_fail,
state.allowed_fail,
Expand All @@ -269,13 +269,20 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
)
} else {
format!(
". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
". {} passed; {} failed; {} ignored; {} measured; {} filtered out",
state.passed, state.failed, state.ignored, state.measured, state.filtered_out
)
};

self.write_plain(&s)?;

if let Some(ref exec_time) = state.exec_time {
let time_str = format!("; finished in {}", exec_time);
self.write_plain(&time_str)?;
}

self.write_plain("\n\n")?;

Ok(success)
}
}
11 changes: 9 additions & 2 deletions library/test/src/formatters/terse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {

let s = if state.allowed_fail > 0 {
format!(
". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n",
". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out",
state.passed,
state.failed + state.allowed_fail,
state.allowed_fail,
Expand All @@ -246,13 +246,20 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
)
} else {
format!(
". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
". {} passed; {} failed; {} ignored; {} measured; {} filtered out",
state.passed, state.failed, state.ignored, state.measured, state.filtered_out
)
};

self.write_plain(&s)?;

if let Some(ref exec_time) = state.exec_time {
let time_str = format!("; finished in {}", exec_time);
self.write_plain(&time_str)?;
}

self.write_plain("\n\n")?;

Ok(success)
}
}
1 change: 1 addition & 0 deletions library/test/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ fn should_sort_failures_before_printing_them() {
allowed_fail: 0,
filtered_out: 0,
measured: 0,
exec_time: None,
metrics: MetricMap::new(),
failures: vec![(test_b, Vec::new()), (test_a, Vec::new())],
options: Options::new(),
Expand Down
15 changes: 13 additions & 2 deletions library/test/src/time.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Module `time` contains everything related to the time measurement of unit tests
//! execution.
//! Two main purposes of this module:
//! The purposes of this module:
//! - Check whether test is timed out.
//! - Provide helpers for `report-time` and `measure-time` options.
//! - Provide newtypes for executions times.

use std::env;
use std::fmt;
Expand Down Expand Up @@ -60,7 +61,7 @@ pub fn get_default_test_timeout() -> Instant {
Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S)
}

/// The meassured execution time of a unit test.
/// The measured execution time of a unit test.
#[derive(Debug, Clone, PartialEq)]
pub struct TestExecTime(pub Duration);

Expand All @@ -70,6 +71,16 @@ impl fmt::Display for TestExecTime {
}
}

/// The measured execution time of the whole test suite.
#[derive(Debug, Clone, Default, PartialEq)]
pub struct TestSuiteExecTime(pub Duration);

impl fmt::Display for TestSuiteExecTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:.2}s", self.0.as_secs_f64())
}
}

/// Structure denoting time limits for test execution.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct TimeThreshold {
Expand Down
6 changes: 3 additions & 3 deletions src/test/run-make-fulldeps/libtest-json/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ all:
cat $(OUTPUT_FILE_DEFAULT) | "$(PYTHON)" validate_json.py
cat $(OUTPUT_FILE_STDOUT_SUCCESS) | "$(PYTHON)" validate_json.py

# Compare to output file
diff output-default.json $(OUTPUT_FILE_DEFAULT)
diff output-stdout-success.json $(OUTPUT_FILE_STDOUT_SUCCESS)
# Normalize the actual output and compare to expected output file
cat $(OUTPUT_FILE_DEFAULT) | sed 's/"exec_time": [0-9.]*/"exec_time": $$TIME/' | diff output-default.json -
cat $(OUTPUT_FILE_STDOUT_SUCCESS) | sed 's/"exec_time": [0-9.]*/"exec_time": $$TIME/' | diff output-stdout-success.json -
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
{ "type": "test", "name": "c", "event": "ok" }
{ "type": "test", "event": "started", "name": "d" }
{ "type": "test", "name": "d", "event": "ignored" }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": 0 }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
{ "type": "test", "name": "c", "event": "ok", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:15:5\n" }
{ "type": "test", "event": "started", "name": "d" }
{ "type": "test", "name": "d", "event": "ignored" }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": 0 }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "allowed_fail": 0, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
1 change: 1 addition & 0 deletions src/test/rustdoc-ui/cfg-test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// check-pass
// compile-flags:--test --test-args --test-threads=1
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"

// Crates like core have doctests gated on `cfg(not(test))` so we need to make
// sure `cfg(test)` is not active when running `rustdoc --test`.
Expand Down
6 changes: 3 additions & 3 deletions src/test/rustdoc-ui/cfg-test.stdout
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

running 2 tests
test $DIR/cfg-test.rs - Bar (line 26) ... ok
test $DIR/cfg-test.rs - Foo (line 18) ... ok
test $DIR/cfg-test.rs - Bar (line 27) ... ok
test $DIR/cfg-test.rs - Foo (line 19) ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

1 change: 1 addition & 0 deletions src/test/rustdoc-ui/doc-test-doctest-feature.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// check-pass
// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"

// Make sure `cfg(doctest)` is set when finding doctests but not inside
// the doctests.
Expand Down
4 changes: 2 additions & 2 deletions src/test/rustdoc-ui/doc-test-doctest-feature.stdout
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

running 1 test
test $DIR/doc-test-doctest-feature.rs - Foo (line 8) ... ok
test $DIR/doc-test-doctest-feature.rs - Foo (line 9) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

1 change: 1 addition & 0 deletions src/test/rustdoc-ui/doc-test-rustdoc-feature.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// check-pass
// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"

#![feature(doc_cfg)]

Expand Down
4 changes: 2 additions & 2 deletions src/test/rustdoc-ui/doc-test-rustdoc-feature.stdout
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

running 1 test
test $DIR/doc-test-rustdoc-feature.rs - Foo (line 9) ... ok
test $DIR/doc-test-rustdoc-feature.rs - Foo (line 10) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

1 change: 1 addition & 0 deletions src/test/rustdoc-ui/doctest-output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// aux-build:extern_macros.rs
// compile-flags:--test --test-args=--test-threads=1
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
// check-pass

//! ```
Expand Down
8 changes: 4 additions & 4 deletions src/test/rustdoc-ui/doctest-output.stdout
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

running 3 tests
test $DIR/doctest-output.rs - (line 7) ... ok
test $DIR/doctest-output.rs - ExpandedStruct (line 23) ... ok
test $DIR/doctest-output.rs - foo::bar (line 17) ... ok
test $DIR/doctest-output.rs - (line 8) ... ok
test $DIR/doctest-output.rs - ExpandedStruct (line 24) ... ok
test $DIR/doctest-output.rs - foo::bar (line 18) ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

1 change: 1 addition & 0 deletions src/test/rustdoc-ui/failed-doctest-compile-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
// failure-status: 101

/// ```compile_fail
Expand Down
8 changes: 4 additions & 4 deletions src/test/rustdoc-ui/failed-doctest-compile-fail.stdout
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@

running 1 test
test $DIR/failed-doctest-compile-fail.rs - Foo (line 8) ... FAILED
test $DIR/failed-doctest-compile-fail.rs - Foo (line 9) ... FAILED

failures:

---- $DIR/failed-doctest-compile-fail.rs - Foo (line 8) stdout ----
---- $DIR/failed-doctest-compile-fail.rs - Foo (line 9) stdout ----
Test compiled successfully, but it's marked `compile_fail`.

failures:
$DIR/failed-doctest-compile-fail.rs - Foo (line 8)
$DIR/failed-doctest-compile-fail.rs - Foo (line 9)

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

1 change: 1 addition & 0 deletions src/test/rustdoc-ui/failed-doctest-missing-codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
// failure-status: 101

/// ```compile_fail,E0004
Expand Down
10 changes: 5 additions & 5 deletions src/test/rustdoc-ui/failed-doctest-missing-codes.stdout
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

running 1 test
test $DIR/failed-doctest-missing-codes.rs - Foo (line 8) ... FAILED
test $DIR/failed-doctest-missing-codes.rs - Foo (line 9) ... FAILED

failures:

---- $DIR/failed-doctest-missing-codes.rs - Foo (line 8) stdout ----
---- $DIR/failed-doctest-missing-codes.rs - Foo (line 9) stdout ----
error[E0308]: mismatched types
--> $DIR/failed-doctest-missing-codes.rs:9:13
--> $DIR/failed-doctest-missing-codes.rs:10:13
|
LL | let x: () = 5i32;
| -- ^^^^ expected `()`, found `i32`
Expand All @@ -19,7 +19,7 @@ For more information about this error, try `rustc --explain E0308`.
Some expected error codes were not found: ["E0004"]

failures:
$DIR/failed-doctest-missing-codes.rs - Foo (line 8)
$DIR/failed-doctest-missing-codes.rs - Foo (line 9)

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

1 change: 1 addition & 0 deletions src/test/rustdoc-ui/failed-doctest-output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// compile-flags:--test --test-args --test-threads=1
// rustc-env:RUST_BACKTRACE=0
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
// failure-status: 101

// doctest fails at runtime
Expand Down
Loading