Skip to main content

futures_test/io/write/
mod.rs

1//! Additional combinators for testing async writers.
2
3use futures_io::AsyncWrite;
4
5pub use super::limited::Limited;
6pub use crate::assert_unmoved::AssertUnmoved;
7pub use crate::interleave_pending::InterleavePending;
8pub use crate::track_closed::TrackClosed;
9
10/// Additional combinators for testing async writers.
11pub trait AsyncWriteTestExt: AsyncWrite {
12    /// Asserts that the given is not moved after being polled.
13    ///
14    /// A check for movement is performed each time the writer is polled
15    /// and when `Drop` is called.
16    ///
17    /// Aside from keeping track of the location at which the writer was first
18    /// polled and providing assertions, this writer adds no runtime behavior
19    /// and simply delegates to the child writer.
20    fn assert_unmoved_write(self) -> AssertUnmoved<Self>
21    where
22        Self: Sized,
23    {
24        AssertUnmoved::new(self)
25    }
26
27    /// Introduces an extra [`Poll::Pending`](futures_core::task::Poll::Pending)
28    /// in between each operation on the writer.
29    ///
30    /// # Examples
31    ///
32    /// ```
33    /// use core::pin::pin;
34    ///
35    /// use futures::task::Poll;
36    /// use futures::io::{AsyncWrite, Cursor};
37    /// use futures_test::task::noop_context;
38    /// use futures_test::io::AsyncWriteTestExt;
39    ///
40    /// let writer = Cursor::new(vec![0u8; 4].into_boxed_slice()).interleave_pending_write();
41    /// let mut writer = pin!(writer);
42    ///
43    /// let mut cx = noop_context();
44    ///
45    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[1, 2])?, Poll::Pending);
46    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[1, 2])?, Poll::Ready(2));
47    /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 0, 0]);
48    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[3, 4])?, Poll::Pending);
49    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[3, 4])?, Poll::Ready(2));
50    /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 3, 4]);
51    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[5, 6])?, Poll::Pending);
52    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[5, 6])?, Poll::Ready(0));
53    ///
54    /// assert_eq!(writer.as_mut().poll_flush(&mut cx)?, Poll::Pending);
55    /// assert_eq!(writer.as_mut().poll_flush(&mut cx)?, Poll::Ready(()));
56    ///
57    /// assert_eq!(writer.as_mut().poll_close(&mut cx)?, Poll::Pending);
58    /// assert_eq!(writer.as_mut().poll_close(&mut cx)?, Poll::Ready(()));
59    ///
60    /// # Ok::<(), std::io::Error>(())
61    /// ```
62    fn interleave_pending_write(self) -> InterleavePending<Self>
63    where
64        Self: Sized,
65    {
66        InterleavePending::new(self)
67    }
68
69    /// Limit the number of bytes allowed to be written on each call to `poll_write`.
70    ///
71    /// # Examples
72    ///
73    /// ```
74    /// use core::pin::pin;
75    ///
76    /// use futures::task::Poll;
77    /// use futures::io::{AsyncWrite, Cursor};
78    /// use futures_test::task::noop_context;
79    /// use futures_test::io::AsyncWriteTestExt;
80    ///
81    /// let writer = Cursor::new(vec![0u8; 4].into_boxed_slice()).limited_write(2);
82    /// let mut writer = pin!(writer);
83    ///
84    /// let mut cx = noop_context();
85    ///
86    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[1, 2])?, Poll::Ready(2));
87    /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 0, 0]);
88    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[3])?, Poll::Ready(1));
89    /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 3, 0]);
90    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[4, 5])?, Poll::Ready(1));
91    /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 3, 4]);
92    /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[5])?, Poll::Ready(0));
93    ///
94    /// # Ok::<(), std::io::Error>(())
95    /// ```
96    fn limited_write(self, limit: usize) -> Limited<Self>
97    where
98        Self: Sized,
99    {
100        Limited::new(self, limit)
101    }
102
103    /// Track whether this stream has been closed and errors if it is used after closing.
104    ///
105    /// # Examples
106    ///
107    /// ```
108    /// # futures::executor::block_on(async {
109    /// use futures::io::{AsyncWriteExt, Cursor};
110    /// use futures_test::io::AsyncWriteTestExt;
111    ///
112    /// let mut writer = Cursor::new(vec![0u8; 4]).track_closed();
113    ///
114    /// writer.write_all(&[1, 2]).await?;
115    /// assert!(!writer.is_closed());
116    /// writer.close().await?;
117    /// assert!(writer.is_closed());
118    ///
119    /// # Ok::<(), std::io::Error>(()) })?;
120    /// # Ok::<(), std::io::Error>(())
121    /// ```
122    ///
123    /// ```
124    /// # futures::executor::block_on(async {
125    /// use futures::io::{AsyncWriteExt, Cursor};
126    /// use futures_test::io::AsyncWriteTestExt;
127    ///
128    /// let mut writer = Cursor::new(vec![0u8; 4]).track_closed();
129    ///
130    /// writer.close().await?;
131    /// assert!(writer.write_all(&[1, 2]).await.is_err());
132    /// # Ok::<(), std::io::Error>(()) })?;
133    /// # Ok::<(), std::io::Error>(())
134    /// ```
135    fn track_closed(self) -> TrackClosed<Self>
136    where
137        Self: Sized,
138    {
139        TrackClosed::new(self)
140    }
141}
142
143impl<W> AsyncWriteTestExt for W where W: AsyncWrite {}