Test with Axum Server & Tungstenite Client hanging #5263
-
I'm honestly not sure where the best place to ask the question is, or whether it's a Tokio, Hyper, Axum, or Tungstenite problem, so please let me know if there's a better place for this! I have a relatively simple web server, which accepts WebSocket connections, then relays requests made to other endpoints over the WebSocket connection. I'm currently looking at how I would test it, and have the following basic test setup: #[cfg(test)]
async fn start_server(listener: TcpListener, rx: Receiver<()>) {
let state = Arc::new(BrokerState{
config: Config::new().unwrap(),
private_filters: Vec::new(),
public_filters: Vec::new(),
websocket_state: Arc::new(WebSocketState {
sockets: Default::default(),
requests: Default::default(),
request_count: Default::default()
}),
primus_state: Arc::new(PrimusState {
sockets: Default::default(),
requests: Default::default(),
primus_poll_requests: Default::default(),
primus_poll_state: Default::default(),
request_count: Default::default()
})
});
let app = crate::server::build_router(state);
trace!("built app");
let server = axum::Server::from_tcp(listener).unwrap()
.serve(app.into_make_service());
trace!("built server, starting with graceful shutdown");
server.with_graceful_shutdown(async {
trace!("awaiting graceful shutdown");
rx.await.ok();
}).await.unwrap();
}
#[tokio::test(flavor = "multi_thread", worker_threads = 8)]
async fn websocket_connects_and_closes() {
tracing_subscriber::registry().with(tracing_subscriber::fmt::layer()).with(tracing_subscriber::EnvFilter::from_default_env()).init();
println!("binding");
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
println!("bound to {}", &addr);
let (tx, rx) = tokio::sync::oneshot::channel::<()>();
spawn(start_server(listener, rx));
tokio::time::sleep(Duration::from_secs(1)).await;
println!("connecting first time");
let mut ws = tungstenite::connect(format!("ws://{}:{}/primus/51013202-d080-4569-a905-021fc474f9db/?sid=abc&transport=websocket", addr.ip().to_string(), addr.port())).unwrap();
println!("sending first time");
ws.0.write_message(tungstenite::protocol::Message::Close(None)).unwrap();
println!("connecting second time");
let mut ws = tungstenite::connect(format!("ws://{}:{}/primus/51013202-d080-4569-a905-021fc474f9db/?sid=abc&transport=websocket", addr.ip().to_string(), addr.port())).unwrap();
println!("sending second time");
ws.0.write_message(tungstenite::protocol::Message::Text("2".to_string())).unwrap();
println!("receiving");
// let duration = Duration::from_secs(30);
let n = ws.0.read_message().unwrap();
assert!(matches!(n, tungstenite::protocol::Message::Text(t) if t == "3".to_string()));
tx.send(()).unwrap();
} When I run it, I get the following output:
And it just sits there, forever. If I make a cURL request against that host/port/path combination then it works fine, so I know that the server code works in general, it's just something is having an issue in the context of a test. Am I trying to do something impossible here, or should this work? Things that might be relevant:
Dependencies
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
It looks like you are using Also, could you include imports in the future? It's easier to figure out issues like this when you do. |
Beta Was this translation helpful? Give feedback.
It looks like you are using
std::net::TcpListener
, in which case it makes perfect sense that your application would hang, as this listener and streams obtained from it are blocking. You need to use the versions intokio::net
instead, andtokio_tungstenite
.Also, could you include imports in the future? It's easier to figure out issues like this when you do.