use coracle_lib::events::{EventContent, HashedEvent}; use coracle_lib::keys::SecretKey; use coracle_lib::prelude::*; use coracle_lib::protected::is_protected; use coracle_lib::tags::{Tag, Tags}; 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 build_hashed(tags: Tags) -> HashedEvent { EventContent::new() .content("hi") .tags(tags) .kind(1) .stamp(1_700_000_000) .own(fixed_secret().public_key()) .hash() } // --- Tag::protected constructor --- #[test] fn tag_constructor_shape() { let t = Tag::protected(); assert_eq!(t.name(), "-"); assert_eq!(t.len(), 1); assert!(t.values().is_empty()); } #[test] fn tag_constructor_serializes_as_single_element() { let t = Tag::protected(); assert_eq!(serde_json::to_string(&t).unwrap(), r#"["-"]"#); } // --- is_protected --- #[test] fn is_protected_false_when_tag_absent() { let tags = Tags::new(); assert!(!is_protected(&tags)); } #[test] fn is_protected_false_with_unrelated_tags() { let tags = Tags::from(vec![Tag::new("t", ["nostr"]), Tag::expiration(100)]); assert!(!is_protected(&tags)); } #[test] fn is_protected_true_when_tag_present() { let tags = Tags::from(vec![Tag::protected()]); assert!(is_protected(&tags)); } #[test] fn is_protected_true_among_other_tags() { let tags = Tags::from(vec![ Tag::new("t", ["nostr"]), Tag::protected(), Tag::expiration(100), ]); assert!(is_protected(&tags)); } #[test] fn is_protected_detects_a_raw_dash_tag() { // The marker is identified by name alone; a hand-built ["-"] is // equivalent to Tag::protected(). let tags = Tags::from(vec![Tag::new("-", Vec::::new())]); assert!(is_protected(&tags)); } // --- HashedEvent method facade --- #[test] fn hashed_event_reports_protected() { let event = build_hashed(Tags::from(vec![Tag::protected()])); assert!(event.is_protected()); } #[test] fn hashed_event_reports_unprotected() { let event = build_hashed(Tags::new()); assert!(!event.is_protected()); } // --- Event method facade --- #[test] fn signed_event_reports_protected() { let sk = fixed_secret(); let hashed = build_hashed(Tags::from(vec![Tag::protected()])); let sig = sk.sign(&hashed.id); let signed = hashed.sign(sig); assert!(signed.is_protected()); } #[test] fn protected_tag_survives_hashing_and_signing() { // The tag is part of the canonical hash input, so it must round-trip // through hash() and sign() intact and still verify. let sk = fixed_secret(); let hashed = build_hashed(Tags::from(vec![Tag::protected()])); let sig = sk.sign(&hashed.id); let signed = hashed.sign(sig); assert!(signed.verify_id()); assert!(signed.is_protected()); } #[test] fn unprotected_event_stays_unprotected_through_signing() { let sk = fixed_secret(); let hashed = build_hashed(Tags::new()); let sig = sk.sign(&hashed.id); let signed = hashed.sign(sig); assert!(!signed.is_protected()); }