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 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 /// ```
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 /// ```
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 /// ```
133 fn track_closed(self) -> TrackClosed<Self>
134 where
135 Self: Sized,
136 {
137 TrackClosed::new(self)
138 }
139}
140
141impl<W> AsyncWriteTestExt for W where W: AsyncWrite {}
142