xtask/tests/clippy_gate.rs
//! **The lint gate reaches every crate, and nothing turns it off wholesale.**
//!
//! `cargo xtask clippy` (see `xtask::clippy`) is the gate. These tests hold its
//! shape: it finds the detached crates `--workspace` does not reach, every run
//! is `--all-targets -D warnings`, and no file carries a crate-wide (inner)
//! allow of a clippy lint, which would make it green by saying nothing.
//! Running clippy itself is the ignored test at the bottom (minutes, and it
//! needs the sibling checkouts).
use std::path::{Path, PathBuf};
fn repo() -> PathBuf {
xtask::workspace_root()
}
#[test]
fn the_gate_finds_every_detached_crate() {
let found: Vec<String> = xtask::clippy::detached_crates(&repo())
.iter()
.map(|m| {
m.parent()
.unwrap()
.file_name()
.unwrap()
.to_string_lossy()
.into_owned()
})
.collect();
// A28 M1 (T14): monetize-front is a root member now, linted by `--workspace`.
for c in ["monetize-admin", "monetize-build-thing", "monetize-fast"] {
assert!(
found.iter().any(|f| f == c),
"{c} is its own workspace and must be linted by --manifest-path; found {found:?}"
);
}
}
#[test]
fn every_run_denies_warnings_over_all_targets() {
let runs = xtask::clippy::runs(&repo());
assert_eq!(
runs.len(),
1 + xtask::clippy::detached_crates(&repo()).len()
);
assert_eq!(runs[0][..2], ["clippy", "--workspace"]);
for r in &runs {
assert_eq!(
r[r.len() - 4..],
["--all-targets", "--", "-D", "warnings"],
"{r:?}"
);
}
}
fn rust_files(dir: &Path, out: &mut Vec<PathBuf>) {
for e in std::fs::read_dir(dir).into_iter().flatten().flatten() {
let p = e.path();
let name = e.file_name();
if p.is_dir() {
if name != "target" && name != ".git" && name != "node_modules" {
rust_files(&p, out);
}
} else if p.extension().is_some_and(|x| x == "rs") {
out.push(p);
}
}
}
#[test]
fn no_file_turns_a_clippy_lint_off_crate_wide() {
let root = repo();
let mut files = Vec::new();
for d in ["crates", "products", "guests", "uitest", "xtask"] {
rust_files(&root.join(d), &mut files);
}
assert!(
files.len() > 50,
"walked {} files: the walk is not reaching the tree",
files.len()
);
let needle = ["#!", "[allow(clippy::"].concat();
let blanket: Vec<String> = files
.iter()
.filter(|f| std::fs::read_to_string(f).is_ok_and(|t| t.contains(&needle)))
.map(|f| f.strip_prefix(&root).unwrap_or(f).display().to_string())
.collect();
assert!(blanket.is_empty(), "a crate-wide clippy allow switches the gate off for the whole crate; fix the lint, or allow it on the one item: {blanket:?}");
}
#[test]
#[ignore = "heavy: runs clippy over the workspace and the detached crates (minutes; needs ../edda, ../Skidbladnir, ../holger); `cargo xtask clippy` is the same gate"]
fn the_tree_is_clippy_clean() {
// A target dir of its own: this test runs inside `cargo test`, which holds
// the lock on the default one.
let root = repo();
let target = xtask::guests::target_dir(&root).join("clippy-gate");
std::env::set_var("CARGO_TARGET_DIR", &target);
xtask::clippy::run(&root).unwrap();
}