use crate::{
ConcurrentWantList, PeerManager, PeerScoringConfig, Priority, Session, SessionConfig,
WantListConfig,
};
use ipfrs_core::Cid;
use multihash::Multihash;
use std::time::Duration;
pub fn test_cid(seed: u64) -> Cid {
let data = seed.to_le_bytes();
let hash = Multihash::wrap(0x12, &data)
.expect("wrapping 8-byte seed into SHA2-256 multihash is infallible");
Cid::new_v1(0x55, hash)
}
pub fn test_cids(count: usize) -> Vec<Cid> {
(0..count).map(|i| test_cid(i as u64)).collect()
}
pub fn test_want_list() -> ConcurrentWantList {
ConcurrentWantList::new(WantListConfig::default())
}
pub fn test_want_list_with_cids(cids: &[Cid], priority: i32) -> ConcurrentWantList {
let want_list = test_want_list();
for cid in cids {
want_list.add_simple(*cid, priority);
}
want_list
}
pub fn test_peer_manager() -> PeerManager {
PeerManager::new(PeerScoringConfig::default())
}
pub fn test_peer_manager_with_config(config: PeerScoringConfig) -> PeerManager {
PeerManager::new(config)
}
pub fn test_session(session_id: u64) -> Session {
let config = SessionConfig {
timeout: Duration::from_secs(60),
default_priority: Priority::Normal,
max_concurrent_blocks: 100,
progress_notifications: false,
};
Session::new(session_id, config, None)
}
pub fn test_session_with_blocks(session_id: u64, cids: &[Cid]) -> Session {
let session = test_session(session_id);
session.add_blocks(cids, None).ok();
session
}
pub fn test_peer_ids(count: usize) -> Vec<String> {
(0..count).map(|i| format!("peer_{}", i)).collect()
}
pub fn add_test_peers(manager: &mut PeerManager, count: usize) {
for i in 0..count {
let peer_id = format!("peer_{}", i);
manager.add_peer(peer_id.clone());
manager.record_success(&peer_id, 1024, Duration::from_millis(10));
}
}
pub fn add_varied_test_peers(manager: &mut PeerManager, count: usize) {
for i in 0..count {
let peer_id = format!("peer_{}", i);
manager.add_peer(peer_id.clone());
let latency_ms = 5 + (i * 95 / count.max(1));
let bytes = (1024 + (i * 9216 / count.max(1))) as u64;
manager.record_success(&peer_id, bytes, Duration::from_millis(latency_ms as u64));
}
}
pub fn minimal_want_list_config() -> WantListConfig {
WantListConfig {
max_wants: 1,
default_timeout: Duration::from_secs(1),
max_retries: 1,
base_retry_delay: Duration::from_millis(10),
max_retry_delay: Duration::from_millis(100),
}
}
pub fn minimal_session_config() -> SessionConfig {
SessionConfig {
timeout: Duration::from_secs(1),
default_priority: Priority::Normal,
max_concurrent_blocks: 1,
progress_notifications: false,
}
}
pub fn minimal_peer_scoring_config() -> PeerScoringConfig {
PeerScoringConfig {
latency_weight: 0.33,
bandwidth_weight: 0.34,
reliability_weight: 0.33,
ewma_alpha: 0.25,
inactivity_decay: 0.02,
min_score: 0.0,
max_failures: 1,
}
}
pub fn assert_approx_eq(a: f64, b: f64, epsilon: f64) {
assert!(
(a - b).abs() <= epsilon,
"Values not approximately equal: {} vs {} (epsilon: {})",
a,
b,
epsilon
);
}
pub fn assert_in_range<T: PartialOrd + std::fmt::Debug>(value: T, min: T, max: T) {
assert!(
value >= min && value <= max,
"Value {:?} not in range [{:?}, {:?}]",
value,
min,
max
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_test_cid() {
let cid1 = test_cid(1);
let cid2 = test_cid(1);
let cid3 = test_cid(2);
assert_eq!(cid1, cid2);
assert_ne!(cid1, cid3);
}
#[test]
fn test_test_cids() {
let cids = test_cids(10);
assert_eq!(cids.len(), 10);
for i in 0..cids.len() {
for j in (i + 1)..cids.len() {
assert_ne!(cids[i], cids[j]);
}
}
}
#[test]
fn test_test_want_list() {
let want_list = test_want_list();
assert_eq!(want_list.len(), 0);
}
#[test]
fn test_test_want_list_with_cids() {
let cids = test_cids(5);
let want_list = test_want_list_with_cids(&cids, 100);
assert_eq!(want_list.len(), 5);
}
#[test]
fn test_test_peer_manager() {
let manager = test_peer_manager();
let stats = manager.stats();
assert_eq!(stats.total_peers, 0);
}
#[test]
fn test_test_session() {
let session = test_session(1);
let stats = session.stats();
assert_eq!(stats.total_blocks, 0);
}
#[test]
fn test_test_session_with_blocks() {
let cids = test_cids(5);
let session = test_session_with_blocks(1, &cids);
let stats = session.stats();
assert_eq!(stats.total_blocks, 5);
}
#[test]
fn test_test_peer_ids() {
let peer_ids = test_peer_ids(3);
assert_eq!(peer_ids.len(), 3);
assert_eq!(peer_ids[0], "peer_0");
assert_eq!(peer_ids[1], "peer_1");
assert_eq!(peer_ids[2], "peer_2");
}
#[test]
fn test_add_test_peers() {
let mut manager = test_peer_manager();
add_test_peers(&mut manager, 5);
let stats = manager.stats();
assert_eq!(stats.total_peers, 5);
}
#[test]
fn test_add_varied_test_peers() {
let mut manager = test_peer_manager();
add_varied_test_peers(&mut manager, 5);
let stats = manager.stats();
assert_eq!(stats.total_peers, 5);
}
#[test]
fn test_minimal_configs() {
use crate::{
validate_peer_scoring_config, validate_session_config, validate_want_list_config,
};
let want_list_config = minimal_want_list_config();
assert!(validate_want_list_config(&want_list_config).is_ok());
let session_config = minimal_session_config();
assert!(validate_session_config(&session_config).is_ok());
let peer_scoring_config = minimal_peer_scoring_config();
assert!(validate_peer_scoring_config(&peer_scoring_config).is_ok());
}
#[test]
fn test_assert_approx_eq() {
assert_approx_eq(1.0, 1.0, 0.01);
assert_approx_eq(1.0, 1.005, 0.01);
}
#[test]
#[should_panic(expected = "Values not approximately equal")]
fn test_assert_approx_eq_fails() {
assert_approx_eq(1.0, 1.1, 0.01);
}
#[test]
fn test_assert_in_range() {
assert_in_range(5, 0, 10);
assert_in_range(0, 0, 10);
assert_in_range(10, 0, 10);
}
#[test]
#[should_panic(expected = "Value")]
fn test_assert_in_range_fails() {
assert_in_range(11, 0, 10);
}
}