diff options
Diffstat (limited to 'src/tools/cargo/crates/cargo-test-support')
7 files changed, 138 insertions, 35 deletions
diff --git a/src/tools/cargo/crates/cargo-test-support/Cargo.toml b/src/tools/cargo/crates/cargo-test-support/Cargo.toml index fc32e1c9c..1098d598d 100644 --- a/src/tools/cargo/crates/cargo-test-support/Cargo.toml +++ b/src/tools/cargo/crates/cargo-test-support/Cargo.toml @@ -29,6 +29,10 @@ tar.workspace = true time.workspace = true toml.workspace = true url.workspace = true +walkdir.workspace = true [target.'cfg(windows)'.dependencies] windows-sys = { workspace = true, features = ["Win32_Storage_FileSystem"] } + +[lints] +workspace = true diff --git a/src/tools/cargo/crates/cargo-test-support/build.rs b/src/tools/cargo/crates/cargo-test-support/build.rs index 478da7d99..8854f461a 100644 --- a/src/tools/cargo/crates/cargo-test-support/build.rs +++ b/src/tools/cargo/crates/cargo-test-support/build.rs @@ -1,3 +1,5 @@ +#![allow(clippy::disallowed_methods)] + fn main() { println!( "cargo:rustc-env=NATIVE_ARCH={}", diff --git a/src/tools/cargo/crates/cargo-test-support/src/compare.rs b/src/tools/cargo/crates/cargo-test-support/src/compare.rs index d9e8d5454..fc1663d34 100644 --- a/src/tools/cargo/crates/cargo-test-support/src/compare.rs +++ b/src/tools/cargo/crates/cargo-test-support/src/compare.rs @@ -591,15 +591,36 @@ fn find_json_mismatch_r<'a>( .next() } (&Object(ref l), &Object(ref r)) => { - let same_keys = l.len() == r.len() && l.keys().all(|k| r.contains_key(k)); - if !same_keys { - return Some((expected, actual)); + let mut expected_entries = l.iter(); + let mut actual_entries = r.iter(); + + // Compilers older than 1.76 do not produce $message_type. + // Treat it as optional for now. + let mut expected_entries_without_message_type; + let expected_entries: &mut dyn Iterator<Item = _> = + if l.contains_key("$message_type") && !r.contains_key("$message_type") { + expected_entries_without_message_type = + expected_entries.filter(|entry| entry.0 != "$message_type"); + &mut expected_entries_without_message_type + } else { + &mut expected_entries + }; + + loop { + match (expected_entries.next(), actual_entries.next()) { + (None, None) => return None, + (Some((expected_key, expected_value)), Some((actual_key, actual_value))) + if expected_key == actual_key => + { + if let mismatch @ Some(_) = + find_json_mismatch_r(expected_value, actual_value, cwd) + { + return mismatch; + } + } + _ => return Some((expected, actual)), + } } - - l.values() - .zip(r.values()) - .filter_map(|(l, r)| find_json_mismatch_r(l, r, cwd)) - .next() } (&Null, &Null) => None, // Magic string literal `"{...}"` acts as wildcard for any sub-JSON. diff --git a/src/tools/cargo/crates/cargo-test-support/src/lib.rs b/src/tools/cargo/crates/cargo-test-support/src/lib.rs index ec74ce0b2..4e3ef6118 100644 --- a/src/tools/cargo/crates/cargo-test-support/src/lib.rs +++ b/src/tools/cargo/crates/cargo-test-support/src/lib.rs @@ -2,7 +2,9 @@ //! //! See <https://rust-lang.github.io/cargo/contrib/> for a guide on writing tests. -#![allow(clippy::all)] +#![allow(clippy::disallowed_methods)] +#![allow(clippy::print_stderr)] +#![allow(clippy::print_stdout)] use std::env; use std::ffi::OsStr; @@ -521,29 +523,6 @@ pub fn cargo_exe() -> PathBuf { snapbox::cmd::cargo_bin("cargo") } -/// A wrapper around `rustc` instead of calling `clippy`. -pub fn wrapped_clippy_driver() -> PathBuf { - let clippy_driver = project() - .at(paths::global_root().join("clippy-driver")) - .file("Cargo.toml", &basic_manifest("clippy-driver", "0.0.1")) - .file( - "src/main.rs", - r#" - fn main() { - let mut args = std::env::args_os(); - let _me = args.next().unwrap(); - let rustc = args.next().unwrap(); - let status = std::process::Command::new(rustc).args(args).status().unwrap(); - std::process::exit(status.code().unwrap_or(1)); - } - "#, - ) - .build(); - clippy_driver.cargo("build").run(); - - clippy_driver.bin("clippy-driver") -} - /// This is the raw output from the process. /// /// This is similar to `std::process::Output`, however the `status` is diff --git a/src/tools/cargo/crates/cargo-test-support/src/paths.rs b/src/tools/cargo/crates/cargo-test-support/src/paths.rs index 50040e1d4..a07491bcc 100644 --- a/src/tools/cargo/crates/cargo-test-support/src/paths.rs +++ b/src/tools/cargo/crates/cargo-test-support/src/paths.rs @@ -114,6 +114,10 @@ pub trait CargoPathExt { fn rm_rf(&self); fn mkdir_p(&self); + /// Returns a list of all files and directories underneath the given + /// directory, recursively, including the starting path. + fn ls_r(&self) -> Vec<PathBuf>; + fn move_into_the_past(&self) { self.move_in_time(|sec, nsec| (sec - 3600, nsec)) } @@ -155,6 +159,14 @@ impl CargoPathExt for Path { .unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e)) } + fn ls_r(&self) -> Vec<PathBuf> { + walkdir::WalkDir::new(self) + .sort_by_file_name() + .into_iter() + .filter_map(|e| e.map(|e| e.path().to_owned()).ok()) + .collect() + } + fn move_in_time<F>(&self, travel_amount: F) where F: Fn(i64, u32) -> (i64, u32), diff --git a/src/tools/cargo/crates/cargo-test-support/src/registry.rs b/src/tools/cargo/crates/cargo-test-support/src/registry.rs index 853829c56..6f9d558a9 100644 --- a/src/tools/cargo/crates/cargo-test-support/src/registry.rs +++ b/src/tools/cargo/crates/cargo-test-support/src/registry.rs @@ -557,6 +557,7 @@ pub struct Dependency { registry: Option<String>, package: Option<String>, optional: bool, + default_features: bool, } /// Entry with data that corresponds to [`tar::EntryType`]. @@ -1161,12 +1162,15 @@ fn save_new_crate( "name": name, "req": dep.version_req, "features": dep.features, - "default_features": true, + "default_features": dep.default_features, "target": dep.target, "optional": dep.optional, "kind": dep.kind, "registry": dep.registry, "package": package, + "artifact": dep.artifact, + "bindep_target": dep.bindep_target, + "lib": dep.lib, }) }) .collect::<Vec<_>>(); @@ -1179,7 +1183,7 @@ fn save_new_crate( new_crate.features, false, new_crate.links, - None, + new_crate.rust_version.as_deref(), None, ); @@ -1415,7 +1419,7 @@ impl Package { "name": dep.name, "req": dep.vers, "features": dep.features, - "default_features": true, + "default_features": dep.default_features, "target": dep.target, "artifact": artifact, "bindep_target": dep.bindep_target, @@ -1523,6 +1527,30 @@ impl Package { manifest.push_str(&format!("rust-version = \"{}\"", version)); } + if !self.features.is_empty() { + let features: Vec<String> = self + .features + .iter() + .map(|(feature, features)| { + if features.is_empty() { + format!("{} = []", feature) + } else { + format!( + "{} = [{}]", + feature, + features + .iter() + .map(|s| format!("\"{}\"", s)) + .collect::<Vec<_>>() + .join(", ") + ) + } + }) + .collect(); + + manifest.push_str(&format!("\n[features]\n{}", features.join("\n"))); + } + for dep in self.deps.iter() { let target = match dep.target { None => String::new(), @@ -1540,6 +1568,9 @@ impl Package { "#, target, kind, dep.name, dep.vers )); + if dep.optional { + manifest.push_str("optional = true\n"); + } if let Some(artifact) = &dep.artifact { manifest.push_str(&format!("artifact = \"{}\"\n", artifact)); } @@ -1553,6 +1584,21 @@ impl Package { assert_eq!(registry, "alternative"); manifest.push_str(&format!("registry-index = \"{}\"", alt_registry_url())); } + if !dep.default_features { + manifest.push_str("default-features = false\n"); + } + if !dep.features.is_empty() { + let mut features = String::new(); + serde::Serialize::serialize( + &dep.features, + toml::ser::ValueSerializer::new(&mut features), + ) + .unwrap(); + manifest.push_str(&format!("features = {}\n", features)); + } + if let Some(package) = &dep.package { + manifest.push_str(&format!("package = \"{}\"\n", package)); + } } if self.proc_macro { manifest.push_str("[lib]\nproc-macro = true\n"); @@ -1631,6 +1677,7 @@ impl Dependency { package: None, optional: false, registry: None, + default_features: true, } } @@ -1683,4 +1730,10 @@ impl Dependency { self.optional = optional; self } + + /// Adds `default-features = false` if the argument is `false`. + pub fn default_features(&mut self, default_features: bool) -> &mut Self { + self.default_features = default_features; + self + } } diff --git a/src/tools/cargo/crates/cargo-test-support/src/tools.rs b/src/tools/cargo/crates/cargo-test-support/src/tools.rs index 2ce2849ae..b6fa4092f 100644 --- a/src/tools/cargo/crates/cargo-test-support/src/tools.rs +++ b/src/tools/cargo/crates/cargo-test-support/src/tools.rs @@ -7,6 +7,7 @@ use std::sync::OnceLock; static ECHO_WRAPPER: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new(); static ECHO: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new(); +static CLIPPY_DRIVER: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new(); /// Returns the path to an executable that works as a wrapper around rustc. /// @@ -107,3 +108,34 @@ pub fn echo_subcommand() -> Project { p.cargo("build").run(); p } + +/// A wrapper around `rustc` instead of calling `clippy`. +pub fn wrapped_clippy_driver() -> PathBuf { + let mut lock = CLIPPY_DRIVER + .get_or_init(|| Default::default()) + .lock() + .unwrap(); + if let Some(path) = &*lock { + return path.clone(); + } + let clippy_driver = project() + .at(paths::global_root().join("clippy-driver")) + .file("Cargo.toml", &basic_manifest("clippy-driver", "0.0.1")) + .file( + "src/main.rs", + r#" + fn main() { + let mut args = std::env::args_os(); + let _me = args.next().unwrap(); + let rustc = args.next().unwrap(); + let status = std::process::Command::new(rustc).args(args).status().unwrap(); + std::process::exit(status.code().unwrap_or(1)); + } + "#, + ) + .build(); + clippy_driver.cargo("build").run(); + let path = clippy_driver.bin("clippy-driver"); + *lock = Some(path.clone()); + path +} |