futures_test/sink/
mod.rs

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