use anyhow::Result;
use mainline::{Dht, Testnet, async_dht::AsyncDht};
use tokio::time::{Duration, sleep};
async fn immutable_roundtrip_test(
writer: AsyncDht,
reader: AsyncDht,
timeout: Duration,
delay: Duration,
poll_interval: Duration,
) -> Result<()> {
assert!(writer.bootstrapped().await, "writer failed to bootstrap");
assert!(reader.bootstrapped().await, "reader failed to bootstrap");
let msg = b"hello from mainline";
let id = writer.put_immutable(msg).await?;
sleep(delay).await;
let start = tokio::time::Instant::now();
let deadline = start + timeout;
let mut got = None;
let mut iterations = 0;
loop {
iterations += 1;
if let Some(bytes) = reader.get_immutable(id).await {
got = Some(bytes);
break;
}
if tokio::time::Instant::now() >= deadline {
break;
}
sleep(poll_interval).await;
}
let elapsed = start.elapsed();
println!(
"Poll stats: {} iterations, interval={:.3}s, total={:.3}s",
iterations,
poll_interval.as_secs_f64(),
elapsed.as_secs_f64()
);
let bytes = got.expect("reader did not retrieve the value in time");
assert_eq!(&*bytes, msg, "round-tripped value must match original");
Ok(())
}
#[tokio::test(flavor = "multi_thread")]
#[ignore = "Proof of Concept only."]
async fn immutable_put_then_get_testnet() -> Result<()> {
let testnet = Testnet::new_async(5).await?;
let writer = Dht::builder()
.bootstrap(&testnet.bootstrap)
.build()?
.as_async();
let reader = Dht::builder()
.bootstrap(&testnet.bootstrap)
.build()?
.as_async();
immutable_roundtrip_test(
writer,
reader,
Duration::from_secs(5),
Duration::from_millis(200),
Duration::from_millis(100),
)
.await
}
#[tokio::test(flavor = "multi_thread")]
#[ignore = "hits the real Mainline DHT and needs UDP connectivity"]
async fn immutable_put_then_get_mainnet() -> Result<()> {
let writer = Dht::client()?.as_async();
let reader = Dht::client()?.as_async();
immutable_roundtrip_test(
writer,
reader,
Duration::from_secs(30),
Duration::from_secs(1),
Duration::from_millis(250),
)
.await
}