package_boundary.rs (4081B)
1 use std::collections::BTreeSet; 2 3 const MANIFEST: &str = include_str!("../Cargo.toml"); 4 const ROOT: &str = include_str!("../src/lib.rs"); 5 const CAPABILITY: &str = include_str!("../src/capability.rs"); 6 const ERROR: &str = include_str!("../src/error.rs"); 7 const EVENT: &str = include_str!("../src/event.rs"); 8 const RADROOTSD: &str = include_str!("../src/radrootsd.rs"); 9 const RUNTIME: &str = include_str!("../src/runtime.rs"); 10 const VERSIONED_SOURCES: &[&str] = &[ 11 include_str!("../src/capability/v1.rs"), 12 include_str!("../src/error/v1.rs"), 13 include_str!("../src/event/v1.rs"), 14 include_str!("../src/radrootsd/transport_publish/v5.rs"), 15 include_str!("../src/runtime/v1.rs"), 16 include_str!("../src/schema.rs"), 17 ]; 18 19 #[test] 20 fn manifest_has_final_identity_features_and_no_radroots_dependencies() { 21 assert!(MANIFEST.contains("name = \"radroots_protocol\"")); 22 assert!(MANIFEST.contains("version = \"0.1.0-alpha\"")); 23 assert!(MANIFEST.contains("publish = [\"crates-io\"]")); 24 assert!(MANIFEST.contains("[lib]\nname = \"radroots_protocol\"")); 25 assert!(MANIFEST.contains("default = [\"std\", \"serde\"]")); 26 assert_eq!( 27 table_keys(MANIFEST, "[features]"), 28 BTreeSet::from(["default", "serde", "std"]) 29 ); 30 assert_eq!( 31 table_keys(MANIFEST, "[dependencies]"), 32 BTreeSet::from(["serde"]) 33 ); 34 assert_eq!( 35 table_keys(MANIFEST, "[dev-dependencies]"), 36 BTreeSet::from(["serde_json"]) 37 ); 38 } 39 40 #[test] 41 fn crate_root_exposes_only_the_approved_versioned_skeleton() { 42 assert!(ROOT.contains("#![cfg_attr(not(feature = \"std\"), no_std)]")); 43 assert_eq!( 44 root_declarations("pub mod "), 45 BTreeSet::from([ 46 "capability", 47 "error", 48 "event", 49 "radrootsd", 50 "runtime", 51 "schema" 52 ]) 53 ); 54 for source in [CAPABILITY, EVENT] { 55 assert!(source.lines().any(|line| line.trim() == "pub mod v1;")); 56 } 57 assert!(ERROR.lines().any(|line| line.trim() == "pub mod v1;")); 58 assert!(RUNTIME.lines().any(|line| line.trim() == "pub mod v1;")); 59 assert!(RADROOTSD.contains("pub mod transport_publish {")); 60 assert!(RADROOTSD.lines().any(|line| line.trim() == "pub mod v5;")); 61 assert!( 62 !ROOT 63 .lines() 64 .map(str::trim) 65 .any(|line| line.starts_with("pub use ")) 66 ); 67 } 68 69 #[test] 70 fn public_contract_sources_exclude_runtime_dependencies_and_wrapper_traits() { 71 assert!(ROOT.contains("#![forbid(unsafe_code)]")); 72 for source in VERSIONED_SOURCES { 73 for forbidden in [ 74 "dto_bindgen", 75 "wasm_bindgen", 76 "uniffi", 77 "tokio::", 78 "sqlx::", 79 "reqwest::", 80 "nostr::", 81 "std::fs", 82 "std::net", 83 "std::process", 84 "impl core::ops::Deref", 85 "impl std::ops::Deref", 86 "unsafe fn", 87 "unsafe impl", 88 "unsafe {", 89 ] { 90 assert!( 91 !source.contains(forbidden), 92 "protocol contract source contains forbidden surface `{forbidden}`" 93 ); 94 } 95 } 96 } 97 98 fn table_keys<'a>(manifest: &'a str, heading: &str) -> BTreeSet<&'a str> { 99 let Some((_, table)) = manifest.split_once(heading) else { 100 return BTreeSet::new(); 101 }; 102 table 103 .lines() 104 .skip(1) 105 .take_while(|line| !line.trim_start().starts_with('[')) 106 .filter_map(|line| { 107 let line = line.trim(); 108 (line 109 .bytes() 110 .next() 111 .is_some_and(|byte| byte.is_ascii_lowercase() || byte == b'_') 112 && !line.starts_with('#')) 113 .then(|| line.split_once('=').map(|(key, _)| key.trim())) 114 .flatten() 115 }) 116 .collect() 117 } 118 119 fn root_declarations(prefix: &str) -> BTreeSet<&str> { 120 ROOT.lines() 121 .map(str::trim) 122 .filter_map(|line| line.strip_prefix(prefix)) 123 .filter_map(|name| name.strip_suffix(';')) 124 .collect() 125 }