diff options
Diffstat (limited to 'src/tools/compiletest')
| -rw-r--r-- | src/tools/compiletest/src/common.rs | 35 | ||||
| -rw-r--r-- | src/tools/compiletest/src/directives.rs | 10 | ||||
| -rw-r--r-- | src/tools/compiletest/src/directives/directive_names.rs | 2 | ||||
| -rw-r--r-- | src/tools/compiletest/src/directives/tests.rs | 18 | ||||
| -rw-r--r-- | src/tools/compiletest/src/lib.rs | 7 | ||||
| -rw-r--r-- | src/tools/compiletest/src/runtest.rs | 119 | ||||
| -rw-r--r-- | src/tools/compiletest/src/runtest/debuginfo.rs | 4 | ||||
| -rw-r--r-- | src/tools/compiletest/src/runtest/rustdoc.rs | 4 | ||||
| -rw-r--r-- | src/tools/compiletest/src/runtest/rustdoc_json.rs | 4 |
9 files changed, 120 insertions, 83 deletions
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index aceae3e3a3b..2d49b1a7097 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -279,6 +279,15 @@ pub struct Config { /// [`Self::rustc_path`]. pub stage0_rustc_path: Option<Utf8PathBuf>, + /// Path to the stage 1 or higher `rustc` used to obtain target information via + /// `--print=all-target-specs-json` and similar queries. + /// + /// Normally this is unset, because [`Self::rustc_path`] can be used instead. + /// But when running "stage 1" ui-fulldeps tests, `rustc_path` is a stage 0 + /// compiler, whereas target specs must be obtained from a stage 1+ compiler + /// (in case the JSON format has changed since the last bootstrap bump). + pub query_rustc_path: Option<Utf8PathBuf>, + /// Path to the `rustdoc`-under-test. Like [`Self::rustc_path`], this `rustdoc` is *staged*. pub rustdoc_path: Option<Utf8PathBuf>, @@ -712,6 +721,7 @@ impl Config { rustc_path: Utf8PathBuf::default(), cargo_path: Default::default(), stage0_rustc_path: Default::default(), + query_rustc_path: Default::default(), rustdoc_path: Default::default(), coverage_dump_path: Default::default(), python: Default::default(), @@ -917,7 +927,7 @@ pub struct TargetCfgs { impl TargetCfgs { fn new(config: &Config) -> TargetCfgs { - let mut targets: HashMap<String, TargetCfg> = serde_json::from_str(&rustc_output( + let mut targets: HashMap<String, TargetCfg> = serde_json::from_str(&query_rustc_output( config, &["--print=all-target-specs-json", "-Zunstable-options"], Default::default(), @@ -950,7 +960,7 @@ impl TargetCfgs { if config.target.ends_with(".json") || !envs.is_empty() { targets.insert( config.target.clone(), - serde_json::from_str(&rustc_output( + serde_json::from_str(&query_rustc_output( config, &[ "--print=target-spec-json", @@ -1009,10 +1019,13 @@ impl TargetCfgs { // which are respected for `--print=cfg` but not for `--print=all-target-specs-json`. The // code below extracts them from `--print=cfg`: make sure to only override fields that can // actually be changed with `-C` flags. - for config in - rustc_output(config, &["--print=cfg", "--target", &config.target], Default::default()) - .trim() - .lines() + for config in query_rustc_output( + config, + &["--print=cfg", "--target", &config.target], + Default::default(), + ) + .trim() + .lines() { let (name, value) = config .split_once("=\"") @@ -1113,7 +1126,7 @@ pub enum Endian { } fn builtin_cfg_names(config: &Config) -> HashSet<String> { - rustc_output( + query_rustc_output( config, &["--print=check-cfg", "-Zunstable-options", "--check-cfg=cfg()"], Default::default(), @@ -1128,7 +1141,7 @@ pub const KNOWN_CRATE_TYPES: &[&str] = &["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]; fn supported_crate_types(config: &Config) -> HashSet<String> { - let crate_types: HashSet<_> = rustc_output( + let crate_types: HashSet<_> = query_rustc_output( config, &["--target", &config.target, "--print=supported-crate-types", "-Zunstable-options"], Default::default(), @@ -1149,8 +1162,10 @@ fn supported_crate_types(config: &Config) -> HashSet<String> { crate_types } -fn rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String { - let mut command = Command::new(&config.rustc_path); +fn query_rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String { + let query_rustc_path = config.query_rustc_path.as_deref().unwrap_or(&config.rustc_path); + + let mut command = Command::new(query_rustc_path); add_dylib_path(&mut command, iter::once(&config.compile_lib_path)); command.args(&config.target_rustcflags).args(args); command.env("RUSTC_BOOTSTRAP", "1"); diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 54511f4fd08..13e694b7f03 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -203,6 +203,8 @@ pub struct TestProps { pub add_core_stubs: bool, /// Whether line annotatins are required for the given error kind. pub dont_require_annotations: HashSet<ErrorKind>, + /// Whether pretty printers should be disabled in gdb. + pub disable_gdb_pretty_printers: bool, } mod directives { @@ -251,6 +253,7 @@ mod directives { pub const ADD_CORE_STUBS: &'static str = "add-core-stubs"; // This isn't a real directive, just one that is probably mistyped often pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags"; + pub const DISABLE_GDB_PRETTY_PRINTERS: &'static str = "disable-gdb-pretty-printers"; } impl TestProps { @@ -306,6 +309,7 @@ impl TestProps { has_enzyme: false, add_core_stubs: false, dont_require_annotations: Default::default(), + disable_gdb_pretty_printers: false, } } @@ -654,6 +658,12 @@ impl TestProps { self.dont_require_annotations .insert(ErrorKind::expect_from_user_str(err_kind.trim())); } + + config.set_name_directive( + ln, + DISABLE_GDB_PRETTY_PRINTERS, + &mut self.disable_gdb_pretty_printers, + ); }, ); diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 7fc76a42e0c..099058bf051 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -18,6 +18,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-stdout", "check-test-line-numbers-match", "compile-flags", + "disable-gdb-pretty-printers", "doc-flags", "dont-check-compiler-stderr", "dont-check-compiler-stdout", @@ -67,6 +68,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-gnu", "ignore-haiku", "ignore-horizon", + "ignore-i586-unknown-linux-gnu", "ignore-i686-pc-windows-gnu", "ignore-i686-pc-windows-msvc", "ignore-illumos", diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs index 5682cc57b6f..30d8537b51a 100644 --- a/src/tools/compiletest/src/directives/tests.rs +++ b/src/tools/compiletest/src/directives/tests.rs @@ -203,22 +203,8 @@ impl ConfigBuilder { } args.push("--rustc-path".to_string()); - // This is a subtle/fragile thing. On rust-lang CI, there is no global - // `rustc`, and Cargo doesn't offer a convenient way to get the path to - // `rustc`. Fortunately bootstrap sets `RUSTC` for us, which is pointing - // to the stage0 compiler. - // - // Otherwise, if you are running compiletests's tests manually, you - // probably don't have `RUSTC` set, in which case this falls back to the - // global rustc. If your global rustc is too far out of sync with stage0, - // then this may cause confusing errors. Or if for some reason you don't - // have rustc in PATH, that would also fail. - args.push(std::env::var("RUSTC").unwrap_or_else(|_| { - eprintln!( - "warning: RUSTC not set, using global rustc (are you not running via bootstrap?)" - ); - "rustc".to_string() - })); + args.push(std::env::var("TEST_RUSTC").expect("must be configured by bootstrap")); + crate::parse_config(args) } } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index c712185733c..f5409e78341 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -63,6 +63,12 @@ pub fn parse_config(args: Vec<String>) -> Config { "path to rustc to use for compiling run-make recipes", "PATH", ) + .optopt( + "", + "query-rustc-path", + "path to rustc to use for querying target information (defaults to `--rustc-path`)", + "PATH", + ) .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH") .optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH") .reqopt("", "python", "path to python to use for doc tests", "PATH") @@ -354,6 +360,7 @@ pub fn parse_config(args: Vec<String>) -> Config { rustc_path: opt_path(matches, "rustc-path"), cargo_path: matches.opt_str("cargo-path").map(Utf8PathBuf::from), stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(Utf8PathBuf::from), + query_rustc_path: matches.opt_str("query-rustc-path").map(Utf8PathBuf::from), rustdoc_path: matches.opt_str("rustdoc-path").map(Utf8PathBuf::from), coverage_dump_path: matches.opt_str("coverage-dump-path").map(Utf8PathBuf::from), python: matches.opt_str("python").unwrap(), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f66d4f98f1f..f283a625f97 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -354,13 +354,10 @@ impl<'test> TestCx<'test> { } } else { if proc_res.status.success() { - { - self.error(&format!("{} test did not emit an error", self.config.mode)); - if self.config.mode == crate::common::TestMode::Ui { - println!("note: by default, ui tests are expected not to compile"); - } - proc_res.fatal(None, || ()); - }; + let err = &format!("{} test did not emit an error", self.config.mode); + let extra_note = (self.config.mode == crate::common::TestMode::Ui) + .then_some("note: by default, ui tests are expected not to compile.\nhint: use check-pass, build-pass, or run-pass directive to change this behavior."); + self.fatal_proc_rec_general(err, extra_note, proc_res, || ()); } if !self.props.dont_check_failure_status { @@ -606,7 +603,10 @@ impl<'test> TestCx<'test> { ); } else { for pattern in missing_patterns { - self.error(&format!("error pattern '{}' not found!", pattern)); + println!( + "\n{prefix}: error pattern '{pattern}' not found!", + prefix = self.error_prefix() + ); } self.fatal_proc_rec("multiple error patterns not found", proc_res); } @@ -765,12 +765,6 @@ impl<'test> TestCx<'test> { } if !unexpected.is_empty() || !not_found.is_empty() { - self.error(&format!( - "{} unexpected diagnostics reported, {} expected diagnostics not reported", - unexpected.len(), - not_found.len() - )); - // Emit locations in a format that is short (relative paths) but "clickable" in editors. // Also normalize path separators to `/`. let file_name = self @@ -794,19 +788,20 @@ impl<'test> TestCx<'test> { |suggestions: &mut Vec<_>, e: &Error, kind, line, msg, color, rank| { let mut ret = String::new(); if kind { - ret += &format!("{} {}", "with kind".color(color), e.kind); + ret += &format!("{} {}", "with different kind:".color(color), e.kind); } if line { if !ret.is_empty() { ret.push(' '); } - ret += &format!("{} {}", "on line".color(color), line_str(e)); + ret += &format!("{} {}", "on different line:".color(color), line_str(e)); } if msg { if !ret.is_empty() { ret.push(' '); } - ret += &format!("{} {}", "with message".color(color), e.msg.cyan()); + ret += + &format!("{} {}", "with different message:".color(color), e.msg.cyan()); } suggestions.push((ret, rank)); }; @@ -829,17 +824,21 @@ impl<'test> TestCx<'test> { // - only known line - meh, but suggested // - others are not worth suggesting if !unexpected.is_empty() { - let header = "--- reported in JSON output but not expected in test file ---"; - println!("{}", header.green()); + println!( + "\n{prefix}: {n} diagnostics reported in JSON output but not expected in test file", + prefix = self.error_prefix(), + n = unexpected.len(), + ); for error in &unexpected { print_error(error); let mut suggestions = Vec::new(); for candidate in ¬_found { + let kind_mismatch = candidate.kind != error.kind; let mut push_red_suggestion = |line, msg, rank| { push_suggestion( &mut suggestions, candidate, - candidate.kind != error.kind, + kind_mismatch, line, msg, Color::Red, @@ -851,26 +850,29 @@ impl<'test> TestCx<'test> { } else if candidate.line_num.is_some() && candidate.line_num == error.line_num { - push_red_suggestion(false, true, 1); + push_red_suggestion(false, true, if kind_mismatch { 2 } else { 1 }); } } show_suggestions(suggestions, "expected", Color::Red); } - println!("{}", "---".green()); } if !not_found.is_empty() { - let header = "--- expected in test file but not reported in JSON output ---"; - println!("{}", header.red()); + println!( + "\n{prefix}: {n} diagnostics expected in test file but not reported in JSON output", + prefix = self.error_prefix(), + n = not_found.len(), + ); for error in ¬_found { print_error(error); let mut suggestions = Vec::new(); for candidate in unexpected.iter().chain(&unimportant) { + let kind_mismatch = candidate.kind != error.kind; let mut push_green_suggestion = |line, msg, rank| { push_suggestion( &mut suggestions, candidate, - candidate.kind != error.kind, + kind_mismatch, line, msg, Color::Green, @@ -882,13 +884,12 @@ impl<'test> TestCx<'test> { } else if candidate.line_num.is_some() && candidate.line_num == error.line_num { - push_green_suggestion(false, true, 1); + push_green_suggestion(false, true, if kind_mismatch { 2 } else { 1 }); } } show_suggestions(suggestions, "reported", Color::Green); } - println!("{}", "---".red()); } panic!( "errors differ from expected\nstatus: {}\ncommand: {}\n", @@ -1996,33 +1997,52 @@ impl<'test> TestCx<'test> { output_base_name(self.config, self.testpaths, self.safe_revision()) } - fn error(&self, err: &str) { + /// Prefix to print before error messages. Normally just `error`, but also + /// includes the revision name for tests that use revisions. + #[must_use] + fn error_prefix(&self) -> String { match self.revision { - Some(rev) => println!("\nerror in revision `{}`: {}", rev, err), - None => println!("\nerror: {}", err), + Some(rev) => format!("error in revision `{rev}`"), + None => format!("error"), } } #[track_caller] fn fatal(&self, err: &str) -> ! { - self.error(err); + println!("\n{prefix}: {err}", prefix = self.error_prefix()); error!("fatal error, panic: {:?}", err); panic!("fatal error"); } fn fatal_proc_rec(&self, err: &str, proc_res: &ProcRes) -> ! { - self.error(err); - proc_res.fatal(None, || ()); + self.fatal_proc_rec_general(err, None, proc_res, || ()); } - fn fatal_proc_rec_with_ctx( + /// Underlying implementation of [`Self::fatal_proc_rec`], providing some + /// extra capabilities not needed by most callers. + fn fatal_proc_rec_general( &self, err: &str, + extra_note: Option<&str>, proc_res: &ProcRes, - on_failure: impl FnOnce(Self), + callback_before_unwind: impl FnOnce(), ) -> ! { - self.error(err); - proc_res.fatal(None, || on_failure(*self)); + println!("\n{prefix}: {err}", prefix = self.error_prefix()); + + // Some callers want to print additional notes after the main error message. + if let Some(note) = extra_note { + println!("{note}"); + } + + // Print the details and output of the subprocess that caused this test to fail. + println!("{}", proc_res.format_info()); + + // Some callers want print more context or show a custom diff before the unwind occurs. + callback_before_unwind(); + + // Use resume_unwind instead of panic!() to prevent a panic message + backtrace from + // compiletest, which is unnecessary noise. + std::panic::resume_unwind(Box::new(())); } // codegen tests (using FileCheck) @@ -2081,7 +2101,7 @@ impl<'test> TestCx<'test> { if cfg!(target_os = "freebsd") { "ISO-8859-1" } else { "UTF-8" } } - fn compare_to_default_rustdoc(&mut self, out_dir: &Utf8Path) { + fn compare_to_default_rustdoc(&self, out_dir: &Utf8Path) { if !self.config.has_html_tidy { return; } @@ -2547,6 +2567,11 @@ impl<'test> TestCx<'test> { }) .into_owned(); + // Normalize thread IDs in panic messages + normalized = static_regex!(r"thread '(?P<name>.*?)' \((rtid )?\d+\) panicked") + .replace_all(&normalized, "thread '$name' ($$TID) panicked") + .into_owned(); + normalized = normalized.replace("\t", "\\t"); // makes tabs visible // Remove test annotations like `//~ ERROR text` from the output, @@ -2958,7 +2983,8 @@ pub struct ProcRes { } impl ProcRes { - pub fn print_info(&self) { + #[must_use] + pub fn format_info(&self) -> String { fn render(name: &str, contents: &str) -> String { let contents = json::extract_rendered(contents); let contents = contents.trim_end(); @@ -2974,24 +3000,13 @@ impl ProcRes { } } - println!( + format!( "status: {}\ncommand: {}\n{}\n{}\n", self.status, self.cmdline, render("stdout", &self.stdout), render("stderr", &self.stderr), - ); - } - - pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! { - if let Some(e) = err { - println!("\nerror: {}", e); - } - self.print_info(); - on_failure(); - // Use resume_unwind instead of panic!() to prevent a panic message + backtrace from - // compiletest, which is unnecessary noise. - std::panic::resume_unwind(Box::new(())); + ) } } diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 471e4a4c819..6114afdc9df 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -259,7 +259,9 @@ impl TestCx<'_> { Some(version) => { println!("NOTE: compiletest thinks it is using GDB version {}", version); - if version > extract_gdb_version("7.4").unwrap() { + if !self.props.disable_gdb_pretty_printers + && version > extract_gdb_version("7.4").unwrap() + { // Add the directory containing the pretty printers to // GDB's script auto loading safe path script_str.push_str(&format!( diff --git a/src/tools/compiletest/src/runtest/rustdoc.rs b/src/tools/compiletest/src/runtest/rustdoc.rs index 236f021ce82..4a143aa5824 100644 --- a/src/tools/compiletest/src/runtest/rustdoc.rs +++ b/src/tools/compiletest/src/runtest/rustdoc.rs @@ -28,8 +28,8 @@ impl TestCx<'_> { } let res = self.run_command_to_procres(&mut cmd); if !res.status.success() { - self.fatal_proc_rec_with_ctx("htmldocck failed!", &res, |mut this| { - this.compare_to_default_rustdoc(&out_dir) + self.fatal_proc_rec_general("htmldocck failed!", None, &res, || { + self.compare_to_default_rustdoc(&out_dir); }); } } diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs index 4f35efedfde..083398f9274 100644 --- a/src/tools/compiletest/src/runtest/rustdoc_json.rs +++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs @@ -29,9 +29,9 @@ impl TestCx<'_> { ); if !res.status.success() { - self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| { + self.fatal_proc_rec_general("jsondocck failed!", None, &res, || { println!("Rustdoc Output:"); - proc_res.print_info(); + println!("{}", proc_res.format_info()); }) } |
