#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use std::net::{Ipv4Addr, SocketAddrV4};
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Duration;
use decdn_node::dht::bucket_refresh::run_bucket_refresh;
use decdn_node::dht::routing::{NodeId, RoutingTable};
use iroh::{Endpoint, RelayMode, SecretKey, endpoint::presets};
use tokio::sync::oneshot;
const Y2020_US: u64 = 1_577_836_800_000_000;
const Y2100_US: u64 = 4_102_444_800_000_000;
async fn local_endpoint(secret_key: SecretKey) -> Endpoint {
let bind = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0);
Endpoint::builder(presets::Minimal)
.secret_key(secret_key)
.relay_mode(RelayMode::Disabled)
.bind_addr(bind)
.expect("bind_addr")
.bind()
.await
.expect("bind")
}
#[tokio::test]
async fn bucket_refresh_stamps_clock_after_first_pass() {
let secret_key = SecretKey::generate();
let public = secret_key.public();
let endpoint = local_endpoint(secret_key).await;
let routing = Arc::new(Mutex::new(RoutingTable::new(NodeId::from_bytes(
*public.as_bytes(),
))));
let clock = Arc::new(AtomicU64::new(0));
let (stop_tx, stop_rx) = oneshot::channel::<()>();
assert_eq!(clock.load(Ordering::Relaxed), 0);
let join = tokio::spawn(run_bucket_refresh(
endpoint,
public,
Arc::clone(&routing),
stop_rx,
Duration::from_millis(50),
Arc::clone(&clock),
Arc::new(decdn_node::metrics::Metrics::new()),
));
let mut stamped = 0;
for _ in 0..100 {
stamped = clock.load(Ordering::Relaxed);
if stamped != 0 {
break;
}
tokio::time::sleep(Duration::from_millis(20)).await;
}
assert!(
stamped != 0,
"refresh clock was never stamped after a pass (still 0)"
);
assert!(
(Y2020_US..Y2100_US).contains(&stamped),
"stamp {stamped} is not a plausible wall-clock microsecond value"
);
let _ = stop_tx.send(());
join.await.expect("refresh task joins cleanly");
}