Rollup merge of #102794 - dtolnay:termination, r=thomcc
Make tests capture the error printed by a Result return An error returned by tests previously would get written directly to stderr, instead of to the capture buffer set up by the test harness. This PR makes it write to the capture buffer so that it can be integrated as part of the test output by build tools such as `buck test`, since being able to read the error message returned by a test is pretty critical to debugging why the test failed. <br> **Before:** ```rust // tests/test.rs #[test] fn test() -> Result<(), &'static str> { println!("STDOUT"); eprintln!("STDERR"); Err("RESULT") } ``` ```console $ cargo build --test test $ target/debug/deps/test-???????????????? -Z unstable-options --format=json { "type": "suite", "event": "started", "test_count": 1 } { "type": "test", "event": "started", "name": "test" } Error: "RESULT" { "type": "test", "name": "test", "event": "failed", "stdout": "STDOUT\nSTDERR\n" } { "type": "suite", "event": "failed", "passed": 0, "failed": 1, "ignored": 0, "measured": 0, "filtered_out": 0, "exec_time": 0.00040313 } ``` **After:** ```console $ target/debug/deps/test-???????????????? -Z unstable-options --format=json { "type": "suite", "event": "started", "test_count": 1 } { "type": "test", "event": "started", "name": "test" } { "type": "test", "name": "test", "event": "failed", "stdout": "STDOUT\nSTDERR\nError: \"RESULT\"" } { "type": "suite", "event": "failed", "passed": 0, "failed": 1, "ignored": 0, "measured": 0, "filtered_out": 0, "exec_time": 0.000261894 } ```
This commit is contained in:
commit
302bf31826
@ -262,6 +262,7 @@ use crate::sys_common::memchr;
|
||||
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
pub use self::buffered::WriterPanicked;
|
||||
pub(crate) use self::stdio::attempt_print_to_stderr;
|
||||
#[unstable(feature = "internal_output_capture", issue = "none")]
|
||||
#[doc(no_inline, hidden)]
|
||||
pub use self::stdio::set_output_capture;
|
||||
|
@ -999,7 +999,18 @@ fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str)
|
||||
where
|
||||
T: Write,
|
||||
{
|
||||
if OUTPUT_CAPTURE_USED.load(Ordering::Relaxed)
|
||||
if print_to_buffer_if_capture_used(args) {
|
||||
// Successfully wrote to capture buffer.
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(e) = global_s().write_fmt(args) {
|
||||
panic!("failed printing to {label}: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
fn print_to_buffer_if_capture_used(args: fmt::Arguments<'_>) -> bool {
|
||||
OUTPUT_CAPTURE_USED.load(Ordering::Relaxed)
|
||||
&& OUTPUT_CAPTURE.try_with(|s| {
|
||||
// Note that we completely remove a local sink to write to in case
|
||||
// our printing recursively panics/prints, so the recursive
|
||||
@ -1009,14 +1020,19 @@ where
|
||||
s.set(Some(w));
|
||||
})
|
||||
}) == Ok(Some(()))
|
||||
{
|
||||
// Successfully wrote to capture buffer.
|
||||
}
|
||||
|
||||
/// Used by impl Termination for Result to print error after `main` or a test
|
||||
/// has returned. Should avoid panicking, although we can't help it if one of
|
||||
/// the Display impls inside args decides to.
|
||||
pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) {
|
||||
if print_to_buffer_if_capture_used(args) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(e) = global_s().write_fmt(args) {
|
||||
panic!("failed printing to {label}: {e}");
|
||||
}
|
||||
// Ignore error if the write fails, for example because stderr is already
|
||||
// closed. There is not much point panicking at this point.
|
||||
let _ = stderr().write_fmt(args);
|
||||
}
|
||||
|
||||
#[unstable(
|
||||
|
@ -2200,9 +2200,7 @@ impl<T: Termination, E: fmt::Debug> Termination for Result<T, E> {
|
||||
match self {
|
||||
Ok(val) => val.report(),
|
||||
Err(err) => {
|
||||
// Ignore error if the write fails, for example because stderr is
|
||||
// already closed. There is not much point panicking at this point.
|
||||
let _ = writeln!(io::stderr(), "Error: {err:?}");
|
||||
io::attempt_print_to_stderr(format_args_nl!("Error: {err:?}"));
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user