mirror of https://github.com/fafhrd91/actix-web
add test for pool
This commit is contained in:
parent
8986e99494
commit
cd1b0dd37a
|
@ -141,6 +141,11 @@ impl<T: AsyncRead + AsyncWrite + Unpin> IoConnection<T> {
|
||||||
pub(crate) fn into_inner(self) -> (ConnectionType<T>, time::Instant) {
|
pub(crate) fn into_inner(self) -> (ConnectionType<T>, time::Instant) {
|
||||||
(self.io.unwrap(), self.created)
|
(self.io.unwrap(), self.created)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) fn into_parts(self) -> (ConnectionType<T>, time::Instant, Acquired<T>) {
|
||||||
|
(self.io.unwrap(), self.created, self.pool.unwrap())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Connection for IoConnection<T>
|
impl<T> Connection for IoConnection<T>
|
||||||
|
|
|
@ -377,3 +377,187 @@ where
|
||||||
let _permit = &mut self.permit;
|
let _permit = &mut self.permit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use http::Uri;
|
||||||
|
|
||||||
|
use crate::client::connection::IoConnection;
|
||||||
|
|
||||||
|
// A stream type always return pending on async read.
|
||||||
|
// mock a usable tcp stream that ready to be used as client
|
||||||
|
struct TestStream;
|
||||||
|
|
||||||
|
impl AsyncRead for TestStream {
|
||||||
|
fn poll_read(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_: &mut Context<'_>,
|
||||||
|
_: &mut ReadBuf<'_>,
|
||||||
|
) -> Poll<io::Result<()>> {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsyncWrite for TestStream {
|
||||||
|
fn poll_write(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_: &mut Context<'_>,
|
||||||
|
_: &[u8],
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_flush(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_: &mut Context<'_>,
|
||||||
|
) -> Poll<io::Result<()>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_shutdown(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
_: &mut Context<'_>,
|
||||||
|
) -> Poll<io::Result<()>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestPoolConnector {
|
||||||
|
generated: Rc<Cell<usize>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Service<Connect> for TestPoolConnector {
|
||||||
|
type Response = (TestStream, Protocol);
|
||||||
|
type Error = ConnectError;
|
||||||
|
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
|
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
unimplemented!("poll_ready is not used in test")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, _: Connect) -> Self::Future {
|
||||||
|
self.generated.set(self.generated.get() + 1);
|
||||||
|
Box::pin(async { Ok((TestStream, Protocol::Http1)) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_pool_limit() {
|
||||||
|
let connector = TestPoolConnector {
|
||||||
|
generated: Rc::new(Cell::new(0)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut config = ConnectorConfig::default();
|
||||||
|
config.limit = 1;
|
||||||
|
|
||||||
|
let pool = super::ConnectionPool::new(connector, config);
|
||||||
|
|
||||||
|
let req = Connect {
|
||||||
|
uri: Uri::from_static("http://localhost"),
|
||||||
|
addr: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let conn = pool.call(req.clone()).await.unwrap();
|
||||||
|
|
||||||
|
let waiting = Rc::new(Cell::new(true));
|
||||||
|
|
||||||
|
let waiting_clone = waiting.clone();
|
||||||
|
actix_rt::spawn(async move {
|
||||||
|
actix_rt::time::sleep(Duration::from_millis(100)).await;
|
||||||
|
waiting_clone.set(false);
|
||||||
|
drop(conn);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(waiting.get());
|
||||||
|
|
||||||
|
let now = Instant::now();
|
||||||
|
let conn = pool.call(req.clone()).await.unwrap();
|
||||||
|
|
||||||
|
drop(conn);
|
||||||
|
assert!(!waiting.get());
|
||||||
|
assert!(now.elapsed() >= Duration::from_millis(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_pool_keep_alive() {
|
||||||
|
let generated = Rc::new(Cell::new(0));
|
||||||
|
let generated_clone = generated.clone();
|
||||||
|
|
||||||
|
let connector = TestPoolConnector { generated };
|
||||||
|
|
||||||
|
let mut config = ConnectorConfig::default();
|
||||||
|
config.conn_keep_alive = Duration::from_secs(1);
|
||||||
|
|
||||||
|
let pool = super::ConnectionPool::new(connector, config);
|
||||||
|
|
||||||
|
let req = Connect {
|
||||||
|
uri: Uri::from_static("http://localhost"),
|
||||||
|
addr: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let conn = pool.call(req.clone()).await.unwrap();
|
||||||
|
assert_eq!(1, generated_clone.get());
|
||||||
|
{
|
||||||
|
let (conn, created, mut acquired) = conn.into_parts();
|
||||||
|
acquired.release(IoConnection::new(conn, created, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
let conn = pool.call(req.clone()).await.unwrap();
|
||||||
|
assert_eq!(1, generated_clone.get());
|
||||||
|
{
|
||||||
|
let (conn, created, mut acquired) = conn.into_parts();
|
||||||
|
acquired.release(IoConnection::new(conn, created, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
actix_rt::time::sleep(Duration::from_millis(1500)).await;
|
||||||
|
actix_rt::task::yield_now().await;
|
||||||
|
|
||||||
|
let conn = pool.call(req.clone()).await.unwrap();
|
||||||
|
assert_eq!(2, generated_clone.get());
|
||||||
|
drop(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_pool_lifetime() {
|
||||||
|
let generated = Rc::new(Cell::new(0));
|
||||||
|
let generated_clone = generated.clone();
|
||||||
|
|
||||||
|
let connector = TestPoolConnector { generated };
|
||||||
|
|
||||||
|
let mut config = ConnectorConfig::default();
|
||||||
|
config.conn_lifetime = Duration::from_secs(1);
|
||||||
|
|
||||||
|
let pool = super::ConnectionPool::new(connector, config);
|
||||||
|
|
||||||
|
let req = Connect {
|
||||||
|
uri: Uri::from_static("http://localhost"),
|
||||||
|
addr: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let conn = pool.call(req.clone()).await.unwrap();
|
||||||
|
assert_eq!(1, generated_clone.get());
|
||||||
|
{
|
||||||
|
let (conn, created, mut acquired) = conn.into_parts();
|
||||||
|
acquired.release(IoConnection::new(conn, created, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
let conn = pool.call(req.clone()).await.unwrap();
|
||||||
|
assert_eq!(1, generated_clone.get());
|
||||||
|
{
|
||||||
|
let (conn, created, mut acquired) = conn.into_parts();
|
||||||
|
acquired.release(IoConnection::new(conn, created, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
actix_rt::time::sleep(Duration::from_millis(1500)).await;
|
||||||
|
actix_rt::task::yield_now().await;
|
||||||
|
|
||||||
|
let conn = pool.call(req.clone()).await.unwrap();
|
||||||
|
assert_eq!(2, generated_clone.get());
|
||||||
|
drop(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue