use std::future::Future;
use std::net::SocketAddr;
use futures::FutureExt;
use tokio::net::TcpListener;
use tokio::net::TcpStream;
use tokio::spawn;
use tungstenite::accept_async as accept_websocket;
use tungstenite::tokio::TokioAdapter;
use tungstenite::tungstenite::Error as WebSocketError;
use tungstenite::WebSocketStream as WsStream;
pub type WebSocketStream = WsStream<TokioAdapter<TcpStream>>;
pub async fn mock_server<F, R>(f: F) -> SocketAddr
where
F: FnOnce(WebSocketStream) -> R + Send + Sync + 'static,
R: Future<Output = Result<(), WebSocketError>> + Send + Sync + 'static,
{
let mut listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let future = async move {
listener
.accept()
.map(move |result| result.unwrap())
.then(|(stream, _addr)| accept_websocket(TokioAdapter(stream)))
.map(move |result| result.unwrap())
.then(move |ws_stream| f(ws_stream))
.await
};
let _ = spawn(future);
addr
}