use crate::load;
use futures_util::pin_mut;
use tokio_test::{assert_pending, assert_ready, assert_ready_ok, task};
use tower_test::{assert_request_eq, mock};
use super::*;
#[tokio::test]
async fn basic() {
let (mock, handle) = mock::pair::<(), load::Constant<mock::Mock<(), &'static str>, usize>>();
pin_mut!(handle);
let mut pool = mock::Spawn::new(Builder::new().build(mock, ()));
assert_pending!(pool.poll_ready());
let (svc1_m, svc1) = mock::pair();
pin_mut!(svc1);
assert_request_eq!(handle, ()).send_response(load::Constant::new(svc1_m, 0));
assert_ready_ok!(pool.poll_ready());
let mut fut = task::spawn(pool.call(()));
assert_pending!(fut.poll());
assert_request_eq!(svc1, ()).send_response("foobar");
assert_eq!(assert_ready_ok!(fut.poll()), "foobar");
}
#[tokio::test]
async fn high_load() {
let (mock, handle) = mock::pair::<(), load::Constant<mock::Mock<(), &'static str>, usize>>();
pin_mut!(handle);
let pool = Builder::new()
.urgency(1.0) .underutilized_below(0.0) .max_services(Some(2))
.build(mock, ());
let mut pool = mock::Spawn::new(pool);
assert_pending!(pool.poll_ready());
let (svc1_m, svc1) = mock::pair();
pin_mut!(svc1);
svc1.allow(1);
assert_request_eq!(handle, ()).send_response(load::Constant::new(svc1_m, 0));
assert_ready_ok!(pool.poll_ready());
let mut fut1 = task::spawn(pool.call(()));
assert_pending!(pool.poll_ready());
let (svc2_m, svc2) = mock::pair();
pin_mut!(svc2);
svc2.allow(1);
assert_request_eq!(handle, ()).send_response(load::Constant::new(svc2_m, 0));
assert_ready_ok!(pool.poll_ready());
let mut fut2 = task::spawn(pool.call(()));
assert_pending!(pool.poll_ready());
assert_pending!(handle.as_mut().poll_request());
assert_request_eq!(svc1, ()).send_response("foo");
assert_request_eq!(svc2, ()).send_response("bar");
assert_eq!(assert_ready_ok!(fut1.poll()), "foo");
assert_eq!(assert_ready_ok!(fut2.poll()), "bar");
}
#[tokio::test]
async fn low_load() {
let (mock, handle) = mock::pair::<(), load::Constant<mock::Mock<(), &'static str>, usize>>();
pin_mut!(handle);
let pool = Builder::new()
.urgency(1.0) .build(mock, ());
let mut pool = mock::Spawn::new(pool);
assert_pending!(pool.poll_ready());
let (svc1_m, svc1) = mock::pair();
pin_mut!(svc1);
svc1.allow(1);
assert_request_eq!(handle, ()).send_response(load::Constant::new(svc1_m, 0));
assert_ready_ok!(pool.poll_ready());
let mut fut = task::spawn(pool.call(()));
assert_request_eq!(svc1, ()).send_response("foo");
assert_eq!(assert_ready_ok!(fut.poll()), "foo");
assert_pending!(pool.poll_ready());
let (svc2_m, svc2) = mock::pair();
pin_mut!(svc2);
svc2.allow(1);
assert_request_eq!(handle, ()).send_response(load::Constant::new(svc2_m, 0));
assert_ready_ok!(pool.poll_ready());
assert_ready_ok!(pool.poll_ready());
let mut fut = task::spawn(pool.call(()));
assert_request_eq!(svc2, ()).send_response("foo");
assert_eq!(assert_ready_ok!(fut.poll()), "foo");
svc2.allow(1);
assert_ready_ok!(pool.poll_ready());
let mut fut = task::spawn(pool.call(()));
assert_request_eq!(svc2, ()).send_response("foo");
assert_eq!(assert_ready_ok!(fut.poll()), "foo");
}
#[tokio::test]
async fn failing_service() {
let (mock, handle) = mock::pair::<(), load::Constant<mock::Mock<(), &'static str>, usize>>();
pin_mut!(handle);
let pool = Builder::new()
.urgency(1.0) .underutilized_below(0.0) .build(mock, ());
let mut pool = mock::Spawn::new(pool);
assert_pending!(pool.poll_ready());
let (svc1_m, svc1) = mock::pair();
pin_mut!(svc1);
svc1.allow(1);
assert_request_eq!(handle, ()).send_response(load::Constant::new(svc1_m, 0));
assert_ready_ok!(pool.poll_ready());
let mut fut = task::spawn(pool.call(()));
assert_request_eq!(svc1, ()).send_response("foo");
assert_eq!(assert_ready_ok!(fut.poll()), "foo");
svc1.send_error("ouch");
assert_pending!(pool.poll_ready());
let (svc2_m, svc2) = mock::pair();
pin_mut!(svc2);
svc2.allow(1);
assert_request_eq!(handle, ()).send_response(load::Constant::new(svc2_m, 0));
assert_ready_ok!(pool.poll_ready());
let mut fut = task::spawn(pool.call(()));
assert_request_eq!(svc2, ()).send_response("bar");
assert_eq!(assert_ready_ok!(fut.poll()), "bar");
}