1 //! Additional combinators for testing async writers.
2 
3 use futures_io::AsyncWrite;
4 
5 pub use super::limited::Limited;
6 pub use crate::assert_unmoved::AssertUnmoved;
7 pub use crate::interleave_pending::InterleavePending;
8 pub use crate::track_closed::TrackClosed;
9 
10 /// Additional combinators for testing async writers.
11 pub 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.
assert_unmoved_write(self) -> AssertUnmoved<Self> where Self: Sized,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 futures::task::Poll;
34     /// use futures::io::{AsyncWrite, Cursor};
35     /// use futures_test::task::noop_context;
36     /// use futures_test::io::AsyncWriteTestExt;
37     /// use futures::pin_mut;
38     ///
39     /// let writer = Cursor::new(vec![0u8; 4].into_boxed_slice()).interleave_pending_write();
40     /// pin_mut!(writer);
41     ///
42     /// let mut cx = noop_context();
43     ///
44     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[1, 2])?, Poll::Pending);
45     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[1, 2])?, Poll::Ready(2));
46     /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 0, 0]);
47     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[3, 4])?, Poll::Pending);
48     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[3, 4])?, Poll::Ready(2));
49     /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 3, 4]);
50     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[5, 6])?, Poll::Pending);
51     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[5, 6])?, Poll::Ready(0));
52     ///
53     /// assert_eq!(writer.as_mut().poll_flush(&mut cx)?, Poll::Pending);
54     /// assert_eq!(writer.as_mut().poll_flush(&mut cx)?, Poll::Ready(()));
55     ///
56     /// assert_eq!(writer.as_mut().poll_close(&mut cx)?, Poll::Pending);
57     /// assert_eq!(writer.as_mut().poll_close(&mut cx)?, Poll::Ready(()));
58     ///
59     /// # Ok::<(), std::io::Error>(())
60     /// ```
interleave_pending_write(self) -> InterleavePending<Self> where Self: Sized,61     fn interleave_pending_write(self) -> InterleavePending<Self>
62     where
63         Self: Sized,
64     {
65         InterleavePending::new(self)
66     }
67 
68     /// Limit the number of bytes allowed to be written on each call to `poll_write`.
69     ///
70     /// # Examples
71     ///
72     /// ```
73     /// use futures::task::Poll;
74     /// use futures::io::{AsyncWrite, Cursor};
75     /// use futures_test::task::noop_context;
76     /// use futures_test::io::AsyncWriteTestExt;
77     /// use futures::pin_mut;
78     ///
79     /// let writer = Cursor::new(vec![0u8; 4].into_boxed_slice()).limited_write(2);
80     /// pin_mut!(writer);
81     ///
82     /// let mut cx = noop_context();
83     ///
84     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[1, 2])?, Poll::Ready(2));
85     /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 0, 0]);
86     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[3])?, Poll::Ready(1));
87     /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 3, 0]);
88     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[4, 5])?, Poll::Ready(1));
89     /// assert_eq!(&writer.get_ref().get_ref()[..], [1, 2, 3, 4]);
90     /// assert_eq!(writer.as_mut().poll_write(&mut cx, &[5])?, Poll::Ready(0));
91     ///
92     /// # Ok::<(), std::io::Error>(())
93     /// ```
limited_write(self, limit: usize) -> Limited<Self> where Self: Sized,94     fn limited_write(self, limit: usize) -> Limited<Self>
95     where
96         Self: Sized,
97     {
98         Limited::new(self, limit)
99     }
100 
101     /// Track whether this stream has been closed and errors if it is used after closing.
102     ///
103     /// # Examples
104     ///
105     /// ```
106     /// # futures::executor::block_on(async {
107     /// use futures::io::{AsyncWriteExt, Cursor};
108     /// use futures_test::io::AsyncWriteTestExt;
109     ///
110     /// let mut writer = Cursor::new(vec![0u8; 4]).track_closed();
111     ///
112     /// writer.write_all(&[1, 2]).await?;
113     /// assert!(!writer.is_closed());
114     /// writer.close().await?;
115     /// assert!(writer.is_closed());
116     ///
117     /// # Ok::<(), std::io::Error>(()) })?;
118     /// # Ok::<(), std::io::Error>(())
119     /// ```
120     ///
121     /// ```
122     /// # futures::executor::block_on(async {
123     /// use futures::io::{AsyncWriteExt, Cursor};
124     /// use futures_test::io::AsyncWriteTestExt;
125     ///
126     /// let mut writer = Cursor::new(vec![0u8; 4]).track_closed();
127     ///
128     /// writer.close().await?;
129     /// assert!(writer.write_all(&[1, 2]).await.is_err());
130     /// # Ok::<(), std::io::Error>(()) })?;
131     /// # Ok::<(), std::io::Error>(())
132     /// ```
track_closed(self) -> TrackClosed<Self> where Self: Sized,133     fn track_closed(self) -> TrackClosed<Self>
134     where
135         Self: Sized,
136     {
137         TrackClosed::new(self)
138     }
139 }
140 
141 impl<W> AsyncWriteTestExt for W where W: AsyncWrite {}
142