Skip to content

Commit

Permalink
simplify test server (#431)
Browse files Browse the repository at this point in the history
  • Loading branch information
robjtede authored Dec 27, 2021
1 parent e92b5aa commit 01d2f18
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 116 deletions.
3 changes: 3 additions & 0 deletions actix-server/CHANGES.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 2 additions & 1 deletion actix-server/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;

Expand Down
76 changes: 32 additions & 44 deletions actix-server/src/test_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<_, ()>(())
Expand All @@ -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,
Expand All @@ -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()
Expand All @@ -93,7 +73,7 @@ impl TestServer {
let host = format!("{}", addr.ip());
let port = addr.port();

TestServerRuntime {
TestServerHandle {
addr,
host,
port,
Expand All @@ -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
Expand All @@ -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()
}
Expand All @@ -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());
}
}
61 changes: 0 additions & 61 deletions actix-server/tests/test_server.rs → actix-server/tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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() {
Expand Down
73 changes: 73 additions & 0 deletions actix-server/tests/testing_server.rs
Original file line number Diff line number Diff line change
@@ -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();
}
2 changes: 1 addition & 1 deletion actix-tls/tests/accept-openssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion actix-tls/tests/accept-rustls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
14 changes: 7 additions & 7 deletions actix-tls/tests/test_connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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?;
Expand All @@ -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?;
Expand All @@ -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?;
Expand Down Expand Up @@ -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?;
Expand All @@ -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?;
Expand All @@ -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?;
Expand All @@ -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?;
Expand Down
Loading

0 comments on commit 01d2f18

Please sign in to comment.