#[tokio::test]
async fn test_open_discovery_sweep_queues_eligible_skips_filtered() {
use crate::config::NostrDiscoveryPolicy;
use crate::discovery::nostr::{NostrDiscovery, OverlayEndpointAdvert, OverlayTransportKind};
use crate::peer::ActivePeer;
use crate::transport::LinkId;
use std::sync::Arc;
let mut config = crate::Config::new();
config.node.discovery.nostr.enabled = true;
config.node.discovery.nostr.policy = NostrDiscoveryPolicy::Open;
let mut node = crate::Node::new(config).unwrap();
let connected_identity = crate::Identity::generate();
let connected_npub = crate::encode_npub(&connected_identity.pubkey());
let connected_node_addr = *connected_identity.node_addr();
let connected_peer_identity = crate::PeerIdentity::from_pubkey(connected_identity.pubkey());
node.peers.insert(
connected_node_addr,
ActivePeer::new(connected_peer_identity, LinkId::new(1), 1_000),
);
let eligible_identity = crate::Identity::generate();
let eligible_npub = crate::encode_npub(&eligible_identity.pubkey());
let eligible_node_addr = *eligible_identity.node_addr();
let self_npub = crate::encode_npub(&node.identity().pubkey());
let self_node_addr = *node.identity().node_addr();
let bootstrap = Arc::new(NostrDiscovery::new_for_test());
let endpoint = OverlayEndpointAdvert {
transport: OverlayTransportKind::Udp,
addr: "203.0.113.7:2121".to_string(),
};
let now_secs = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
for npub in [&eligible_npub, &connected_npub, &self_npub] {
let advert =
NostrDiscovery::cached_advert_for_test(npub.clone(), endpoint.clone(), now_secs);
bootstrap.insert_advert_for_test(npub.clone(), advert).await;
}
node.run_open_discovery_sweep(&bootstrap, Some(3_600), "test")
.await;
assert!(
node.retry_pending.contains_key(&eligible_node_addr),
"eligible advert should be queued for retry"
);
let queued = node.retry_pending.get(&eligible_node_addr).unwrap();
assert_eq!(queued.peer_config.npub, eligible_npub);
assert!(
!node.retry_pending.contains_key(&connected_node_addr),
"advert for already-connected peer must not be queued"
);
assert!(
!node.retry_pending.contains_key(&self_node_addr),
"advert authored by own node must not be queued"
);
assert_eq!(node.retry_pending.len(), 1);
}
#[tokio::test]
async fn test_open_discovery_sweep_expedites_configured_peer_retry() {
use crate::config::{ConnectPolicy, NostrDiscoveryPolicy, PeerAddress, PeerConfig};
use crate::discovery::nostr::{NostrDiscovery, OverlayEndpointAdvert, OverlayTransportKind};
use std::sync::Arc;
let configured_identity = crate::Identity::generate();
let configured_npub = crate::encode_npub(&configured_identity.pubkey());
let configured_node_addr = *configured_identity.node_addr();
let mut config = crate::Config::new();
config.node.discovery.nostr.enabled = true;
config.node.discovery.nostr.policy = NostrDiscoveryPolicy::Open;
config.peers.push(PeerConfig {
npub: configured_npub.clone(),
alias: Some("test-peer".to_string()),
addresses: vec![PeerAddress::new("udp", "203.0.113.99:51820")],
connect_policy: ConnectPolicy::AutoConnect,
auto_reconnect: true,
discovery_fallback_transit: true,
});
let mut node = crate::Node::new(config).unwrap();
let pc = node
.config
.peers()
.iter()
.find(|pc| pc.npub == configured_npub)
.cloned()
.unwrap();
let now_ms = crate::Node::now_ms();
let scheduled_at_ms = now_ms + 60_000;
let mut state = crate::node::retry::RetryState::new(pc);
state.retry_count = 3;
state.retry_after_ms = scheduled_at_ms;
node.retry_pending.insert(configured_node_addr, state);
let bootstrap = Arc::new(NostrDiscovery::new_for_test());
let endpoint = OverlayEndpointAdvert {
transport: OverlayTransportKind::Udp,
addr: "203.0.113.7:2121".to_string(),
};
let now_secs = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
let advert =
NostrDiscovery::cached_advert_for_test(configured_npub.clone(), endpoint, now_secs);
bootstrap
.insert_advert_for_test(configured_npub.clone(), advert)
.await;
node.run_open_discovery_sweep(&bootstrap, Some(3_600), "test")
.await;
let state = node
.retry_pending
.get(&configured_node_addr)
.expect("retry entry must still exist; sweep should expedite, not remove");
assert!(
state.retry_after_ms <= crate::Node::now_ms(),
"expected retry_after_ms ≤ now (expedited); got {} (now ≈ {})",
state.retry_after_ms,
crate::Node::now_ms()
);
assert!(
state.retry_after_ms < scheduled_at_ms,
"expected retry_after_ms < original scheduled_at_ms; got {} >= {}",
state.retry_after_ms,
scheduled_at_ms
);
assert_eq!(state.peer_config.npub, configured_npub);
assert_eq!(state.peer_config.alias.as_deref(), Some("test-peer"));
}