diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 229adf714598b..4555f0d20912e 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -22,13 +22,7 @@ fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
}
fn configure_with_args(cmd: &[&str], host: &[&str], target: &[&str]) -> Config {
- TestCtx::new()
- .config(cmd[0])
- .args(&cmd[1..])
- .hosts(host)
- .targets(target)
- .args(&["--build", TEST_TRIPLE_1])
- .create_config()
+ TestCtx::new().config(cmd[0]).args(&cmd[1..]).hosts(host).targets(target).create_config()
}
fn first(v: Vec<(A, B)>) -> Vec {
@@ -218,18 +212,17 @@ fn prepare_rustc_checkout(ctx: &mut GitCtx) {
/// Parses a Config directory from `path`, with the given value of `download_rustc`.
fn parse_config_download_rustc_at(path: &Path, download_rustc: &str, ci: bool) -> Config {
- Config::parse_inner(
- Flags::parse(&[
- "build".to_owned(),
- "--dry-run".to_owned(),
- "--ci".to_owned(),
- if ci { "true" } else { "false" }.to_owned(),
- format!("--set=rust.download-rustc='{download_rustc}'"),
- "--src".to_owned(),
- path.to_str().unwrap().to_owned(),
- ]),
- |&_| Ok(Default::default()),
- )
+ TestCtx::new()
+ .config("build")
+ .args(&[
+ "--ci",
+ if ci { "true" } else { "false" },
+ format!("--set=rust.download-rustc='{download_rustc}'").as_str(),
+ "--src",
+ path.to_str().unwrap(),
+ ])
+ .no_override_download_ci_llvm()
+ .create_config()
}
mod dist {
@@ -237,6 +230,7 @@ mod dist {
use super::{Config, TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, first, run_build};
use crate::Flags;
+ use crate::core::builder::tests::host_target;
use crate::core::builder::*;
fn configure(host: &[&str], target: &[&str]) -> Config {
@@ -245,11 +239,11 @@ mod dist {
#[test]
fn llvm_out_behaviour() {
- let mut config = configure(&[TEST_TRIPLE_1], &[TEST_TRIPLE_2]);
+ let mut config = configure(&[], &[TEST_TRIPLE_2]);
config.llvm_from_ci = true;
let build = Build::new(config.clone());
- let target = TargetSelection::from_user(TEST_TRIPLE_1);
+ let target = TargetSelection::from_user(&host_target());
assert!(build.llvm_out(target).ends_with("ci-llvm"));
let target = TargetSelection::from_user(TEST_TRIPLE_2);
assert!(build.llvm_out(target).ends_with("llvm"));
@@ -314,7 +308,7 @@ mod sysroot_target_dirs {
/// cg_gcc tests instead.
#[test]
fn test_test_compiler() {
- let config = configure_with_args(&["test", "compiler"], &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]);
+ let config = configure_with_args(&["test", "compiler"], &[&host_target()], &[TEST_TRIPLE_1]);
let cache = run_build(&config.paths.clone(), config);
let compiler = cache.contains::();
@@ -347,7 +341,7 @@ fn test_test_coverage() {
// Print each test case so that if one fails, the most recently printed
// case is the one that failed.
println!("Testing case: {cmd:?}");
- let config = configure_with_args(cmd, &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]);
+ let config = configure_with_args(cmd, &[], &[TEST_TRIPLE_1]);
let mut cache = run_build(&config.paths.clone(), config);
let modes =
@@ -359,14 +353,7 @@ fn test_test_coverage() {
#[test]
fn test_prebuilt_llvm_config_path_resolution() {
fn configure(config: &str) -> Config {
- Config::parse_inner(
- Flags::parse(&[
- "build".to_string(),
- "--dry-run".to_string(),
- "--config=/does/not/exist".to_string(),
- ]),
- |&_| toml::from_str(&config),
- )
+ TestCtx::new().config("build").with_default_toml_config(config).create_config()
}
// Removes Windows disk prefix if present
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index dd2d5a1fd5332..07a6616be0c98 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -414,14 +414,28 @@ impl Config {
// Set config values based on flags.
let mut exec_ctx = ExecutionContext::new(flags_verbose, flags_cmd.fail_fast());
exec_ctx.set_dry_run(if flags_dry_run { DryRun::UserSelected } else { DryRun::Disabled });
- let mut src = {
+
+ let default_src_dir = {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
// Undo `src/bootstrap`
manifest_dir.parent().unwrap().parent().unwrap().to_owned()
};
+ let src = if let Some(s) = compute_src_directory(flags_src, &exec_ctx) {
+ s
+ } else {
+ default_src_dir.clone()
+ };
- if let Some(src_) = compute_src_directory(flags_src, &exec_ctx) {
- src = src_;
+ #[cfg(test)]
+ {
+ if let Some(config_path) = flags_config.as_ref() {
+ assert!(
+ !config_path.starts_with(&src),
+ "Path {config_path:?} should not be inside or equal to src dir {src:?}"
+ );
+ } else {
+ panic!("During test the config should be explicitly added");
+ }
}
// Now load the TOML config, as soon as possible
@@ -630,19 +644,13 @@ impl Config {
let llvm_assertions = llvm_assertions.unwrap_or(false);
let mut target_config = HashMap::new();
let mut channel = "dev".to_string();
- let out = flags_build_dir.or(build_build_dir.map(PathBuf::from)).unwrap_or_else(|| {
- if cfg!(test) {
- // Use the build directory of the original x.py invocation, so that we can set `initial_rustc` properly.
- Path::new(
- &env::var_os("CARGO_TARGET_DIR").expect("cargo test directly is not supported"),
- )
- .parent()
- .unwrap()
- .to_path_buf()
- } else {
- PathBuf::from("build")
- }
- });
+
+ let out = flags_build_dir.or_else(|| build_build_dir.map(PathBuf::from));
+ let out = if cfg!(test) {
+ out.expect("--build-dir has to be specified in tests")
+ } else {
+ out.unwrap_or_else(|| PathBuf::from("build"))
+ };
// NOTE: Bootstrap spawns various commands with different working directories.
// To avoid writing to random places on the file system, `config.out` needs to be an absolute path.
@@ -653,6 +661,10 @@ impl Config {
out
};
+ let default_stage0_rustc_path = |dir: &Path| {
+ dir.join(host_target).join("stage0").join("bin").join(exe("rustc", host_target))
+ };
+
if cfg!(test) {
// When configuring bootstrap for tests, make sure to set the rustc and Cargo to the
// same ones used to call the tests (if custom ones are not defined in the toml). If we
@@ -661,6 +673,22 @@ impl Config {
// Cargo in their bootstrap.toml.
build_rustc = build_rustc.take().or(std::env::var_os("RUSTC").map(|p| p.into()));
build_cargo = build_cargo.take().or(std::env::var_os("CARGO").map(|p| p.into()));
+
+ // If we are running only `cargo test` (and not `x test bootstrap`), which is useful
+ // e.g. for debugging bootstrap itself, then we won't have RUSTC and CARGO set to the
+ // proper paths.
+ // We thus "guess" that the build directory is located at /build, and try to load
+ // rustc and cargo from there
+ let is_test_outside_x = std::env::var("CARGO_TARGET_DIR").is_err();
+ if is_test_outside_x && build_rustc.is_none() {
+ let stage0_rustc = default_stage0_rustc_path(&default_src_dir.join("build"));
+ assert!(
+ stage0_rustc.exists(),
+ "Trying to run cargo test without having a stage0 rustc available in {}",
+ stage0_rustc.display()
+ );
+ build_rustc = Some(stage0_rustc);
+ }
}
if !flags_skip_stage0_validation {
@@ -694,7 +722,7 @@ impl Config {
let initial_rustc = build_rustc.unwrap_or_else(|| {
download_beta_toolchain(&dwn_ctx, &out);
- out.join(host_target).join("stage0").join("bin").join(exe("rustc", host_target))
+ default_stage0_rustc_path(&out)
});
let initial_sysroot = t!(PathBuf::from_str(
@@ -1534,11 +1562,11 @@ impl Config {
println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
println!("HELP: Consider rebasing to a newer commit if available.");
return None;
- },
+ }
Err(e) => {
eprintln!("ERROR: Failed to parse CI rustc bootstrap.toml: {e}");
exit!(2);
- },
+ }
};
let current_config_toml = Self::get_toml(config_path).unwrap();
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index e93525fbd09ce..4f2df76a15658 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -14,17 +14,15 @@ use super::toml::change_id::ChangeIdWrapper;
use super::{Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS};
use crate::ChangeId;
use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order};
-use crate::core::build_steps::llvm;
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
+use crate::core::build_steps::{llvm, test};
use crate::core::config::toml::TomlConfig;
use crate::core::config::{CompilerBuiltins, LldMode, StringOrBool, Target, TargetSelection};
+use crate::utils::tests::TestCtx;
use crate::utils::tests::git::git_test;
pub(crate) fn parse(config: &str) -> Config {
- Config::parse_inner(
- Flags::parse(&["check".to_string(), "--config=/does/not/exist".to_string()]),
- |&_| toml::from_str(&config),
- )
+ TestCtx::new().config("check").with_default_toml_config(config).create_config()
}
fn get_toml(file: &Path) -> Result {
@@ -32,28 +30,16 @@ fn get_toml(file: &Path) -> Result {
toml::from_str(&contents).and_then(|table: toml::Value| TomlConfig::deserialize(table))
}
-/// Helps with debugging by using consistent test-specific directories instead of
-/// random temporary directories.
-fn prepare_test_specific_dir() -> PathBuf {
- let current = std::thread::current();
- // Replace "::" with "_" to make it safe for directory names on Windows systems
- let test_path = current.name().unwrap().replace("::", "_");
-
- let testdir = parse("").tempdir().join(test_path);
-
- // clean up any old test files
- let _ = fs::remove_dir_all(&testdir);
- let _ = fs::create_dir_all(&testdir);
-
- testdir
-}
-
#[test]
fn download_ci_llvm() {
- let config = parse("llvm.download-ci-llvm = false");
+ let config = TestCtx::new().config("check").create_config();
assert!(!config.llvm_from_ci);
- let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\"");
+ // this doesn't make sense, as we are overriding it later.
+ let if_unchanged_config = TestCtx::new()
+ .config("check")
+ .with_default_toml_config("llvm.download-ci-llvm = \"if-unchanged\"")
+ .create_config();
if if_unchanged_config.llvm_from_ci && if_unchanged_config.is_running_on_ci {
let has_changes = if_unchanged_config.has_changes_from_upstream(LLVM_INVALIDATION_PATHS);
@@ -64,62 +50,6 @@ fn download_ci_llvm() {
}
}
-// FIXME(onur-ozkan): extend scope of the test
-// refs:
-// - https://github.com/rust-lang/rust/issues/109120
-// - https://github.com/rust-lang/rust/pull/109162#issuecomment-1496782487
-#[test]
-fn detect_src_and_out() {
- fn test(cfg: Config, build_dir: Option<&str>) {
- // This will bring absolute form of `src/bootstrap` path
- let current_dir = std::env::current_dir().unwrap();
-
- // get `src` by moving into project root path
- let expected_src = current_dir.ancestors().nth(2).unwrap();
- assert_eq!(&cfg.src, expected_src);
-
- // Sanity check for `src`
- let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
- let expected_src = manifest_dir.ancestors().nth(2).unwrap();
- assert_eq!(&cfg.src, expected_src);
-
- // test if build-dir was manually given in bootstrap.toml
- if let Some(custom_build_dir) = build_dir {
- assert_eq!(&cfg.out, Path::new(custom_build_dir));
- }
- // test the native bootstrap way
- else {
- // This should bring output path of bootstrap in absolute form
- let cargo_target_dir = env::var_os("CARGO_TARGET_DIR").expect(
- "CARGO_TARGET_DIR must been provided for the test environment from bootstrap",
- );
-
- // Move to `build` from `build/bootstrap`
- let expected_out = Path::new(&cargo_target_dir).parent().unwrap();
- assert_eq!(&cfg.out, expected_out);
-
- let args: Vec = env::args().collect();
-
- // Another test for `out` as a sanity check
- //
- // This will bring something similar to:
- // `{build-dir}/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804`
- // `{build-dir}` can be anywhere, not just in the rust project directory.
- let dep = Path::new(args.first().unwrap());
- let expected_out = dep.ancestors().nth(5).unwrap();
-
- assert_eq!(&cfg.out, expected_out);
- }
- }
-
- test(parse(""), None);
-
- {
- let build_dir = if cfg!(windows) { "C:\\tmp" } else { "/tmp" };
- test(parse(&format!("build.build-dir = '{build_dir}'")), Some(build_dir));
- }
-}
-
#[test]
fn clap_verify() {
Flags::command().debug_assert();
@@ -127,54 +57,54 @@ fn clap_verify() {
#[test]
fn override_toml() {
- let config = Config::parse_inner(
- Flags::parse(&[
- "check".to_owned(),
- "--config=/does/not/exist".to_owned(),
- "--set=change-id=1".to_owned(),
- "--set=rust.lto=fat".to_owned(),
- "--set=rust.deny-warnings=false".to_owned(),
- "--set=build.optimized-compiler-builtins=true".to_owned(),
- "--set=build.gdb=\"bar\"".to_owned(),
- "--set=build.tools=[\"cargo\"]".to_owned(),
- "--set=llvm.build-config={\"foo\" = \"bar\"}".to_owned(),
- "--set=target.x86_64-unknown-linux-gnu.runner=bar".to_owned(),
- "--set=target.x86_64-unknown-linux-gnu.rpath=false".to_owned(),
- "--set=target.aarch64-unknown-linux-gnu.sanitizers=false".to_owned(),
- "--set=target.aarch64-apple-darwin.runner=apple".to_owned(),
- "--set=target.aarch64-apple-darwin.optimized-compiler-builtins=false".to_owned(),
- ]),
- |&_| {
- toml::from_str(
- r#"
-change-id = 0
-[rust]
-lto = "off"
-deny-warnings = true
-download-rustc=false
-
-[build]
-gdb = "foo"
-tools = []
-
-[llvm]
-download-ci-llvm = false
-build-config = {}
-
-[target.aarch64-unknown-linux-gnu]
-sanitizers = true
-rpath = true
-runner = "aarch64-runner"
-
-[target.x86_64-unknown-linux-gnu]
-sanitizers = true
-rpath = true
-runner = "x86_64-runner"
-
- "#,
- )
- },
- );
+ let config_toml: &str = r#"
+ change-id = 0
+
+ [rust]
+ lto = "off"
+ deny-warnings = true
+ download-rustc = false
+
+ [build]
+ gdb = "foo"
+ tools = []
+
+ [llvm]
+ download-ci-llvm = false
+ build-config = {}
+
+ [target.aarch64-unknown-linux-gnu]
+ sanitizers = true
+ rpath = true
+ runner = "aarch64-runner"
+
+ [target.x86_64-unknown-linux-gnu]
+ sanitizers = true
+ rpath = true
+ runner = "x86_64-runner"
+ "#;
+
+ let args = [
+ "--set=change-id=1",
+ "--set=rust.lto=fat",
+ "--set=rust.deny-warnings=false",
+ "--set=build.optimized-compiler-builtins=true",
+ "--set=build.gdb=\"bar\"",
+ "--set=build.tools=[\"cargo\"]",
+ "--set=llvm.build-config={\"foo\" = \"bar\"}",
+ "--set=target.x86_64-unknown-linux-gnu.runner=bar",
+ "--set=target.x86_64-unknown-linux-gnu.rpath=false",
+ "--set=target.aarch64-unknown-linux-gnu.sanitizers=false",
+ "--set=target.aarch64-apple-darwin.runner=apple",
+ "--set=target.aarch64-apple-darwin.optimized-compiler-builtins=false",
+ ];
+
+ let config = TestCtx::new()
+ .config("check")
+ .with_default_toml_config(config_toml)
+ .args(&args)
+ .create_config();
+
assert_eq!(config.change_id, Some(ChangeId::Id(1)), "setting top-level value");
assert_eq!(
config.rust_lto,
@@ -233,33 +163,26 @@ runner = "x86_64-runner"
#[test]
#[should_panic]
fn override_toml_duplicate() {
- Config::parse_inner(
- Flags::parse(&[
- "check".to_owned(),
- "--config=/does/not/exist".to_string(),
- "--set=change-id=1".to_owned(),
- "--set=change-id=2".to_owned(),
- ]),
- |&_| toml::from_str("change-id = 0"),
- );
+ TestCtx::new()
+ .config("check")
+ .with_default_toml_config("change-id = 0")
+ .arg("--set")
+ .arg("change-id=1")
+ .arg("--set")
+ .arg("change-id=2")
+ .create_config();
}
#[test]
fn profile_user_dist() {
- fn get_toml(file: &Path) -> Result {
- let contents = if file.ends_with("bootstrap.toml")
- || file.ends_with("config.toml")
- || env::var_os("RUST_BOOTSTRAP_CONFIG").is_some()
- {
- "profile = \"user\"".to_owned()
- } else {
- assert!(file.ends_with("config.dist.toml") || file.ends_with("bootstrap.dist.toml"));
- std::fs::read_to_string(file).unwrap()
- };
-
- toml::from_str(&contents).and_then(|table: toml::Value| TomlConfig::deserialize(table))
- }
- Config::parse_inner(Flags::parse(&["check".to_owned()]), get_toml);
+ TestCtx::new()
+ .config("check")
+ .with_default_toml_config(
+ r#"
+ profile = "user"
+ "#,
+ )
+ .create_config();
}
#[test]
@@ -277,12 +200,15 @@ fn rust_optimize() {
#[test]
#[should_panic]
fn invalid_rust_optimize() {
- parse("rust.optimize = \"a\"");
+ TestCtx::new()
+ .config("check")
+ .with_default_toml_config("rust.optimize = \"a\"")
+ .create_config();
}
#[test]
fn verify_file_integrity() {
- let config = parse("");
+ let config = TestCtx::new().config("check").no_dry_run().create_config();
let tempfile = config.tempdir().join(".tmp-test-file");
File::create(&tempfile).unwrap().write_all(b"dummy value").unwrap();
@@ -292,8 +218,6 @@ fn verify_file_integrity() {
config
.verify(&tempfile, "7e255dd9542648a8779268a0f268b891a198e9828e860ed23f826440e786eae5")
);
-
- remove_file(tempfile).unwrap();
}
#[test]
@@ -324,22 +248,23 @@ fn parse_change_id_with_unknown_field() {
#[test]
fn order_of_clippy_rules() {
- let args = vec![
- "clippy".to_string(),
- "--fix".to_string(),
- "--allow-dirty".to_string(),
- "--allow-staged".to_string(),
- "-Aclippy:all".to_string(),
- "-Wclippy::style".to_string(),
- "-Aclippy::foo1".to_string(),
- "-Aclippy::foo2".to_string(),
+ let args = [
+ "clippy",
+ "--fix",
+ "--allow-dirty",
+ "--allow-staged",
+ "-Aclippy:all",
+ "-Wclippy::style",
+ "-Aclippy::foo1",
+ "-Aclippy::foo2",
];
- let config = Config::parse(Flags::parse(&args));
+ let config = TestCtx::new().config(&args[0]).args(&args[1..]).create_config();
let actual = match config.cmd.clone() {
crate::Subcommand::Clippy { allow, deny, warn, forbid, .. } => {
let cfg = LintConfig { allow, deny, warn, forbid };
- get_clippy_rules_in_order(&args, &cfg)
+ let args_vec: Vec = args.iter().map(|s| s.to_string()).collect();
+ get_clippy_rules_in_order(&args_vec, &cfg)
}
_ => panic!("invalid subcommand"),
};
@@ -356,14 +281,14 @@ fn order_of_clippy_rules() {
#[test]
fn clippy_rule_separate_prefix() {
- let args =
- vec!["clippy".to_string(), "-A clippy:all".to_string(), "-W clippy::style".to_string()];
- let config = Config::parse(Flags::parse(&args));
+ let args = ["clippy", "-A clippy:all", "-W clippy::style"];
+ let config = TestCtx::new().config(&args[0]).args(&args[1..]).create_config();
let actual = match config.cmd.clone() {
crate::Subcommand::Clippy { allow, deny, warn, forbid, .. } => {
let cfg = LintConfig { allow, deny, warn, forbid };
- get_clippy_rules_in_order(&args, &cfg)
+ let args_vec: Vec = args.iter().map(|s| s.to_string()).collect();
+ get_clippy_rules_in_order(&args_vec, &cfg)
}
_ => panic!("invalid subcommand"),
};
@@ -374,16 +299,20 @@ fn clippy_rule_separate_prefix() {
#[test]
fn verbose_tests_default_value() {
- let config = Config::parse(Flags::parse(&["build".into(), "compiler".into()]));
+ let config = TestCtx::new().config("build").args(&["compiler".into()]).create_config();
assert_eq!(config.verbose_tests, false);
- let config = Config::parse(Flags::parse(&["build".into(), "compiler".into(), "-v".into()]));
+ let config =
+ TestCtx::new().config("build").args(&["compiler".into(), "-v".into()]).create_config();
assert_eq!(config.verbose_tests, true);
}
#[test]
fn parse_rust_std_features() {
- let config = parse("rust.std-features = [\"panic-unwind\", \"backtrace\"]");
+ let config = TestCtx::new()
+ .config("check")
+ .with_default_toml_config("rust.std-features = [\"panic-unwind\", \"backtrace\"]")
+ .create_config();
let expected_features: BTreeSet =
["panic-unwind", "backtrace"].into_iter().map(|s| s.to_string()).collect();
assert_eq!(config.rust_std_features, expected_features);
@@ -391,7 +320,10 @@ fn parse_rust_std_features() {
#[test]
fn parse_rust_std_features_empty() {
- let config = parse("rust.std-features = []");
+ let config = TestCtx::new()
+ .config("check")
+ .with_default_toml_config("rust.std-features = []")
+ .create_config();
let expected_features: BTreeSet = BTreeSet::new();
assert_eq!(config.rust_std_features, expected_features);
}
@@ -399,70 +331,65 @@ fn parse_rust_std_features_empty() {
#[test]
#[should_panic]
fn parse_rust_std_features_invalid() {
- parse("rust.std-features = \"backtrace\"");
+ TestCtx::new()
+ .config("check")
+ .with_default_toml_config("rust.std-features = \"backtrace\"")
+ .create_config();
}
#[test]
fn parse_jobs() {
- assert_eq!(parse("build.jobs = 1").jobs, Some(1));
+ assert_eq!(
+ TestCtx::new()
+ .config("check")
+ .with_default_toml_config("build.jobs = 1")
+ .create_config()
+ .jobs,
+ Some(1)
+ );
}
#[test]
fn jobs_precedence() {
// `--jobs` should take precedence over using `--set build.jobs`.
- let config = Config::parse_inner(
- Flags::parse(&[
- "check".to_owned(),
- "--config=/does/not/exist".to_owned(),
- "--jobs=67890".to_owned(),
- "--set=build.jobs=12345".to_owned(),
- ]),
- |&_| toml::from_str(""),
- );
+ let config = TestCtx::new()
+ .config("check")
+ .args(&["--jobs=67890", "--set=build.jobs=12345"])
+ .create_config();
assert_eq!(config.jobs, Some(67890));
// `--set build.jobs` should take precedence over `bootstrap.toml`.
- let config = Config::parse_inner(
- Flags::parse(&[
- "check".to_owned(),
- "--config=/does/not/exist".to_owned(),
- "--set=build.jobs=12345".to_owned(),
- ]),
- |&_| {
- toml::from_str(
- r#"
- [build]
- jobs = 67890
- "#,
- )
- },
- );
+ let config = TestCtx::new()
+ .config("check")
+ .args(&["--set=build.jobs=12345"])
+ .with_default_toml_config(
+ r#"
+ [build]
+ jobs = 67890
+ "#,
+ )
+ .create_config();
+
assert_eq!(config.jobs, Some(12345));
// `--jobs` > `--set build.jobs` > `bootstrap.toml`
- let config = Config::parse_inner(
- Flags::parse(&[
- "check".to_owned(),
- "--jobs=123".to_owned(),
- "--config=/does/not/exist".to_owned(),
- "--set=build.jobs=456".to_owned(),
- ]),
- |&_| {
- toml::from_str(
- r#"
- [build]
- jobs = 789
- "#,
- )
- },
- );
+ let config = TestCtx::new()
+ .config("check")
+ .args(&["--jobs=123", "--set=build.jobs=456"])
+ .with_default_toml_config(
+ r#"
+ [build]
+ jobs = 789
+ "#,
+ )
+ .create_config();
assert_eq!(config.jobs, Some(123));
}
#[test]
fn check_rustc_if_unchanged_paths() {
- let config = parse("");
+ let config = TestCtx::new().config("check").create_config();
let normalised_allowed_paths: Vec<_> = RUSTC_IF_UNCHANGED_ALLOWED_PATHS
.iter()
.map(|t| {
@@ -477,59 +404,42 @@ fn check_rustc_if_unchanged_paths() {
#[test]
fn test_explicit_stage() {
- let config = Config::parse_inner(
- Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]),
- |&_| {
- toml::from_str(
- r#"
+ let config = TestCtx::new()
+ .config("check")
+ .with_default_toml_config(
+ r#"
[build]
test-stage = 1
"#,
- )
- },
- );
+ )
+ .create_config();
assert!(!config.explicit_stage_from_cli);
assert!(config.explicit_stage_from_config);
assert!(config.is_explicit_stage());
- let config = Config::parse_inner(
- Flags::parse(&[
- "check".to_owned(),
- "--stage=2".to_owned(),
- "--config=/does/not/exist".to_owned(),
- ]),
- |&_| toml::from_str(""),
- );
+ let config = TestCtx::new().config("check").stage(2).create_config();
assert!(config.explicit_stage_from_cli);
assert!(!config.explicit_stage_from_config);
assert!(config.is_explicit_stage());
- let config = Config::parse_inner(
- Flags::parse(&[
- "check".to_owned(),
- "--stage=2".to_owned(),
- "--config=/does/not/exist".to_owned(),
- ]),
- |&_| {
- toml::from_str(
- r#"
+ let config = TestCtx::new()
+ .config("check")
+ .stage(2)
+ .with_default_toml_config(
+ r#"
[build]
test-stage = 1
"#,
- )
- },
- );
+ )
+ .create_config();
assert!(config.explicit_stage_from_cli);
assert!(config.explicit_stage_from_config);
assert!(config.is_explicit_stage());
- let config = Config::parse_inner(
- Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]),
- |&_| toml::from_str(""),
- );
+ let config = TestCtx::new().config("check").create_config();
assert!(!config.explicit_stage_from_cli);
assert!(!config.explicit_stage_from_config);
@@ -539,7 +449,10 @@ fn test_explicit_stage() {
#[test]
fn test_exclude() {
let exclude_path = "compiler";
- let config = parse(&format!("build.exclude=[\"{}\"]", exclude_path));
+ let config = TestCtx::new()
+ .config("check")
+ .with_default_toml_config(&format!("build.exclude=[\"{}\"]", exclude_path))
+ .create_config();
let first_excluded = config
.skip
@@ -553,32 +466,20 @@ fn test_exclude() {
#[test]
fn test_ci_flag() {
- let config = Config::parse_inner(Flags::parse(&["check".into(), "--ci=false".into()]), |&_| {
- toml::from_str("")
- });
+ let config = TestCtx::new().config("check").arg("--ci").arg("false").create_config();
assert!(!config.is_running_on_ci);
- let config = Config::parse_inner(Flags::parse(&["check".into(), "--ci=true".into()]), |&_| {
- toml::from_str("")
- });
+ let config = TestCtx::new().config("check").arg("--ci").arg("true").create_config();
assert!(config.is_running_on_ci);
- let config = Config::parse_inner(Flags::parse(&["check".into()]), |&_| toml::from_str(""));
+ let config = TestCtx::new().config("check").create_config();
assert_eq!(config.is_running_on_ci, CiEnv::is_ci());
}
#[test]
fn test_precedence_of_includes() {
- let testdir = prepare_test_specific_dir();
-
- let root_config = testdir.join("config.toml");
- let root_config_content = br#"
- include = ["./extension.toml"]
-
- [llvm]
- link-jobs = 2
- "#;
- File::create(&root_config).unwrap().write_all(root_config_content).unwrap();
+ let test_ctx = TestCtx::new();
+ let testdir = test_ctx.dir();
let extension = testdir.join("extension.toml");
let extension_content = br#"
@@ -599,10 +500,17 @@ fn test_precedence_of_includes() {
"#;
File::create(extension).unwrap().write_all(extension_content).unwrap();
- let config = Config::parse_inner(
- Flags::parse(&["check".to_owned(), format!("--config={}", root_config.to_str().unwrap())]),
- get_toml,
- );
+ let config = test_ctx
+ .config("check")
+ .with_default_toml_config(
+ r#"
+ include = ["./extension.toml"]
+
+ [llvm]
+ link-jobs = 2
+ "#,
+ )
+ .create_config();
assert_eq!(config.change_id.unwrap(), ChangeId::Id(543));
assert_eq!(config.llvm_link_jobs.unwrap(), 2);
@@ -612,36 +520,29 @@ fn test_precedence_of_includes() {
#[test]
#[should_panic(expected = "Cyclic inclusion detected")]
fn test_cyclic_include_direct() {
- let testdir = prepare_test_specific_dir();
-
- let root_config = testdir.join("config.toml");
- let root_config_content = br#"
- include = ["./extension.toml"]
- "#;
- File::create(&root_config).unwrap().write_all(root_config_content).unwrap();
-
+ let test_ctx = TestCtx::new();
+ let testdir = test_ctx.dir();
let extension = testdir.join("extension.toml");
let extension_content = br#"
- include = ["./config.toml"]
+ include = ["./bootstrap.toml"]
"#;
File::create(extension).unwrap().write_all(extension_content).unwrap();
- let config = Config::parse_inner(
- Flags::parse(&["check".to_owned(), format!("--config={}", root_config.to_str().unwrap())]),
- get_toml,
- );
+ test_ctx
+ .config("check")
+ .with_default_toml_config(
+ r#"
+ include = ["./extension.toml"]
+ "#,
+ )
+ .create_config();
}
#[test]
#[should_panic(expected = "Cyclic inclusion detected")]
fn test_cyclic_include_indirect() {
- let testdir = prepare_test_specific_dir();
-
- let root_config = testdir.join("config.toml");
- let root_config_content = br#"
- include = ["./extension.toml"]
- "#;
- File::create(&root_config).unwrap().write_all(root_config_content).unwrap();
+ let test_ctx = TestCtx::new();
+ let testdir = test_ctx.dir();
let extension = testdir.join("extension.toml");
let extension_content = br#"
@@ -661,43 +562,37 @@ fn test_cyclic_include_indirect() {
"#;
File::create(extension).unwrap().write_all(extension_content).unwrap();
- let config = Config::parse_inner(
- Flags::parse(&["check".to_owned(), format!("--config={}", root_config.to_str().unwrap())]),
- get_toml,
- );
+ test_ctx
+ .config("check")
+ .with_default_toml_config(
+ r#"
+ include = ["./extension.toml"]
+ "#,
+ )
+ .create_config();
}
#[test]
fn test_include_absolute_paths() {
- let testdir = prepare_test_specific_dir();
+ let test_ctx = TestCtx::new();
+ let testdir = test_ctx.dir();
let extension = testdir.join("extension.toml");
File::create(&extension).unwrap().write_all(&[]).unwrap();
- let root_config = testdir.join("config.toml");
let extension_absolute_path =
extension.canonicalize().unwrap().to_str().unwrap().replace('\\', r"\\");
let root_config_content = format!(r#"include = ["{}"]"#, extension_absolute_path);
- File::create(&root_config).unwrap().write_all(root_config_content.as_bytes()).unwrap();
-
- let config = Config::parse_inner(
- Flags::parse(&["check".to_owned(), format!("--config={}", root_config.to_str().unwrap())]),
- get_toml,
- );
+ test_ctx.config("check").with_default_toml_config(&root_config_content).create_config();
}
#[test]
fn test_include_relative_paths() {
- let testdir = prepare_test_specific_dir();
+ let test_ctx = TestCtx::new();
+ let testdir = test_ctx.dir();
let _ = fs::create_dir_all(&testdir.join("subdir/another_subdir"));
- let root_config = testdir.join("config.toml");
- let root_config_content = br#"
- include = ["./subdir/extension.toml"]
- "#;
- File::create(&root_config).unwrap().write_all(root_config_content).unwrap();
-
let extension = testdir.join("subdir/extension.toml");
let extension_content = br#"
include = ["../extension2.toml"]
@@ -719,22 +614,20 @@ fn test_include_relative_paths() {
let extension = testdir.join("extension4.toml");
File::create(extension).unwrap().write_all(&[]).unwrap();
- let config = Config::parse_inner(
- Flags::parse(&["check".to_owned(), format!("--config={}", root_config.to_str().unwrap())]),
- get_toml,
- );
+ test_ctx
+ .config("check")
+ .with_default_toml_config(
+ r#"
+ include = ["./subdir/extension.toml"]
+ "#,
+ )
+ .create_config();
}
#[test]
fn test_include_precedence_over_profile() {
- let testdir = prepare_test_specific_dir();
-
- let root_config = testdir.join("config.toml");
- let root_config_content = br#"
- profile = "dist"
- include = ["./extension.toml"]
- "#;
- File::create(&root_config).unwrap().write_all(root_config_content).unwrap();
+ let test_ctx = TestCtx::new();
+ let testdir = test_ctx.dir();
let extension = testdir.join("extension.toml");
let extension_content = br#"
@@ -743,10 +636,15 @@ fn test_include_precedence_over_profile() {
"#;
File::create(extension).unwrap().write_all(extension_content).unwrap();
- let config = Config::parse_inner(
- Flags::parse(&["check".to_owned(), format!("--config={}", root_config.to_str().unwrap())]),
- get_toml,
- );
+ let config = test_ctx
+ .config("check")
+ .with_default_toml_config(
+ r#"
+ profile = "dist"
+ include = ["./extension.toml"]
+ "#,
+ )
+ .create_config();
// "dist" profile would normally set the channel to "auto-detect", but includes should
// override profile settings, so we expect this to be "dev" here.
diff --git a/src/bootstrap/src/core/config/toml/mod.rs b/src/bootstrap/src/core/config/toml/mod.rs
index 7af22432ef8ca..f6dc5b67e1010 100644
--- a/src/bootstrap/src/core/config/toml/mod.rs
+++ b/src/bootstrap/src/core/config/toml/mod.rs
@@ -152,10 +152,6 @@ impl Config {
}
pub(crate) fn get_toml(file: &Path) -> Result {
- #[cfg(test)]
- return Ok(TomlConfig::default());
-
- #[cfg(not(test))]
Self::get_toml_inner(file)
}
diff --git a/src/bootstrap/src/utils/helpers/tests.rs b/src/bootstrap/src/utils/helpers/tests.rs
index 9030ca2820a8b..676fe6cbd5fe5 100644
--- a/src/bootstrap/src/utils/helpers/tests.rs
+++ b/src/bootstrap/src/utils/helpers/tests.rs
@@ -6,6 +6,7 @@ use crate::utils::helpers::{
check_cfg_arg, extract_beta_rev, hex_encode, make, set_file_times, submodule_path_of,
symlink_dir,
};
+use crate::utils::tests::TestCtx;
use crate::{Config, Flags};
#[test]
@@ -59,8 +60,7 @@ fn test_check_cfg_arg() {
#[test]
fn test_symlink_dir() {
- let config =
- Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]));
+ let config = TestCtx::new().config("check").no_dry_run().create_config();
let tempdir = config.tempdir().join(".tmp-dir");
let link_path = config.tempdir().join(".tmp-link");
@@ -80,8 +80,7 @@ fn test_symlink_dir() {
#[test]
fn test_set_file_times_sanity_check() {
- let config =
- Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]));
+ let config = TestCtx::new().config("check").create_config();
let tempfile = config.tempdir().join(".tmp-file");
{
@@ -102,9 +101,7 @@ fn test_set_file_times_sanity_check() {
#[test]
fn test_submodule_path_of() {
- let config = Config::parse_inner(Flags::parse(&["build".into(), "--dry-run".into()]), |&_| {
- Ok(Default::default())
- });
+ let config = TestCtx::new().config("build").create_config();
let build = crate::Build::new(config.clone());
let builder = crate::core::builder::Builder::new(&build);
diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs
index 3332187e2a853..764b89086cf2f 100644
--- a/src/bootstrap/src/utils/tests/mod.rs
+++ b/src/bootstrap/src/utils/tests/mod.rs
@@ -48,11 +48,20 @@ impl TestCtx {
pub struct ConfigBuilder {
args: Vec,
directory: PathBuf,
+ override_download_ci_llvm: bool,
+ dry_run: bool,
+ explicit_config: bool,
}
impl ConfigBuilder {
fn from_args(args: &[&str], directory: PathBuf) -> Self {
- Self { args: args.iter().copied().map(String::from).collect(), directory }
+ Self {
+ args: args.iter().copied().map(String::from).collect(),
+ directory,
+ override_download_ci_llvm: true,
+ dry_run: true,
+ explicit_config: true,
+ }
}
pub fn path(mut self, path: &str) -> Self {
@@ -98,18 +107,46 @@ impl ConfigBuilder {
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());
+ pub fn with_default_toml_config(mut self, config_toml: &str) -> Self {
+ let toml_path = self.directory.join("bootstrap.toml");
+ std::fs::write(&toml_path, config_toml).unwrap();
+ self.explicit_config = false;
+ self.args.push("--config".to_string());
+ self.args.push(toml_path.display().to_string());
+ self
+ }
+
+ pub fn no_override_download_ci_llvm(mut self) -> Self {
+ self.override_download_ci_llvm = false;
+ self
+ }
+
+ pub fn no_dry_run(mut self) -> Self {
+ self.dry_run = false;
+ self
+ }
+ pub fn create_config(mut self) -> Config {
+ if self.dry_run {
+ // Run in dry-check, otherwise the test would be too slow
+ self.args.push("--dry-run".to_string());
+ }
// Ignore submodules
self.args.push("--set".to_string());
self.args.push("build.submodules=false".to_string());
- // Override any external LLVM set and inhibit CI LLVM; pretend that we're always building
- // in-tree LLVM from sources.
- self.args.push("--set".to_string());
- self.args.push("llvm.download-ci-llvm=false".to_string());
+ if self.override_download_ci_llvm {
+ // Override any external LLVM set and inhibit CI LLVM; pretend that we're always building
+ // in-tree LLVM from sources.
+ self.args.push("--set".to_string());
+ self.args.push("llvm.download-ci-llvm=false".to_string());
+ }
+
+ // always use the bootstrap toml created in the
+ // temporary directory and not from the
+ if self.explicit_config {
+ self = self.with_default_toml_config("");
+ }
// Do not mess with the local rustc checkout build directory
self.args.push("--build-dir".to_string());