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. |
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 | |
141 | impl<W> AsyncWriteTestExt for W where W: AsyncWrite {} |
142 | |