futures_test/sink/mod.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
//! Additional combinators for testing sinks.
use futures_sink::Sink;
pub use crate::assert_unmoved::AssertUnmoved;
pub use crate::interleave_pending::InterleavePending;
pub use crate::track_closed::TrackClosed;
/// Additional combinators for testing sinks.
pub trait SinkTestExt<Item>: Sink<Item> {
/// Asserts that the given is not moved after being polled.
///
/// A check for movement is performed each time the sink is polled
/// and when `Drop` is called.
///
/// Aside from keeping track of the location at which the sink was first
/// polled and providing assertions, this sink adds no runtime behavior
/// and simply delegates to the child sink.
fn assert_unmoved_sink(self) -> AssertUnmoved<Self>
where
Self: Sized,
{
AssertUnmoved::new(self)
}
/// Introduces an extra [`Poll::Pending`](futures_core::task::Poll::Pending)
/// in between each operation on the sink.
fn interleave_pending_sink(self) -> InterleavePending<Self>
where
Self: Sized,
{
InterleavePending::new(self)
}
/// Track whether this sink has been closed and panics if it is used after closing.
///
/// # Examples
///
/// ```
/// # futures::executor::block_on(async {
/// use futures::sink::{SinkExt, drain};
/// use futures_test::sink::SinkTestExt;
///
/// let mut sink = drain::<i32>().track_closed();
///
/// sink.send(1).await?;
/// assert!(!sink.is_closed());
/// sink.close().await?;
/// assert!(sink.is_closed());
///
/// # Ok::<(), std::convert::Infallible>(()) })?;
/// # Ok::<(), std::convert::Infallible>(())
/// ```
///
/// Note: Unlike [`AsyncWriteTestExt::track_closed`] when
/// used as a sink the adaptor will panic if closed too early as there's no easy way to
/// integrate as an error.
///
/// [`AsyncWriteTestExt::track_closed`]: crate::io::AsyncWriteTestExt::track_closed
///
/// ```
/// # futures::executor::block_on(async {
/// use std::panic::AssertUnwindSafe;
/// use futures::{sink::{SinkExt, drain}, future::FutureExt};
/// use futures_test::sink::SinkTestExt;
///
/// let mut sink = drain::<i32>().track_closed();
///
/// sink.close().await?;
/// assert!(AssertUnwindSafe(sink.send(1)).catch_unwind().await.is_err());
/// # Ok::<(), std::convert::Infallible>(()) })?;
/// # Ok::<(), std::convert::Infallible>(())
/// ```
fn track_closed(self) -> TrackClosed<Self>
where
Self: Sized,
{
TrackClosed::new(self)
}
}
impl<Item, W> SinkTestExt<Item> for W where W: Sink<Item> {}