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 {}