use std::{io, net, thread};
use ntex_net::{tcp_connect, Io};
use ntex_rt::System;
use ntex_service::ServiceFactory;
use socket2::{Domain, SockAddr, Socket, Type};
use super::{Server, ServerBuilder};
pub fn test_server<F, R>(factory: F) -> TestServer
where
F: Fn() -> R + Send + Clone + 'static,
R: ServiceFactory<Io> + 'static,
{
let (tx, rx) = oneshot::channel();
thread::spawn(move || {
let sys = System::new("ntex-test-server");
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
let local_addr = tcp.local_addr().unwrap();
let system = sys.system();
sys.run(move || {
let server = ServerBuilder::new()
.listen("test", tcp, move |_| factory())?
.set_tag("test", "TEST-SERVER")
.workers(1)
.disable_signals()
.run();
ntex_rt::spawn(async move {
ntex_util::time::sleep(ntex_util::time::Millis(75)).await;
tx.send((system, local_addr, server))
.expect("Failed to send Server to TestServer");
});
Ok(())
})
});
let (system, addr, server) = rx.recv().unwrap();
TestServer {
addr,
server,
system,
}
}
pub fn build_test_server<F>(factory: F) -> TestServer
where
F: FnOnce(ServerBuilder) -> ServerBuilder + Send + 'static,
{
let (tx, rx) = oneshot::channel();
thread::spawn(move || {
let sys = System::new("ntex-test-server");
let system = sys.system();
sys.run(|| {
let server = factory(super::build()).workers(1).disable_signals().run();
tx.send((system, server))
.expect("Failed to send Server to TestServer");
Ok(())
})
});
let (system, server) = rx.recv().unwrap();
TestServer {
system,
server,
addr: "127.0.0.1:0".parse().unwrap(),
}
}
#[derive(Debug)]
pub struct TestServer {
addr: net::SocketAddr,
system: System,
server: Server,
}
impl TestServer {
pub fn addr(&self) -> net::SocketAddr {
self.addr
}
pub fn set_addr(mut self, addr: net::SocketAddr) -> Self {
self.addr = addr;
self
}
pub async fn connect(&self) -> io::Result<Io> {
tcp_connect(self.addr).await
}
pub fn stop(&self) {
self.system.stop();
}
pub fn unused_addr() -> net::SocketAddr {
let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap();
let socket = Socket::new(Domain::IPV4, Type::STREAM, None).unwrap();
socket.set_reuse_address(true).unwrap();
socket.bind(&SockAddr::from(addr)).unwrap();
let tcp = net::TcpListener::from(socket);
tcp.local_addr().unwrap()
}
pub fn server(&self) -> Server {
self.server.clone()
}
}
impl Drop for TestServer {
fn drop(&mut self) {
self.stop()
}
}