207 lines
5.8 KiB
Rust
207 lines
5.8 KiB
Rust
use coracle_lib::addresses::{Address, AddressError};
|
|
use coracle_lib::events::EventContent;
|
|
use coracle_lib::keys::SecretKey;
|
|
use coracle_lib::tags::Tag;
|
|
|
|
|
|
fn fixed_secret() -> SecretKey {
|
|
let bytes: [u8; 32] = [
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
|
25, 26, 27, 28, 29, 30, 31, 32,
|
|
];
|
|
SecretKey::from_hex(&hex::encode(bytes)).unwrap()
|
|
}
|
|
|
|
fn make_signed_event(kind: u16, tags: Vec<Tag>) -> coracle_lib::events::Event {
|
|
let sk = fixed_secret();
|
|
let pk = sk.public_key();
|
|
let hashed = EventContent::new("test", tags)
|
|
.kind(kind)
|
|
.stamp(1_700_000_000)
|
|
.own(pk)
|
|
.hash();
|
|
let sig = sk.sign(&hashed.id);
|
|
hashed.sign(sig)
|
|
}
|
|
|
|
// --- Construction ---
|
|
|
|
#[test]
|
|
fn new_basic() {
|
|
let pk = fixed_secret().public_key();
|
|
let addr = Address::new(30023, pk, "my-article");
|
|
assert_eq!(addr.kind, 30023);
|
|
assert_eq!(addr.pubkey, pk);
|
|
assert_eq!(addr.identifier, "my-article");
|
|
assert!(addr.hints.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn hints_builder() {
|
|
let pk = fixed_secret().public_key();
|
|
let addr = Address::new(30023, pk, "my-article")
|
|
.hints(["wss://relay.example.com", "wss://other.relay"]);
|
|
assert_eq!(addr.hints.len(), 2);
|
|
assert_eq!(addr.hints[0], "wss://relay.example.com");
|
|
}
|
|
|
|
#[test]
|
|
fn equality_ignores_hints() {
|
|
let pk = fixed_secret().public_key();
|
|
let a = Address::new(30023, pk, "slug");
|
|
let b = Address::new(30023, pk, "slug").hints(["wss://relay.example.com"]);
|
|
assert_eq!(a, b);
|
|
}
|
|
|
|
// --- from_event ---
|
|
|
|
#[test]
|
|
fn from_event_addressable() {
|
|
let event = make_signed_event(30023, vec![Tag::new("d", ["my-article"])]);
|
|
let addr = Address::from_event(&event).unwrap();
|
|
assert_eq!(addr.kind, 30023);
|
|
assert_eq!(addr.identifier, "my-article");
|
|
assert_eq!(addr.pubkey, event.pubkey);
|
|
assert!(addr.hints.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn from_event_replaceable_kind_0() {
|
|
let event = make_signed_event(0, vec![]);
|
|
let addr = Address::from_event(&event).unwrap();
|
|
assert_eq!(addr.kind, 0);
|
|
assert_eq!(addr.identifier, "");
|
|
}
|
|
|
|
#[test]
|
|
fn from_event_replaceable_kind_3() {
|
|
let event = make_signed_event(3, vec![]);
|
|
let addr = Address::from_event(&event).unwrap();
|
|
assert_eq!(addr.kind, 3);
|
|
assert_eq!(addr.identifier, "");
|
|
}
|
|
|
|
#[test]
|
|
fn from_event_replaceable_range() {
|
|
let event = make_signed_event(10002, vec![]);
|
|
let addr = Address::from_event(&event).unwrap();
|
|
assert_eq!(addr.kind, 10002);
|
|
assert_eq!(addr.identifier, "");
|
|
}
|
|
|
|
#[test]
|
|
fn from_event_replaceable_ignores_d_tag() {
|
|
let event = make_signed_event(0, vec![Tag::new("d", ["should-be-ignored"])]);
|
|
let addr = Address::from_event(&event).unwrap();
|
|
assert_eq!(addr.kind, 0);
|
|
assert_eq!(addr.identifier, "");
|
|
}
|
|
|
|
#[test]
|
|
fn from_event_regular_returns_none() {
|
|
let event = make_signed_event(1, vec![]);
|
|
assert!(Address::from_event(&event).is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn from_event_ephemeral_returns_none() {
|
|
let event = make_signed_event(20000, vec![]);
|
|
assert!(Address::from_event(&event).is_none());
|
|
}
|
|
|
|
// --- Display / FromStr ---
|
|
|
|
#[test]
|
|
fn display_roundtrip() {
|
|
let pk = fixed_secret().public_key();
|
|
let addr = Address::new(30023, pk, "my-article");
|
|
let s = addr.to_string();
|
|
assert!(s.starts_with("30023:"));
|
|
assert!(s.ends_with(":my-article"));
|
|
let parsed: Address = s.parse().unwrap();
|
|
assert_eq!(parsed, addr);
|
|
}
|
|
|
|
#[test]
|
|
fn fromstr_empty_identifier() {
|
|
let pk = fixed_secret().public_key();
|
|
let addr = Address::new(0, pk, "");
|
|
let s = addr.to_string();
|
|
let parsed: Address = s.parse().unwrap();
|
|
assert_eq!(parsed.identifier, "");
|
|
assert_eq!(parsed, addr);
|
|
}
|
|
|
|
#[test]
|
|
fn fromstr_identifier_with_colons() {
|
|
let pk = fixed_secret().public_key();
|
|
let addr = Address::new(30023, pk, "has:colons:inside");
|
|
let s = addr.to_string();
|
|
let parsed: Address = s.parse().unwrap();
|
|
assert_eq!(parsed.identifier, "has:colons:inside");
|
|
assert_eq!(parsed, addr);
|
|
}
|
|
|
|
#[test]
|
|
fn fromstr_invalid() {
|
|
assert!("not-an-address".parse::<Address>().is_err());
|
|
assert!("123".parse::<Address>().is_err());
|
|
assert!("abc:def:ghi".parse::<Address>().is_err());
|
|
}
|
|
|
|
// --- naddr encoding ---
|
|
|
|
#[test]
|
|
fn naddr_roundtrip_no_relays() {
|
|
let pk = fixed_secret().public_key();
|
|
let addr = Address::new(30023, pk, "my-article");
|
|
let naddr = addr.to_naddr();
|
|
assert!(naddr.starts_with("naddr1"));
|
|
let decoded = Address::from_naddr(&naddr).unwrap();
|
|
assert_eq!(decoded, addr);
|
|
assert!(decoded.hints.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn naddr_roundtrip_with_relays() {
|
|
let pk = fixed_secret().public_key();
|
|
let addr = Address::new(30023, pk, "my-article")
|
|
.hints(["wss://relay.example.com", "wss://other.relay"]);
|
|
let naddr = addr.to_naddr();
|
|
let decoded = Address::from_naddr(&naddr).unwrap();
|
|
assert_eq!(decoded, addr);
|
|
assert_eq!(
|
|
decoded.hints,
|
|
vec!["wss://relay.example.com", "wss://other.relay"]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn naddr_roundtrip_empty_identifier() {
|
|
let pk = fixed_secret().public_key();
|
|
let addr = Address::new(10002, pk, "");
|
|
let naddr = addr.to_naddr();
|
|
let decoded = Address::from_naddr(&naddr).unwrap();
|
|
assert_eq!(decoded, addr);
|
|
}
|
|
|
|
#[test]
|
|
fn fromstr_accepts_naddr() {
|
|
let pk = fixed_secret().public_key();
|
|
let addr = Address::new(30023, pk, "my-article")
|
|
.hints(["wss://relay.example.com"]);
|
|
let naddr = addr.to_naddr();
|
|
let parsed: Address = naddr.parse().unwrap();
|
|
assert_eq!(parsed, addr);
|
|
assert_eq!(parsed.hints, vec!["wss://relay.example.com"]);
|
|
}
|
|
|
|
#[test]
|
|
fn from_naddr_wrong_prefix() {
|
|
let pk = fixed_secret().public_key();
|
|
let npub = pk.to_npub();
|
|
let err = Address::from_naddr(&npub).unwrap_err();
|
|
assert!(matches!(err, AddressError::WrongPrefix { .. }));
|
|
}
|
|
|