diff --git a/zebra-network/src/peer_set/candidate_set.rs b/zebra-network/src/peer_set/candidate_set.rs index afe52546..ae0d0328 100644 --- a/zebra-network/src/peer_set/candidate_set.rs +++ b/zebra-network/src/peer_set/candidate_set.rs @@ -8,6 +8,9 @@ use zebra_chain::serialization::DateTime32; use crate::{constants, types::MetaAddr, AddressBook, BoxError, Request, Response}; +#[cfg(test)] +mod tests; + /// The `CandidateSet` manages the `PeerSet`'s peer reconnection attempts. /// /// It divides the set of all possible candidate peers into disjoint subsets, diff --git a/zebra-network/src/peer_set/candidate_set/tests.rs b/zebra-network/src/peer_set/candidate_set/tests.rs new file mode 100644 index 00000000..b834868f --- /dev/null +++ b/zebra-network/src/peer_set/candidate_set/tests.rs @@ -0,0 +1,3 @@ +//! [`CandidateSet`] tests. + +mod vectors; diff --git a/zebra-network/src/peer_set/candidate_set/tests/vectors.rs b/zebra-network/src/peer_set/candidate_set/tests/vectors.rs new file mode 100644 index 00000000..53828f3e --- /dev/null +++ b/zebra-network/src/peer_set/candidate_set/tests/vectors.rs @@ -0,0 +1,56 @@ +use std::{ + convert::TryInto, + net::{IpAddr, SocketAddr}, +}; + +use chrono::{DateTime, Duration, Utc}; + +use zebra_chain::serialization::DateTime32; + +use super::super::validate_addrs; +use crate::types::{MetaAddr, PeerServices}; + +/// Test that offset is applied when all addresses have `last_seen` times in the future. +#[test] +fn offsets_last_seen_times_in_the_future() { + let last_seen_limit = DateTime32::now(); + let last_seen_limit_chrono = last_seen_limit.to_chrono(); + + let input_peers = mock_gossiped_peers(vec![ + last_seen_limit_chrono + Duration::minutes(30), + last_seen_limit_chrono + Duration::minutes(15), + last_seen_limit_chrono + Duration::minutes(45), + ]); + + let validated_peers: Vec<_> = validate_addrs(input_peers, last_seen_limit).collect(); + + let expected_offset = Duration::minutes(45); + let expected_peers = mock_gossiped_peers(vec![ + last_seen_limit_chrono + Duration::minutes(30) - expected_offset, + last_seen_limit_chrono + Duration::minutes(15) - expected_offset, + last_seen_limit_chrono + Duration::minutes(45) - expected_offset, + ]); + + assert_eq!(validated_peers, expected_peers); +} + +/// Create a mock list of gossiped [`MetaAddr`]s with the specified `last_seen_times`. +/// +/// The IP address and port of the generated ports should not matter for the test. +fn mock_gossiped_peers(last_seen_times: impl IntoIterator>) -> Vec { + last_seen_times + .into_iter() + .enumerate() + .map(|(index, last_seen_chrono)| { + let last_seen = last_seen_chrono + .try_into() + .expect("`last_seen` time doesn't fit in a `DateTime32`"); + + MetaAddr::new_gossiped_meta_addr( + SocketAddr::new(IpAddr::from([192, 168, 1, index as u8]), 20_000), + PeerServices::NODE_NETWORK, + last_seen, + ) + }) + .collect() +}