package_boundary.rs (4625B)
1 use std::fs; 2 use std::path::PathBuf; 3 4 const README: &str = include_str!("../README.md"); 5 const JOURNAL: &str = include_str!("../src/journal.rs"); 6 7 #[test] 8 fn manifest_matches_the_release_v1_package_boundary() { 9 let manifest = fs::read_to_string(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml")) 10 .expect("storage package manifest must be readable"); 11 12 for required in [ 13 "radroots_event", 14 "radroots_protocol", 15 "radroots_trade", 16 "radroots_transport", 17 ] { 18 assert!( 19 manifest.contains(&format!("{required} = {{ workspace = true")), 20 "missing required Radroots dependency {required}" 21 ); 22 } 23 24 for forbidden in ["sqlx", "rusqlite", "reqwest", "nostr-sdk"] { 25 assert!( 26 !manifest.contains(forbidden), 27 "storage SPI must not depend on {forbidden}" 28 ); 29 } 30 31 for feature in [ 32 "default = [\"memory\", \"serde\"]", 33 "memory = []", 34 "serde = [", 35 ] { 36 assert!(manifest.contains(feature), "missing feature law: {feature}"); 37 } 38 for forbidden_feature in ["sqlite =", "tokio =", "nostr =", "runtime ="] { 39 assert!( 40 !manifest.contains(forbidden_feature), 41 "storage SPI declares forbidden feature {forbidden_feature}" 42 ); 43 } 44 } 45 46 #[test] 47 fn release_v1_public_module_skeleton_is_declared() { 48 let root = include_str!("../src/lib.rs"); 49 for module in [ 50 "atomic", 51 "backup", 52 "event", 53 "journal", 54 "memory", 55 "outbox", 56 "private_artifact", 57 "projection", 58 "status", 59 ] { 60 assert!( 61 root.contains(&format!("pub mod {module};")), 62 "missing public module {module}" 63 ); 64 } 65 } 66 67 #[test] 68 fn root_exports_are_exact_and_implementation_types_do_not_leak() { 69 let root = include_str!("../src/lib.rs"); 70 for required in [ 71 "pub trait Storage:", 72 "pub use backup::StorageReliability as BackupSource;", 73 "pub use error::Error;", 74 "pub use event::EventStore;", 75 "pub use journal::Journal;", 76 "pub use outbox::Outbox;", 77 "pub use projection::ProjectionStore;", 78 "pub use status::StorageStatus;", 79 ] { 80 assert!(root.contains(required), "missing root contract: {required}"); 81 } 82 for forbidden in [ 83 "pub use atomic::AtomicStorage", 84 "pub use backup::StorageReliability;", 85 "pub use private_artifact::PrivateArtifactStore", 86 ] { 87 assert!( 88 !root.contains(forbidden), 89 "forbidden root export: {forbidden}" 90 ); 91 } 92 93 let source_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src"); 94 let mut source = String::new(); 95 for entry in fs::read_dir(source_root).expect("source directory") { 96 let path = entry.expect("source entry").path(); 97 if path.extension().and_then(|value| value.to_str()) == Some("rs") { 98 source.push_str(&fs::read_to_string(path).expect("source file")); 99 } 100 } 101 for forbidden in [ 102 "sqlx::", 103 "rusqlite::", 104 "nostr_sdk::", 105 "std::path::Path", 106 "tokio::runtime", 107 ] { 108 assert!( 109 !source.contains(forbidden), 110 "public storage source leaks implementation path {forbidden}" 111 ); 112 } 113 } 114 115 #[test] 116 fn idempotency_keys_validate_borrowed_input_before_bounded_allocation() { 117 for required in [ 118 "Idempotency-key construction validates borrowed input before allocating its\nbounded owned representation", 119 "rejected oversized input cannot force a\nsecond attacker-sized allocation", 120 ] { 121 assert!(README.contains(required), "README is missing `{required}`"); 122 } 123 let parser = JOURNAL 124 .split_once("pub fn parse(value: impl AsRef<str>)") 125 .expect("borrowed idempotency parser") 126 .1 127 .split_once("pub fn as_str") 128 .expect("idempotency accessor") 129 .0; 130 assert!(parser.contains("let value = value.as_ref();")); 131 assert_eq!(parser.matches("to_owned()").count(), 1); 132 let validation = parser 133 .find("value.len() > IDEMPOTENCY_KEY_MAX_BYTES") 134 .expect("pre-allocation byte bound"); 135 let allocation = parser 136 .find("Self(value.to_owned())") 137 .expect("bounded owned representation"); 138 assert!(validation < allocation); 139 for forbidden in ["impl Into<String>", "let value = value.into()"] { 140 assert!( 141 !parser.contains(forbidden), 142 "idempotency parser contains pre-validation allocation `{forbidden}`" 143 ); 144 } 145 }