plugin/guest-allocation/tests/no_money_word.rs
//! The open build never mentions money. This is the crate-local half of that
//! law: an allow-list of resource and provenance words, asserted over this
//! crate's own source, so a word that has no business here cannot be added
//! without the test naming it.
//!
//! It is stronger than grepping for known-bad words: a new money word nobody
//! thought to ban is still caught, because it is simply not on the list.
use std::collections::BTreeSet;
/// Words that may appear in a metering crate in the open build: resources,
/// provenance and measurement.
const ALLOWED_DOMAIN_WORDS: &[&str] = &[
"allocation",
"artifact",
"artifacts",
"archive",
"audit",
"bytes",
"capacity",
"capability",
"clock",
"counted",
"digest",
"enforcement",
"files",
"guest",
"host",
"manifest",
"measured",
"meter",
"meters",
"principal",
"provisioned",
"reading",
"refused",
"repository",
"scope",
"selftest",
"servable",
"storage",
"store",
"tenant",
"total",
"usage",
"used",
"verdict",
];
/// Words that are the business, and must not be in the open build at all. The
/// test does not rely on this list — the allow-list above does the work — but a
/// hit here names the offence instead of just failing.
const NAMED_OFFENCES: &[&str] = &[
"plan",
"price",
"pricing",
"invoice",
"stripe",
"upcloud",
"paid",
"quota",
"subscription",
"billing",
"charge",
"payment",
"licence",
"license",
"entitlement",
"cap",
"expiry",
"expires",
"money",
"currency",
"trial",
"tier",
];
fn words(src: &str) -> BTreeSet<String> {
src.split(|c: char| !c.is_ascii_alphabetic())
.filter(|w| w.len() > 2)
.map(|w| w.to_ascii_lowercase())
.collect()
}
#[test]
fn this_crate_speaks_no_money() {
let mut sources = vec![
("src/lib.rs", include_str!("../src/lib.rs")),
("tests/allow_is_total.rs", include_str!("allow_is_total.rs")),
];
// This file names the offences on purpose, so it is not its own subject.
sources.retain(|(name, _)| !name.contains("no_money_word"));
for (name, src) in sources {
let found = words(src);
for bad in NAMED_OFFENCES {
assert!(
!found.contains(*bad),
"{name} contains the word `{bad}`; the open build never mentions money"
);
}
}
}
#[test]
fn the_guard_would_catch_a_leak() {
// The negative control: the test above is only worth something if it fires.
let found = words("fn charge_the_customer() { let invoice = 1; }");
assert!(NAMED_OFFENCES.iter().any(|bad| found.contains(*bad)));
}
#[test]
fn the_allow_list_is_the_vocabulary_this_crate_actually_uses() {
// Every allowed word is a resource or provenance word, and none of them is
// an offence. This keeps the two lists from drifting into each other.
for w in ALLOWED_DOMAIN_WORDS {
assert!(!NAMED_OFFENCES.contains(w), "`{w}` is on both lists");
}
}