75 lines
2.5 KiB
Rust
75 lines
2.5 KiB
Rust
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
const TARGET_MANIFESTS: &[&str] =
|
|
&["crates/console/prometeu-bytecode/Cargo.toml", "crates/console/prometeu-vm/Cargo.toml"];
|
|
|
|
const FORBIDDEN_DEPENDENCY_FRAGMENTS: &[&str] = &["compiler", "frontend"];
|
|
|
|
#[test]
|
|
fn pbx_and_pvm_crates_must_not_depend_on_compiler_or_frontend_crates() {
|
|
let workspace_root = find_workspace_root().expect("runtime workspace root");
|
|
let mut violations = Vec::new();
|
|
|
|
for relative_path in TARGET_MANIFESTS {
|
|
let manifest_path = workspace_root.join(relative_path);
|
|
let manifest = fs::read_to_string(&manifest_path)
|
|
.unwrap_or_else(|error| panic!("failed to read {}: {error}", manifest_path.display()));
|
|
|
|
for dependency in dependency_names(&manifest) {
|
|
let normalized = dependency.to_ascii_lowercase();
|
|
if FORBIDDEN_DEPENDENCY_FRAGMENTS.iter().any(|fragment| normalized.contains(fragment)) {
|
|
violations.push(format!("{relative_path}: forbidden dependency `{dependency}`"));
|
|
}
|
|
}
|
|
}
|
|
|
|
assert!(
|
|
violations.is_empty(),
|
|
"PBX/PVM crates must remain independent of compiler and frontend crates:\n{}",
|
|
violations.join("\n")
|
|
);
|
|
}
|
|
|
|
fn dependency_names(manifest: &str) -> Vec<&str> {
|
|
let mut names = Vec::new();
|
|
let mut in_dependency_section = false;
|
|
|
|
for raw_line in manifest.lines() {
|
|
let line = raw_line.trim();
|
|
if line.starts_with('[') && line.ends_with(']') {
|
|
let section = &line[1..line.len() - 1];
|
|
in_dependency_section = section == "dependencies"
|
|
|| section == "dev-dependencies"
|
|
|| section == "build-dependencies"
|
|
|| section.ends_with(".dependencies")
|
|
|| section.ends_with(".dev-dependencies")
|
|
|| section.ends_with(".build-dependencies");
|
|
continue;
|
|
}
|
|
|
|
if !in_dependency_section || line.is_empty() || line.starts_with('#') {
|
|
continue;
|
|
}
|
|
|
|
if let Some((name, _)) = line.split_once('=') {
|
|
names.push(name.trim().trim_matches('"'));
|
|
}
|
|
}
|
|
|
|
names
|
|
}
|
|
|
|
fn find_workspace_root() -> Option<PathBuf> {
|
|
let mut cursor = Path::new(env!("CARGO_MANIFEST_DIR")).to_path_buf();
|
|
loop {
|
|
let manifest = cursor.join("Cargo.toml");
|
|
if fs::read_to_string(&manifest).is_ok_and(|contents| contents.contains("[workspace]")) {
|
|
return Some(cursor);
|
|
}
|
|
if !cursor.pop() {
|
|
return None;
|
|
}
|
|
}
|
|
}
|