notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit bbcafbf2e8fe58136c01d03b1d20def9dc322b34
parent 7f0263741331edcbb6642b6774e15bd890866ce7
Author: kernelkind <kernelkind@gmail.com>
Date:   Mon,  2 Feb 2026 12:31:13 -0500

test(outbox): `RelayCoordinator`

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Mcrates/enostr/src/relay/coordinator.rs | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 141 insertions(+), 0 deletions(-)

diff --git a/crates/enostr/src/relay/coordinator.rs b/crates/enostr/src/relay/coordinator.rs @@ -422,3 +422,144 @@ impl CoordinationSession { self.tasks.insert(id, CoordinationTask::Unsubscribe); } } + +#[cfg(test)] +mod tests { + use super::*; + + /// Returns the task held for `id`, panicking when no matching task exists. + #[track_caller] + fn expect_task<'a>(session: &'a CoordinationSession, id: OutboxSubId) -> &'a CoordinationTask { + session + .tasks + .get(&id) + .unwrap_or_else(|| panic!("Expected task for {:?}", id)) + } + + // ==================== CoordinationSession tests ==================== + + /// Newly created coordination sessions hold no tasks. + #[test] + fn coordination_session_default_empty() { + let session = CoordinationSession::default(); + assert!(session.tasks.is_empty()); + } + + /// Transparent subscriptions should be recorded as TransparentSub tasks. + #[test] + fn coordination_session_subscribe_transparent() { + let mut session = CoordinationSession::default(); + + session.subscribe(OutboxSubId(0), true); // use_transparent = true + + assert!(matches!( + expect_task(&session, OutboxSubId(0)), + CoordinationTask::TransparentSub + )); + } + + /// Compaction mode subscriptions should be recorded as CompactionSub tasks. + #[test] + fn coordination_session_subscribe_compaction() { + let mut session = CoordinationSession::default(); + + session.subscribe(OutboxSubId(0), false); // use_transparent = false means compaction + + assert!(matches!( + expect_task(&session, OutboxSubId(0)), + CoordinationTask::CompactionSub + )); + } + + /// Unsubscribe should record an Unsubscribe task. + #[test] + fn coordination_session_unsubscribe() { + let mut session = CoordinationSession::default(); + + session.unsubscribe(OutboxSubId(42)); + + assert!(matches!( + expect_task(&session, OutboxSubId(42)), + CoordinationTask::Unsubscribe + )); + } + + /// Subsequent subscribe calls should overwrite previous modes. + #[test] + fn coordination_session_subscribe_overwrites_previous() { + let mut session = CoordinationSession::default(); + + // First subscribe as transparent + session.subscribe(OutboxSubId(0), true); + + assert!(matches!( + expect_task(&session, OutboxSubId(0)), + CoordinationTask::TransparentSub + )); + + // Then as compaction + session.subscribe(OutboxSubId(0), false); + + // Should be compaction now + assert!(matches!( + expect_task(&session, OutboxSubId(0)), + CoordinationTask::CompactionSub + )); + } + + /// Unsubscribe should override any prior subscribe entries. + #[test] + fn coordination_session_unsubscribe_overwrites_subscribe() { + let mut session = CoordinationSession::default(); + + session.subscribe(OutboxSubId(0), true); + assert!(matches!( + expect_task(&session, OutboxSubId(0)), + CoordinationTask::TransparentSub + )); + session.unsubscribe(OutboxSubId(0)); + + assert!(matches!( + expect_task(&session, OutboxSubId(0)), + CoordinationTask::Unsubscribe + )); + } + + /// Multiple tasks can be recorded in a single session. + #[test] + fn coordination_session_multiple_tasks() { + let mut session = CoordinationSession::default(); + + session.subscribe(OutboxSubId(0), true); + session.subscribe(OutboxSubId(1), false); + session.unsubscribe(OutboxSubId(2)); + + assert_eq!(session.tasks.len(), 3); + } + + // ==================== EoseIds tests ==================== + + #[test] + fn eose_ids_default_empty() { + let eose_ids = EoseIds::default(); + assert!(eose_ids.oneshots.is_empty()); + assert!(eose_ids.normal.is_empty()); + } + + /// absorb merges oneshot and normal ID sets into the target accumulator. + #[test] + fn eose_ids_absorb_merges_both_sets() { + let mut acc = EoseIds::default(); + let mut incoming = EoseIds::default(); + + acc.oneshots.insert(OutboxSubId(1)); + incoming.oneshots.insert(OutboxSubId(2)); + incoming.normal.insert(OutboxSubId(3)); + + acc.absorb(incoming); + + assert!(acc.oneshots.contains(&OutboxSubId(1))); + assert!(acc.oneshots.contains(&OutboxSubId(2))); + assert!(acc.normal.contains(&OutboxSubId(3))); + } +}