// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/dependency_boundary.rs // version: 3 //! Dependency firewall canaries for the RAW transaction ingest Worker foundation. #[test] fn pre_002_manifest_dependency_surface_is_exact() { let manifest = include_str!("../Cargo.toml"); let dependencies = dependency_section(manifest); let names = manifest_dependency_names(dependencies); assert_eq!(names, vec!["ksp-core-lib", "ksp-logging-lib", "ksp-raw-transaction-lib", "ksp-store-lib", "ksp-worker-api", "sha2", "tokio",],); for required in [ "ksp-core-lib = { path = \"../ksp-core-lib\" }", "ksp-logging-lib = { path = \"../ksp-logging-lib\" }", "ksp-raw-transaction-lib = { path = \"../ksp-raw-transaction-lib\" }", "ksp-store-lib = { path = \"../ksp-store-lib\", default-features = false }", "ksp-worker-api = { path = \"../ksp-worker-api\" }", "sha2 = { workspace = true }", "tokio = { workspace = true, features = [\"macros\", \"rt\", \"sync\", \"time\"] }", ] { assert!(dependencies.contains(required), "required Worker dependency missing: {required}"); } return; } #[test] fn pre_002_manifest_keeps_forbidden_layers_and_live_sources_out() { let manifest = include_str!("../Cargo.toml"); let dependencies = dependency_section(manifest); for forbidden in [ "futures-util", "ksp-config-lib", "ksp-interface-lib", "ksp-job-api", "ksp-job-backfill-lib", "ksp-onchain-transport-lib", "ksp-program-api", "ksp-store-api", "ksp-store-postgres-lib", "ksp-wallet-lib", "reqwest", "solana-", "tokio-tungstenite", "tonic", "yellowstone-grpc-proto", ] { assert!(!dependencies.contains(forbidden), "forbidden Worker dependency present: {forbidden}"); } assert!(!manifest.contains("[dev-dependencies]"), "foundation requires no test-only dependency"); assert!(!manifest.contains("[build-dependencies]"), "foundation requires no build dependency"); return; } #[test] fn pre_004_source_surface_opens_lifecycle_without_supervisor_admission_or_live_sources() { let root = include_str!("../src/lib.rs"); let runtime = include_str!("../src/runtime.rs"); for required in [ "mod runtime;", "pub use self::runtime::RawTransactionIngestHandle;", "pub use self::runtime::RawTransactionIngestTerminalFuture;", "pub use self::runtime::RawTransactionIngestWorker;", "pub fn start(", "pub fn request_stop(&self) -> bool", "pub fn wait_terminal(&self)", ] { assert!(root.contains(required) || runtime.contains(required), "required pre.004 runtime contract missing: {required}"); } for forbidden in [ "JoinSet", "mpsc::", "canonicalize_raw_transaction", "persist_raw_transaction", "ksp_onchain_transport_lib::", "RawTransactionIngestSnapshot", "WorkerSnapshotSource", ] { assert!(!root.contains(forbidden) && !runtime.contains(forbidden), "pre.004 opened later runtime scope too early: {forbidden}"); } return; } fn dependency_section(manifest: &str) -> &str { let after_header = match manifest.split_once("[dependencies]") { std::option::Option::Some((_, section)) => section, std::option::Option::None => { return ""; }, }; let end = match after_header.find("\n[") { std::option::Option::Some(index) => index, std::option::Option::None => after_header.len(), }; return &after_header[..end]; } 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; }