diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
commit | ef24de24a82fe681581cc130f342363c47c0969a (patch) | |
tree | 0d494f7e1a38b95c92426f58fe6eaa877303a86c /src/tools/compiletest | |
parent | Releasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip |
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/compiletest')
-rw-r--r-- | src/tools/compiletest/Cargo.toml | 1 | ||||
-rw-r--r-- | src/tools/compiletest/src/common.rs | 23 | ||||
-rw-r--r-- | src/tools/compiletest/src/header.rs | 14 | ||||
-rw-r--r-- | src/tools/compiletest/src/header/needs.rs | 4 | ||||
-rw-r--r-- | src/tools/compiletest/src/header/tests.rs | 2 | ||||
-rw-r--r-- | src/tools/compiletest/src/lib.rs | 12 | ||||
-rw-r--r-- | src/tools/compiletest/src/runtest.rs | 145 |
7 files changed, 125 insertions, 76 deletions
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index bb1fa6e92..31c6353e6 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -11,6 +11,7 @@ colored = "2" diff = "0.1.10" unified-diff = "0.2.1" getopts = "0.2" +indexmap = "2.0.0" miropt-test-tools = { path = "../miropt-test-tools" } build_helper = { path = "../build_helper" } tracing = "0.1" diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 0e1bf0c6c..1e9684555 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -8,6 +8,7 @@ use std::process::Command; use std::str::FromStr; use crate::util::{add_dylib_path, PathBufExt}; +use build_helper::git::GitConfig; use lazycell::AtomicLazyCell; use serde::de::{Deserialize, Deserializer, Error as _}; use std::collections::{HashMap, HashSet}; @@ -67,7 +68,7 @@ string_enum! { MirOpt => "mir-opt", Assembly => "assembly", CoverageMap => "coverage-map", - RunCoverage => "run-coverage", + CoverageRun => "coverage-run", } } @@ -78,7 +79,7 @@ impl Default for Mode { } impl Mode { - pub fn disambiguator(self) -> &'static str { + pub fn aux_dir_disambiguator(self) -> &'static str { // Pretty-printing tests could run concurrently, and if they do, // they need to keep their output segregated. match self { @@ -86,6 +87,15 @@ impl Mode { _ => "", } } + + pub fn output_dir_disambiguator(self) -> &'static str { + // Coverage tests use the same test files for multiple test modes, + // so each mode should have a separate output directory. + match self { + CoverageMap | CoverageRun => self.to_str(), + _ => "", + } + } } string_enum! { @@ -370,6 +380,10 @@ pub struct Config { pub target_cfgs: AtomicLazyCell<TargetCfgs>, pub nocapture: bool, + + // Needed both to construct build_helper::git::GitConfig + pub git_repository: String, + pub nightly_branch: String, } impl Config { @@ -441,6 +455,10 @@ impl Config { ]; ASM_SUPPORTED_ARCHS.contains(&self.target_cfg().arch.as_str()) } + + pub fn git_config(&self) -> GitConfig<'_> { + GitConfig { git_repository: &self.git_repository, nightly_branch: &self.nightly_branch } + } } #[derive(Debug, Clone)] @@ -699,6 +717,7 @@ pub fn output_testname_unique( let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str()); let debugger = config.debugger.as_ref().map_or("", |m| m.to_str()); PathBuf::from(&testpaths.file.file_stem().unwrap()) + .with_extra_extension(config.mode.output_dir_disambiguator()) .with_extra_extension(revision.unwrap_or("")) .with_extra_extension(mode) .with_extra_extension(debugger) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 269d93843..d6516cff6 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -322,7 +322,15 @@ impl TestProps { ); if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) { - self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned())); + self.compile_flags.extend( + flags + .split("'") + .enumerate() + .flat_map(|(i, f)| { + if i % 2 == 1 { vec![f] } else { f.split_whitespace().collect() } + }) + .map(|s| s.to_owned()), + ); } if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() { panic!("`compiler-flags` directive should be spelled `compile-flags`"); @@ -903,11 +911,11 @@ pub fn make_test_description<R: Read>( let mut should_fail = false; let extra_directives: &[&str] = match config.mode { - // The run-coverage tests are treated as having these extra directives, + // The coverage-run tests are treated as having these extra directives, // without needing to specify them manually in every test file. // (Some of the comments below have been copied over from // `tests/run-make/coverage-reports/Makefile`, which no longer exists.) - Mode::RunCoverage => { + Mode::CoverageRun => { &[ "needs-profiler-support", // FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 2b7a4387c..4a40fb55f 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -241,8 +241,8 @@ impl CachedNeedsConditions { profiler_support: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(), xray: config.target_cfg().xray, - // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find - // whether `rust-lld` is present in the compiler under test. + // For tests using the `needs-rust-lld` directive (e.g. for `-Clink-self-contained=+linker`), + // we need to find whether `rust-lld` is present in the compiler under test. // // The --compile-lib-path is the path to host shared libraries, but depends on the OS. For // example: diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 2fd80b52c..85e745bed 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -126,6 +126,8 @@ impl ConfigBuilder { self.host.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), "--target", self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), + "--git-repository=", + "--nightly-branch=", ]; let mut args: Vec<String> = args.iter().map(ToString::to_string).collect(); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 619ff9b32..bb09c03ef 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -144,7 +144,9 @@ pub fn parse_config(args: Vec<String>) -> Config { .optflag("h", "help", "show this message") .reqopt("", "channel", "current Rust channel", "CHANNEL") .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries") - .optopt("", "edition", "default Rust edition", "EDITION"); + .optopt("", "edition", "default Rust edition", "EDITION") + .reqopt("", "git-repository", "name of the git repository", "ORG/REPO") + .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH"); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { @@ -307,6 +309,9 @@ pub fn parse_config(args: Vec<String>) -> Config { target_cfgs: AtomicLazyCell::new(), nocapture: matches.opt_present("nocapture"), + + git_repository: matches.opt_str("git-repository").unwrap(), + nightly_branch: matches.opt_str("nightly-branch").unwrap(), } } @@ -609,9 +614,10 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> { return Ok(vec![]); } let files = - get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]); + get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])? + .unwrap_or(vec![]); // Add new test cases to the list, it will be convenient in daily development. - let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]); + let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]); let all_paths = [&files[..], &untracked_files[..]].concat(); let full_paths = { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 657d074b3..63e8ba7c7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -6,7 +6,7 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc}; use crate::common::{CompareMode, FailMode, PassMode}; use crate::common::{Config, TestPaths}; -use crate::common::{CoverageMap, Pretty, RunCoverage, RunPassValgrind}; +use crate::common::{CoverageMap, CoverageRun, Pretty, RunPassValgrind}; use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP, UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; @@ -15,6 +15,7 @@ use crate::json; use crate::read2::{read2_abbreviated, Truncated}; use crate::util::{add_dylib_path, dylib_env_var, logv, PathBufExt}; use crate::ColorConfig; +use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile}; use regex::{Captures, Regex}; use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; @@ -229,6 +230,7 @@ enum Emit { None, Metadata, LlvmIr, + Mir, Asm, LinkArgsAsm, } @@ -255,7 +257,7 @@ impl<'test> TestCx<'test> { Assembly => self.run_assembly_test(), JsDocTest => self.run_js_doc_test(), CoverageMap => self.run_coverage_map_test(), - RunCoverage => self.run_coverage_test(), + CoverageRun => self.run_coverage_run_test(), } } @@ -508,7 +510,7 @@ impl<'test> TestCx<'test> { } } - fn run_coverage_test(&self) { + fn run_coverage_run_test(&self) { let should_run = self.run_if_enabled(); let proc_res = self.compile_test(should_run, Emit::None); @@ -547,7 +549,7 @@ impl<'test> TestCx<'test> { let mut profraw_paths = vec![profraw_path]; let mut bin_paths = vec![self.make_exe_name()]; - if self.config.suite == "run-coverage-rustdoc" { + if self.config.suite == "coverage-run-rustdoc" { self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths); } @@ -2191,7 +2193,7 @@ impl<'test> TestCx<'test> { || self.is_vxworks_pure_static() || self.config.target.contains("bpf") || !self.config.target_cfg().dynamic_linking - || self.config.mode == RunCoverage + || matches!(self.config.mode, CoverageMap | CoverageRun) { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible @@ -2335,17 +2337,14 @@ impl<'test> TestCx<'test> { rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX"); rustc.arg("-Ztranslate-remapped-path-to-local-path=no"); - // #[cfg(not(bootstrap))]: After beta bump, this should **always** run. - if !(self.config.stage_id.starts_with("stage1-") && self.config.suite == "ui-fulldeps") { - // Hide Cargo dependency sources from ui tests to make sure the error message doesn't - // change depending on whether $CARGO_HOME is remapped or not. If this is not present, - // when $CARGO_HOME is remapped the source won't be shown, and when it's not remapped the - // source will be shown, causing a blessing hell. - rustc.arg("-Z").arg(format!( - "ignore-directory-in-diagnostics-source-blocks={}", - home::cargo_home().expect("failed to find cargo home").to_str().unwrap() - )); - } + // Hide Cargo dependency sources from ui tests to make sure the error message doesn't + // change depending on whether $CARGO_HOME is remapped or not. If this is not present, + // when $CARGO_HOME is remapped the source won't be shown, and when it's not remapped the + // source will be shown, causing a blessing hell. + rustc.arg("-Z").arg(format!( + "ignore-directory-in-diagnostics-source-blocks={}", + home::cargo_home().expect("failed to find cargo home").to_str().unwrap() + )); // Optionally prevent default --sysroot if specified in test compile-flags. if !self.props.compile_flags.iter().any(|flag| flag.starts_with("--sysroot")) @@ -2396,7 +2395,7 @@ impl<'test> TestCx<'test> { } } DebugInfo => { /* debuginfo tests must be unoptimized */ } - CoverageMap | RunCoverage => { + CoverageMap | CoverageRun => { // Coverage mappings and coverage reports are affected by // optimization level, so they ignore the optimize-tests // setting and set an optimization level in their mode's @@ -2471,7 +2470,7 @@ impl<'test> TestCx<'test> { } CoverageMap => { rustc.arg("-Cinstrument-coverage"); - // These tests only compile to MIR, so they don't need the + // These tests only compile to LLVM IR, so they don't need the // profiler runtime to be present. rustc.arg("-Zno-profiler-runtime"); // Coverage mappings are sensitive to MIR optimizations, and @@ -2479,12 +2478,12 @@ impl<'test> TestCx<'test> { // by `compile-flags`. rustc.arg("-Copt-level=2"); } - RunCoverage => { + CoverageRun => { rustc.arg("-Cinstrument-coverage"); // Coverage reports are sometimes sensitive to optimizations, - // and the current snapshots assume no optimization unless + // and the current snapshots assume `opt-level=2` unless // overridden by `compile-flags`. - rustc.arg("-Copt-level=0"); + rustc.arg("-Copt-level=2"); } RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake | CodegenUnits | JsDocTest | Assembly => { @@ -2509,6 +2508,9 @@ impl<'test> TestCx<'test> { Emit::LlvmIr => { rustc.args(&["--emit", "llvm-ir"]); } + Emit::Mir => { + rustc.args(&["--emit", "mir"]); + } Emit::Asm => { rustc.args(&["--emit", "asm"]); } @@ -2718,7 +2720,7 @@ impl<'test> TestCx<'test> { fn aux_output_dir_name(&self) -> PathBuf { self.output_base_dir() .join("auxiliary") - .with_extra_extension(self.config.mode.disambiguator()) + .with_extra_extension(self.config.mode.aux_dir_disambiguator()) } /// Generates a unique name for the test, such as `testname.revision.mode`. @@ -3544,10 +3546,6 @@ impl<'test> TestCx<'test> { cmd.env("RUSTDOC", cwd.join(rustdoc)); } - if let Some(ref rust_demangler) = self.config.rust_demangler_path { - cmd.env("RUST_DEMANGLER", cwd.join(rust_demangler)); - } - if let Some(ref node) = self.config.nodejs { cmd.env("NODE", node); } @@ -3964,7 +3962,7 @@ impl<'test> TestCx<'test> { // And finally, compile the fixed code and make sure it both // succeeds and has no diagnostics. let rustc = self.make_compile_args( - &self.testpaths.file.with_extension(UI_FIXED), + &self.expected_output_path(UI_FIXED), TargetLocation::ThisFile(self.make_exe_name()), emit_metadata, AllowUnused::No, @@ -3987,14 +3985,20 @@ impl<'test> TestCx<'test> { fn run_mir_opt_test(&self) { let pm = self.pass_mode(); let should_run = self.should_run(pm); - let emit_metadata = self.should_emit_metadata(pm); - let passes = self.get_passes(); - let proc_res = self.compile_test_with_passes(should_run, emit_metadata, passes); - self.check_mir_dump(); + let mut test_info = files_for_miropt_test( + &self.testpaths.file, + self.config.get_pointer_width(), + self.config.target_cfg().panic.for_miropt_test_tools(), + ); + + let passes = std::mem::take(&mut test_info.passes); + + let proc_res = self.compile_test_with_passes(should_run, Emit::Mir, passes); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); } + self.check_mir_dump(test_info); if let WillExecute::Yes = should_run { let proc_res = self.exec_compiled_test(); @@ -4005,37 +4009,12 @@ impl<'test> TestCx<'test> { } } - fn get_passes(&self) -> Vec<String> { - let files = miropt_test_tools::files_for_miropt_test( - &self.testpaths.file, - self.config.get_pointer_width(), - self.config.target_cfg().panic.for_miropt_test_tools(), - ); - - let mut out = Vec::new(); - - for miropt_test_tools::MiroptTestFiles { - from_file: _, - to_file: _, - expected_file: _, - passes, - } in files - { - out.extend(passes); - } - out - } - - fn check_mir_dump(&self) { + fn check_mir_dump(&self, test_info: MiroptTest) { let test_dir = self.testpaths.file.parent().unwrap(); let test_crate = self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace("-", "_"); - let suffix = miropt_test_tools::output_file_suffix( - &self.testpaths.file, - self.config.get_pointer_width(), - self.config.target_cfg().panic.for_miropt_test_tools(), - ); + let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info; if self.config.bless { for e in @@ -4050,14 +4029,7 @@ impl<'test> TestCx<'test> { } } - let files = miropt_test_tools::files_for_miropt_test( - &self.testpaths.file, - self.config.get_pointer_width(), - self.config.target_cfg().panic.for_miropt_test_tools(), - ); - for miropt_test_tools::MiroptTestFiles { from_file, to_file, expected_file, passes: _ } in - files - { + for MiroptTestFile { from_file, to_file, expected_file } in files { let dumped_string = if let Some(after) = to_file { self.diff_mir_files(from_file.into(), after.into()) } else { @@ -4098,6 +4070,14 @@ impl<'test> TestCx<'test> { } } } + + if run_filecheck { + let output_path = self.output_base_name().with_extension("mir"); + let proc_res = self.verify_with_filecheck(&output_path); + if !proc_res.status.success() { + self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res); + } + } } fn diff_mir_files(&self, before: PathBuf, after: PathBuf) -> String { @@ -4261,6 +4241,39 @@ impl<'test> TestCx<'test> { V0_BACK_REF_RE.replace_all(&normalized, V0_BACK_REF_PLACEHOLDER).into_owned(); } + // AllocId are numbered globally in a compilation session. This can lead to changes + // depending on the exact compilation flags and host architecture. Meanwhile, we want + // to keep them numbered, to see if the same id appears multiple times. + // So we remap to deterministic numbers that only depend on the subset of allocations + // that actually appear in the output. + // We use uppercase ALLOC to distinguish from the non-normalized version. + { + let mut seen_allocs = indexmap::IndexSet::new(); + + // The alloc-id appears in pretty-printed allocations. + let re = Regex::new(r"╾─*a(lloc)?([0-9]+)(\+0x[0-9]+)?─*╼").unwrap(); + normalized = re + .replace_all(&normalized, |caps: &Captures<'_>| { + // Renumber the captured index. + let index = caps.get(2).unwrap().as_str().to_string(); + let (index, _) = seen_allocs.insert_full(index); + let offset = caps.get(3).map_or("", |c| c.as_str()); + // Do not bother keeping it pretty, just make it deterministic. + format!("╾ALLOC{index}{offset}╼") + }) + .into_owned(); + + // The alloc-id appears in a sentence. + let re = Regex::new(r"\balloc([0-9]+)\b").unwrap(); + normalized = re + .replace_all(&normalized, |caps: &Captures<'_>| { + let index = caps.get(1).unwrap().as_str().to_string(); + let (index, _) = seen_allocs.insert_full(index); + format!("ALLOC{index}") + }) + .into_owned(); + } + // Custom normalization rules for rule in custom_rules { let re = Regex::new(&rule.0).expect("bad regex in custom normalization rule"); |