capability_status.rs (4968B)
1 use radroots_transport::{ 2 SinkStatus, SourceStatus, TransportId, 3 capability::{Availability, Maturity, SinkCapabilities, SourceCapabilities}, 4 }; 5 6 #[test] 7 fn maturity_and_availability_round_trip_through_protocol_dtos() { 8 for maturity in [Maturity::Experimental, Maturity::Preview, Maturity::Stable] { 9 let protocol = radroots_protocol::capability::v1::Maturity::from(maturity); 10 assert_eq!(Maturity::from(protocol), maturity); 11 } 12 13 for availability in [ 14 Availability::Available, 15 Availability::Degraded, 16 Availability::Unavailable, 17 ] { 18 let protocol = radroots_protocol::capability::v1::Availability::from(availability); 19 assert_eq!(Availability::from(protocol), availability); 20 } 21 } 22 23 #[test] 24 fn runtime_state_dimensions_are_independent() { 25 let transport_id = TransportId::parse("future-mesh").expect("custom transport"); 26 let states = [ 27 (false, Maturity::Experimental, Availability::Available), 28 (true, Maturity::Preview, Availability::Degraded), 29 (true, Maturity::Stable, Availability::Unavailable), 30 ]; 31 32 for (configured, maturity, availability) in states { 33 let status = SourceStatus::new( 34 transport_id, 35 configured, 36 maturity, 37 availability, 38 SourceCapabilities::NONE, 39 "explicit state", 40 ); 41 assert_eq!(status.transport_id(), transport_id); 42 assert_eq!(status.is_configured(), configured); 43 assert_eq!(status.maturity(), maturity); 44 assert_eq!(status.availability(), availability); 45 assert_eq!(status.message(), "explicit state"); 46 } 47 } 48 49 #[test] 50 fn source_and_sink_capabilities_are_separate_contracts() { 51 let source = SourceStatus::new( 52 TransportId::NOSTR, 53 true, 54 Maturity::Stable, 55 Availability::Available, 56 SourceCapabilities::FETCH.with_discovery(true), 57 "source", 58 ); 59 assert!(source.capabilities().can_fetch()); 60 assert!(source.capabilities().can_discover()); 61 assert_eq!(source.transport_id(), TransportId::NOSTR); 62 63 let sink = SinkStatus::new( 64 TransportId::NOSTR, 65 true, 66 Maturity::Stable, 67 Availability::Available, 68 SinkCapabilities::DELIVER 69 .with_gateway_forwarding(true) 70 .with_receipt_observation(true), 71 "sink", 72 ); 73 assert!(sink.capabilities().can_deliver()); 74 assert!(sink.capabilities().can_gateway_forward()); 75 assert!(sink.capabilities().can_observe_receipts()); 76 assert_eq!(sink.transport_id(), TransportId::NOSTR); 77 } 78 79 #[test] 80 fn protocol_descriptors_preserve_unknown_transports_and_split_capabilities() { 81 use radroots_protocol::capability::v1::{ 82 Availability as ProtocolAvailability, Maturity as ProtocolMaturity, TransportDescriptor, 83 TransportKind, 84 }; 85 86 let descriptor = TransportDescriptor { 87 kind: TransportKind::parse("future-mesh").expect("custom protocol transport"), 88 maturity: ProtocolMaturity::Experimental, 89 availability: ProtocolAvailability::Degraded, 90 can_deliver: true, 91 can_fetch: false, 92 can_discover: true, 93 can_gateway_forward: true, 94 can_observe_receipts: false, 95 required_for_v1: false, 96 }; 97 98 let source = SourceStatus::from_descriptor(&descriptor, false, "source not configured"); 99 assert_eq!(source.transport_id().as_str(), "future-mesh"); 100 assert!(!source.is_configured()); 101 assert_eq!(source.maturity(), Maturity::Experimental); 102 assert_eq!(source.availability(), Availability::Degraded); 103 assert!(!source.capabilities().can_fetch()); 104 assert!(source.capabilities().can_discover()); 105 106 let sink = SinkStatus::from_descriptor(&descriptor, true, "sink configured"); 107 assert_eq!(sink.transport_id().as_str(), "future-mesh"); 108 assert!(sink.is_configured()); 109 assert!(sink.capabilities().can_deliver()); 110 assert!(sink.capabilities().can_gateway_forward()); 111 assert!(!sink.capabilities().can_observe_receipts()); 112 } 113 114 #[cfg(feature = "serde")] 115 #[test] 116 fn experimental_maturity_has_a_stable_wire_spelling() { 117 assert_eq!( 118 serde_json::to_string(&Maturity::Experimental).expect("serialize maturity"), 119 "\"experimental\"" 120 ); 121 assert_eq!( 122 serde_json::from_str::<Maturity>("\"experimental\"").expect("deserialize maturity"), 123 Maturity::Experimental 124 ); 125 126 let status = SourceStatus::new( 127 TransportId::parse("future-mesh").expect("custom transport"), 128 true, 129 Maturity::Experimental, 130 Availability::Degraded, 131 SourceCapabilities::FETCH, 132 "degraded source", 133 ); 134 let encoded = serde_json::to_string(&status).expect("serialize source status"); 135 assert!(encoded.contains("\"transport_id\":\"future-mesh\"")); 136 assert_eq!( 137 serde_json::from_str::<SourceStatus>(&encoded).expect("deserialize source status"), 138 status 139 ); 140 }