// file: crates/ksp-core-lib/tests/workspace_dependencies.rs // version: 5 //! Workspace-level dependency policy canaries owned by the foundational KSP test surface. 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(), }; } #[test] fn workspace_dependency_table_does_not_activate_consumer_features() { let manifest_path = workspace_root().join("Cargo.toml"); let manifest = std::fs::read_to_string(manifest_path.as_path()); assert!(manifest.is_ok(), "workspace manifest must be readable during integration tests"); let manifest = match manifest { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => return, }; let workspace_dependencies = match manifest.split("[workspace.dependencies]").nth(1) { std::option::Option::Some(tail) => tail.split("[workspace.lints.rust]").next(), std::option::Option::None => std::option::Option::None, }; assert!(workspace_dependencies.is_some(), "workspace dependencies section must exist"); let workspace_dependencies = match workspace_dependencies { std::option::Option::Some(value) => value, std::option::Option::None => return, }; for line in workspace_dependencies.lines() { let content = match line.split('#').next() { std::option::Option::Some(value) => value, std::option::Option::None => continue, }; for inline_field in content.split(',') { let key = match inline_field.split('=').next() { std::option::Option::Some(value) => value.trim().trim_start_matches('{').trim(), std::option::Option::None => continue, }; assert_ne!(key, "features", "consumer feature activation must stay in member manifests"); } } } #[test] fn transport_manifest_preserves_ksp_dependency_firewall() { let manifest_path = workspace_root().join("crates/ksp-onchain-transport-lib/Cargo.toml"); let manifest = std::fs::read_to_string(manifest_path).expect("transport manifest must be readable during workspace integration tests"); for forbidden in ["ksp-config-lib", "ksp-store-api", "ksp-store-lib", "ksp-program-api", "ksp-program-lib", "tracing =", "tracing."] { assert!(!manifest.contains(forbidden), "forbidden direct transport dependency detected: {forbidden}"); } assert!(manifest.contains("ksp-core-lib")); assert!(manifest.contains("ksp-logging-lib")); assert!(manifest.contains("futures-util = { workspace = true, features = [\"sink\", \"std\"] }")); assert!(manifest.contains("reqwest = { workspace = true, features = [\"rustls\"] }")); assert!(manifest.contains("tokio = { workspace = true, features = [\"macros\", \"net\", \"rt\", \"sync\", \"time\"] }")); assert!(manifest.contains("tokio-tungstenite = { workspace = true, features = [\"connect\", \"rustls-tls-webpki-roots\"] }")); assert!(manifest.contains("[dev-dependencies]")); assert!(manifest.contains("tokio = { workspace = true, features = [\"io-util\", \"net\", \"rt\", \"test-util\"] }")); } #[test] fn transport_manifest_runtime_and_dev_dependency_names_are_exact() { let manifest_path = workspace_root().join("crates/ksp-onchain-transport-lib/Cargo.toml"); let manifest = std::fs::read_to_string(manifest_path).expect("transport manifest must be readable during workspace integration tests"); let dependencies_tail = manifest.split("[dependencies]").nth(1); assert!(dependencies_tail.is_some(), "transport dependencies section must exist"); let dependencies_tail = match dependencies_tail { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let dependencies = match dependencies_tail.split("[dev-dependencies]").next() { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let dependency_names = manifest_dependency_names(dependencies); assert_eq!( dependency_names, std::vec!["futures-util", "ksp-core-lib", "ksp-logging-lib", "reqwest", "serde", "serde_json", "tokio", "tokio-tungstenite"] ); let dev_dependencies_tail = manifest.split("[dev-dependencies]").nth(1); assert!(dev_dependencies_tail.is_some(), "transport dev-dependencies section must exist"); let dev_dependencies_tail = match dev_dependencies_tail { std::option::Option::Some(value) => value, std::option::Option::None => return, }; let dev_dependencies = match dev_dependencies_tail.split("[lints]").next() { std::option::Option::Some(value) => value, std::option::Option::None => return, }; assert_eq!(manifest_dependency_names(dev_dependencies), std::vec!["tokio"]); } fn manifest_dependency_names(section: &str) -> std::vec::Vec<&str> { let mut names = std::vec::Vec::new(); for line in section.lines() { let content = match line.split('#').next() { std::option::Option::Some(value) => value.trim(), std::option::Option::None => continue, }; if content.is_empty() { continue; } let name = match content.split('=').next() { std::option::Option::Some(value) => value.trim().trim_end_matches(".workspace"), std::option::Option::None => continue, }; if !name.is_empty() { names.push(name); } } names.sort_unstable(); return names; }