diff options
| -rw-r--r-- | src/bootstrap/src/core/builder/tests.rs | 49 | ||||
| -rw-r--r-- | src/bootstrap/src/core/config/config.rs | 66 | ||||
| -rw-r--r-- | src/bootstrap/src/core/config/tests.rs | 548 | ||||
| -rw-r--r-- | src/bootstrap/src/core/config/toml/mod.rs | 4 | ||||
| -rw-r--r-- | src/bootstrap/src/utils/helpers/tests.rs | 11 | ||||
| -rw-r--r-- | src/bootstrap/src/utils/tests/mod.rs | 53 |
6 files changed, 337 insertions, 394 deletions
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 229adf71459..4555f0d2091 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<A, B>(v: Vec<(A, B)>) -> Vec<A> { @@ -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::<test::CrateLibrustc>(); @@ -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 fb7c334491b..6d9e3b54156 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 <src>/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 e93525fbd09..4f2df76a156 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<TomlConfig, toml::de::Error> { @@ -32,28 +30,16 @@ fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> { 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<String> = 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<TomlConfig, toml::de::Error> { - 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<String> = 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<String> = 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<String> = ["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<String> = 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 7af22432ef8..f6dc5b67e10 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<TomlConfig, toml::de::Error> { - #[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 9030ca2820a..676fe6cbd5f 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 3332187e2a8..764b89086cf 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<String>, 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 <src> + 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()); |
