summaryrefslogtreecommitdiffstats
path: root/src/bootstrap/test.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/test.rs')
-rw-r--r--src/bootstrap/test.rs787
1 files changed, 341 insertions, 446 deletions
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index aedf1ecab..44cd84be7 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -5,15 +5,17 @@
use std::env;
use std::ffi::OsString;
-use std::fmt;
use std::fs;
use std::iter;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
+use clap_complete::shells;
+
use crate::builder::crate_description;
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
+use crate::cache::INTERNER;
use crate::compile;
use crate::config::TargetSelection;
use crate::dist;
@@ -28,44 +30,6 @@ use crate::{envify, CLang, DocTests, GitRepo, Mode};
const ADB_TEST_DIR: &str = "/data/local/tmp/work";
-/// The two modes of the test runner; tests or benchmarks.
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
-pub enum TestKind {
- /// Run `cargo test`.
- Test,
- /// Run `cargo bench`.
- Bench,
-}
-
-impl From<Kind> for TestKind {
- fn from(kind: Kind) -> Self {
- match kind {
- Kind::Test => TestKind::Test,
- Kind::Bench => TestKind::Bench,
- _ => panic!("unexpected kind in crate: {:?}", kind),
- }
- }
-}
-
-impl TestKind {
- // Return the cargo subcommand for this test kind
- fn subcommand(self) -> &'static str {
- match self {
- TestKind::Test => "test",
- TestKind::Bench => "bench",
- }
- }
-}
-
-impl fmt::Display for TestKind {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(match *self {
- TestKind::Test => "Testing",
- TestKind::Bench => "Benchmarking",
- })
- }
-}
-
fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
if !builder.fail_fast {
if !builder.try_run(cmd) {
@@ -93,26 +57,37 @@ fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct CrateJsonDocLint {
+pub struct CrateBootstrap {
+ path: Interned<PathBuf>,
host: TargetSelection,
}
-impl Step for CrateJsonDocLint {
+impl Step for CrateBootstrap {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/jsondoclint")
+ .path("src/tools/suggest-tests")
+ .path("src/tools/replace-version-placeholder")
+ .alias("tidyselftest")
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(CrateJsonDocLint { host: run.target });
+ for path in run.paths {
+ let path = INTERNER.intern_path(path.assert_single_path().path.clone());
+ run.builder.ensure(CrateBootstrap { host: run.target, path });
+ }
}
fn run(self, builder: &Builder<'_>) {
let bootstrap_host = builder.config.build;
let compiler = builder.compiler(0, bootstrap_host);
+ let mut path = self.path.to_str().unwrap();
+ if path == "tidyselftest" {
+ path = "src/tools/tidy";
+ }
let cargo = tool::prepare_tool_cargo(
builder,
@@ -120,47 +95,18 @@ impl Step for CrateJsonDocLint {
Mode::ToolBootstrap,
bootstrap_host,
"test",
- "src/tools/jsondoclint",
+ path,
SourceType::InTree,
&[],
);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct SuggestTestsCrate {
- host: TargetSelection,
-}
-
-impl Step for SuggestTestsCrate {
- type Output = ();
- const ONLY_HOSTS: bool = true;
- const DEFAULT: bool = true;
-
- fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/tools/suggest-tests")
- }
-
- fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(SuggestTestsCrate { host: run.target });
- }
-
- fn run(self, builder: &Builder<'_>) {
- let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
-
- let suggest_tests = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolBootstrap,
+ builder.info(&format!(
+ "{} {} stage0 ({})",
+ builder.kind.test_description(),
+ path,
bootstrap_host,
- "test",
- "src/tools/suggest-tests",
- SourceType::InTree,
- &[],
- );
- add_flags_and_try_run_tests(builder, &mut suggest_tests.into());
+ ));
+ let crate_name = path.rsplit_once('/').unwrap().1;
+ run_cargo_test(cargo, &[], &[], crate_name, compiler, bootstrap_host, builder);
}
}
@@ -209,7 +155,11 @@ You can skip linkcheck with --exclude src/tools/linkchecker"
SourceType::InTree,
&[],
);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "linkchecker", compiler, bootstrap_host, builder);
+
+ if builder.doc_tests == DocTests::No {
+ return;
+ }
// Build all the default documentation.
builder.default_doc(&[]);
@@ -315,7 +265,7 @@ impl Step for Cargotest {
builder,
cmd.arg(&cargo)
.arg(&out_dir)
- .args(builder.config.cmd.test_args())
+ .args(builder.config.test_args())
.env("RUSTC", builder.rustc(compiler))
.env("RUSTDOC", builder.rustdoc(compiler)),
);
@@ -345,7 +295,7 @@ impl Step for Cargo {
let compiler = builder.compiler(self.stage, self.host);
builder.ensure(tool::Cargo { compiler, target: self.host });
- let mut cargo = tool::prepare_tool_cargo(
+ let cargo = tool::prepare_tool_cargo(
builder,
compiler,
Mode::ToolRustc,
@@ -356,10 +306,8 @@ impl Step for Cargo {
&[],
);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
- cargo.arg("--").args(builder.config.cmd.test_args());
+ // NOTE: can't use `run_cargo_test` because we need to overwrite `PATH`
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "cargo", compiler, self.host, builder);
// Don't run cross-compile tests, we may not have cross-compiled libstd libs
// available.
@@ -367,10 +315,21 @@ impl Step for Cargo {
// Forcibly disable tests using nightly features since any changes to
// those features won't be able to land.
cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
-
cargo.env("PATH", &path_for_cargo(builder, compiler));
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::CargoPackage {
+ crates: vec!["cargo".into()],
+ target: self.host.triple.to_string(),
+ host: self.host.triple.to_string(),
+ stage: self.stage,
+ },
+ builder,
+ );
+
+ let _time = util::timeit(&builder);
+ add_flags_and_try_run_tests(builder, &mut cargo);
}
}
@@ -427,9 +386,7 @@ impl Step for RustAnalyzer {
cargo.env("SKIP_SLOW_TESTS", "1");
cargo.add_rustc_lib_path(builder, compiler);
- cargo.arg("--").args(builder.config.cmd.test_args());
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "rust-analyzer", compiler, host, builder);
}
}
@@ -472,17 +429,13 @@ impl Step for Rustfmt {
&[],
);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
let dir = testdir(builder, compiler.host);
t!(fs::create_dir_all(&dir));
cargo.env("RUSTFMT_TEST_DIR", dir);
cargo.add_rustc_lib_path(builder, compiler);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "rustfmt", compiler, host, builder);
}
}
@@ -528,12 +481,9 @@ impl Step for RustDemangler {
t!(fs::create_dir_all(&dir));
cargo.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler);
-
- cargo.arg("--").args(builder.config.cmd.test_args());
-
cargo.add_rustc_lib_path(builder, compiler);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "rust-demangler", compiler, host, builder);
}
}
@@ -656,10 +606,6 @@ impl Step for Miri {
);
cargo.add_rustc_lib_path(builder, compiler);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
// miri tests need to know about the stage sysroot
cargo.env("MIRI_SYSROOT", &miri_sysroot);
cargo.env("MIRI_HOST_SYSROOT", sysroot);
@@ -671,13 +617,31 @@ impl Step for Miri {
// Set the target.
cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
- // Forward test filters.
- cargo.arg("--").args(builder.config.cmd.test_args());
- // This can NOT be `add_flags_and_try_run_tests` since the Miri test runner
- // does not understand those flags!
- let mut cargo = Command::from(cargo);
- builder.run(&mut cargo);
+ // This can NOT be `run_cargo_test` since the Miri test runner
+ // does not understand the flags added by `add_flags_and_try_run_test`.
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
+ {
+ let _time = util::timeit(&builder);
+ builder.run(&mut cargo);
+ }
+
+ // Run it again for mir-opt-level 4 to catch some miscompilations.
+ if builder.config.test_args().is_empty() {
+ cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
+ // Optimizations can change backtraces
+ cargo.env("MIRI_SKIP_UI_CHECKS", "1");
+ // `MIRI_SKIP_UI_CHECKS` and `MIRI_BLESS` are incompatible
+ cargo.env_remove("MIRI_BLESS");
+ // Optimizations can change error locations and remove UB so don't run `fail` tests.
+ cargo.args(&["tests/pass", "tests/panic"]);
+
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
+ {
+ let _time = util::timeit(&builder);
+ builder.run(&mut cargo);
+ }
+ }
// # Run `cargo miri test`.
// This is just a smoke test (Miri's own CI invokes this in a bunch of different ways and ensures
@@ -700,7 +664,7 @@ impl Step for Miri {
.arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml"));
cargo.arg("--target").arg(target.rustc_target_arg());
cargo.arg("--tests"); // don't run doctests, they are too confused by the staging
- cargo.arg("--").args(builder.config.cmd.test_args());
+ cargo.arg("--").args(builder.config.test_args());
// Tell `cargo miri` where to find things.
cargo.env("MIRI_SYSROOT", &miri_sysroot);
@@ -710,7 +674,10 @@ impl Step for Miri {
cargo.env("RUST_BACKTRACE", "1");
let mut cargo = Command::from(cargo);
- builder.run(&mut cargo);
+ {
+ let _time = util::timeit(&builder);
+ builder.run(&mut cargo);
+ }
}
}
@@ -749,8 +716,7 @@ impl Step for CompiletestTest {
&[],
);
cargo.allow_features("test");
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "compiletest", compiler, host, builder);
}
}
@@ -793,20 +759,15 @@ impl Step for Clippy {
&[],
);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir());
cargo.env("HOST_LIBS", host_libs);
- cargo.arg("--").args(builder.config.cmd.test_args());
-
cargo.add_rustc_lib_path(builder, compiler);
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder);
- if builder.try_run(&mut cargo.into()) {
+ if builder.try_run(&mut cargo) {
// The tests succeeded; nothing to do.
return;
}
@@ -994,28 +955,6 @@ fn get_browser_ui_test_version(npm: &Path) -> Option<String> {
.or_else(|| get_browser_ui_test_version_inner(npm, true))
}
-fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
- match fs::read_to_string(
- src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"),
- ) {
- Ok(v) => {
- if v.trim() != installed_version {
- eprintln!(
- "⚠️ Installed version of browser-ui-test (`{}`) is different than the \
- one used in the CI (`{}`)",
- installed_version, v
- );
- eprintln!(
- "You can install this version using `npm update browser-ui-test` or by using \
- `npm install browser-ui-test@{}`",
- v,
- );
- }
- }
- Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
- }
-}
-
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustdocGUI {
pub target: TargetSelection,
@@ -1047,79 +986,30 @@ impl Step for RustdocGUI {
}
fn run(self, builder: &Builder<'_>) {
- let nodejs = builder.config.nodejs.as_ref().expect("nodejs isn't available");
- let npm = builder.config.npm.as_ref().expect("npm isn't available");
-
builder.ensure(compile::Std::new(self.compiler, self.target));
- // The goal here is to check if the necessary packages are installed, and if not, we
- // panic.
- match get_browser_ui_test_version(&npm) {
- Some(version) => {
- // We also check the version currently used in CI and emit a warning if it's not the
- // same one.
- compare_browser_ui_test_version(&version, &builder.build.src);
- }
- None => {
- eprintln!(
- "error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` \
- dependency is missing",
- );
- eprintln!(
- "If you want to install the `{0}` dependency, run `npm install {0}`",
- "browser-ui-test",
- );
- panic!("Cannot run rustdoc-gui tests");
- }
- }
+ let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
let out_dir = builder.test_out(self.target).join("rustdoc-gui");
-
- // We remove existing folder to be sure there won't be artifacts remaining.
builder.clear_if_dirty(&out_dir, &builder.rustdoc(self.compiler));
- let src_path = builder.build.src.join("tests/rustdoc-gui/src");
- // We generate docs for the libraries present in the rustdoc-gui's src folder.
- for entry in src_path.read_dir().expect("read_dir call failed") {
- if let Ok(entry) = entry {
- let path = entry.path();
+ if let Some(src) = builder.config.src.to_str() {
+ cmd.arg("--rust-src").arg(src);
+ }
- if !path.is_dir() {
- continue;
- }
+ if let Some(out_dir) = out_dir.to_str() {
+ cmd.arg("--out-dir").arg(out_dir);
+ }
- let mut cargo = Command::new(&builder.initial_cargo);
- cargo
- .arg("doc")
- .arg("--target-dir")
- .arg(&out_dir)
- .env("RUSTC_BOOTSTRAP", "1")
- .env("RUSTDOC", builder.rustdoc(self.compiler))
- .env("RUSTC", builder.rustc(self.compiler))
- .current_dir(path);
- // FIXME: implement a `// compile-flags` command or similar
- // instead of hard-coding this test
- if entry.file_name() == "link_to_definition" {
- cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
- } else if entry.file_name() == "scrape_examples" {
- cargo.arg("-Zrustdoc-scrape-examples");
- } else if entry.file_name() == "extend_css" {
- cargo.env("RUSTDOCFLAGS", &format!("--extend-css extra.css"));
- }
- builder.run(&mut cargo);
- }
+ if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
+ cmd.arg("--initial-cargo").arg(initial_cargo);
}
- // We now run GUI tests.
- let mut command = Command::new(&nodejs);
- command
- .arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js"))
- .arg("--jobs")
- .arg(&builder.jobs().to_string())
- .arg("--doc-folder")
- .arg(out_dir.join("doc"))
- .arg("--tests-folder")
- .arg(builder.build.src.join("tests/rustdoc-gui"));
+ cmd.arg("--jobs").arg(builder.jobs().to_string());
+
+ cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
+ .env("RUSTC", builder.rustc(self.compiler));
+
for path in &builder.paths {
if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
if !p.ends_with(".goml") {
@@ -1127,14 +1017,25 @@ impl Step for RustdocGUI {
panic!("Cannot run rustdoc-gui tests");
}
if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
- command.arg("--file").arg(name);
+ cmd.arg("--goml-file").arg(name);
}
}
}
- for test_arg in builder.config.cmd.test_args() {
- command.arg(test_arg);
+
+ for test_arg in builder.config.test_args() {
+ cmd.arg("--test-arg").arg(test_arg);
}
- builder.run(&mut command);
+
+ if let Some(ref nodejs) = builder.config.nodejs {
+ cmd.arg("--nodejs").arg(nodejs);
+ }
+
+ if let Some(ref npm) = builder.config.npm {
+ cmd.arg("--npm").arg(npm);
+ }
+
+ let _time = util::timeit(&builder);
+ crate::render_tests::try_run_tests(builder, &mut cmd);
}
}
@@ -1192,7 +1093,24 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
builder.info("tidy check");
try_run(builder, &mut cmd);
- builder.ensure(ExpandYamlAnchors {});
+ builder.ensure(ExpandYamlAnchors);
+
+ builder.info("x.py completions check");
+ let [bash, fish, powershell] = ["x.py.sh", "x.py.fish", "x.py.ps1"]
+ .map(|filename| builder.src.join("src/etc/completions").join(filename));
+ if builder.config.cmd.bless() {
+ builder.ensure(crate::run::GenerateCompletions);
+ } else {
+ if crate::flags::get_completion(shells::Bash, &bash).is_some()
+ || crate::flags::get_completion(shells::Fish, &fish).is_some()
+ || crate::flags::get_completion(shells::PowerShell, &powershell).is_some()
+ {
+ eprintln!(
+ "x.py completions were changed; run `x.py run generate-completions` to update them"
+ );
+ crate::detail_exit(1);
+ }
+ }
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1204,40 +1122,6 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
}
}
-/// Runs tidy's own tests.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct TidySelfTest;
-
-impl Step for TidySelfTest {
- type Output = ();
- const DEFAULT: bool = true;
- const ONLY_HOSTS: bool = true;
-
- fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.alias("tidyselftest")
- }
-
- fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(TidySelfTest);
- }
-
- fn run(self, builder: &Builder<'_>) {
- let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
- let cargo = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolBootstrap,
- bootstrap_host,
- "test",
- "src/tools/tidy",
- SourceType::InTree,
- &[],
- );
- add_flags_and_try_run_tests(builder, &mut cargo.into());
- }
-}
-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ExpandYamlAnchors;
@@ -1448,7 +1332,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
crate::detail_exit(1);
}
- let compiler = self.compiler;
+ let mut compiler = self.compiler;
let target = self.target;
let mode = self.mode;
let suite = self.suite;
@@ -1461,15 +1345,28 @@ note: if you're sure you want to do this, please open an issue as to why. In the
return;
}
- if suite == "debuginfo" {
- builder
- .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
- }
+ // Support stage 1 ui-fulldeps. This is somewhat complicated: ui-fulldeps tests for the most
+ // part test the *API* of the compiler, not how it compiles a given file. As a result, we
+ // can run them against the stage 1 sources as long as we build them with the stage 0
+ // bootstrap compiler.
+ // NOTE: Only stage 1 is special cased because we need the rustc_private artifacts to match the
+ // running compiler in stage 2 when plugins run.
+ let stage_id = if suite == "ui-fulldeps" && compiler.stage == 1 {
+ compiler = builder.compiler(compiler.stage - 1, target);
+ format!("stage{}-{}", compiler.stage + 1, target)
+ } else {
+ format!("stage{}-{}", compiler.stage, target)
+ };
if suite.ends_with("fulldeps") {
builder.ensure(compile::Rustc::new(compiler, target));
}
+ if suite == "debuginfo" {
+ builder
+ .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
+ }
+
builder.ensure(compile::Std::new(compiler, target));
// ensure that `libproc_macro` is available on the host.
builder.ensure(compile::Std::new(compiler, compiler.host));
@@ -1528,7 +1425,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
cmd.arg("--src-base").arg(builder.src.join("tests").join(suite));
cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
cmd.arg("--sysroot-base").arg(builder.sysroot(compiler));
- cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
+ cmd.arg("--stage-id").arg(stage_id);
cmd.arg("--suite").arg(suite);
cmd.arg("--mode").arg(mode);
cmd.arg("--target").arg(target.rustc_target_arg());
@@ -1637,7 +1534,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
// Get paths from cmd args
let paths = match &builder.config.cmd {
- Subcommand::Test { ref paths, .. } => &paths[..],
+ Subcommand::Test { .. } => &builder.config.paths[..],
_ => &[],
};
@@ -1647,8 +1544,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
.filter_map(|p| util::is_valid_test_suite_arg(p, suite_path, builder))
.collect();
- test_args.append(&mut builder.config.cmd.test_args());
- test_args.extend(builder.config.free_args.iter().map(|s| s.as_str()));
+ test_args.append(&mut builder.config.test_args());
// On Windows, replace forward slashes in test-args by backslashes
// so the correct filters are passed to libtest
@@ -1804,12 +1700,29 @@ note: if you're sure you want to do this, please open an issue as to why. In the
cmd.arg("--channel").arg(&builder.config.channel);
+ if !builder.config.omit_git_hash {
+ cmd.arg("--git-hash");
+ }
+
if let Some(commit) = builder.config.download_rustc_commit() {
cmd.env("FAKE_DOWNLOAD_RUSTC_PREFIX", format!("/rustc/{commit}"));
}
builder.ci_env.force_coloring_in_ci(&mut cmd);
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::Compiletest {
+ suite: suite.into(),
+ mode: mode.into(),
+ compare_mode: None,
+ target: self.target.triple.to_string(),
+ host: self.compiler.host.triple.to_string(),
+ stage: self.compiler.stage,
+ },
+ builder,
+ );
+
builder.info(&format!(
"Check compiletest suite={} mode={} ({} -> {})",
suite, mode, &compiler.host, target
@@ -1819,6 +1732,20 @@ note: if you're sure you want to do this, please open an issue as to why. In the
if let Some(compare_mode) = compare_mode {
cmd.arg("--compare-mode").arg(compare_mode);
+
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::Compiletest {
+ suite: suite.into(),
+ mode: mode.into(),
+ compare_mode: Some(compare_mode.into()),
+ target: self.target.triple.to_string(),
+ host: self.compiler.host.triple.to_string(),
+ stage: self.compiler.stage,
+ },
+ builder,
+ );
+
builder.info(&format!(
"Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
suite, mode, compare_mode, &compiler.host, target
@@ -1888,7 +1815,13 @@ impl BookTest {
rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
builder.add_rust_test_threads(&mut rustbook_cmd);
- builder.info(&format!("Testing rustbook {}", self.path.display()));
+ let _guard = builder.msg(
+ Kind::Test,
+ compiler.stage,
+ format_args!("rustbook {}", self.path.display()),
+ compiler.host,
+ compiler.host,
+ );
let _time = util::timeit(&builder);
let toolstate = if try_run(builder, &mut rustbook_cmd) {
ToolState::TestPass
@@ -2016,7 +1949,8 @@ impl Step for ErrorIndex {
let mut tool = tool::ErrorIndex::command(builder);
tool.arg("markdown").arg(&output);
- builder.info(&format!("Testing error-index stage{}", compiler.stage));
+ let _guard =
+ builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
let _time = util::timeit(&builder);
builder.run_quiet(&mut tool);
// The tests themselves need to link to std, so make sure it is
@@ -2043,7 +1977,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
cmd.arg(markdown);
cmd.env("RUSTC_BOOTSTRAP", "1");
- let test_args = builder.config.cmd.test_args().join(" ");
+ let test_args = builder.config.test_args().join(" ");
cmd.arg("--test-args").arg(test_args);
if builder.config.verbose_tests {
@@ -2088,7 +2022,6 @@ impl Step for RustcGuide {
pub struct CrateLibrustc {
compiler: Compiler,
target: TargetSelection,
- test_kind: TestKind,
crates: Vec<Interned<String>>,
}
@@ -2110,9 +2043,8 @@ impl Step for CrateLibrustc {
.iter()
.map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
.collect();
- let test_kind = builder.kind.into();
- builder.ensure(CrateLibrustc { compiler, target: run.target, test_kind, crates });
+ builder.ensure(CrateLibrustc { compiler, target: run.target, crates });
}
fn run(self, builder: &Builder<'_>) {
@@ -2120,18 +2052,117 @@ impl Step for CrateLibrustc {
compiler: self.compiler,
target: self.target,
mode: Mode::Rustc,
- test_kind: self.test_kind,
crates: self.crates,
});
}
}
+/// Given a `cargo test` subcommand, add the appropriate flags and run it.
+///
+/// Returns whether the test succeeded.
+fn run_cargo_test(
+ cargo: impl Into<Command>,
+ libtest_args: &[&str],
+ crates: &[Interned<String>],
+ primary_crate: &str,
+ compiler: Compiler,
+ target: TargetSelection,
+ builder: &Builder<'_>,
+) -> bool {
+ let mut cargo =
+ prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder);
+ let _time = util::timeit(&builder);
+
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::CargoPackage {
+ crates: crates.iter().map(|c| c.to_string()).collect(),
+ target: target.triple.to_string(),
+ host: compiler.host.triple.to_string(),
+ stage: compiler.stage,
+ },
+ builder,
+ );
+ add_flags_and_try_run_tests(builder, &mut cargo)
+}
+
+/// Given a `cargo test` subcommand, pass it the appropriate test flags given a `builder`.
+fn prepare_cargo_test(
+ cargo: impl Into<Command>,
+ libtest_args: &[&str],
+ crates: &[Interned<String>],
+ primary_crate: &str,
+ compiler: Compiler,
+ target: TargetSelection,
+ builder: &Builder<'_>,
+) -> Command {
+ let mut cargo = cargo.into();
+
+ // Pass in some standard flags then iterate over the graph we've discovered
+ // in `cargo metadata` with the maps above and figure out what `-p`
+ // arguments need to get passed.
+ if builder.kind == Kind::Test && !builder.fail_fast {
+ cargo.arg("--no-fail-fast");
+ }
+ match builder.doc_tests {
+ DocTests::Only => {
+ cargo.arg("--doc");
+ }
+ DocTests::No => {
+ let krate = &builder
+ .crates
+ .get(&INTERNER.intern_str(primary_crate))
+ .unwrap_or_else(|| panic!("missing crate {primary_crate}"));
+ if krate.has_lib {
+ cargo.arg("--lib");
+ }
+ cargo.args(&["--bins", "--examples", "--tests", "--benches"]);
+ }
+ DocTests::Yes => {}
+ }
+
+ for &krate in crates {
+ cargo.arg("-p").arg(krate);
+ }
+
+ cargo.arg("--").args(&builder.config.test_args()).args(libtest_args);
+ if !builder.config.verbose_tests {
+ cargo.arg("--quiet");
+ }
+
+ // The tests are going to run with the *target* libraries, so we need to
+ // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
+ //
+ // Note that to run the compiler we need to run with the *host* libraries,
+ // but our wrapper scripts arrange for that to be the case anyway.
+ let mut dylib_path = dylib_path();
+ dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
+ cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
+
+ if target.contains("emscripten") {
+ cargo.env(
+ format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
+ builder.config.nodejs.as_ref().expect("nodejs not configured"),
+ );
+ } else if target.starts_with("wasm32") {
+ let node = builder.config.nodejs.as_ref().expect("nodejs not configured");
+ let runner = format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display());
+ cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner);
+ } else if builder.remote_tested(target) {
+ cargo.env(
+ format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
+ format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
+ );
+ }
+
+ cargo
+}
+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Crate {
pub compiler: Compiler,
pub target: TargetSelection,
pub mode: Mode,
- pub test_kind: TestKind,
pub crates: Vec<Interned<String>>,
}
@@ -2140,21 +2171,20 @@ impl Step for Crate {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.crate_or_deps("test")
+ run.crate_or_deps("sysroot")
}
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
let host = run.build_triple();
let compiler = builder.compiler_for(builder.top_stage, host, host);
- let test_kind = builder.kind.into();
let crates = run
.paths
.iter()
.map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
.collect();
- builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, test_kind, crates });
+ builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
}
/// Runs all unit tests plus documentation tests for a given crate defined
@@ -2169,7 +2199,6 @@ impl Step for Crate {
let compiler = self.compiler;
let target = self.target;
let mode = self.mode;
- let test_kind = self.test_kind;
builder.ensure(compile::Std::new(compiler, target));
builder.ensure(RemoteCopyLibs { compiler, target });
@@ -2181,7 +2210,7 @@ impl Step for Crate {
let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
let mut cargo =
- builder.cargo(compiler, mode, SourceType::InTree, target, test_kind.subcommand());
+ builder.cargo(compiler, mode, SourceType::InTree, target, builder.kind.as_str());
match mode {
Mode::Std => {
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
@@ -2192,70 +2221,14 @@ impl Step for Crate {
_ => panic!("can only test libraries"),
};
- // Build up the base `cargo test` command.
- //
- // Pass in some standard flags then iterate over the graph we've discovered
- // in `cargo metadata` with the maps above and figure out what `-p`
- // arguments need to get passed.
- if test_kind.subcommand() == "test" && !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
- match builder.doc_tests {
- DocTests::Only => {
- cargo.arg("--doc");
- }
- DocTests::No => {
- cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
- }
- DocTests::Yes => {}
- }
-
- for krate in &self.crates {
- cargo.arg("-p").arg(krate);
- }
-
- // The tests are going to run with the *target* libraries, so we need to
- // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
- //
- // Note that to run the compiler we need to run with the *host* libraries,
- // but our wrapper scripts arrange for that to be the case anyway.
- let mut dylib_path = dylib_path();
- dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
- cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
-
- cargo.arg("--");
- cargo.args(&builder.config.cmd.test_args());
-
- cargo.arg("-Z").arg("unstable-options");
- cargo.arg("--format").arg("json");
-
- if target.contains("emscripten") {
- cargo.env(
- format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
- builder.config.nodejs.as_ref().expect("nodejs not configured"),
- );
- } else if target.starts_with("wasm32") {
- let node = builder.config.nodejs.as_ref().expect("nodejs not configured");
- let runner =
- format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display());
- cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner);
- } else if builder.remote_tested(target) {
- cargo.env(
- format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
- format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
- );
- }
-
- builder.info(&format!(
- "{}{} stage{} ({} -> {})",
- test_kind,
- crate_description(&self.crates),
+ let _guard = builder.msg(
+ builder.kind,
compiler.stage,
- &compiler.host,
- target
- ));
- let _time = util::timeit(&builder);
- crate::render_tests::try_run_tests(builder, &mut cargo.into());
+ crate_description(&self.crates),
+ compiler.host,
+ target,
+ );
+ run_cargo_test(cargo, &[], &self.crates, &self.crates[0], compiler, target, builder);
}
}
@@ -2263,7 +2236,6 @@ impl Step for Crate {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CrateRustdoc {
host: TargetSelection,
- test_kind: TestKind,
}
impl Step for CrateRustdoc {
@@ -2278,13 +2250,10 @@ impl Step for CrateRustdoc {
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
- let test_kind = builder.kind.into();
-
- builder.ensure(CrateRustdoc { host: run.target, test_kind });
+ builder.ensure(CrateRustdoc { host: run.target });
}
fn run(self, builder: &Builder<'_>) {
- let test_kind = self.test_kind;
let target = self.host;
let compiler = if builder.download_rustc() {
@@ -2303,29 +2272,11 @@ impl Step for CrateRustdoc {
compiler,
Mode::ToolRustc,
target,
- test_kind.subcommand(),
+ builder.kind.as_str(),
"src/tools/rustdoc",
SourceType::InTree,
&[],
);
- if test_kind.subcommand() == "test" && !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
- match builder.doc_tests {
- DocTests::Only => {
- cargo.arg("--doc");
- }
- DocTests::No => {
- cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
- }
- DocTests::Yes => {}
- }
-
- cargo.arg("-p").arg("rustdoc:0.0.0");
-
- cargo.arg("--");
- cargo.args(&builder.config.cmd.test_args());
-
if self.host.contains("musl") {
cargo.arg("'-Ctarget-feature=-crt-static'");
}
@@ -2365,24 +2316,22 @@ impl Step for CrateRustdoc {
dylib_path.insert(0, PathBuf::from(&*libdir));
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
- if !builder.config.verbose_tests {
- cargo.arg("--quiet");
- }
-
- builder.info(&format!(
- "{} rustdoc stage{} ({} -> {})",
- test_kind, compiler.stage, &compiler.host, target
- ));
- let _time = util::timeit(&builder);
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ let _guard = builder.msg(builder.kind, compiler.stage, "rustdoc", compiler.host, target);
+ run_cargo_test(
+ cargo,
+ &[],
+ &[INTERNER.intern_str("rustdoc:0.0.0")],
+ "rustdoc",
+ compiler,
+ target,
+ builder,
+ );
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CrateRustdocJsonTypes {
host: TargetSelection,
- test_kind: TestKind,
}
impl Step for CrateRustdocJsonTypes {
@@ -2397,13 +2346,10 @@ impl Step for CrateRustdocJsonTypes {
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
- let test_kind = builder.kind.into();
-
- builder.ensure(CrateRustdocJsonTypes { host: run.target, test_kind });
+ builder.ensure(CrateRustdocJsonTypes { host: run.target });
}
fn run(self, builder: &Builder<'_>) {
- let test_kind = self.test_kind;
let target = self.host;
// Use the previous stage compiler to reuse the artifacts that are
@@ -2413,36 +2359,35 @@ impl Step for CrateRustdocJsonTypes {
let compiler = builder.compiler_for(builder.top_stage, target, target);
builder.ensure(compile::Rustc::new(compiler, target));
- let mut cargo = tool::prepare_tool_cargo(
+ let cargo = tool::prepare_tool_cargo(
builder,
compiler,
Mode::ToolRustc,
target,
- test_kind.subcommand(),
+ builder.kind.as_str(),
"src/rustdoc-json-types",
SourceType::InTree,
&[],
);
- if test_kind.subcommand() == "test" && !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
- cargo.arg("-p").arg("rustdoc-json-types");
- cargo.arg("--");
- cargo.args(&builder.config.cmd.test_args());
-
- if self.host.contains("musl") {
- cargo.arg("'-Ctarget-feature=-crt-static'");
- }
-
- builder.info(&format!(
- "{} rustdoc-json-types stage{} ({} -> {})",
- test_kind, compiler.stage, &compiler.host, target
- ));
- let _time = util::timeit(&builder);
+ // FIXME: this looks very wrong, libtest doesn't accept `-C` arguments and the quotes are fishy.
+ let libtest_args = if self.host.contains("musl") {
+ ["'-Ctarget-feature=-crt-static'"].as_slice()
+ } else {
+ &[]
+ };
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ let _guard =
+ builder.msg(builder.kind, compiler.stage, "rustdoc-json-types", compiler.host, target);
+ run_cargo_test(
+ cargo,
+ libtest_args,
+ &[INTERNER.intern_str("rustdoc-json-types")],
+ "rustdoc-json-types",
+ compiler,
+ target,
+ builder,
+ );
}
}
@@ -2580,13 +2525,15 @@ impl Step for Bootstrap {
check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/"));
try_run(builder, &mut check_bootstrap);
+ let host = builder.config.build;
+ let compiler = builder.compiler(0, host);
let mut cmd = Command::new(&builder.initial_cargo);
cmd.arg("test")
.current_dir(builder.src.join("src/bootstrap"))
.env("RUSTFLAGS", "-Cdebuginfo=2")
.env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
.env("RUSTC_BOOTSTRAP", "1")
- .env("RUSTDOC", builder.rustdoc(builder.compiler(0, builder.build.build)))
+ .env("RUSTDOC", builder.rustdoc(compiler))
.env("RUSTC", &builder.initial_rustc);
if let Some(flags) = option_env!("RUSTFLAGS") {
// Use the same rustc flags for testing as for "normal" compilation,
@@ -2594,24 +2541,9 @@ impl Step for Bootstrap {
// https://github.com/rust-lang/rust/issues/49215
cmd.env("RUSTFLAGS", flags);
}
- if !builder.fail_fast {
- cmd.arg("--no-fail-fast");
- }
- match builder.doc_tests {
- DocTests::Only => {
- cmd.arg("--doc");
- }
- DocTests::No => {
- cmd.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
- }
- DocTests::Yes => {}
- }
-
- cmd.arg("--").args(&builder.config.cmd.test_args());
// rustbuild tests are racy on directory creation so just run them one at a time.
// Since there's not many this shouldn't be a problem.
- cmd.arg("--test-threads=1");
- add_flags_and_try_run_tests(builder, &mut cmd);
+ run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", compiler, host, builder);
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -2668,43 +2600,6 @@ impl Step for TierCheck {
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct ReplacePlaceholderTest;
-
-impl Step for ReplacePlaceholderTest {
- type Output = ();
- const ONLY_HOSTS: bool = true;
- const DEFAULT: bool = true;
-
- /// Ensure the version placeholder replacement tool builds
- fn run(self, builder: &Builder<'_>) {
- builder.info("build check for version replacement placeholder");
-
- // Test the version placeholder replacement tool itself.
- let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
- let cargo = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolBootstrap,
- bootstrap_host,
- "test",
- "src/tools/replace-version-placeholder",
- SourceType::InTree,
- &[],
- );
- add_flags_and_try_run_tests(builder, &mut cargo.into());
- }
-
- fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/tools/replace-version-placeholder")
- }
-
- fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(Self);
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct LintDocs {
pub compiler: Compiler,
pub target: TargetSelection,
@@ -2761,7 +2656,7 @@ impl Step for RustInstaller {
SourceType::InTree,
&[],
);
- try_run(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "installer", compiler, bootstrap_host, builder);
// We currently don't support running the test.sh script outside linux(?) environments.
// Eventually this should likely migrate to #[test]s in rust-installer proper rather than a
@@ -2828,7 +2723,7 @@ impl Step for TestHelpers {
return;
}
- builder.info("Building test helpers");
+ let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
t!(fs::create_dir_all(&dst));
let mut cfg = cc::Build::new();
// FIXME: Workaround for https://github.com/emscripten-core/emscripten/issues/9013