use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
fn packaged() -> Vec<String> {
let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned());
let mut cmd = crate::spawn::command(&cargo);
cmd.current_dir(root())
.args(["package", "--list", "--offline", "--allow-dirty"]);
let out = crate::spawn::output(&mut cmd).expect("cargo runs");
assert!(
out.status.success(),
"cargo package --list did not answer: {}",
String::from_utf8_lossy(&out.stderr)
);
String::from_utf8_lossy(&out.stdout)
.lines()
.map(str::to_owned)
.collect()
}
fn root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}
fn is_ruled_in(path: &str) -> bool {
let named = matches!(
path,
"Cargo.toml"
| "Cargo.lock"
| "Cargo.toml.orig"
| ".cargo_vcs_info.json"
| "README.md"
| "LICENSE"
);
named
|| path
.strip_prefix("src/")
.is_some_and(|rest| Path::new(rest).extension().is_some_and(|ext| ext == "rs"))
}
#[test]
fn no_commentary_or_apparatus_ships() {
let strays: Vec<String> = packaged().into_iter().filter(|p| !is_ruled_in(p)).collect();
assert!(
strays.is_empty(),
"paths `cargo publish` would upload that no class rules in. A yanked \
version stays downloadable, so widen `include` in Cargo.toml only with \
a reason, and add the class beside it here:\n{}",
strays.join("\n")
);
}
#[test]
fn the_files_a_registry_needs_ship() {
let list = packaged();
for needed in [
"Cargo.toml",
"Cargo.lock",
"README.md",
"LICENSE",
"src/lib.rs",
"src/main.rs",
] {
assert!(
list.iter().any(|p| p == needed),
"{needed} is not in the packaged list — `include` dropped a file the \
registry or the build needs"
);
}
}
#[test]
fn the_list_is_not_vacuous() {
let list = packaged();
let sources = list.iter().filter(|p| p.starts_with("src/")).count();
assert!(
sources > 30,
"the packaged list carries {sources} src paths over {} entries — the \
spawn is broken, not the tree",
list.len()
);
}
#[test]
fn nothing_the_build_reads_is_left_out_of_the_package() {
let embedding = sources_that_embed(&root().join("src"));
assert!(
embedding.is_empty(),
"these files read a build input at compile time. Every such input must \
be ruled into `include` in Cargo.toml and into is_ruled_in above, or \
the published crate cannot compile:\n{}",
embedding
.iter()
.map(|p| p.display().to_string())
.collect::<Vec<_>>()
.join("\n")
);
}
fn embed_spellings() -> [String; 2] {
["bytes", "str"].map(|kind| format!("include_{kind}!"))
}
fn sources_that_embed(dir: &Path) -> BTreeSet<PathBuf> {
let mut found = BTreeSet::new();
let Ok(entries) = std::fs::read_dir(dir) else {
return found;
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
found.extend(sources_that_embed(&path));
} else if std::fs::read_to_string(&path).is_ok_and(|text| {
embed_spellings()
.iter()
.any(|spelling| text.contains(spelling))
}) {
found.insert(path);
}
}
found
}
#[test]
fn the_allowlist_sees_its_own_violations() {
for stray in [
"docs/DESIGN.md",
"AGENTS.md",
"CLAUDE.md",
"Makefile",
"Containerfile",
"deny.toml",
"clippy.toml",
"tarpaulin.toml",
"rules/no-bare-command.yml",
"rules/fixtures/violations.rs",
".githooks/pre-commit",
".github/workflows/release-plz.yml",
"scripts/leak-scan.sh",
"scripts/leak-fixtures/README.md",
"scripts/leak-fixtures/private-key.txt",
] {
assert!(!is_ruled_in(stray), "{stray} must not be ruled in");
}
for shipped in ["src/main.rs", "src/channel/tls.rs", "LICENSE"] {
assert!(is_ruled_in(shipped), "{shipped} must be ruled in");
}
}
#[test]
fn the_embed_sweep_sees_an_embed() {
let scratch = crate::test_support::Scratch::new();
let nested = scratch.path().join("nested");
std::fs::create_dir(&nested).expect("a directory");
let planted = nested.join("embeds.rs");
let [bytes, _] = embed_spellings();
std::fs::write(
&planted,
format!("const X: &[u8] = {bytes}(\"../x.bin\");\n"),
)
.expect("the plant is written");
std::fs::write(nested.join("plain.rs"), "const X: u8 = 1;\n").expect("a plain file");
assert_eq!(
sources_that_embed(scratch.path()),
BTreeSet::from([planted])
);
assert!(sources_that_embed(&scratch.path().join("absent")).is_empty());
}
#[test]
fn the_readme_names_the_install_route_for_the_published_crate() {
let readme = std::fs::read_to_string(root().join("README.md")).expect("the README");
assert!(
readme.contains("cargo install thrall --locked"),
"the README no longer names the crate route. It is the file crates.io \
renders, so it is the one page a stranger who found this crate reads, \
and `cargo install` is what they came for"
);
}