From 62639c9b56e0d17a8de36e40eceddd45c9644774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 23 Jun 2025 16:56:30 +0200 Subject: [PATCH] Port more tests to snapshot tests --- src/bootstrap/src/core/build_steps/dist.rs | 22 +- src/bootstrap/src/core/build_steps/doc.rs | 7 +- src/bootstrap/src/core/build_steps/test.rs | 17 +- src/bootstrap/src/core/build_steps/tool.rs | 10 + src/bootstrap/src/core/builder/mod.rs | 20 +- src/bootstrap/src/core/builder/tests.rs | 1161 +++++++++----------- src/bootstrap/src/utils/tests/mod.rs | 26 + 7 files changed, 615 insertions(+), 648 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 235c90539dcd..95fc2f1aef92 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -23,7 +23,7 @@ use crate::core::build_steps::doc::DocumentationFormat; use crate::core::build_steps::tool::{self, Tool}; use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor}; use crate::core::build_steps::{compile, llvm}; -use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; +use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata}; use crate::core::config::TargetSelection; use crate::utils::build_stamp::{self, BuildStamp}; use crate::utils::channel::{self, Info}; @@ -84,6 +84,10 @@ impl Step for Docs { tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular); Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("docs", self.host)) + } } #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] @@ -354,6 +358,10 @@ impl Step for Mingw { Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("mingw", self.host)) + } } #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] @@ -540,6 +548,10 @@ impl Step for Rustc { } } } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("rustc", self.compiler.host)) + } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -723,6 +735,10 @@ impl Step for Std { Some(tarball.generate()) } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("std", self.target).built_by(self.compiler)) + } } /// Tarball containing the compiler that gets downloaded and used by @@ -1002,6 +1018,10 @@ impl Step for Src { tarball.generate() } + + fn metadata(&self) -> Option { + Some(StepMetadata::dist("src", TargetSelection::default())) + } } #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 210975995615..f7c4c5ad0bbd 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -14,7 +14,8 @@ use std::{env, fs, mem}; use crate::core::build_steps::compile; use crate::core::build_steps::tool::{self, SourceType, Tool, prepare_tool_cargo}; use crate::core::builder::{ - self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, crate_description, + self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, StepMetadata, + crate_description, }; use crate::core::config::{Config, TargetSelection}; use crate::helpers::{submodule_path_of, symlink_dir, t, up_to_date}; @@ -662,6 +663,10 @@ impl Step for Std { } } } + + fn metadata(&self) -> Option { + Some(StepMetadata::doc("std", self.target).stage(self.stage)) + } } /// Name of the crates that are visible to consumers of the standard library. diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 3b3e85260a6b..01b181f55de6 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -19,7 +19,8 @@ use crate::core::build_steps::tool::{self, COMPILETEST_ALLOW_FEATURES, SourceTyp use crate::core::build_steps::toolstate::ToolState; use crate::core::build_steps::{compile, dist, llvm}; use crate::core::builder::{ - self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, crate_description, + self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, StepMetadata, + crate_description, }; use crate::core::config::TargetSelection; use crate::core::config::flags::{Subcommand, get_completion}; @@ -1174,6 +1175,10 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to fn make_run(run: RunConfig<'_>) { run.builder.ensure(Tidy); } + + fn metadata(&self) -> Option { + Some(StepMetadata::test("tidy", TargetSelection::default())) + } } fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf { @@ -1236,6 +1241,12 @@ macro_rules! test { }), }) } + + fn metadata(&self) -> Option { + Some( + StepMetadata::test(stringify!($name), self.target) + ) + } } }; } @@ -2483,6 +2494,10 @@ impl Step for CrateLibrustc { crates: self.crates, }); } + + fn metadata(&self) -> Option { + Some(StepMetadata::test("CrateLibrustc", self.target)) + } } /// Given a `cargo test` subcommand, add the appropriate flags and run it. diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index af2953b9fd69..c71bd5e842e9 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -786,6 +786,16 @@ impl Step for Rustdoc { ToolBuildResult { tool_path, build_compiler, target_compiler } } } + + fn metadata(&self) -> Option { + Some( + StepMetadata::build("rustdoc", self.compiler.host) + // rustdoc is ToolRustc, so stage N rustdoc is built by stage N-1 rustc + // FIXME: make this stage deduction automatic somehow + // FIXME: log the compiler that actually built ToolRustc steps + .stage(self.compiler.stage.saturating_sub(1)), + ) + } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 72a70dd4ef84..7cb7866953a8 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -140,7 +140,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// Metadata that describes an executed step, mostly for testing and tracing. #[allow(unused)] -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub struct StepMetadata { name: &'static str, kind: Kind, @@ -151,7 +151,23 @@ pub struct StepMetadata { impl StepMetadata { pub fn build(name: &'static str, target: TargetSelection) -> Self { - Self { name, kind: Kind::Build, target, built_by: None, stage: None } + Self::new(name, target, Kind::Build) + } + + pub fn doc(name: &'static str, target: TargetSelection) -> Self { + Self::new(name, target, Kind::Doc) + } + + pub fn dist(name: &'static str, target: TargetSelection) -> Self { + Self::new(name, target, Kind::Dist) + } + + pub fn test(name: &'static str, target: TargetSelection) -> Self { + Self::new(name, target, Kind::Test) + } + + fn new(name: &'static str, target: TargetSelection, kind: Kind) -> Self { + Self { name, kind, target, built_by: None, stage: None } } pub fn built_by(mut self, compiler: Compiler) -> Self { diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 76477f001b08..fa5786744c76 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -10,6 +10,7 @@ use crate::core::build_steps::doc::DocumentationFormat; use crate::core::config::Config; use crate::utils::cache::ExecutedStep; use crate::utils::helpers::get_host_target; +use crate::utils::tests::ConfigBuilder; use crate::utils::tests::git::{GitCtx, git_test}; static TEST_TRIPLE_1: &str = "i686-unknown-haiku"; @@ -192,58 +193,6 @@ fn check_missing_paths_for_x_test_tests() { } } -#[test] -fn test_exclude() { - let mut config = configure("test", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); - config.skip = vec!["src/tools/tidy".into()]; - let cache = run_build(&[], config); - - // Ensure we have really excluded tidy - assert!(!cache.contains::()); - - // Ensure other tests are not affected. - assert!(cache.contains::()); -} - -#[test] -fn test_exclude_kind() { - let path = PathBuf::from("compiler/rustc_data_structures"); - - let mut config = configure("test", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); - // Ensure our test is valid, and `test::Rustc` would be run without the exclude. - assert!(run_build(&[], config.clone()).contains::()); - // Ensure tests for rustc are not skipped. - config.skip = vec![path.clone()]; - assert!(run_build(&[], config.clone()).contains::()); - // Ensure builds for rustc are not skipped. - assert!(run_build(&[], config).contains::()); -} - -/// Ensure that if someone passes both a single crate and `library`, all library crates get built. -#[test] -fn alias_and_path_for_library() { - let mut cache = run_build( - &["library".into(), "core".into()], - configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]), - ); - assert_eq!( - first(cache.all::()), - &[ - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1) - ] - ); - - let mut cache = run_build( - &["library".into(), "core".into()], - configure("doc", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]), - ); - assert_eq!( - first(cache.all::()), - &[doc_std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1)] - ); -} - #[test] fn ci_rustc_if_unchanged_invalidate_on_compiler_changes() { git_test(|ctx| { @@ -315,101 +264,6 @@ mod defaults { use crate::Config; use crate::core::builder::*; - #[test] - fn build_default() { - let mut cache = run_build(&[], configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1])); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - assert_eq!( - first(cache.all::()), - &[ - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1), - ] - ); - assert!(!cache.all::().is_empty()); - // Make sure rustdoc is only built once. - assert_eq!( - first(cache.all::()), - // Recall that rustdoc stages are off-by-one - // - this is the compiler it's _linked_ to, not built with. - &[tool::Rustdoc { compiler: Compiler::new(1, a) }], - ); - assert_eq!( - first(cache.all::()), - &[rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0)], - ); - } - - #[test] - fn build_stage_0() { - let config = Config { stage: 0, ..configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]) }; - let mut cache = run_build(&[], config); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - assert_eq!( - first(cache.all::()), - &[std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0)] - ); - assert!(!cache.all::().is_empty()); - assert_eq!( - first(cache.all::()), - // This is the beta rustdoc. - // Add an assert here to make sure this is the only rustdoc built. - &[tool::Rustdoc { compiler: Compiler::new(0, a) }], - ); - assert!(cache.all::().is_empty()); - } - - #[test] - fn build_cross_compile() { - let config = Config { - stage: 1, - ..configure("build", &[TEST_TRIPLE_1, TEST_TRIPLE_2], &[TEST_TRIPLE_1, TEST_TRIPLE_2]) - }; - let mut cache = run_build(&[], config); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - let b = TargetSelection::from_user(TEST_TRIPLE_2); - - // Ideally, this build wouldn't actually have `target: a` - // rustdoc/rustcc/std here (the user only requested a host=B build, so - // there's not really a need for us to build for target A in this case - // (since we're producing stage 1 libraries/binaries). But currently - // bootstrap is just a bit buggy here; this should be fixed though. - assert_eq!( - first(cache.all::()), - &[ - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 0), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 1), - ] - ); - assert_eq!( - first(cache.all::()), - &[ - compile::Assemble { target_compiler: Compiler::new(0, a) }, - compile::Assemble { target_compiler: Compiler::new(1, a) }, - compile::Assemble { target_compiler: Compiler::new(1, b) }, - ] - ); - assert_eq!( - first(cache.all::()), - &[ - tool::Rustdoc { compiler: Compiler::new(1, a) }, - tool::Rustdoc { compiler: Compiler::new(1, b) }, - ], - ); - assert_eq!( - first(cache.all::()), - &[ - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 0), - ] - ); - } - #[test] fn doc_default() { let mut config = configure("doc", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); @@ -446,326 +300,6 @@ mod dist { Config { stage: 2, ..super::configure("dist", host, target) } } - #[test] - fn dist_baseline() { - let mut cache = run_build(&[], configure(&[TEST_TRIPLE_1], &[TEST_TRIPLE_1])); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - - assert_eq!(first(cache.all::()), &[dist::Docs { host: a },]); - assert_eq!(first(cache.all::()), &[dist::Mingw { host: a },]); - assert_eq!( - first(cache.all::()), - &[dist::Rustc { compiler: Compiler::new(2, a) },] - ); - assert_eq!( - first(cache.all::()), - &[dist::Std { compiler: Compiler::new(1, a), target: a },] - ); - assert_eq!(first(cache.all::()), &[dist::Src]); - // Make sure rustdoc is only built once. - assert_eq!( - first(cache.all::()), - &[tool::Rustdoc { compiler: Compiler::new(2, a) },] - ); - } - - #[test] - fn dist_with_targets() { - let mut cache = - run_build(&[], configure(&[TEST_TRIPLE_1], &[TEST_TRIPLE_1, TEST_TRIPLE_2])); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - let b = TargetSelection::from_user(TEST_TRIPLE_2); - - assert_eq!( - first(cache.all::()), - &[dist::Docs { host: a }, dist::Docs { host: b },] - ); - assert_eq!( - first(cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(cache.all::()), - &[dist::Rustc { compiler: Compiler::new(2, a) },] - ); - assert_eq!( - first(cache.all::()), - &[ - dist::Std { compiler: Compiler::new(1, a), target: a }, - dist::Std { compiler: Compiler::new(2, a), target: b }, - ] - ); - assert_eq!(first(cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_with_hosts() { - let mut cache = run_build( - &[], - configure(&[TEST_TRIPLE_1, TEST_TRIPLE_2], &[TEST_TRIPLE_1, TEST_TRIPLE_2]), - ); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - let b = TargetSelection::from_user(TEST_TRIPLE_2); - - assert_eq!( - first(cache.all::()), - &[dist::Docs { host: a }, dist::Docs { host: b },] - ); - assert_eq!( - first(cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(cache.all::()), - &[ - dist::Rustc { compiler: Compiler::new(2, a) }, - dist::Rustc { compiler: Compiler::new(2, b) }, - ] - ); - assert_eq!( - first(cache.all::()), - &[ - dist::Std { compiler: Compiler::new(1, a), target: a }, - dist::Std { compiler: Compiler::new(1, a), target: b }, - ] - ); - assert_eq!( - first(cache.all::()), - &[ - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 2), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 1), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 2), - ], - ); - assert_eq!(first(cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_only_cross_host() { - let b = TargetSelection::from_user(TEST_TRIPLE_2); - let mut config = - configure(&[TEST_TRIPLE_1, TEST_TRIPLE_2], &[TEST_TRIPLE_1, TEST_TRIPLE_2]); - config.docs = false; - config.extended = true; - config.hosts = vec![b]; - let mut cache = run_build(&[], config); - - assert_eq!( - first(cache.all::()), - &[dist::Rustc { compiler: Compiler::new(2, b) },] - ); - assert_eq!( - first(cache.all::()), - &[ - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 1), - ] - ); - } - - #[test] - fn dist_with_targets_and_hosts() { - let mut cache = run_build( - &[], - configure( - &[TEST_TRIPLE_1, TEST_TRIPLE_2], - &[TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3], - ), - ); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - let b = TargetSelection::from_user(TEST_TRIPLE_2); - let c = TargetSelection::from_user(TEST_TRIPLE_3); - - assert_eq!( - first(cache.all::()), - &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },] - ); - assert_eq!( - first(cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },] - ); - assert_eq!( - first(cache.all::()), - &[ - dist::Rustc { compiler: Compiler::new(2, a) }, - dist::Rustc { compiler: Compiler::new(2, b) }, - ] - ); - assert_eq!( - first(cache.all::()), - &[ - dist::Std { compiler: Compiler::new(1, a), target: a }, - dist::Std { compiler: Compiler::new(1, a), target: b }, - dist::Std { compiler: Compiler::new(2, a), target: c }, - ] - ); - assert_eq!(first(cache.all::()), &[dist::Src]); - } - - #[test] - fn dist_with_empty_host() { - let config = configure(&[], &[TEST_TRIPLE_3]); - let mut cache = run_build(&[], config); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - let c = TargetSelection::from_user(TEST_TRIPLE_3); - - assert_eq!(first(cache.all::()), &[dist::Docs { host: c },]); - assert_eq!(first(cache.all::()), &[dist::Mingw { host: c },]); - assert_eq!( - first(cache.all::()), - &[dist::Std { compiler: Compiler::new(2, a), target: c },] - ); - } - - #[test] - fn dist_with_same_targets_and_hosts() { - let mut cache = run_build( - &[], - configure(&[TEST_TRIPLE_1, TEST_TRIPLE_2], &[TEST_TRIPLE_1, TEST_TRIPLE_2]), - ); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - let b = TargetSelection::from_user(TEST_TRIPLE_2); - - assert_eq!( - first(cache.all::()), - &[dist::Docs { host: a }, dist::Docs { host: b },] - ); - assert_eq!( - first(cache.all::()), - &[dist::Mingw { host: a }, dist::Mingw { host: b },] - ); - assert_eq!( - first(cache.all::()), - &[ - dist::Rustc { compiler: Compiler::new(2, a) }, - dist::Rustc { compiler: Compiler::new(2, b) }, - ] - ); - assert_eq!( - first(cache.all::()), - &[ - dist::Std { compiler: Compiler::new(1, a), target: a }, - dist::Std { compiler: Compiler::new(1, a), target: b }, - ] - ); - assert_eq!(first(cache.all::()), &[dist::Src]); - assert_eq!( - first(cache.all::()), - &[ - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 2), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 1), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 2), - ] - ); - assert_eq!( - first(cache.all::()), - &[ - compile::Assemble { target_compiler: Compiler::new(0, a) }, - compile::Assemble { target_compiler: Compiler::new(1, a) }, - compile::Assemble { target_compiler: Compiler::new(2, a) }, - compile::Assemble { target_compiler: Compiler::new(2, b) }, - ] - ); - } - - /// This also serves as an important regression test for - /// and . - #[test] - fn dist_all_cross() { - let cmd_args = - &["dist", "--stage", "2", "--dry-run", "--config=/does/not/exist"].map(str::to_owned); - let config_str = r#" - [rust] - channel = "nightly" - - [build] - extended = true - - build = "i686-unknown-haiku" - host = ["i686-unknown-netbsd"] - target = ["i686-unknown-netbsd"] - "#; - let config = Config::parse_inner(Flags::parse(cmd_args), |&_| toml::from_str(config_str)); - let mut cache = run_build(&[], config); - - // Stage 2 `compile::Rustc` should **NEVER** be cached here. - assert_eq!( - first(cache.all::()), - &[ - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1), - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_3, stage = 1), - ] - ); - } - - #[test] - fn build_all() { - let build = Build::new(configure( - &[TEST_TRIPLE_1, TEST_TRIPLE_2], - &[TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3], - )); - let mut builder = Builder::new(&build); - builder.run_step_descriptions( - &Builder::get_step_descriptions(Kind::Build), - &["compiler/rustc".into(), "library".into()], - ); - - assert_eq!(builder.config.stage, 2); - - // `compile::Rustc` includes one-stage-off compiler information as the target compiler - // artifacts get copied from there to the target stage sysroot. - // For example, `stage2/bin/rustc` gets copied from the `stage1-rustc` build directory. - assert_eq!( - first(builder.cache.all::()), - &[ - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1), - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 1), - ] - ); - - assert_eq!( - first(builder.cache.all::()), - &[ - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 2), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 1), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 2), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_3, stage = 2), - ] - ); - - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Assemble { - target_compiler: Compiler::new(0, TargetSelection::from_user(TEST_TRIPLE_1),) - }, - compile::Assemble { - target_compiler: Compiler::new(1, TargetSelection::from_user(TEST_TRIPLE_1),) - }, - compile::Assemble { - target_compiler: Compiler::new(2, TargetSelection::from_user(TEST_TRIPLE_1),) - }, - compile::Assemble { - target_compiler: Compiler::new(2, TargetSelection::from_user(TEST_TRIPLE_2),) - }, - ] - ); - } - #[test] fn llvm_out_behaviour() { let mut config = configure(&[TEST_TRIPLE_1], &[TEST_TRIPLE_2]); @@ -783,85 +317,6 @@ mod dist { assert!(build.llvm_out(target).ends_with("llvm")); } - #[test] - fn build_with_empty_host() { - let config = configure(&[], &[TEST_TRIPLE_3]); - let build = Build::new(config); - let mut builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); - - let a = TargetSelection::from_user(TEST_TRIPLE_1); - - assert_eq!( - first(builder.cache.all::()), - &[ - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1), - std!(TEST_TRIPLE_1 => TEST_TRIPLE_3, stage = 2), - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - compile::Assemble { target_compiler: Compiler::new(0, a) }, - compile::Assemble { target_compiler: Compiler::new(1, a) }, - compile::Assemble { target_compiler: Compiler::new(2, a) }, - ] - ); - assert_eq!( - first(builder.cache.all::()), - &[ - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0), - rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1), - ] - ); - } - - #[test] - fn test_with_no_doc_stage0() { - let mut config = configure(&[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); - config.stage = 0; - config.paths = vec!["library/std".into()]; - config.cmd = Subcommand::Test { - test_args: vec![], - compiletest_rustc_args: vec![], - no_fail_fast: false, - no_doc: true, - doc: false, - bless: false, - force_rerun: false, - compare_mode: None, - rustfix_coverage: false, - pass: None, - run: None, - only_modified: false, - extra_checks: None, - no_capture: false, - }; - - let build = Build::new(config); - let mut builder = Builder::new(&build); - - let host = TargetSelection::from_user(TEST_TRIPLE_1); - - builder.run_step_descriptions( - &[StepDescription::from::(Kind::Test)], - &["library/std".into()], - ); - - // Ensure we don't build any compiler artifacts. - assert!(!builder.cache.contains::()); - assert_eq!( - first(builder.cache.all::()), - &[test::Crate { - compiler: Compiler::new(0, host), - target: host, - mode: crate::Mode::Std, - crates: vec!["std".to_owned()], - },] - ); - } - #[test] fn doc_ci() { let mut config = configure(&[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); @@ -889,65 +344,6 @@ mod dist { &[tool::Rustdoc { compiler: Compiler::new(2, a) },] ); } - - #[test] - fn test_docs() { - // Behavior of `x.py test` doing various documentation tests. - let mut config = configure(&[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); - config.cmd = Subcommand::Test { - test_args: vec![], - compiletest_rustc_args: vec![], - no_fail_fast: false, - doc: true, - no_doc: false, - bless: false, - force_rerun: false, - compare_mode: None, - rustfix_coverage: false, - pass: None, - run: None, - only_modified: false, - extra_checks: None, - no_capture: false, - }; - // Make sure rustfmt binary not being found isn't an error. - config.channel = "beta".to_string(); - let build = Build::new(config); - let mut builder = Builder::new(&build); - - builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]); - let a = TargetSelection::from_user(TEST_TRIPLE_1); - - // error_index_generator uses stage 1 to share rustdoc artifacts with the - // rustdoc tool. - assert_eq!( - first(builder.cache.all::()), - &[doc::ErrorIndex { target: a },] - ); - assert_eq!( - first(builder.cache.all::()), - &[tool::ErrorIndex { compiler: Compiler::new(1, a) }] - ); - // Unfortunately rustdoc is built twice. Once from stage1 for compiletest - // (and other things), and once from stage0 for std crates. Ideally it - // would only be built once. If someone wants to fix this, it might be - // worth investigating if it would be possible to test std from stage1. - // Note that the stages here are +1 than what they actually are because - // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is - // not 0. - // - // The stage 0 copy is the one downloaded for bootstrapping. It is - // (currently) needed to run "cargo test" on the linkchecker, and - // should be relatively "free". - assert_eq!( - first(builder.cache.all::()), - &[ - tool::Rustdoc { compiler: Compiler::new(0, a) }, - tool::Rustdoc { compiler: Compiler::new(1, a) }, - tool::Rustdoc { compiler: Compiler::new(2, a) }, - ] - ); - } } mod sysroot_target_dirs { @@ -1234,16 +630,77 @@ fn any_debug() { assert_eq!(x.downcast_ref::(), Some(&MyStruct { x: 7 })); } -/// The staging tests use insta for snapshot testing. +/// These tests use insta for snapshot testing. /// See bootstrap's README on how to bless the snapshots. -mod staging { - use crate::Build; - use crate::core::builder::Builder; +mod snapshot { + use std::path::PathBuf; + + use crate::core::build_steps::{compile, dist, doc, test, tool}; use crate::core::builder::tests::{ - TEST_TRIPLE_1, configure, configure_with_args, render_steps, run_build, + TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, configure, configure_with_args, first, + host_target, render_steps, run_build, }; + use crate::core::builder::{Builder, Kind, StepDescription, StepMetadata}; + use crate::core::config::TargetSelection; use crate::utils::cache::Cache; + use crate::utils::helpers::get_host_target; use crate::utils::tests::{ConfigBuilder, TestCtx}; + use crate::{Build, Compiler, Config, Flags, Subcommand}; + + #[test] + fn build_default() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("build") + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 0 + "); + } + + #[test] + fn build_cross_compile() { + let ctx = TestCtx::new(); + + insta::assert_snapshot!( + ctx.config("build") + // Cross-compilation fails on stage 1, as we don't have a stage0 std available + // for non-host targets. + .stage(2) + .hosts(&[&host_target(), TEST_TRIPLE_1]) + .targets(&[&host_target(), TEST_TRIPLE_1]) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [build] rustdoc 1 + [build] llvm + [build] rustc 1 -> rustc 2 + [build] rustdoc 1 + "); + } + + #[test] + fn build_with_empty_host() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("build") + .hosts(&[]) + .targets(&[TEST_TRIPLE_1]) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + " + ); + } #[test] fn build_compiler_no_stage() { @@ -1251,7 +708,7 @@ mod staging { insta::assert_snapshot!( ctx.config("build") .path("compiler") - .get_steps(), @r" + .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 "); @@ -1271,7 +728,7 @@ mod staging { ctx.config("build") .path("compiler") .stage(1) - .get_steps(), @r" + .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 "); @@ -1284,7 +741,7 @@ mod staging { ctx.config("build") .path("compiler") .stage(2) - .get_steps(), @r" + .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 @@ -1298,7 +755,7 @@ mod staging { insta::assert_snapshot!( ctx.config("build") .path("library") - .get_steps(), @r" + .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 @@ -1319,7 +776,7 @@ mod staging { ctx.config("build") .path("library") .stage(1) - .get_steps(), @r" + .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 @@ -1333,7 +790,7 @@ mod staging { ctx.config("build") .path("library") .stage(2) - .get_steps(), @r" + .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 @@ -1348,7 +805,7 @@ mod staging { insta::assert_snapshot!( ctx.config("build") .path("miri") - .get_steps(), @r" + .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 "); @@ -1368,7 +825,7 @@ mod staging { ctx.config("build") .path("miri") .stage(1) - .get_steps(), @r" + .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 "); @@ -1381,7 +838,7 @@ mod staging { ctx.config("build") .path("miri") .stage(2) - .get_steps(), @r" + .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 @@ -1395,7 +852,7 @@ mod staging { insta::assert_snapshot!( ctx.config("build") .path("opt-dist") - .get_steps(), @"[build] rustc 0 -> OptimizedDist "); + .render_steps(), @"[build] rustc 0 -> OptimizedDist "); } #[test] @@ -1412,7 +869,7 @@ mod staging { ctx.config("build") .path("opt-dist") .stage(1) - .get_steps(), @"[build] rustc 0 -> OptimizedDist "); + .render_steps(), @"[build] rustc 0 -> OptimizedDist "); } #[test] @@ -1422,25 +879,432 @@ mod staging { ctx.config("build") .path("opt-dist") .stage(2) - .get_steps(), @"[build] rustc 0 -> OptimizedDist "); + .render_steps(), @"[build] rustc 0 -> OptimizedDist "); } - impl ConfigBuilder { - fn run(self) -> Cache { - let config = self.create_config(); + #[test] + fn build_default_stage() { + let ctx = TestCtx::new(); + assert_eq!(ctx.config("build").path("compiler").create_config().stage, 1); + } - let kind = config.cmd.kind(); - let build = Build::new(config); - let builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(kind), &builder.paths); - builder.cache - } + /// Ensure that if someone passes both a single crate and `library`, all + /// library crates get built. + #[test] + fn alias_and_path_for_library() { + let ctx = TestCtx::new(); + insta::assert_snapshot!(ctx.config("build") + .paths(&["library", "core"]) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + "); - fn get_steps(self) -> String { - let cache = self.run(); - render_steps(&cache.into_executed_steps()) + insta::assert_snapshot!(ctx.config("doc") + .paths(&["library", "core"]) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 0 + [doc] std 1 + "); + } + + #[test] + fn build_all() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("build") + .stage(2) + .paths(&["compiler/rustc", "library"]) + .hosts(&[&host_target(), TEST_TRIPLE_1]) + .targets(&[&host_target(), TEST_TRIPLE_1, TEST_TRIPLE_2]) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] llvm + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 2 -> std 2 + [build] rustc 2 -> std 2 + "); + } + + #[test] + fn dist_default_stage() { + let ctx = TestCtx::new(); + assert_eq!(ctx.config("dist").path("compiler").create_config().stage, 2); + } + + #[test] + fn dist_baseline() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .render_steps(), @r" + [build] rustc 0 -> UnstableBookGen + [build] rustc 0 -> Rustbook + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustdoc 1 + [doc] std 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> LintDocs + [build] rustc 0 -> RustInstaller + [dist] docs + [doc] std 2 + [dist] mingw + [build] rustc 0 -> GenerateCopyright + [dist] rustc + [dist] rustc 1 -> std + [dist] src <> + " + ); + } + + #[test] + fn dist_extended() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .args(&["--set", "build.extended=true"]) + .render_steps(), @r" + [build] rustc 0 -> UnstableBookGen + [build] rustc 0 -> Rustbook + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> WasmComponentLd + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> WasmComponentLd + [build] rustdoc 1 + [doc] std 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> LintDocs + [build] rustc 0 -> RustInstaller + [dist] docs + [doc] std 2 + [dist] mingw + [build] rustc 0 -> GenerateCopyright + [dist] rustc + [dist] rustc 1 -> std + [dist] src <> + "); + } + + #[test] + fn dist_with_targets() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .hosts(&[&host_target()]) + .targets(&[&host_target(), TEST_TRIPLE_1]) + .render_steps(), @r" + [build] rustc 0 -> UnstableBookGen + [build] rustc 0 -> Rustbook + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustdoc 1 + [doc] std 2 + [doc] std 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> LintDocs + [build] rustc 0 -> RustInstaller + [dist] docs + [dist] docs + [doc] std 2 + [doc] std 2 + [dist] mingw + [dist] mingw + [build] rustc 0 -> GenerateCopyright + [dist] rustc + [dist] rustc 1 -> std + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std + [dist] src <> + " + ); + } + + #[test] + fn dist_with_hosts() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .hosts(&[&host_target(), TEST_TRIPLE_1]) + .targets(&[&host_target()]) + .render_steps(), @r" + [build] rustc 0 -> UnstableBookGen + [build] rustc 0 -> Rustbook + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustdoc 1 + [doc] std 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> LintDocs + [build] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [build] rustc 0 -> RustInstaller + [dist] docs + [doc] std 2 + [dist] mingw + [build] rustc 0 -> GenerateCopyright + [dist] rustc + [build] llvm + [build] rustc 1 -> rustc 2 + [build] rustdoc 1 + [dist] rustc + [dist] rustc 1 -> std + [dist] src <> + " + ); + } + + #[test] + fn dist_with_targets_and_hosts() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .hosts(&[&host_target(), TEST_TRIPLE_1]) + .targets(&[&host_target(), TEST_TRIPLE_1]) + .render_steps(), @r" + [build] rustc 0 -> UnstableBookGen + [build] rustc 0 -> Rustbook + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustdoc 1 + [doc] std 2 + [doc] std 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> LintDocs + [build] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [build] rustc 0 -> RustInstaller + [dist] docs + [dist] docs + [doc] std 2 + [doc] std 2 + [dist] mingw + [dist] mingw + [build] rustc 0 -> GenerateCopyright + [dist] rustc + [build] llvm + [build] rustc 1 -> rustc 2 + [build] rustdoc 1 + [dist] rustc + [dist] rustc 1 -> std + [dist] rustc 1 -> std + [dist] src <> + " + ); + } + + #[test] + fn dist_with_empty_host() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .hosts(&[]) + .targets(&[TEST_TRIPLE_1]) + .render_steps(), @r" + [build] rustc 0 -> UnstableBookGen + [build] rustc 0 -> Rustbook + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustdoc 1 + [doc] std 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> RustInstaller + [dist] docs + [doc] std 2 + [dist] mingw + [build] rustc 2 -> std 2 + [dist] rustc 2 -> std + "); + } + + /// This also serves as an important regression test for + /// and . + #[test] + fn dist_all_cross() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .hosts(&[TEST_TRIPLE_1]) + .targets(&[TEST_TRIPLE_1]) + .args(&["--set", "rust.channel=nightly", "--set", "build.extended=true"]) + .render_steps(), @r" + [build] rustc 0 -> UnstableBookGen + [build] rustc 0 -> Rustbook + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> WasmComponentLd + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> WasmComponentLd + [build] rustdoc 1 + [doc] std 2 + [build] rustc 2 -> std 2 + [build] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [build] rustc 0 -> LintDocs + [build] rustc 0 -> RustInstaller + [dist] docs + [doc] std 2 + [dist] mingw + [build] llvm + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> WasmComponentLd + [build] rustdoc 1 + [build] rustc 0 -> GenerateCopyright + [dist] rustc + [dist] rustc 1 -> std + [dist] src <> + "); + } + + #[test] + fn test_exclude() { + let ctx = TestCtx::new(); + let steps = ctx.config("test").args(&["--skip", "src/tools/tidy"]).get_steps(); + + let host = TargetSelection::from_user(&host_target()); + steps.assert_contains(StepMetadata::test("RustdocUi", host)); + steps.assert_not_contains(test::Tidy); + } + + #[test] + fn test_exclude_kind() { + let ctx = TestCtx::new(); + let host = TargetSelection::from_user(&host_target()); + + let get_steps = |args: &[&str]| ctx.config("test").args(args).get_steps(); + + // Ensure our test is valid, and `test::Rustc` would be run without the exclude. + get_steps(&[]).assert_contains(StepMetadata::test("CrateLibrustc", host)); + + let steps = get_steps(&["--skip", "compiler/rustc_data_structures"]); + + // Ensure tests for rustc are not skipped. + steps.assert_contains(StepMetadata::test("CrateLibrustc", host)); + steps.assert_contains_fuzzy(StepMetadata::build("rustc", host)); + } +} + +struct ExecutedSteps { + steps: Vec, +} + +impl ExecutedSteps { + fn render(&self) -> String { + render_steps(&self.steps) + } + + #[track_caller] + fn assert_contains>(&self, metadata: M) { + let metadata = metadata.into(); + if !self.contains(&metadata) { + panic!( + "Metadata `{}` ({metadata:?}) not found in executed steps:\n{}", + render_metadata(&metadata), + self.render() + ); } } + + /// Try to match metadata by similarity, it does not need to match exactly. + /// Stages (and built_by compiler) do not need to match, but name, target and + /// kind has to match. + #[track_caller] + fn assert_contains_fuzzy>(&self, metadata: M) { + let metadata = metadata.into(); + if !self.contains_fuzzy(&metadata) { + panic!( + "Metadata `{}` ({metadata:?}) not found in executed steps:\n{}", + render_metadata(&metadata), + self.render() + ); + } + } + + #[track_caller] + fn assert_not_contains>(&self, metadata: M) { + let metadata = metadata.into(); + if self.contains(&metadata) { + panic!( + "Metadata `{}` ({metadata:?}) found in executed steps (it should not be there):\n{}", + render_metadata(&metadata), + self.render() + ); + } + } + + fn contains(&self, metadata: &StepMetadata) -> bool { + self.steps + .iter() + .filter_map(|s| s.metadata.as_ref()) + .any(|executed_metadata| executed_metadata == metadata) + } + + fn contains_fuzzy(&self, metadata: &StepMetadata) -> bool { + self.steps + .iter() + .filter_map(|s| s.metadata.as_ref()) + .any(|executed_metadata| fuzzy_metadata_eq(executed_metadata, metadata)) + } +} + +fn fuzzy_metadata_eq(executed: &StepMetadata, to_match: &StepMetadata) -> bool { + let StepMetadata { name, kind, target, built_by: _, stage: _ } = executed; + *name == to_match.name && *kind == to_match.kind && *target == to_match.target +} + +impl From for StepMetadata { + fn from(step: S) -> Self { + step.metadata().expect("step has no metadata") + } +} + +impl ConfigBuilder { + fn run(self) -> Cache { + let config = self.create_config(); + + let kind = config.cmd.kind(); + let build = Build::new(config); + let builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(kind), &builder.paths); + builder.cache + } + + fn get_steps(self) -> ExecutedSteps { + let cache = self.run(); + ExecutedSteps { steps: cache.into_executed_steps() } + } + + fn render_steps(self) -> String { + self.get_steps().render() + } } /// Renders the executed bootstrap steps for usage in snapshot tests with insta. @@ -1460,23 +1324,34 @@ fn render_steps(steps: &[ExecutedStep]) -> String { return None; }; - let mut record = format!("[{}] ", metadata.kind.as_str()); - if let Some(compiler) = metadata.built_by { - write!(record, "{} -> ", render_compiler(compiler)); - } - let stage = - if let Some(stage) = metadata.stage { format!("{stage} ") } else { "".to_string() }; - write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target)); - Some(record) + Some(render_metadata(&metadata)) }) .collect::>() .join("\n") } +fn render_metadata(metadata: &StepMetadata) -> String { + let mut record = format!("[{}] ", metadata.kind.as_str()); + if let Some(compiler) = metadata.built_by { + write!(record, "{} -> ", render_compiler(compiler)); + } + let stage = if let Some(stage) = metadata.stage { format!("{stage} ") } else { "".to_string() }; + write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target)); + record +} + fn normalize_target(target: TargetSelection) -> String { - target.to_string().replace(&get_host_target().to_string(), "host") + target + .to_string() + .replace(&host_target(), "host") + .replace(TEST_TRIPLE_1, "target1") + .replace(TEST_TRIPLE_2, "target2") } fn render_compiler(compiler: Compiler) -> String { format!("rustc {} <{}>", compiler.stage, normalize_target(compiler.host)) } + +fn host_target() -> String { + get_host_target().to_string() +} diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs index 91877fd0da4d..b8984d1f3aaf 100644 --- a/src/bootstrap/src/utils/tests/mod.rs +++ b/src/bootstrap/src/utils/tests/mod.rs @@ -51,12 +51,38 @@ impl ConfigBuilder { self } + pub fn paths(mut self, paths: &[&str]) -> Self { + for path in paths { + self = self.path(path); + } + self + } + + pub fn hosts(mut self, targets: &[&str]) -> Self { + self.args.push("--host".to_string()); + self.args.push(targets.join(",")); + self + } + + pub fn targets(mut self, targets: &[&str]) -> Self { + self.args.push("--target".to_string()); + self.args.push(targets.join(",")); + self + } + pub fn stage(mut self, stage: u32) -> Self { self.args.push("--stage".to_string()); self.args.push(stage.to_string()); self } + pub fn args(mut self, args: &[&str]) -> Self { + for arg in args { + self.args.push(arg.to_string()); + } + self + } + pub fn create_config(mut self) -> Config { // Run in dry-check, otherwise the test would be too slow self.args.push("--dry-run".to_string());