Skip to content

Commit 84b6025

Browse files
Rollup merge of #144805 - Zalathar:proc-res, r=jieyouxu
compiletest: Preliminary cleanup of `ProcRes` printing/unwinding While experimenting with changes to how compiletest handles output capture, error reporting, and unwinding, I repeatedly ran in to difficulties with this core code for reporting test failures caused by a subprocess. There should be no change in compiletest output. r? jieyouxu
2 parents c6d3a55 + 1063b0f commit 84b6025

File tree

3 files changed

+56
-45
lines changed

3 files changed

+56
-45
lines changed

src/tools/compiletest/src/runtest.rs

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,10 @@ impl<'test> TestCx<'test> {
354354
}
355355
} else {
356356
if proc_res.status.success() {
357-
{
358-
self.error(&format!("{} test did not emit an error", self.config.mode));
359-
if self.config.mode == crate::common::TestMode::Ui {
360-
println!("note: by default, ui tests are expected not to compile");
361-
}
362-
proc_res.fatal(None, || ());
363-
};
357+
let err = &format!("{} test did not emit an error", self.config.mode);
358+
let extra_note = (self.config.mode == crate::common::TestMode::Ui)
359+
.then_some("note: by default, ui tests are expected not to compile");
360+
self.fatal_proc_rec_general(err, extra_note, proc_res, || ());
364361
}
365362

366363
if !self.props.dont_check_failure_status {
@@ -606,7 +603,10 @@ impl<'test> TestCx<'test> {
606603
);
607604
} else {
608605
for pattern in missing_patterns {
609-
self.error(&format!("error pattern '{}' not found!", pattern));
606+
println!(
607+
"\n{prefix}: error pattern '{pattern}' not found!",
608+
prefix = self.error_prefix()
609+
);
610610
}
611611
self.fatal_proc_rec("multiple error patterns not found", proc_res);
612612
}
@@ -824,10 +824,11 @@ impl<'test> TestCx<'test> {
824824
// - only known line - meh, but suggested
825825
// - others are not worth suggesting
826826
if !unexpected.is_empty() {
827-
self.error(&format!(
828-
"{} diagnostics reported in JSON output but not expected in test file",
829-
unexpected.len(),
830-
));
827+
println!(
828+
"\n{prefix}: {n} diagnostics reported in JSON output but not expected in test file",
829+
prefix = self.error_prefix(),
830+
n = unexpected.len(),
831+
);
831832
for error in &unexpected {
832833
print_error(error);
833834
let mut suggestions = Vec::new();
@@ -857,10 +858,11 @@ impl<'test> TestCx<'test> {
857858
}
858859
}
859860
if !not_found.is_empty() {
860-
self.error(&format!(
861-
"{} diagnostics expected in test file but not reported in JSON output",
862-
not_found.len()
863-
));
861+
println!(
862+
"\n{prefix}: {n} diagnostics expected in test file but not reported in JSON output",
863+
prefix = self.error_prefix(),
864+
n = not_found.len(),
865+
);
864866
for error in &not_found {
865867
print_error(error);
866868
let mut suggestions = Vec::new();
@@ -1995,33 +1997,52 @@ impl<'test> TestCx<'test> {
19951997
output_base_name(self.config, self.testpaths, self.safe_revision())
19961998
}
19971999

1998-
fn error(&self, err: &str) {
2000+
/// Prefix to print before error messages. Normally just `error`, but also
2001+
/// includes the revision name for tests that use revisions.
2002+
#[must_use]
2003+
fn error_prefix(&self) -> String {
19992004
match self.revision {
2000-
Some(rev) => println!("\nerror in revision `{}`: {}", rev, err),
2001-
None => println!("\nerror: {}", err),
2005+
Some(rev) => format!("error in revision `{rev}`"),
2006+
None => format!("error"),
20022007
}
20032008
}
20042009

20052010
#[track_caller]
20062011
fn fatal(&self, err: &str) -> ! {
2007-
self.error(err);
2012+
println!("\n{prefix}: {err}", prefix = self.error_prefix());
20082013
error!("fatal error, panic: {:?}", err);
20092014
panic!("fatal error");
20102015
}
20112016

20122017
fn fatal_proc_rec(&self, err: &str, proc_res: &ProcRes) -> ! {
2013-
self.error(err);
2014-
proc_res.fatal(None, || ());
2018+
self.fatal_proc_rec_general(err, None, proc_res, || ());
20152019
}
20162020

2017-
fn fatal_proc_rec_with_ctx(
2021+
/// Underlying implementation of [`Self::fatal_proc_rec`], providing some
2022+
/// extra capabilities not needed by most callers.
2023+
fn fatal_proc_rec_general(
20182024
&self,
20192025
err: &str,
2026+
extra_note: Option<&str>,
20202027
proc_res: &ProcRes,
2021-
on_failure: impl FnOnce(Self),
2028+
callback_before_unwind: impl FnOnce(),
20222029
) -> ! {
2023-
self.error(err);
2024-
proc_res.fatal(None, || on_failure(*self));
2030+
println!("\n{prefix}: {err}", prefix = self.error_prefix());
2031+
2032+
// Some callers want to print additional notes after the main error message.
2033+
if let Some(note) = extra_note {
2034+
println!("{note}");
2035+
}
2036+
2037+
// Print the details and output of the subprocess that caused this test to fail.
2038+
println!("{}", proc_res.format_info());
2039+
2040+
// Some callers want print more context or show a custom diff before the unwind occurs.
2041+
callback_before_unwind();
2042+
2043+
// Use resume_unwind instead of panic!() to prevent a panic message + backtrace from
2044+
// compiletest, which is unnecessary noise.
2045+
std::panic::resume_unwind(Box::new(()));
20252046
}
20262047

20272048
// codegen tests (using FileCheck)
@@ -2080,7 +2101,7 @@ impl<'test> TestCx<'test> {
20802101
if cfg!(target_os = "freebsd") { "ISO-8859-1" } else { "UTF-8" }
20812102
}
20822103

2083-
fn compare_to_default_rustdoc(&mut self, out_dir: &Utf8Path) {
2104+
fn compare_to_default_rustdoc(&self, out_dir: &Utf8Path) {
20842105
if !self.config.has_html_tidy {
20852106
return;
20862107
}
@@ -2957,7 +2978,8 @@ pub struct ProcRes {
29572978
}
29582979

29592980
impl ProcRes {
2960-
pub fn print_info(&self) {
2981+
#[must_use]
2982+
pub fn format_info(&self) -> String {
29612983
fn render(name: &str, contents: &str) -> String {
29622984
let contents = json::extract_rendered(contents);
29632985
let contents = contents.trim_end();
@@ -2973,24 +2995,13 @@ impl ProcRes {
29732995
}
29742996
}
29752997

2976-
println!(
2998+
format!(
29772999
"status: {}\ncommand: {}\n{}\n{}\n",
29783000
self.status,
29793001
self.cmdline,
29803002
render("stdout", &self.stdout),
29813003
render("stderr", &self.stderr),
2982-
);
2983-
}
2984-
2985-
pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! {
2986-
if let Some(e) = err {
2987-
println!("\nerror: {}", e);
2988-
}
2989-
self.print_info();
2990-
on_failure();
2991-
// Use resume_unwind instead of panic!() to prevent a panic message + backtrace from
2992-
// compiletest, which is unnecessary noise.
2993-
std::panic::resume_unwind(Box::new(()));
3004+
)
29943005
}
29953006
}
29963007

src/tools/compiletest/src/runtest/rustdoc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ impl TestCx<'_> {
2828
}
2929
let res = self.run_command_to_procres(&mut cmd);
3030
if !res.status.success() {
31-
self.fatal_proc_rec_with_ctx("htmldocck failed!", &res, |mut this| {
32-
this.compare_to_default_rustdoc(&out_dir)
31+
self.fatal_proc_rec_general("htmldocck failed!", None, &res, || {
32+
self.compare_to_default_rustdoc(&out_dir);
3333
});
3434
}
3535
}

src/tools/compiletest/src/runtest/rustdoc_json.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ impl TestCx<'_> {
2929
);
3030

3131
if !res.status.success() {
32-
self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| {
32+
self.fatal_proc_rec_general("jsondocck failed!", None, &res, || {
3333
println!("Rustdoc Output:");
34-
proc_res.print_info();
34+
println!("{}", proc_res.format_info());
3535
})
3636
}
3737

0 commit comments

Comments
 (0)