use crate::channels::transport_ready::{CONNECT_GRACE, await_transport};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
#[derive(Clone, Default)]
struct Slot(Arc<std::sync::Mutex<Option<&'static str>>>);
impl Slot {
fn connect(&self, name: &'static str) {
*self.0.lock().expect("slot poisoned") = Some(name);
}
fn get(&self) -> Option<&'static str> {
*self.0.lock().expect("slot poisoned")
}
}
#[tokio::test(start_paused = true)]
async fn an_already_connected_transport_costs_no_wait() {
let slot = Slot::default();
slot.connect("bot");
let started = tokio::time::Instant::now();
let got = await_transport("telegram", uuid::Uuid::nil(), || async { slot.get() }).await;
assert_eq!(got, Some("bot"));
assert_eq!(
started.elapsed(),
Duration::ZERO,
"the ordinary case must be exactly as fast as the bare check it replaced"
);
}
#[tokio::test(start_paused = true)]
async fn a_late_connect_is_picked_up_rather_than_dropped() {
let slot = Slot::default();
let filler = slot.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_secs(5)).await;
filler.connect("bot");
});
let got = await_transport("telegram", uuid::Uuid::nil(), || async { slot.get() }).await;
assert_eq!(got, Some("bot"), "a wake was dropped on a late connect");
}
#[tokio::test(start_paused = true)]
async fn a_late_connect_is_served_within_the_grace_window() {
let slot = Slot::default();
let filler = slot.clone();
tokio::spawn(async move {
tokio::time::sleep(CONNECT_GRACE - Duration::from_secs(1)).await;
filler.connect("bot");
});
let started = tokio::time::Instant::now();
let got = await_transport("telegram", uuid::Uuid::nil(), || async { slot.get() }).await;
assert_eq!(got, Some("bot"));
assert!(
started.elapsed() <= CONNECT_GRACE,
"a connect inside the window was still missed after {:?}",
started.elapsed()
);
}
#[tokio::test(start_paused = true)]
async fn a_connect_follows_closely_rather_than_on_the_next_second() {
let slot = Slot::default();
let filler = slot.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_millis(10)).await;
filler.connect("bot");
});
let started = tokio::time::Instant::now();
await_transport("telegram", uuid::Uuid::nil(), || async { slot.get() }).await;
assert!(
started.elapsed() < Duration::from_secs(1),
"wake trailed its connect by {:?}",
started.elapsed()
);
}
#[tokio::test(start_paused = true)]
async fn a_channel_that_never_connects_gives_up_bounded() {
let slot = Slot::default();
let started = tokio::time::Instant::now();
let got = await_transport("telegram", uuid::Uuid::nil(), || async { slot.get() }).await;
assert_eq!(got, None);
assert!(
started.elapsed() >= CONNECT_GRACE,
"gave up after only {:?}, short of the grace window",
started.elapsed()
);
assert!(
started.elapsed() < CONNECT_GRACE * 2,
"overshot the grace window by more than a whole window: {:?}",
started.elapsed()
);
}
#[tokio::test(start_paused = true)]
async fn readiness_is_re_read_every_poll() {
let calls = Arc::new(AtomicUsize::new(0));
let counter = calls.clone();
let slot = Slot::default();
let filler = slot.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_secs(2)).await;
filler.connect("bot");
});
let got = await_transport("telegram", uuid::Uuid::nil(), || {
counter.fetch_add(1, Ordering::SeqCst);
async { slot.get() }
})
.await;
assert_eq!(got, Some("bot"));
assert!(
calls.load(Ordering::SeqCst) > 1,
"the slot was read once and cached, so a later connect could never be seen"
);
}
#[test]
fn the_two_startup_flush_paths_share_one_window() {
assert_eq!(
CONNECT_GRACE,
crate::brain::agent::service::restart_recovery::ROUTE_GRACE,
"the wake wait and the parked-report flush drifted apart again"
);
}