zebra_test/
service_extensions.rs

1//! Extension traits for [`Service`] types to help with testing.
2
3use std::task::Poll;
4
5use futures::future::{BoxFuture, FutureExt};
6use tower::{Service, ServiceExt};
7
8/// An extension trait to check if a [`Service`] is immediately ready to be called.
9pub trait IsReady<Request>: Service<Request> {
10    /// Poll the [`Service`] once, and return true if it is immediately ready to be called.
11    #[allow(clippy::wrong_self_convention)]
12    fn is_ready(&mut self) -> BoxFuture<bool>;
13
14    /// Poll the [`Service`] once, and return true if it is pending.
15    #[allow(clippy::wrong_self_convention)]
16    fn is_pending(&mut self) -> BoxFuture<bool>;
17
18    /// Poll the [`Service`] once, and return true if it has failed.
19    #[allow(clippy::wrong_self_convention)]
20    fn is_failed(&mut self) -> BoxFuture<bool>;
21}
22
23impl<S, Request> IsReady<Request> for S
24where
25    S: Service<Request> + Send,
26    Request: 'static,
27{
28    fn is_ready(&mut self) -> BoxFuture<bool> {
29        async move {
30            let ready_result = futures::poll!(self.ready());
31            matches!(ready_result, Poll::Ready(Ok(_)))
32        }
33        .boxed()
34    }
35
36    fn is_pending(&mut self) -> BoxFuture<bool> {
37        async move {
38            let ready_result = futures::poll!(self.ready());
39            ready_result.is_pending()
40        }
41        .boxed()
42    }
43
44    fn is_failed(&mut self) -> BoxFuture<bool> {
45        async move {
46            let ready_result = futures::poll!(self.ready());
47            matches!(ready_result, Poll::Ready(Err(_)))
48        }
49        .boxed()
50    }
51}