Skip to content

Commit a885811

Browse files
committed
Auto merge of #146595 - Shourya742:make-cargo-test-work-for-self-test, r=Kobzol
Make cargo test work for bootstrap self test This PR enables the bootstrap self-test to run via cargo test. I have removed the detect_src_and_out test for now, but it will be reintroduced in a follow-up PR where all bootstrap tests will be migrated to use testCtx. r? `@Kobzol` try-job: aarch64-apple
2 parents 5b9007b + 191c7ed commit a885811

File tree

6 files changed

+337
-394
lines changed

6 files changed

+337
-394
lines changed

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

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,7 @@ fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
2222
}
2323

2424
fn configure_with_args(cmd: &[&str], host: &[&str], target: &[&str]) -> Config {
25-
TestCtx::new()
26-
.config(cmd[0])
27-
.args(&cmd[1..])
28-
.hosts(host)
29-
.targets(target)
30-
.args(&["--build", TEST_TRIPLE_1])
31-
.create_config()
25+
TestCtx::new().config(cmd[0]).args(&cmd[1..]).hosts(host).targets(target).create_config()
3226
}
3327

3428
fn first<A, B>(v: Vec<(A, B)>) -> Vec<A> {
@@ -218,25 +212,25 @@ fn prepare_rustc_checkout(ctx: &mut GitCtx) {
218212

219213
/// Parses a Config directory from `path`, with the given value of `download_rustc`.
220214
fn parse_config_download_rustc_at(path: &Path, download_rustc: &str, ci: bool) -> Config {
221-
Config::parse_inner(
222-
Flags::parse(&[
223-
"build".to_owned(),
224-
"--dry-run".to_owned(),
225-
"--ci".to_owned(),
226-
if ci { "true" } else { "false" }.to_owned(),
227-
format!("--set=rust.download-rustc='{download_rustc}'"),
228-
"--src".to_owned(),
229-
path.to_str().unwrap().to_owned(),
230-
]),
231-
|&_| Ok(Default::default()),
232-
)
215+
TestCtx::new()
216+
.config("build")
217+
.args(&[
218+
"--ci",
219+
if ci { "true" } else { "false" },
220+
format!("--set=rust.download-rustc='{download_rustc}'").as_str(),
221+
"--src",
222+
path.to_str().unwrap(),
223+
])
224+
.no_override_download_ci_llvm()
225+
.create_config()
233226
}
234227

235228
mod dist {
236229
use pretty_assertions::assert_eq;
237230

238231
use super::{Config, TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, first, run_build};
239232
use crate::Flags;
233+
use crate::core::builder::tests::host_target;
240234
use crate::core::builder::*;
241235

242236
fn configure(host: &[&str], target: &[&str]) -> Config {
@@ -245,11 +239,11 @@ mod dist {
245239

246240
#[test]
247241
fn llvm_out_behaviour() {
248-
let mut config = configure(&[TEST_TRIPLE_1], &[TEST_TRIPLE_2]);
242+
let mut config = configure(&[], &[TEST_TRIPLE_2]);
249243
config.llvm_from_ci = true;
250244
let build = Build::new(config.clone());
251245

252-
let target = TargetSelection::from_user(TEST_TRIPLE_1);
246+
let target = TargetSelection::from_user(&host_target());
253247
assert!(build.llvm_out(target).ends_with("ci-llvm"));
254248
let target = TargetSelection::from_user(TEST_TRIPLE_2);
255249
assert!(build.llvm_out(target).ends_with("llvm"));
@@ -314,7 +308,7 @@ mod sysroot_target_dirs {
314308
/// cg_gcc tests instead.
315309
#[test]
316310
fn test_test_compiler() {
317-
let config = configure_with_args(&["test", "compiler"], &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]);
311+
let config = configure_with_args(&["test", "compiler"], &[&host_target()], &[TEST_TRIPLE_1]);
318312
let cache = run_build(&config.paths.clone(), config);
319313

320314
let compiler = cache.contains::<test::CrateLibrustc>();
@@ -347,7 +341,7 @@ fn test_test_coverage() {
347341
// Print each test case so that if one fails, the most recently printed
348342
// case is the one that failed.
349343
println!("Testing case: {cmd:?}");
350-
let config = configure_with_args(cmd, &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]);
344+
let config = configure_with_args(cmd, &[], &[TEST_TRIPLE_1]);
351345
let mut cache = run_build(&config.paths.clone(), config);
352346

353347
let modes =
@@ -359,14 +353,7 @@ fn test_test_coverage() {
359353
#[test]
360354
fn test_prebuilt_llvm_config_path_resolution() {
361355
fn configure(config: &str) -> Config {
362-
Config::parse_inner(
363-
Flags::parse(&[
364-
"build".to_string(),
365-
"--dry-run".to_string(),
366-
"--config=/does/not/exist".to_string(),
367-
]),
368-
|&_| toml::from_str(&config),
369-
)
356+
TestCtx::new().config("build").with_default_toml_config(config).create_config()
370357
}
371358

372359
// Removes Windows disk prefix if present

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

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -414,14 +414,28 @@ impl Config {
414414
// Set config values based on flags.
415415
let mut exec_ctx = ExecutionContext::new(flags_verbose, flags_cmd.fail_fast());
416416
exec_ctx.set_dry_run(if flags_dry_run { DryRun::UserSelected } else { DryRun::Disabled });
417-
let mut src = {
417+
418+
let default_src_dir = {
418419
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
419420
// Undo `src/bootstrap`
420421
manifest_dir.parent().unwrap().parent().unwrap().to_owned()
421422
};
423+
let src = if let Some(s) = compute_src_directory(flags_src, &exec_ctx) {
424+
s
425+
} else {
426+
default_src_dir.clone()
427+
};
422428

423-
if let Some(src_) = compute_src_directory(flags_src, &exec_ctx) {
424-
src = src_;
429+
#[cfg(test)]
430+
{
431+
if let Some(config_path) = flags_config.as_ref() {
432+
assert!(
433+
!config_path.starts_with(&src),
434+
"Path {config_path:?} should not be inside or equal to src dir {src:?}"
435+
);
436+
} else {
437+
panic!("During test the config should be explicitly added");
438+
}
425439
}
426440

427441
// Now load the TOML config, as soon as possible
@@ -630,19 +644,13 @@ impl Config {
630644
let llvm_assertions = llvm_assertions.unwrap_or(false);
631645
let mut target_config = HashMap::new();
632646
let mut channel = "dev".to_string();
633-
let out = flags_build_dir.or(build_build_dir.map(PathBuf::from)).unwrap_or_else(|| {
634-
if cfg!(test) {
635-
// Use the build directory of the original x.py invocation, so that we can set `initial_rustc` properly.
636-
Path::new(
637-
&env::var_os("CARGO_TARGET_DIR").expect("cargo test directly is not supported"),
638-
)
639-
.parent()
640-
.unwrap()
641-
.to_path_buf()
642-
} else {
643-
PathBuf::from("build")
644-
}
645-
});
647+
648+
let out = flags_build_dir.or_else(|| build_build_dir.map(PathBuf::from));
649+
let out = if cfg!(test) {
650+
out.expect("--build-dir has to be specified in tests")
651+
} else {
652+
out.unwrap_or_else(|| PathBuf::from("build"))
653+
};
646654

647655
// NOTE: Bootstrap spawns various commands with different working directories.
648656
// To avoid writing to random places on the file system, `config.out` needs to be an absolute path.
@@ -653,6 +661,10 @@ impl Config {
653661
out
654662
};
655663

664+
let default_stage0_rustc_path = |dir: &Path| {
665+
dir.join(host_target).join("stage0").join("bin").join(exe("rustc", host_target))
666+
};
667+
656668
if cfg!(test) {
657669
// When configuring bootstrap for tests, make sure to set the rustc and Cargo to the
658670
// same ones used to call the tests (if custom ones are not defined in the toml). If we
@@ -661,6 +673,22 @@ impl Config {
661673
// Cargo in their bootstrap.toml.
662674
build_rustc = build_rustc.take().or(std::env::var_os("RUSTC").map(|p| p.into()));
663675
build_cargo = build_cargo.take().or(std::env::var_os("CARGO").map(|p| p.into()));
676+
677+
// If we are running only `cargo test` (and not `x test bootstrap`), which is useful
678+
// e.g. for debugging bootstrap itself, then we won't have RUSTC and CARGO set to the
679+
// proper paths.
680+
// We thus "guess" that the build directory is located at <src>/build, and try to load
681+
// rustc and cargo from there
682+
let is_test_outside_x = std::env::var("CARGO_TARGET_DIR").is_err();
683+
if is_test_outside_x && build_rustc.is_none() {
684+
let stage0_rustc = default_stage0_rustc_path(&default_src_dir.join("build"));
685+
assert!(
686+
stage0_rustc.exists(),
687+
"Trying to run cargo test without having a stage0 rustc available in {}",
688+
stage0_rustc.display()
689+
);
690+
build_rustc = Some(stage0_rustc);
691+
}
664692
}
665693

666694
if !flags_skip_stage0_validation {
@@ -694,7 +722,7 @@ impl Config {
694722

695723
let initial_rustc = build_rustc.unwrap_or_else(|| {
696724
download_beta_toolchain(&dwn_ctx, &out);
697-
out.join(host_target).join("stage0").join("bin").join(exe("rustc", host_target))
725+
default_stage0_rustc_path(&out)
698726
});
699727

700728
let initial_sysroot = t!(PathBuf::from_str(
@@ -1534,11 +1562,11 @@ impl Config {
15341562
println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
15351563
println!("HELP: Consider rebasing to a newer commit if available.");
15361564
return None;
1537-
},
1565+
}
15381566
Err(e) => {
15391567
eprintln!("ERROR: Failed to parse CI rustc bootstrap.toml: {e}");
15401568
exit!(2);
1541-
},
1569+
}
15421570
};
15431571

15441572
let current_config_toml = Self::get_toml(config_path).unwrap();

0 commit comments

Comments
 (0)