Skip to content

Commit 3db9d38

Browse files
authored
Rollup merge of rust-lang#142629 - Kobzol:bootstrap-tests-builder, r=jieyouxu,Shourya742
Add config builder for bootstrap tests I started writing a bunch of snapshot tests for build/check steps, and quickly realized that the current interface for defining them won't be enough, so I created a simple builder, which can scale to pretty much any kind of configuration in the future.
2 parents f22e22f + 718e475 commit 3db9d38

File tree

4 files changed

+85
-19
lines changed

4 files changed

+85
-19
lines changed

src/bootstrap/src/core/builder/tests.rs

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::Flags;
99
use crate::core::build_steps::doc::DocumentationFormat;
1010
use crate::core::config::Config;
1111
use crate::utils::cache::ExecutedStep;
12+
use crate::utils::helpers::get_host_target;
1213
use crate::utils::tests::git::{GitCtx, git_test};
1314

1415
static TEST_TRIPLE_1: &str = "i686-unknown-haiku";
@@ -1236,29 +1237,47 @@ fn any_debug() {
12361237
/// The staging tests use insta for snapshot testing.
12371238
/// See bootstrap's README on how to bless the snapshots.
12381239
mod staging {
1240+
use crate::Build;
1241+
use crate::core::builder::Builder;
12391242
use crate::core::builder::tests::{
12401243
TEST_TRIPLE_1, configure, configure_with_args, render_steps, run_build,
12411244
};
1245+
use crate::utils::tests::ConfigBuilder;
12421246

12431247
#[test]
12441248
fn build_compiler_stage_1() {
1245-
let mut cache = run_build(
1246-
&["compiler".into()],
1247-
configure_with_args(&["build", "--stage", "1"], &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]),
1248-
);
1249-
let steps = cache.into_executed_steps();
1250-
insta::assert_snapshot!(render_steps(&steps), @r"
1251-
[build] rustc 0 <target1> -> std 0 <target1>
1252-
[build] llvm <target1>
1253-
[build] rustc 0 <target1> -> rustc 1 <target1>
1254-
[build] rustc 0 <target1> -> rustc 1 <target1>
1249+
insta::assert_snapshot!(
1250+
ConfigBuilder::build()
1251+
.path("compiler")
1252+
.stage(1)
1253+
.get_steps(), @r"
1254+
[build] rustc 0 <host> -> std 0 <host>
1255+
[build] llvm <host>
1256+
[build] rustc 0 <host> -> rustc 1 <host>
1257+
[build] rustc 0 <host> -> rustc 1 <host>
12551258
");
12561259
}
1260+
1261+
impl ConfigBuilder {
1262+
fn get_steps(self) -> String {
1263+
let config = self.create_config();
1264+
1265+
let kind = config.cmd.kind();
1266+
let build = Build::new(config);
1267+
let builder = Builder::new(&build);
1268+
builder.run_step_descriptions(&Builder::get_step_descriptions(kind), &builder.paths);
1269+
render_steps(&builder.cache.into_executed_steps())
1270+
}
1271+
}
12571272
}
12581273

12591274
/// Renders the executed bootstrap steps for usage in snapshot tests with insta.
12601275
/// Only renders certain important steps.
12611276
/// Each value in `steps` should be a tuple of (Step, step output).
1277+
///
1278+
/// The arrow in the rendered output (`X -> Y`) means `X builds Y`.
1279+
/// This is similar to the output printed by bootstrap to stdout, but here it is
1280+
/// generated purely for the purpose of tests.
12621281
fn render_steps(steps: &[ExecutedStep]) -> String {
12631282
steps
12641283
.iter()
@@ -1275,18 +1294,17 @@ fn render_steps(steps: &[ExecutedStep]) -> String {
12751294
}
12761295
let stage =
12771296
if let Some(stage) = metadata.stage { format!("{stage} ") } else { "".to_string() };
1278-
write!(record, "{} {stage}<{}>", metadata.name, metadata.target);
1297+
write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target));
12791298
Some(record)
12801299
})
1281-
.map(|line| {
1282-
line.replace(TEST_TRIPLE_1, "target1")
1283-
.replace(TEST_TRIPLE_2, "target2")
1284-
.replace(TEST_TRIPLE_3, "target3")
1285-
})
12861300
.collect::<Vec<_>>()
12871301
.join("\n")
12881302
}
12891303

1304+
fn normalize_target(target: TargetSelection) -> String {
1305+
target.to_string().replace(&get_host_target().to_string(), "host")
1306+
}
1307+
12901308
fn render_compiler(compiler: Compiler) -> String {
1291-
format!("rustc {} <{}>", compiler.stage, compiler.host)
1309+
format!("rustc {} <{}>", compiler.stage, normalize_target(compiler.host))
12921310
}

src/bootstrap/src/core/config/config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use crate::core::download::is_download_ci_available;
4949
use crate::utils::channel;
5050
use crate::utils::exec::command;
5151
use crate::utils::execution_context::ExecutionContext;
52-
use crate::utils::helpers::exe;
52+
use crate::utils::helpers::{exe, get_host_target};
5353
use crate::{GitInfo, OnceLock, TargetSelection, check_ci_llvm, helpers, t};
5454

5555
/// Each path in this list is considered "allowed" in the `download-rustc="if-unchanged"` logic.
@@ -349,7 +349,7 @@ impl Config {
349349
stderr_is_tty: std::io::stderr().is_terminal(),
350350

351351
// set by build.rs
352-
host_target: TargetSelection::from_user(env!("BUILD_TRIPLE")),
352+
host_target: get_host_target(),
353353

354354
src: {
355355
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

src/bootstrap/src/utils/helpers.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result<
178178
}
179179
}
180180

181+
/// Return the host target on which we are currently running.
182+
pub fn get_host_target() -> TargetSelection {
183+
TargetSelection::from_user(env!("BUILD_TRIPLE"))
184+
}
185+
181186
/// Rename a file if from and to are in the same filesystem or
182187
/// copy and remove the file otherwise
183188
pub fn move_file<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {

src/bootstrap/src/utils/tests/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,46 @@
11
//! This module contains shared utilities for bootstrap tests.
22
3+
use crate::core::builder::Builder;
4+
use crate::core::config::DryRun;
5+
use crate::{Build, Config, Flags};
6+
37
pub mod git;
8+
9+
/// Used to configure an invocation of bootstrap.
10+
/// Currently runs in the rustc checkout, long-term it should be switched
11+
/// to run in a (cache-primed) temporary directory instead.
12+
pub struct ConfigBuilder {
13+
args: Vec<String>,
14+
}
15+
16+
impl ConfigBuilder {
17+
pub fn from_args(args: &[&str]) -> Self {
18+
Self::new(args)
19+
}
20+
21+
pub fn build() -> Self {
22+
Self::new(&["build"])
23+
}
24+
25+
pub fn path(mut self, path: &str) -> Self {
26+
self.args.push(path.to_string());
27+
self
28+
}
29+
30+
pub fn stage(mut self, stage: u32) -> Self {
31+
self.args.push("--stage".to_string());
32+
self.args.push(stage.to_string());
33+
self
34+
}
35+
36+
fn new(args: &[&str]) -> Self {
37+
Self { args: args.iter().copied().map(String::from).collect() }
38+
}
39+
40+
pub fn create_config(mut self) -> Config {
41+
let mut config = Config::parse(Flags::parse(&self.args));
42+
// Run in dry-check, otherwise the test would be too slow
43+
config.set_dry_run(DryRun::SelfCheck);
44+
config
45+
}
46+
}

0 commit comments

Comments
 (0)