122 lines
5.0 KiB
Rust
122 lines
5.0 KiB
Rust
// file: crates/ksp-core-lib/tests/workspace_logging.rs
|
|
// version: 1
|
|
|
|
//! Workspace-level logging ownership canaries for KSP behavioral crates.
|
|
|
|
fn workspace_root() -> std::path::PathBuf {
|
|
let manifest_directory = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
|
|
let parent = manifest_directory.parent();
|
|
assert!(parent.is_some(), "core crate must have a crates directory parent");
|
|
let parent = match parent {
|
|
std::option::Option::Some(value) => value,
|
|
std::option::Option::None => return manifest_directory.to_path_buf(),
|
|
};
|
|
let root = parent.parent();
|
|
assert!(root.is_some(), "core crate must have a workspace root");
|
|
return match root {
|
|
std::option::Option::Some(value) => value.to_path_buf(),
|
|
std::option::Option::None => parent.to_path_buf(),
|
|
};
|
|
}
|
|
|
|
fn rust_source_files(directory: &std::path::Path) -> std::vec::Vec<std::path::PathBuf> {
|
|
let mut files = std::vec::Vec::new();
|
|
let entries = std::fs::read_dir(directory);
|
|
if entries.is_err() {
|
|
return files;
|
|
}
|
|
let entries = match entries {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return files,
|
|
};
|
|
for entry in entries {
|
|
let entry = match entry {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => continue,
|
|
};
|
|
let path = entry.path();
|
|
if path.is_dir() {
|
|
files.extend(rust_source_files(path.as_path()));
|
|
} else if path.extension() == std::option::Option::Some(std::ffi::OsStr::new("rs")) {
|
|
files.push(path);
|
|
}
|
|
}
|
|
return files;
|
|
}
|
|
|
|
fn package_name(manifest: &str) -> std::option::Option<&str> {
|
|
for line in manifest.lines() {
|
|
let trimmed = line.trim();
|
|
if !trimmed.starts_with("name = ") {
|
|
continue;
|
|
}
|
|
return trimmed.split('"').nth(1);
|
|
}
|
|
return std::option::Option::None;
|
|
}
|
|
|
|
#[test]
|
|
fn behavioral_crates_own_explicit_tracing_targets() {
|
|
let crates_root = workspace_root().join("crates");
|
|
let entries = std::fs::read_dir(crates_root.as_path());
|
|
assert!(entries.is_ok(), "workspace crates directory must be readable");
|
|
let entries = match entries {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
for entry in entries {
|
|
let entry = match entry {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => continue,
|
|
};
|
|
let crate_root = entry.path();
|
|
if !crate_root.is_dir() {
|
|
continue;
|
|
}
|
|
let source_root = crate_root.join("src");
|
|
let source_files = rust_source_files(source_root.as_path());
|
|
let mut emits_ksp_logs = false;
|
|
for source_file in source_files.iter() {
|
|
let source = std::fs::read_to_string(source_file.as_path());
|
|
assert!(source.is_ok(), "Rust source must be readable: {}", source_file.display());
|
|
let source = match source {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => continue,
|
|
};
|
|
if source.contains("ksp_logging_lib::") {
|
|
emits_ksp_logs = true;
|
|
}
|
|
assert!(
|
|
!source.contains("target: env!(\"CARGO_PKG_NAME\")"),
|
|
"KSP tracing target must be explicit rather than derived from Cargo metadata: {}",
|
|
source_file.display()
|
|
);
|
|
assert!(!source.contains("target: \"ksp-"), "KSP tracing target literals must be owned by src/constants.rs: {}", source_file.display());
|
|
}
|
|
if !emits_ksp_logs {
|
|
continue;
|
|
}
|
|
let manifest = std::fs::read_to_string(crate_root.join("Cargo.toml"));
|
|
assert!(manifest.is_ok(), "behavioral crate manifest must be readable: {}", crate_root.display());
|
|
let manifest = match manifest {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => continue,
|
|
};
|
|
let package_name = package_name(manifest.as_str());
|
|
assert!(package_name.is_some(), "behavioral crate package name must be discoverable: {}", crate_root.display());
|
|
let package_name = match package_name {
|
|
std::option::Option::Some(value) => value,
|
|
std::option::Option::None => continue,
|
|
};
|
|
let constants_path = source_root.join("constants.rs");
|
|
let constants = std::fs::read_to_string(constants_path.as_path());
|
|
assert!(constants.is_ok(), "behavioral crate must own src/constants.rs: {}", crate_root.display());
|
|
let constants = match constants {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => continue,
|
|
};
|
|
let expected = std::format!("pub(crate) const TRACING_TARGET: &str = \"{package_name}\";");
|
|
assert!(constants.contains(expected.as_str()), "behavioral crate must own its Cargo-name tracing target: {}", crate_root.display());
|
|
}
|
|
}
|