#![cfg(not(miri))]
use std::collections::BTreeSet;
use std::fs;
use camino::Utf8PathBuf;
use cargo_gamma_lib::internals::config::Config;
use cargo_gamma_lib::internals::docs;
const FILES: &[&str] = &["README.md", "docs/CMDLINE.md", "docs/MUTATORS.md"];
fn root_dir() -> Utf8PathBuf {
Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../cargo-gamma")
}
fn workspace_dir() -> Utf8PathBuf {
Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..")
}
fn regenerate(text: &str, path: &str) -> String {
let mut out = String::new();
let mut rest = text;
while let Some((before, after_marker)) = rest.split_once(docs::BEGIN) {
out.push_str(before);
assert!(
after_marker.contains(" -->"),
"{path}: a `{}` marker is never terminated",
docs::BEGIN
);
let (name, after_name) = after_marker.split_once(" -->").expect("the marker terminator is present");
assert!(docs::block(name).is_some(), "{path}: there is no generated block named `{name}`");
let body = docs::block(name).expect("the block name is known");
assert!(
after_name.contains(docs::END),
"{path}: block `{name}` is never closed with `{}`",
docs::END
);
let (_, after_end) = after_name.split_once(docs::END).expect("the closing marker is present");
out.push_str(docs::BEGIN);
out.push_str(name);
out.push_str(" -->\n\n");
out.push_str(&body);
out.push_str("\n\n");
out.push_str(docs::END);
rest = after_end;
}
out.push_str(rest);
out
}
#[test]
fn the_generated_reference_tables_match_the_registry() {
let dir = root_dir();
let blessing = std::env::var_os("GAMMA_BLESS_DOCS").is_some();
let mut stale = Vec::new();
for name in FILES {
let path = dir.join(name);
let text = fs::read_to_string(path.as_std_path()).unwrap_or_else(|_| panic!("could not read {path}"));
let expected = regenerate(&text, name);
if text == expected {
continue;
}
if blessing {
fs::write(path.as_std_path(), &expected).unwrap_or_else(|_| panic!("could not write {path}"));
} else {
stale.push((*name).to_owned());
}
}
assert!(
stale.is_empty(),
"{} is out of date with the mutator registry. Run `GAMMA_BLESS_DOCS=1 cargo test --all-features --test docs` to regenerate.",
stale.join(", ")
);
}
#[test]
fn every_documentation_file_the_readme_points_at_exists() {
let root = root_dir();
let readme = fs::read_to_string(root.join("README.md").as_std_path()).expect("could not read README.md");
let mut checked = 0;
for link in linked_documents(&readme) {
assert!(
root.join(&link).as_std_path().exists(),
"{link} is linked from README.md but missing"
);
checked += 1;
}
assert!(checked > 0, "no documentation links were found, so this test proves nothing");
}
#[test]
fn the_optimized_campaign_profile_is_valid_and_preserves_development_checks() {
let readme = fs::read_to_string(root_dir().join("README.md").as_std_path()).expect("could not read README.md");
let section = readme
.split_once("### Optimizing compute-heavy suites")
.expect("README.md has no optimized-profile guidance")
.1
.split_once("\n### ")
.map_or_else(|| readme.as_str(), |(section, _rest)| section);
let example = section
.split_once("```toml\n")
.expect("the optimized-profile guidance has no TOML example")
.1
.split_once("\n```")
.expect("the optimized-profile TOML fence is never closed")
.0;
let manifest: toml::Value = toml::from_str(example).expect("the optimized-profile example is not valid TOML");
let profile = &manifest["profile"]["gamma"];
assert_eq!(profile["inherits"].as_str(), Some("dev"));
assert_eq!(profile["opt-level"].as_integer(), Some(2));
assert_eq!(profile["debug-assertions"].as_bool(), Some(true));
assert_eq!(profile["overflow-checks"].as_bool(), Some(true));
let prose = section.split_whitespace().collect::<Vec<_>>().join(" ");
assert!(prose.contains("cargo gamma run --profile gamma"));
assert!(prose.contains("not directly comparable"));
assert!(prose.contains("invalidates unviability reuse"));
}
fn linked_documents(readme: &str) -> Vec<String> {
let mut found: Vec<String> = Vec::new();
for tail in readme.split("docs/").skip(1) {
let name: String = tail
.chars()
.take_while(|c| c.is_ascii_alphanumeric() || "_-.".contains(*c))
.collect();
let Some((stem, _)) = name.split_once(".md") else {
continue;
};
let link = format!("docs/{stem}.md");
if !found.contains(&link) {
found.push(link);
}
}
found
}
fn kebab(name: &str) -> String {
name.replace('_', "-")
}
fn fields(source: &str, name: &str) -> Vec<String> {
let public = format!("pub struct {name} {{");
let private = format!("struct {name} {{");
let header = if source.contains(&public) { public } else { private };
assert!(source.contains(&header), "config.rs declares no struct named {name}");
let (_, body) = source.split_once(header.as_str()).expect("the struct header is present");
body.lines()
.take_while(|line| !line.starts_with('}'))
.filter_map(|line| line.strip_prefix(" "))
.map(|line| line.strip_prefix("pub ").unwrap_or(line))
.filter_map(|rest| rest.split_once(':').map(|(field, _type)| field))
.filter(|field| field.chars().all(|character| character.is_ascii_alphanumeric() || character == '_'))
.map(kebab)
.collect()
}
#[test]
fn every_configuration_key_is_documented() {
let source = include_str!("../src/config.rs");
let keys: Vec<String> = ["Config", "Shard"].iter().flat_map(|name| fields(source, name)).collect();
for doc in ["docs/CONFIG.md", "docs/gamma.toml"] {
let path = root_dir().join(doc);
let text = fs::read_to_string(path.as_std_path()).unwrap_or_else(|_| panic!("could not read {doc}"));
for key in &keys {
assert!(
text.contains(&format!("`{key}`"))
|| text.contains(&format!("[{key}]"))
|| text.contains(&format!("\n{key} ="))
|| text.contains(&format!("# {key} =")),
"{doc} never mentions the `{key}` key"
);
}
}
}
#[test]
fn the_example_configuration_is_inert_and_parses() {
let path = root_dir().join("docs/gamma.toml");
let text = fs::read_to_string(path.as_std_path()).expect("could not read docs/gamma.toml");
let config = Config::parse(&text).expect("docs/gamma.toml is not a valid configuration file");
assert_eq!(
format!("{config:?}"),
format!("{:?}", Config::default()),
"docs/gamma.toml sets a key rather than only documenting it, so copying it would change behavior"
);
}
#[test]
fn the_workspace_configuration_loads_with_its_settings_intact() {
let config = Config::load(&workspace_dir()).expect("the workspace gamma.toml is not a valid configuration file");
assert!(
config.exclude_files.iter().any(|pattern| pattern == "crates/automation/**"),
"the workspace configuration no longer excludes the automation crate: {:?}",
config.exclude_files
);
assert_eq!(
config.exclude_trait_impls,
["Debug"],
"the diagnostic-output trait exclusion changed"
);
}
#[test]
fn one_row_of_every_generated_block_is_pinned_to_a_hand_written_expectation() {
let mutators = docs::block("mutators").expect("the mutator block exists");
let presets = docs::block("presets").expect("the preset block exists");
let families = docs::block("families").expect("the family block exists");
assert!(
mutators.contains("| `relational.lt_to_le` | replace < with <= | `ROR` | yes |"),
"the mutator row is not rendered as expected:\n{mutators}"
);
assert!(
presets.contains("| `@boundary` | relational and boundary conditions | `relational`, `range` |"),
"the preset row is not rendered as expected:\n{presets}"
);
assert!(
families.contains("| [`logical`](#logical) | 2 | Is this `&&` really an `&&`? |"),
"the family row is not rendered as expected:\n{families}"
);
assert!(mutators.contains("#### `relational`\n"), "{mutators}");
}
#[test]
fn every_option_names_its_own_help_heading() {
const STRUCTS: &[&str] = &[
"MergeArgs",
"SuppressArgs",
"UnsuppressArgs",
"SelectArgs",
"FeatureArgs",
"ConfigArgs",
"BuildLimitArgs",
"MeasureArgs",
"RunArgs",
"CompletionsArgs",
"ListArgs",
"ExplainArgs",
];
let source = include_str!("../src/commands/cli.rs");
let mut checked = 0;
for name in STRUCTS {
let header = format!("pub struct {name} {{");
let (_, body) = source
.split_once(header.as_str())
.unwrap_or_else(|| panic!("cli.rs declares no struct named {name}"));
let body: String = body
.lines()
.take_while(|line| !line.starts_with('}'))
.collect::<Vec<_>>()
.join("\n");
if struct_has_group(source, name) {
continue;
}
for field in body.split(" pub ").skip(1) {
let field_name = field.split(':').next().unwrap_or_default();
let declaration = field.lines().next().unwrap_or_default();
if declaration.contains("Args") || field_name == "command" {
continue;
}
let attributes = body.split(&format!("pub {field_name}:")).next().unwrap_or_default();
let last = attributes.rfind("#[arg(").unwrap_or(0);
let attributes = attributes.get(last..).unwrap_or_default();
if !attributes.contains("long") {
continue;
}
assert!(
attributes.contains("help_heading"),
"{name}::{field_name} inherits its help heading instead of naming one"
);
checked += 1;
}
}
assert!(checked > 20, "too few options were checked to prove anything: {checked}");
}
fn struct_has_group(source: &str, name: &str) -> bool {
let header = format!("pub struct {name} {{");
let before = source.split(header.as_str()).next().unwrap_or_default();
let start = before.rfind("#[derive(").unwrap_or(0);
before.get(start..).unwrap_or_default().contains("next_help_heading")
}
#[test]
fn every_crate_that_can_forbid_unsafe_code_does() {
const ALLOWED: &[&str] = &[
"cargo-gamma-unsafe",
"cargo-gamma-rt",
];
let crates = workspace_dir().join("crates");
let mut unguarded = Vec::new();
for entry in fs::read_dir(crates.as_std_path())
.expect("the workspace has a crates directory")
.flatten()
{
let path = Utf8PathBuf::from_path_buf(entry.path()).expect("the repository has no non-UTF-8 paths");
let name = path.file_name().unwrap_or_default().to_owned();
if !path.is_dir() || !name.starts_with("cargo-gamma") || ALLOWED.contains(&name.as_str()) {
continue;
}
let guarded = ["src/lib.rs", "src/main.rs"]
.iter()
.any(|root| fs::read_to_string(path.join(root).as_std_path()).is_ok_and(|text| text.contains("#![forbid(\n unsafe_code,")));
if !guarded {
unguarded.push(name);
}
}
assert!(
unguarded.is_empty(),
"these crates neither forbid `unsafe_code` nor are listed as exempt: {}",
unguarded.join(", ")
);
}
const ENVIRONMENT_WRITERS: [(&str, &str); 0] = [];
#[test]
fn nothing_writes_the_process_environment() {
let root = workspace_dir();
let mut offenders = Vec::new();
let mut allowances_used = BTreeSet::new();
for path in gamma_crates() {
for entry in walk(&path.join("src")).into_iter().chain(walk_optional(&path.join("tests"))) {
let relative = entry
.strip_prefix(&root)
.map_or_else(|_| entry.to_string(), ToString::to_string)
.replace('\\', "/");
let text = fs::read_to_string(entry.as_std_path()).unwrap_or_else(|_| panic!("could not read {entry}"));
let mut enclosing = "";
for (number, line) in text.lines().enumerate() {
if let Some(name) = function_name(line) {
enclosing = name;
}
if !["set_var(", "remove_var("]
.iter()
.any(|call| line.contains(&format!("env::{call}")))
{
continue;
}
let allowed = ENVIRONMENT_WRITERS
.iter()
.position(|(file, function)| *file == relative && *function == enclosing);
if let Some(index) = allowed {
let _new = allowances_used.insert(index);
} else {
offenders.push(format!("{relative}:{} in `{enclosing}`", number + 1));
}
}
}
}
assert!(
offenders.is_empty(),
"these write the process environment, which races every other thread's read: {}",
offenders.join(", ")
);
let stale: Vec<String> = ENVIRONMENT_WRITERS
.iter()
.enumerate()
.filter(|(index, _allowance)| !allowances_used.contains(index))
.map(|(_index, (file, function))| format!("{file} `{function}`"))
.collect();
assert!(
stale.is_empty(),
"these allowances match nothing and have to be deleted rather than left to cover the next write: {}",
stale.join(", ")
);
}
fn function_name(line: &str) -> Option<&str> {
let rest = line.trim_start();
let rest = rest.strip_prefix("pub ").unwrap_or(rest);
let rest = rest
.strip_prefix("pub(crate) ")
.or_else(|| rest.strip_prefix("pub(super) "))
.unwrap_or(rest);
let rest = rest.strip_prefix("async ").unwrap_or(rest);
let rest = rest.strip_prefix("const ").unwrap_or(rest);
let rest = rest.strip_prefix("unsafe ").unwrap_or(rest);
let rest = rest.strip_prefix("extern \"C\" ").unwrap_or(rest);
let name = rest.strip_prefix("fn ")?.split(['(', '<', ' ']).next()?;
(!name.is_empty()).then_some(name)
}
fn walk(directory: &Utf8PathBuf) -> Vec<Utf8PathBuf> {
assert!(
directory.is_dir(),
"{directory} is not a directory, so a check walking it would pass by reading nothing"
);
walk_optional(directory)
}
fn walk_optional(directory: &Utf8PathBuf) -> Vec<Utf8PathBuf> {
let mut found = Vec::new();
let Ok(entries) = fs::read_dir(directory.as_std_path()) else {
return found;
};
for entry in entries.flatten() {
let path = Utf8PathBuf::from_path_buf(entry.path()).expect("the repository has no non-UTF-8 paths");
if path.is_dir() {
found.extend(walk_optional(&path));
} else if path.extension() == Some("rs") {
found.push(path);
}
}
found
}
fn gamma_crates() -> Vec<Utf8PathBuf> {
let mut found = Vec::new();
for entry in fs::read_dir(workspace_dir().join("crates").as_std_path())
.expect("the workspace has a crates directory")
.flatten()
{
let path = Utf8PathBuf::from_path_buf(entry.path()).expect("the repository has no non-UTF-8 paths");
if path.is_dir() && path.file_name().unwrap_or_default().starts_with("cargo-gamma") {
found.push(path);
}
}
assert!(
!found.is_empty(),
"no cargo-gamma crate was found, so this check would pass vacuously"
);
found
}
fn declared_modules(sources: &[Utf8PathBuf]) -> BTreeSet<String> {
let mut names = BTreeSet::new();
for path in sources {
let text = fs::read_to_string(path.as_std_path()).unwrap_or_else(|_| panic!("could not read {path}"));
for line in text.lines() {
let trimmed = line.trim_start();
let declaration = trimmed
.strip_prefix("pub(crate) mod ")
.or_else(|| trimmed.strip_prefix("pub(super) mod "))
.or_else(|| trimmed.strip_prefix("pub mod "))
.or_else(|| trimmed.strip_prefix("mod "));
if let Some(rest) = declaration {
let name: String = rest.chars().take_while(|c| c.is_alphanumeric() || *c == '_').collect();
if !name.is_empty() {
let _inserted = names.insert(name);
}
}
}
}
names
}
fn reexported_root(line: &str) -> Option<&str> {
let rest = line.trim_start().strip_prefix("pub use ")?;
let segment = rest.split(&[':', ' ', ';', '{', ','][..]).next()?.trim();
(!segment.is_empty()).then_some(segment)
}
#[test]
fn no_public_facade_re_exports_by_glob() {
let glob = format!("::{}", '*');
let mut globs = Vec::new();
for path in gamma_crates() {
for source in walk(&path.join("src")) {
let text = fs::read_to_string(source.as_std_path()).unwrap_or_else(|_| panic!("could not read {source}"));
for (number, line) in text.lines().enumerate() {
if line.trim_start().starts_with("pub use ") && line.contains(&glob) {
globs.push(format!("{source}:{}", number + 1));
}
}
}
}
assert!(
globs.is_empty(),
"these re-export by glob, so an item added to the module behind them joins a public surface without review: {}",
globs.join(", ")
);
}
#[test]
fn every_local_re_export_states_how_it_is_documented() {
let mut bare = Vec::new();
let mut redundant = Vec::new();
for path in gamma_crates() {
let sources = walk(&path.join("src"));
let modules = declared_modules(&sources);
for source in &sources {
let text = fs::read_to_string(source.as_std_path()).unwrap_or_else(|_| panic!("could not read {source}"));
let lines: Vec<&str> = text.lines().collect();
for (index, line) in lines.iter().enumerate() {
let Some(root) = reexported_root(line) else {
continue;
};
let attributes: Vec<&str> = lines[..index]
.iter()
.rev()
.take_while(|previous| previous.trim_start().starts_with('#'))
.copied()
.collect();
let local = ["crate", "self", "super"].contains(&root) || modules.contains(root);
if !local {
if attributes
.iter()
.any(|previous| previous.trim_start().starts_with("#[doc(inline)]"))
{
redundant.push(format!("{source}:{}", index + 1));
}
continue;
}
if !attributes.iter().any(|previous| previous.trim_start().starts_with("#[doc(")) {
bare.push(format!("{source}:{}", index + 1));
}
}
}
}
assert!(
bare.is_empty(),
"these re-export a local item without saying whether it is inlined or hidden, so rustdoc \
publishes a canonical path pointing at the implementation module: {}",
bare.join(", ")
);
assert!(
redundant.is_empty(),
"these inline a re-export from another crate, which rustdoc already does, copying that \
crate's documentation in where it goes stale silently: {}",
redundant.join(", ")
);
}