use std::path::Path;
const FORBIDDEN_DIRECT_DEPS: &[&str] = &[
"axum",
"curl",
"h2",
"http",
"hyper",
"isahc",
"native-tls",
"openssl",
"quinn",
"reqwest",
"rustls",
"surf",
"tokio-tungstenite",
"tonic",
"tungstenite",
"warp",
];
#[test]
fn broker_crate_has_no_direct_network_or_tls_dependencies() {
let manifest = Path::new(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml");
let raw = std::fs::read_to_string(&manifest)
.unwrap_or_else(|err| panic!("failed to read {}: {err}", manifest.display()));
let direct_dependencies = direct_dependency_names(&raw);
let forbidden = direct_dependencies
.iter()
.filter(|name| FORBIDDEN_DIRECT_DEPS.contains(&name.as_str()))
.cloned()
.collect::<Vec<_>>();
assert!(
forbidden.is_empty(),
"running-process v1 broker must stay local-IPC-only; forbidden direct deps: {forbidden:?}"
);
}
fn direct_dependency_names(manifest: &str) -> Vec<String> {
let mut section = Section::Other;
let mut names = Vec::new();
for line in manifest.lines() {
let trimmed = line.trim();
if trimmed.starts_with('[') && trimmed.ends_with(']') {
section = Section::from_header(trimmed);
continue;
}
if !section.is_direct_dependencies() || trimmed.is_empty() || trimmed.starts_with('#') {
continue;
}
if let Some(name) = trimmed.split_once('=').map(|(name, _)| name.trim()) {
names.push(name.trim_matches('"').to_owned());
}
}
names
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Section {
DirectDependencies,
TargetDirectDependencies,
Other,
}
impl Section {
fn from_header(header: &str) -> Self {
if header == "[dependencies]" {
return Self::DirectDependencies;
}
if header.starts_with("[target.") && header.ends_with(".dependencies]") {
return Self::TargetDirectDependencies;
}
Self::Other
}
fn is_direct_dependencies(self) -> bool {
matches!(
self,
Self::DirectDependencies | Self::TargetDirectDependencies
)
}
}
#[cfg(test)]
mod tests {
use super::direct_dependency_names;
#[test]
fn parser_ignores_dev_and_build_dependencies() {
let names = direct_dependency_names(
r#"
[dependencies]
prost = "0.14"
[build-dependencies]
reqwest = "0.12"
[dev-dependencies]
hyper = "1"
[target.'cfg(windows)'.dependencies]
winapi = "0.3"
"#,
);
assert_eq!(names, ["prost", "winapi"]);
}
}