use std::{fs, path::Path};
#[test]
fn ui() {
let cases = trybuild::TestCases::new();
cases.compile_fail("tests/ui/macros/*.rs");
cases.compile_fail("tests/ui/schema/*.rs");
cases.compile_fail("tests/ui/antipattern/*.rs");
cases.compile_fail("tests/ui/traits/*.rs");
cases.pass("tests/ui/pass/*.rs");
}
#[test]
fn every_rejected_schema_type_has_a_case() {
const SOURCE: &str = include_str!("../src/schema/mod.rs");
let rows = rejection_table_rows(SOURCE);
assert!(
rows > 0,
"the rejection table in `schema/mod.rs` was not found; this test is looking for the \
heading `# Types deliberately left without an implementation`"
);
let cases = compile_fail_cases(&Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/ui/schema"));
assert_eq!(
cases, rows,
"`tests/ui/schema/` holds {cases} case(s) for {rows} row(s) of the rejection table in \
`schema/mod.rs`; a row added without a case leaves a documented refusal that nothing \
checks"
);
}
fn rejection_table_rows(source: &str) -> usize {
source
.lines()
.map(str::trim_start)
.skip_while(|line| !line.ends_with("# Types deliberately left without an implementation"))
.map(|line| line.trim_start_matches("//!").trim())
.skip_while(|line| !line.starts_with('|'))
.take_while(|line| line.starts_with('|'))
.skip(2)
.count()
}
fn compile_fail_cases(directory: &Path) -> usize {
fs::read_dir(directory)
.unwrap_or_else(|error| panic!("reading {}: {error}", directory.display()))
.filter_map(Result::ok)
.filter(|entry| entry.path().extension().is_some_and(|it| it == "rs"))
.count()
}
#[test]
fn every_guided_diagnostic_has_a_snapshot() {
const RECORDED: &[(&str, &str)] = &[
("Alternative", "traits/alternative.stderr"),
("ByteSource", "traits/byte_source.stderr"),
("Carries", "traits/carries.stderr"),
("Describe", "traits/describe.stderr"),
("EndpointMeta", "traits/endpoint_meta.stderr"),
("FromRequest", "antipattern/raw_request_extractor.stderr"),
(
"FromRequestParts",
"antipattern/raw_header_map_extractor.stderr",
),
("Handler", "traits/handler.stderr"),
("IntoEndpoints", "traits/into_endpoints.stderr"),
("IntoResponse", "antipattern/bare_status_code.stderr"),
("MapKey", "traits/map_key.stderr"),
("Provides", "antipattern/inject_without_provider.stderr"),
("Rangeable", "traits/rangeable.stderr"),
("RequestContent", "traits/request_content.stderr"),
("Responses", "antipattern/problem_as_return_type.stderr"),
("Schema", "schema/serde_json_value.stderr"),
("ShortCircuit", "traits/short_circuit.stderr"),
];
let root = Path::new(env!("CARGO_MANIFEST_DIR"));
for (trait_name, snapshot) in RECORDED {
let path = root.join("tests/ui").join(snapshot);
let recorded = fs::read_to_string(&path)
.unwrap_or_else(|_| panic!("`{trait_name}` names {snapshot}, which is not there"));
assert!(
!recorded.trim().is_empty(),
"`{trait_name}`'s snapshot is empty, so it records no diagnostic"
);
}
let guided = guided_traits_in_source(&root.join("src"));
assert_eq!(
guided,
RECORDED.len(),
"`crates/kynos/src` guides {guided} trait(s) and {} have a snapshot; a diagnostic nobody \
snapshotted is a diagnostic nobody checked",
RECORDED.len()
);
}
fn guided_traits_in_source(directory: &Path) -> usize {
let mut found = 0;
for entry in fs::read_dir(directory).expect("the crate's own source is readable") {
let path = entry.expect("readable entry").path();
if path.is_dir() {
found += guided_traits_in_source(&path);
continue;
}
if path.extension().is_none_or(|extension| extension != "rs") {
continue;
}
found += fs::read_to_string(&path)
.expect("readable source")
.matches("#[diagnostic::on_unimplemented")
.count();
}
found
}