1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-23 20:51:06 +01:00

simplify test server (#431)

This commit is contained in:
Rob Ede 2021-12-27 18:27:54 +00:00 committed by GitHub
parent e92b5aaf31
commit 01d2f18f68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 120 additions and 116 deletions

View File

@ -1,6 +1,9 @@
# Changes
## Unreleased - 2021-xx-xx
- Simplify `TestServer`. [#431]
[#431]: https://github.com/actix/actix-net/pull/431
## 2.0.0-rc.1 - 2021-12-05

View File

@ -140,10 +140,11 @@ impl ServerBuilder {
}
/// Add new service to the server.
pub fn bind<F, U, N: AsRef<str>>(mut self, name: N, addr: U, factory: F) -> io::Result<Self>
pub fn bind<F, U, N>(mut self, name: N, addr: U, factory: F) -> io::Result<Self>
where
F: ServerServiceFactory<TcpStream>,
U: ToSocketAddrs,
N: AsRef<str>,
{
let sockets = bind_addr(addr, self.backlog)?;

View File

@ -16,7 +16,7 @@ use crate::{Server, ServerBuilder, ServerHandle, ServerServiceFactory};
///
/// #[actix_rt::main]
/// async fn main() {
/// let srv = TestServer::with(|| fn_service(
/// let srv = TestServer::start(|| fn_service(
/// |sock| async move {
/// println!("New connection: {:?}", sock);
/// Ok::<_, ()>(())
@ -28,8 +28,8 @@ use crate::{Server, ServerBuilder, ServerHandle, ServerServiceFactory};
/// ```
pub struct TestServer;
/// Test server runtime
pub struct TestServerRuntime {
/// Test server handle.
pub struct TestServerHandle {
addr: net::SocketAddr,
host: String,
port: u16,
@ -38,46 +38,26 @@ pub struct TestServerRuntime {
}
impl TestServer {
/// Start new server with server builder.
pub fn start<F>(mut factory: F) -> TestServerRuntime
where
F: FnMut(ServerBuilder) -> ServerBuilder + Send + 'static,
{
let (tx, rx) = mpsc::channel();
// run server in separate thread
let thread_handle = thread::spawn(move || {
System::new().block_on(async {
let server = factory(Server::build()).workers(1).disable_signals().run();
tx.send(server.handle()).unwrap();
server.await
})
});
let server_handle = rx.recv().unwrap();
TestServerRuntime {
addr: "127.0.0.1:0".parse().unwrap(),
host: "127.0.0.1".to_string(),
port: 0,
server_handle,
thread_handle: Some(thread_handle),
}
/// Start new `TestServer` using application factory and default server config.
pub fn start(factory: impl ServerServiceFactory<TcpStream>) -> TestServerHandle {
Self::start_with_builder(Server::build(), factory)
}
/// Start new test server with application factory.
pub fn with<F: ServerServiceFactory<TcpStream>>(factory: F) -> TestServerRuntime {
/// Start new `TestServer` using application factory and server builder.
pub fn start_with_builder(
server_builder: ServerBuilder,
factory: impl ServerServiceFactory<TcpStream>,
) -> TestServerHandle {
let (tx, rx) = mpsc::channel();
// run server in separate thread
let thread_handle = thread::spawn(move || {
let sys = System::new();
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
let local_addr = tcp.local_addr().unwrap();
let lst = net::TcpListener::bind("127.0.0.1:0").unwrap();
let local_addr = lst.local_addr().unwrap();
sys.block_on(async {
let server = Server::build()
.listen("test", tcp, factory)
System::new().block_on(async {
let server = server_builder
.listen("test", lst, factory)
.unwrap()
.workers(1)
.disable_signals()
@ -93,7 +73,7 @@ impl TestServer {
let host = format!("{}", addr.ip());
let port = addr.port();
TestServerRuntime {
TestServerHandle {
addr,
host,
port,
@ -107,17 +87,19 @@ impl TestServer {
use socket2::{Domain, Protocol, Socket, Type};
let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap();
let socket =
Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP)).unwrap();
let domain = Domain::for_address(addr);
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP)).unwrap();
socket.set_reuse_address(true).unwrap();
socket.set_nonblocking(true).unwrap();
socket.bind(&addr.into()).unwrap();
socket.listen(1024).unwrap();
net::TcpListener::from(socket).local_addr().unwrap()
}
}
impl TestServerRuntime {
impl TestServerHandle {
/// Test server host.
pub fn host(&self) -> &str {
&self.host
@ -140,12 +122,12 @@ impl TestServerRuntime {
}
/// Connect to server, returning a Tokio `TcpStream`.
pub fn connect(&self) -> std::io::Result<TcpStream> {
pub fn connect(&self) -> io::Result<TcpStream> {
TcpStream::from_std(net::TcpStream::connect(self.addr)?)
}
}
impl Drop for TestServerRuntime {
impl Drop for TestServerHandle {
fn drop(&mut self) {
self.stop()
}
@ -158,8 +140,14 @@ mod tests {
use super::*;
#[tokio::test]
async fn plain_tokio_runtime() {
let srv = TestServer::with(|| fn_service(|_sock| async move { Ok::<_, ()>(()) }));
async fn connect_in_tokio_runtime() {
let srv = TestServer::start(|| fn_service(|_sock| async move { Ok::<_, ()>(()) }));
assert!(srv.connect().is_ok());
}
#[actix_rt::test]
async fn connect_in_actix_runtime() {
let srv = TestServer::start(|| fn_service(|_sock| async move { Ok::<_, ()>(()) }));
assert!(srv.connect().is_ok());
}
}

View File

@ -79,35 +79,6 @@ fn test_listen() {
h.join().unwrap().unwrap();
}
// #[test]
// fn test_bind() {
// let addr = unused_addr();
// let (tx, rx) = mpsc::channel();
// let h = thread::spawn(move || {
// actix_rt::System::new().block_on(async {
// let srv = Server::build()
// .workers(1)
// .disable_signals()
// .bind("test", addr, move || {
// fn_service(|_| async { Ok::<_, ()>(()) })
// })?
// .run();
// let _ = tx.send(srv.handle());
// srv.await
// })
// });
// let srv = rx.recv().unwrap();
// thread::sleep(Duration::from_millis(500));
// assert!(net::TcpStream::connect(addr).is_ok());
// let _ = srv.stop(true);
// h.join().unwrap().unwrap();
// }
#[test]
fn plain_tokio_runtime() {
let addr = unused_addr();
@ -143,38 +114,6 @@ fn plain_tokio_runtime() {
h.join().unwrap().unwrap();
}
// #[test]
// fn test_listen() {
// let addr = unused_addr();
// let lst = net::TcpListener::bind(addr).unwrap();
// let (tx, rx) = mpsc::channel();
// let h = thread::spawn(move || {
// actix_rt::System::new().block_on(async {
// let srv = Server::build()
// .disable_signals()
// .workers(1)
// .listen("test", lst, move || {
// fn_service(|_| async { Ok::<_, ()>(()) })
// })?
// .run();
// let _ = tx.send(srv.handle());
// srv.await
// })
// });
// let srv = rx.recv().unwrap();
// thread::sleep(Duration::from_millis(500));
// assert!(net::TcpStream::connect(addr).is_ok());
// let _ = srv.stop(true);
// h.join().unwrap().unwrap();
// }
#[test]
#[cfg(unix)]
fn test_start() {

View File

@ -0,0 +1,73 @@
use std::net;
use actix_rt::net::TcpStream;
use actix_server::{Server, TestServer};
use actix_service::fn_service;
use bytes::BytesMut;
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
macro_rules! await_timeout_ms {
($fut:expr, $limit:expr) => {
::actix_rt::time::timeout(::std::time::Duration::from_millis($limit), $fut)
.await
.unwrap()
.unwrap();
};
}
#[tokio::test]
async fn testing_server_echo() {
let srv = TestServer::start(|| {
fn_service(move |mut stream: TcpStream| async move {
let mut size = 0;
let mut buf = BytesMut::new();
match stream.read_buf(&mut buf).await {
Ok(0) => return Err(()),
Ok(bytes_read) => {
stream.write_all(&buf[size..]).await.unwrap();
size += bytes_read;
}
Err(_) => return Err(()),
}
Ok((buf.freeze(), size))
})
});
let mut conn = srv.connect().unwrap();
await_timeout_ms!(conn.write_all(b"test"), 200);
let mut buf = Vec::new();
await_timeout_ms!(conn.read_to_end(&mut buf), 200);
assert_eq!(&buf, b"test".as_ref());
}
#[tokio::test]
async fn new_with_builder() {
let alt_addr = TestServer::unused_addr();
let srv = TestServer::start_with_builder(
Server::build()
.bind("alt", alt_addr, || {
fn_service(|_| async { Ok::<_, ()>(()) })
})
.unwrap(),
|| {
fn_service(|mut sock: TcpStream| async move {
let mut buf = [0u8; 16];
sock.read_exact(&mut buf).await
})
},
);
// connect to test server
srv.connect().unwrap();
// connect to alt service defined in custom ServerBuilder
TcpStream::from_std(net::TcpStream::connect(alt_addr).unwrap()).unwrap();
}

View File

@ -94,7 +94,7 @@ fn rustls_connector(_cert: String, _key: String) -> ClientConfig {
async fn accepts_connections() {
let (cert, key) = new_cert_and_key();
let srv = TestServer::with({
let srv = TestServer::start({
let cert = cert.clone();
let key = key.clone();

View File

@ -74,7 +74,7 @@ fn openssl_connector(cert: String, key: String) -> SslConnector {
async fn accepts_connections() {
let (cert, key) = new_cert_and_key();
let srv = TestServer::with({
let srv = TestServer::start({
let cert = cert.clone();
let key = key.clone();

View File

@ -17,7 +17,7 @@ use actix_tls::connect::{ConnectError, ConnectInfo, Connection, Connector, Host}
#[cfg(feature = "openssl")]
#[actix_rt::test]
async fn test_string() {
let srv = TestServer::with(|| {
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
framed.send(Bytes::from_static(b"test")).await?;
@ -34,7 +34,7 @@ async fn test_string() {
#[cfg(feature = "rustls")]
#[actix_rt::test]
async fn test_rustls_string() {
let srv = TestServer::with(|| {
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
framed.send(Bytes::from_static(b"test")).await?;
@ -50,7 +50,7 @@ async fn test_rustls_string() {
#[actix_rt::test]
async fn test_static_str() {
let srv = TestServer::with(|| {
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
framed.send(Bytes::from_static(b"test")).await?;
@ -81,7 +81,7 @@ async fn service_factory() {
Connector::default()
}
let srv = TestServer::with(|| {
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
framed.send(Bytes::from_static(b"test")).await?;
@ -101,7 +101,7 @@ async fn service_factory() {
async fn test_openssl_uri() {
use std::convert::TryFrom;
let srv = TestServer::with(|| {
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
framed.send(Bytes::from_static(b"test")).await?;
@ -120,7 +120,7 @@ async fn test_openssl_uri() {
async fn test_rustls_uri() {
use std::convert::TryFrom;
let srv = TestServer::with(|| {
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
framed.send(Bytes::from_static(b"test")).await?;
@ -136,7 +136,7 @@ async fn test_rustls_uri() {
#[actix_rt::test]
async fn test_local_addr() {
let srv = TestServer::with(|| {
let srv = TestServer::start(|| {
fn_service(|io: TcpStream| async {
let mut framed = Framed::new(io, BytesCodec);
framed.send(Bytes::from_static(b"test")).await?;

View File

@ -53,7 +53,7 @@ async fn custom_resolver_connect() {
use trust_dns_resolver::TokioAsyncResolver;
let srv =
TestServer::with(|| fn_service(|_io: TcpStream| async { Ok::<_, io::Error>(()) }));
TestServer::start(|| fn_service(|_io: TcpStream| async { Ok::<_, io::Error>(()) }));
struct MyResolver {
trust_dns: TokioAsyncResolver,