#![allow(unused_crate_dependencies)]
use async_trait::async_trait;
use eyre::Report;
use std::sync::{
Arc,
atomic::{AtomicUsize, Ordering},
};
use volli_agent::AgentConfig;
use volli_core::Message;
use volli_transport::Transport;
#[derive(Default)]
struct MockTransport;
#[async_trait]
impl Transport for MockTransport {
async fn send(&mut self, _msg: &Message) -> Result<(), Report> {
Ok(())
}
async fn recv(&mut self) -> Result<Option<Message>, Report> {
Ok(None)
}
}
#[tokio::test]
async fn quic_failure_falls_back_to_tcp() {
let quic_called = Arc::new(AtomicUsize::new(0));
let tcp_called = Arc::new(AtomicUsize::new(0));
let q = quic_called.clone();
let quic = move |_cfg: &AgentConfig| {
let q = q.clone();
async move {
q.fetch_add(1, Ordering::SeqCst);
Err(eyre::eyre!("quic fail"))
}
};
let t = tcp_called.clone();
let tcp = move |_cfg: &AgentConfig| {
let t = t.clone();
async move {
t.fetch_add(1, Ordering::SeqCst);
Ok((
Box::new(MockTransport::default()) as Box<dyn Transport>,
"peer".into(),
))
}
};
async fn attempt<FQ, FutQ, FT, FutT>(cfg: &AgentConfig, quic: FQ, tcp: FT) -> Result<(), Report>
where
FQ: Fn(&AgentConfig) -> FutQ,
FutQ: std::future::Future<Output = Result<(Box<dyn Transport>, String), Report>>,
FT: Fn(&AgentConfig) -> FutT,
FutT: std::future::Future<Output = Result<(Box<dyn Transport>, String), Report>>,
{
match quic(cfg).await {
Ok(_) => Ok(()),
Err(_) => tcp(cfg).await.map(|_| ()),
}
}
let cfg = AgentConfig::default();
attempt(&cfg, quic, tcp).await.unwrap();
assert_eq!(quic_called.load(Ordering::SeqCst), 1);
assert_eq!(tcp_called.load(Ordering::SeqCst), 1);
}