mod.rs (5372B)
1 pub mod decode; 2 pub mod encode; 3 4 #[cfg(test)] 5 mod tests { 6 use radroots_events::{kinds::KIND_POST, relay_auth::RadrootsRelayAuth}; 7 8 use crate::error::{EventEncodeError, EventParseError}; 9 use crate::relay_auth::decode::{data_from_event, parsed_from_event, relay_auth_from_event}; 10 use crate::relay_auth::encode::{ 11 relay_auth_build_tags, to_wire_parts, to_wire_parts_with_kind, 12 }; 13 14 #[test] 15 fn relay_auth_encodes_and_decodes_nip42_event() { 16 let auth = sample_auth(); 17 let parts = to_wire_parts(&auth).expect("relay auth wire parts"); 18 19 assert_eq!(parts.kind, 22242); 20 assert_eq!(parts.content, ""); 21 assert!(parts.tags.contains(&tag("relay", auth.relay.as_str()))); 22 assert!( 23 parts 24 .tags 25 .contains(&tag("challenge", auth.challenge.as_str())) 26 ); 27 28 let decoded = 29 relay_auth_from_event(parts.kind, &parts.tags, &parts.content).expect("decode"); 30 assert_eq!(decoded, auth); 31 } 32 33 #[test] 34 fn relay_auth_rejects_missing_challenge_non_empty_content_and_wrong_kind() { 35 let parts = to_wire_parts(&sample_auth()).expect("relay auth wire parts"); 36 let without_relay = parts 37 .tags 38 .iter() 39 .filter(|tag| tag.first().map(|value| value.as_str()) != Some("relay")) 40 .cloned() 41 .collect::<Vec<_>>(); 42 let missing_relay = 43 relay_auth_from_event(parts.kind, &without_relay, &parts.content).unwrap_err(); 44 assert!(matches!( 45 missing_relay, 46 EventParseError::MissingTag("relay") 47 )); 48 49 let without_challenge = parts 50 .tags 51 .iter() 52 .filter(|tag| tag.first().map(|value| value.as_str()) != Some("challenge")) 53 .cloned() 54 .collect::<Vec<_>>(); 55 let missing = 56 relay_auth_from_event(parts.kind, &without_challenge, &parts.content).unwrap_err(); 57 assert!(matches!(missing, EventParseError::MissingTag("challenge"))); 58 59 let content_err = relay_auth_from_event(parts.kind, &parts.tags, "not empty").unwrap_err(); 60 assert!(matches!( 61 content_err, 62 EventParseError::InvalidJson("content") 63 )); 64 65 let wrong_kind = to_wire_parts_with_kind(&sample_auth(), KIND_POST).unwrap_err(); 66 assert!(matches!( 67 wrong_kind, 68 EventEncodeError::InvalidKind(KIND_POST) 69 )); 70 71 let decode_wrong_kind = relay_auth_from_event(KIND_POST, &parts.tags, "").unwrap_err(); 72 assert!(matches!( 73 decode_wrong_kind, 74 EventParseError::InvalidKind { 75 expected: "22242", 76 got: KIND_POST 77 } 78 )); 79 } 80 81 #[test] 82 fn relay_auth_rejects_empty_required_fields() { 83 let mut auth = sample_auth(); 84 auth.relay.clear(); 85 let relay_err = relay_auth_build_tags(&auth).unwrap_err(); 86 assert!(matches!( 87 relay_err, 88 EventEncodeError::EmptyRequiredField("relay") 89 )); 90 91 let mut auth = sample_auth(); 92 auth.challenge.clear(); 93 let challenge_err = relay_auth_build_tags(&auth).unwrap_err(); 94 assert!(matches!( 95 challenge_err, 96 EventEncodeError::EmptyRequiredField("challenge") 97 )); 98 99 let parts = to_wire_parts(&sample_auth()).expect("relay auth wire parts"); 100 let mut empty_relay = parts.tags.clone(); 101 replace_tag_value(&mut empty_relay, "relay", " "); 102 let relay_tag_err = relay_auth_from_event(parts.kind, &empty_relay, "").unwrap_err(); 103 assert!(matches!( 104 relay_tag_err, 105 EventParseError::InvalidTag("relay") 106 )); 107 } 108 109 #[test] 110 fn relay_auth_wrappers_preserve_event_metadata() { 111 let auth = sample_auth(); 112 let parts = to_wire_parts(&auth).expect("relay auth wire parts"); 113 114 let data = data_from_event( 115 "event-id".to_string(), 116 "author-pubkey".to_string(), 117 99, 118 parts.kind, 119 parts.content.clone(), 120 parts.tags.clone(), 121 ) 122 .expect("parsed data"); 123 assert_eq!(data.id, "event-id"); 124 assert_eq!(data.author, "author-pubkey"); 125 assert_eq!(data.published_at, 99); 126 assert_eq!(data.data, auth); 127 128 let parsed = parsed_from_event( 129 "event-id".to_string(), 130 "author-pubkey".to_string(), 131 99, 132 parts.kind, 133 parts.content, 134 parts.tags, 135 "sig".to_string(), 136 ) 137 .expect("parsed event"); 138 assert_eq!(parsed.event.sig, "sig"); 139 assert_eq!(parsed.data.data, auth); 140 } 141 142 fn sample_auth() -> RadrootsRelayAuth { 143 RadrootsRelayAuth { 144 relay: "wss://relay.example.invalid/farm/field-group".to_string(), 145 challenge: "relay-provided-challenge".to_string(), 146 } 147 } 148 149 fn tag(key: &str, value: &str) -> Vec<String> { 150 vec![key.to_string(), value.to_string()] 151 } 152 153 fn replace_tag_value(tags: &mut [Vec<String>], key: &str, value: &str) { 154 let tag = tags 155 .iter_mut() 156 .find(|tag| tag.first().map(String::as_str) == Some(key)) 157 .expect("tag"); 158 tag[1] = value.to_string(); 159 } 160 }