public_api.rs (8149B)
1 use std::{any::type_name, collections::BTreeSet}; 2 3 const ACTIVE_MODULES: &[(&str, &str)] = &[ 4 ("capability", include_str!("../src/capability.rs")), 5 ("client", include_str!("../src/client.rs")), 6 ("diagnostics", include_str!("../src/diagnostics.rs")), 7 ("error", include_str!("../src/error.rs")), 8 ("farm", include_str!("../src/farm.rs")), 9 ("listing", include_str!("../src/listing.rs")), 10 ("signing", include_str!("../src/signing.rs")), 11 ("storage", include_str!("../src/storage.rs")), 12 ("sync", include_str!("../src/sync.rs")), 13 ("trade", include_str!("../src/trade.rs")), 14 ("transport", include_str!("../src/transport.rs")), 15 ]; 16 17 #[test] 18 fn public_native_type_snapshot_uses_contextual_names() { 19 let actual = BTreeSet::from([ 20 type_name::<radroots_sdk::Client>(), 21 type_name::<radroots_sdk::ClientBuilder>(), 22 type_name::<radroots_sdk::capability::Availability>(), 23 type_name::<radroots_sdk::capability::CapabilityId>(), 24 type_name::<radroots_sdk::capability::CapabilityReport>(), 25 type_name::<radroots_sdk::capability::CapabilityStatus>(), 26 type_name::<radroots_sdk::capability::Maturity>(), 27 type_name::<radroots_sdk::diagnostics::Report>(), 28 type_name::<radroots_sdk::error::Error>(), 29 type_name::<radroots_sdk::error::ErrorDescriptor>(), 30 type_name::<radroots_sdk::error::ErrorKind>(), 31 type_name::<radroots_sdk::farm::Plan>(), 32 type_name::<radroots_sdk::farm::PrepareError>(), 33 type_name::<radroots_sdk::farm::PrepareErrorKind>(), 34 type_name::<radroots_sdk::farm::PrepareRequest>(), 35 type_name::<radroots_sdk::listing::Action>(), 36 type_name::<radroots_sdk::listing::Plan>(), 37 type_name::<radroots_sdk::listing::PrepareError>(), 38 type_name::<radroots_sdk::listing::PrepareErrorKind>(), 39 type_name::<radroots_sdk::listing::PrepareRequest>(), 40 type_name::<radroots_sdk::signing::Mode>(), 41 type_name::<radroots_sdk::signing::Operations<'static>>(), 42 type_name::<radroots_sdk::signing::Provider>(), 43 type_name::<radroots_sdk::signing::BlossomAuthorizationPlan>(), 44 type_name::<radroots_sdk::storage::Operations<'static>>(), 45 type_name::<radroots_sdk::trade::Plan>(), 46 type_name::<radroots_sdk::trade::PrepareError>(), 47 type_name::<radroots_sdk::trade::PrepareErrorKind>(), 48 type_name::<radroots_sdk::trade::PrepareRequest>(), 49 type_name::<radroots_sdk::transport::Profile>(), 50 ]); 51 #[cfg(feature = "sync")] 52 let actual = actual 53 .into_iter() 54 .chain([ 55 type_name::<radroots_sdk::farm::EnqueueRequest>(), 56 type_name::<radroots_sdk::farm::Operations<'static>>(), 57 type_name::<radroots_sdk::listing::EnqueueRequest>(), 58 type_name::<radroots_sdk::listing::Operations<'static>>(), 59 type_name::<radroots_sdk::sync::Operations<'static>>(), 60 type_name::<radroots_sdk::sync::HostPolicy>(), 61 type_name::<radroots_sdk::trade::EnqueueRequest>(), 62 type_name::<radroots_sdk::trade::Operations<'static>>(), 63 type_name::<radroots_sdk::trade::PrivateTermsError>(), 64 ]) 65 .collect::<BTreeSet<_>>(); 66 #[cfg(feature = "nostr")] 67 let actual = actual 68 .into_iter() 69 .chain([type_name::<radroots_sdk::transport::NostrSlot>()]) 70 .collect::<BTreeSet<_>>(); 71 #[cfg(feature = "blossom")] 72 let actual = actual 73 .into_iter() 74 .chain([ 75 type_name::<radroots_sdk::signing::AuthorizationHeader>(), 76 type_name::<radroots_sdk::signing::BlossomSigningError>(), 77 type_name::<radroots_sdk::transport::BlossomCancellation>(), 78 type_name::<radroots_sdk::transport::BlossomConfig>(), 79 type_name::<radroots_sdk::transport::BlossomConfigFingerprint>(), 80 type_name::<radroots_sdk::transport::BlossomEndpoint>(), 81 type_name::<radroots_sdk::transport::BlossomEndpointAuthority>(), 82 type_name::<radroots_sdk::transport::BlossomEndpointEvidence>(), 83 type_name::<radroots_sdk::transport::BlossomError>(), 84 type_name::<radroots_sdk::transport::BlossomErrorKind>(), 85 type_name::<radroots_sdk::transport::BlossomEvidenceState>(), 86 type_name::<radroots_sdk::transport::BlossomHostKind>(), 87 type_name::<radroots_sdk::transport::BlossomImageDimensions>(), 88 type_name::<radroots_sdk::transport::BlossomInboundReceipt>(), 89 type_name::<radroots_sdk::transport::BlossomInboundRequest>(), 90 type_name::<radroots_sdk::transport::BlossomPhase>(), 91 type_name::<radroots_sdk::transport::BlossomProfile>(), 92 type_name::<radroots_sdk::transport::BlossomSlot>(), 93 type_name::<radroots_sdk::transport::BlossomUploadReceipt>(), 94 type_name::<radroots_sdk::transport::BlossomUploadRequest>(), 95 type_name::<radroots_sdk::transport::BlossomUploadTransaction>(), 96 type_name::<radroots_sdk::transport::BlossomTransportSecurity>(), 97 ]) 98 .collect::<BTreeSet<_>>(); 99 #[cfg(feature = "radrootsd")] 100 let actual = actual 101 .into_iter() 102 .chain([ 103 type_name::<radroots_sdk::transport::DaemonAuth>(), 104 type_name::<radroots_sdk::transport::DaemonConfig>(), 105 type_name::<radroots_sdk::transport::DaemonDelivery>(), 106 type_name::<radroots_sdk::transport::DaemonError>(), 107 type_name::<radroots_sdk::transport::DaemonErrorKind>(), 108 ]) 109 .collect::<BTreeSet<_>>(); 110 111 assert!(actual.iter().all(|name| !name.contains("RadrootsSdk"))); 112 assert!(actual.iter().all(|name| { 113 name.rsplit("::") 114 .next() 115 .is_some_and(|item| !item.starts_with("Sdk")) 116 })); 117 assert_eq!(actual.len(), expected_public_type_count()); 118 } 119 120 #[test] 121 fn active_native_api_has_no_sdk_owned_traits_or_public_field_layout() { 122 for (module, source) in ACTIVE_MODULES { 123 for line in source.lines() { 124 let line = line.trim_start(); 125 assert!( 126 !line.starts_with("pub trait "), 127 "{module} must reuse lower host SPIs instead of exposing an SDK-owned trait" 128 ); 129 for declaration in ["pub struct ", "pub enum ", "pub trait ", "pub type "] { 130 if let Some(item) = line.strip_prefix(declaration) { 131 let item = item 132 .split(|character: char| { 133 character == '<' 134 || character == '(' 135 || character == '{' 136 || character == ';' 137 || character.is_whitespace() 138 }) 139 .next() 140 .expect("public item name"); 141 assert!( 142 !item.starts_with("RadrootsSdk") && !item.starts_with("Sdk"), 143 "{module} exposes representation-prefixed item {item}" 144 ); 145 } 146 } 147 148 let public_field = line.starts_with("pub ") 149 && line.contains(':') 150 && ![ 151 "pub async fn ", 152 "pub const ", 153 "pub enum ", 154 "pub fn ", 155 "pub mod ", 156 "pub static ", 157 "pub struct ", 158 "pub trait ", 159 "pub type ", 160 "pub use ", 161 ] 162 .iter() 163 .any(|prefix| line.starts_with(prefix)); 164 assert!(!public_field, "{module} exposes native field `{line}`"); 165 } 166 } 167 } 168 169 const fn expected_public_type_count() -> usize { 170 let count = 30; 171 #[cfg(feature = "sync")] 172 let count = count + 9; 173 #[cfg(feature = "nostr")] 174 let count = count + 1; 175 #[cfg(feature = "blossom")] 176 let count = count + 22; 177 #[cfg(feature = "radrootsd")] 178 let count = count + 5; 179 count 180 }