lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

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 }