use livekit_net::{
Header, HttpMethod, HttpResponse, TransportError, WsClient, WsConnectResult, WsConnection,
};
use livekit_protocol as proto;
use prost::Message as _;
use std::sync::{Arc, Once};
use tokio::sync::Mutex as AsyncMutex;
pub struct MockConn {
outbound: AsyncMutex<Vec<Vec<u8>>>,
}
#[async_trait::async_trait]
impl WsConnection for MockConn {
async fn send(&self, _frame: Vec<u8>) -> Result<(), TransportError> {
Ok(())
}
async fn recv(&self) -> Result<Option<Vec<u8>>, TransportError> {
Ok(self.outbound.lock().await.pop())
}
async fn close(&self) {}
}
pub struct MockTransport;
#[async_trait::async_trait]
impl WsClient for MockTransport {
async fn connect(
&self,
_url: String,
_headers: Vec<Header>,
_timeout_ms: u64,
) -> Result<WsConnectResult, TransportError> {
let pong = proto::SignalResponse {
message: Some(proto::signal_response::Message::PongResp(proto::Pong::default())),
};
let frames = vec![pong.encode_to_vec()];
Ok(WsConnectResult { connection: Arc::new(MockConn { outbound: AsyncMutex::new(frames) }) })
}
}
#[async_trait::async_trait]
impl livekit_net::HttpClient for MockTransport {
async fn request(
&self,
_method: HttpMethod,
url: String,
headers: Vec<Header>,
_body: Option<Vec<u8>>,
) -> Result<HttpResponse, TransportError> {
let has_bearer = headers.iter().any(|h| {
h.name.eq_ignore_ascii_case("Authorization")
&& h.value.starts_with("Bearer ")
&& h.value.len() > "Bearer ".len()
});
if !has_bearer {
return Ok(HttpResponse {
status: 401,
headers: vec![],
body: b"missing bearer".to_vec(),
});
}
if url.contains("connrefused") {
return Err(TransportError::Connection(
"error trying to connect: connection refused".into(),
));
}
if url.contains("badjson") {
return Ok(HttpResponse {
status: 200,
headers: vec![],
body: b"this is not json".to_vec(),
});
}
if url.contains("/settings/regions") {
let body = br#"{"regions":[{"region":"us-mock-1","url":"wss://us-mock.livekit.cloud","distance":"10"}]}"#;
return Ok(HttpResponse { status: 200, headers: vec![], body: body.to_vec() });
}
Ok(HttpResponse { status: 200, headers: vec![], body: vec![] })
}
}
static INSTALL: Once = Once::new();
pub fn install_mock_transport() {
INSTALL.call_once(|| {
livekit_net::set_ws_client(Arc::new(MockTransport));
livekit_net::set_http_client(Arc::new(MockTransport));
});
}