use std::{fs, path::Path};
#[test]
fn public_docs_reference_only_builder_entry_points() {
let root = Path::new(env!("CARGO_MANIFEST_DIR"));
let mut paths = Vec::new();
collect_markdown(root, &mut paths);
collect_files(&root.join("examples"), &mut paths);
for facade_source in [
"src/client_component.rs",
"src/server_component.rs",
"src/intermediary_component.rs",
"src/runtime_middleware.rs",
"src/pipeline.rs",
"src/codec.rs",
"src/demux.rs",
"src/pre_startup.rs",
"src/startup.rs",
] {
paths.push(root.join(facade_source));
}
paths.sort();
paths.dedup();
let forbidden = ["pg_proto::Conn", "SessionPair", "Middleware::new"];
let private_modules = [
"auth",
"codec",
"grammar",
"intermediary",
"middleware",
"pipeline",
"pre_startup",
"session",
"transport",
];
for path in paths {
let source = fs::read_to_string(&path).expect("public documentation must be readable");
let documentation = if path.starts_with(root.join("src")) {
rustdoc_without_compile_fail_examples(&source)
} else {
source
};
let compact = documentation.split_whitespace().collect::<String>();
for legacy in forbidden {
assert!(
!documentation.contains(legacy),
"{} contains legacy public API reference `{legacy}`",
path.display()
);
}
for module in private_modules {
for legacy in [
format!("pg_proto::{module}::"),
format!("pg_proto::{module}as"),
format!("pg_proto::{module};"),
] {
assert!(
!compact.contains(&legacy),
"{} contains legacy public module reference `{legacy}`",
path.display()
);
}
assert!(
!contains_grouped_module(&compact, module),
"{} contains grouped legacy public module reference `{module}`",
path.display()
);
}
}
}
fn contains_grouped_module(source: &str, module: &str) -> bool {
let mut remaining = source;
while let Some(start) = remaining.find("pg_proto::{") {
remaining = &remaining[start + "pg_proto::{".len()..];
let Some(end) = remaining.find('}') else {
return false;
};
if remaining[..end].split(',').any(|item| {
item == module
|| item.starts_with(&format!("{module}::"))
|| item.starts_with(&format!("{module}as"))
}) {
return true;
}
remaining = &remaining[end + 1..];
}
false
}
fn rustdoc_without_compile_fail_examples(source: &str) -> String {
let mut in_compile_fail = false;
source
.lines()
.filter_map(|line| {
let trimmed = line.trim_start();
if !(trimmed.starts_with("///") || trimmed.starts_with("//!")) {
return None;
}
let content = trimmed
.strip_prefix("///")
.or_else(|| trimmed.strip_prefix("//!"))
.unwrap()
.trim_start();
if content.starts_with("```rust,compile_fail") {
in_compile_fail = true;
return None;
}
if in_compile_fail && content.starts_with("```") {
in_compile_fail = false;
return None;
}
(!in_compile_fail).then_some(content)
})
.collect::<Vec<_>>()
.join("\n")
}
#[test]
fn readme_leads_with_all_complete_builder_workflows_and_guardrails() {
let readme = fs::read_to_string(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md")).unwrap();
let security = readme.find("## Security choices come first").unwrap();
let client = readme.find("## Client: connect to PostgreSQL").unwrap();
let server = readme.find("## Server: accept PostgreSQL clients").unwrap();
let intermediary = readme.find("## Intermediary: compose both roles").unwrap();
assert!(security < client && client < server && server < intermediary);
assert_eq!(readme.matches("```rust,no_run").count(), 3);
for entry in [
"Client::builder()",
"Server::builder()",
"Intermediary::builder()",
] {
assert!(readme.contains(entry), "README is missing `{entry}`");
}
for guardrail in [
"plaintext",
"unverified trust",
"VerifyFull",
"without_frame_limit",
] {
assert!(
readme.contains(guardrail),
"README is missing `{guardrail}` guardrail"
);
}
}
#[test]
fn documentation_code_fences_specify_a_language() {
let root = Path::new(env!("CARGO_MANIFEST_DIR"));
let mut paths = Vec::new();
collect_markdown(root, &mut paths);
collect_files(&root.join("src"), &mut paths);
paths.sort();
paths.dedup();
for path in paths {
let source = fs::read_to_string(&path).expect("documentation must be readable");
let mut in_fence = false;
for (index, line) in source.lines().enumerate() {
let trimmed = line.trim_start();
let trimmed = if path.extension().is_some_and(|extension| extension == "rs") {
let Some(documentation) = trimmed
.strip_prefix("///")
.or_else(|| trimmed.strip_prefix("//!"))
else {
continue;
};
documentation.trim_start()
} else {
trimmed
};
if !trimmed.starts_with("```") {
continue;
}
if in_fence {
assert_eq!(
trimmed,
"```",
"{}:{} has an invalid closing fence",
path.display(),
index + 1
);
} else {
assert!(
trimmed.len() > 3,
"{}:{} has a code fence without a language",
path.display(),
index + 1
);
}
in_fence = !in_fence;
}
assert!(!in_fence, "{} has an unclosed code fence", path.display());
}
}
fn collect_files(root: &Path, paths: &mut Vec<std::path::PathBuf>) {
let mut entries = fs::read_dir(root)
.expect("documentation directory must exist")
.map(|entry| entry.unwrap().path())
.collect::<Vec<_>>();
entries.sort();
for path in entries {
if path.is_dir() {
collect_files(&path, paths);
} else if matches!(
path.extension().and_then(|value| value.to_str()),
Some("md" | "rs")
) {
paths.push(path);
}
}
}
fn collect_markdown(root: &Path, paths: &mut Vec<std::path::PathBuf>) {
let mut entries = fs::read_dir(root)
.expect("repository directory must exist")
.map(|entry| entry.unwrap().path())
.collect::<Vec<_>>();
entries.sort();
for path in entries {
if path.is_dir() {
let name = path.file_name().and_then(|value| value.to_str());
if !matches!(name, Some(".git" | "target" | "tests")) {
collect_markdown(&path, paths);
}
} else if path.extension().is_some_and(|extension| extension == "md") {
paths.push(path);
}
}
}