actix_http/test/
test_seq_buffer.rs1use std::{
2 cell::{Ref, RefCell},
3 io::{self, Read, Write},
4 pin::Pin,
5 rc::Rc,
6 task::{Context, Poll},
7};
8
9use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
10use bytes::{Bytes, BytesMut};
11
12#[derive(Clone)]
14pub struct TestSeqBuffer(Rc<RefCell<TestSeqInner>>);
15
16impl TestSeqBuffer {
17 pub fn new<T>(data: T) -> Self
19 where
20 T: Into<BytesMut>,
21 {
22 Self(Rc::new(RefCell::new(TestSeqInner {
23 read_buf: data.into(),
24 read_closed: false,
25 write_buf: BytesMut::new(),
26 err: None,
27 })))
28 }
29
30 pub fn empty() -> Self {
32 Self::new(BytesMut::new())
33 }
34
35 pub fn read_buf(&self) -> Ref<'_, BytesMut> {
36 Ref::map(self.0.borrow(), |inner| &inner.read_buf)
37 }
38
39 pub fn write_buf(&self) -> Ref<'_, BytesMut> {
40 Ref::map(self.0.borrow(), |inner| &inner.write_buf)
41 }
42
43 pub fn take_write_buf(&self) -> Bytes {
44 self.0.borrow_mut().write_buf.split().freeze()
45 }
46
47 pub fn err(&self) -> Ref<'_, Option<io::Error>> {
48 Ref::map(self.0.borrow(), |inner| &inner.err)
49 }
50
51 pub fn extend_read_buf<T: AsRef<[u8]>>(&mut self, data: T) {
57 let mut inner = self.0.borrow_mut();
58 if inner.read_closed {
59 panic!("Tried to extend the read buffer after calling close_read");
60 }
61
62 inner.read_buf.extend_from_slice(data.as_ref())
63 }
64
65 pub fn close_read(&self) {
70 self.0.borrow_mut().read_closed = true;
71 }
72}
73
74pub struct TestSeqInner {
75 read_buf: BytesMut,
76 read_closed: bool,
77 write_buf: BytesMut,
78 err: Option<io::Error>,
79}
80
81impl io::Read for TestSeqBuffer {
82 fn read(&mut self, dst: &mut [u8]) -> Result<usize, io::Error> {
83 let mut inner = self.0.borrow_mut();
84
85 if inner.read_buf.is_empty() {
86 if let Some(err) = inner.err.take() {
87 Err(err)
88 } else if inner.read_closed {
89 Ok(0)
90 } else {
91 Err(io::Error::new(io::ErrorKind::WouldBlock, ""))
92 }
93 } else {
94 let size = std::cmp::min(inner.read_buf.len(), dst.len());
95 let b = inner.read_buf.split_to(size);
96 dst[..size].copy_from_slice(&b);
97 Ok(size)
98 }
99 }
100}
101
102impl io::Write for TestSeqBuffer {
103 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
104 self.0.borrow_mut().write_buf.extend(buf);
105 Ok(buf.len())
106 }
107
108 fn flush(&mut self) -> io::Result<()> {
109 Ok(())
110 }
111}
112
113impl AsyncRead for TestSeqBuffer {
114 fn poll_read(
115 self: Pin<&mut Self>,
116 _: &mut Context<'_>,
117 buf: &mut ReadBuf<'_>,
118 ) -> Poll<io::Result<()>> {
119 let dst = buf.initialize_unfilled();
120 let r = self.get_mut().read(dst);
121 match r {
122 Ok(n) => {
123 buf.advance(n);
124 Poll::Ready(Ok(()))
125 }
126 Err(err) if err.kind() == io::ErrorKind::WouldBlock => Poll::Pending,
127 Err(err) => Poll::Ready(Err(err)),
128 }
129 }
130}
131
132impl AsyncWrite for TestSeqBuffer {
133 fn poll_write(
134 self: Pin<&mut Self>,
135 _: &mut Context<'_>,
136 buf: &[u8],
137 ) -> Poll<io::Result<usize>> {
138 Poll::Ready(self.get_mut().write(buf))
139 }
140
141 fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
142 Poll::Ready(Ok(()))
143 }
144
145 fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
146 Poll::Ready(Ok(()))
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use std::{io, task::Context};
153
154 use futures_util::task::noop_waker_ref;
155 use tokio_test::{assert_pending, assert_ready_err, assert_ready_ok};
156
157 use super::*;
158
159 #[test]
160 fn buffer_read_write() {
161 let mut buffer = TestSeqBuffer::new("read");
162 let clone = buffer.clone();
163
164 assert_eq!(buffer.read_buf().as_ref(), b"read");
165 assert!(buffer.err().is_none());
166 buffer.extend_read_buf("!");
167
168 let mut read = [0; 5];
169 assert_eq!(io::Read::read(&mut buffer, &mut read).unwrap(), 5);
170 assert_eq!(&read, b"read!");
171
172 io::Write::write_all(&mut buffer, b"write").unwrap();
173 io::Write::flush(&mut buffer).unwrap();
174 assert_eq!(buffer.write_buf().as_ref(), b"write");
175 assert_eq!(clone.take_write_buf(), Bytes::from_static(b"write"));
176 assert!(buffer.write_buf().is_empty());
177
178 assert_eq!(
179 io::Read::read(&mut buffer, &mut []).unwrap_err().kind(),
180 io::ErrorKind::WouldBlock
181 );
182 buffer.close_read();
183 assert_eq!(io::Read::read(&mut buffer, &mut []).unwrap(), 0);
184
185 let mut error = TestSeqBuffer::empty();
186 error.0.borrow_mut().err = Some(io::Error::other("error"));
187 assert_eq!(
188 io::Read::read(&mut error, &mut []).unwrap_err().to_string(),
189 "error"
190 );
191 }
192
193 #[test]
194 fn buffer_async_io() {
195 let mut cx = Context::from_waker(noop_waker_ref());
196
197 let mut pending = TestSeqBuffer::empty();
198 let mut read = [];
199 let mut read_buf = ReadBuf::new(&mut read);
200 assert_pending!(Pin::new(&mut pending).poll_read(&mut cx, &mut read_buf));
201
202 let mut buffer = TestSeqBuffer::new("read");
203 let mut read = [0; 4];
204 let mut read_buf = ReadBuf::new(&mut read);
205 assert_ready_ok!(Pin::new(&mut buffer).poll_read(&mut cx, &mut read_buf));
206 assert_eq!(read_buf.filled(), b"read");
207
208 let mut error = TestSeqBuffer::empty();
209 error.0.borrow_mut().err = Some(io::Error::other("error"));
210 let mut read = [];
211 let mut read_buf = ReadBuf::new(&mut read);
212 let error = assert_ready_err!(
213 Pin::new(&mut error).poll_read(&mut cx, &mut read_buf),
214 "expected a ready error"
215 );
216 assert_eq!(error.to_string(), "error");
217
218 let mut buffer = TestSeqBuffer::empty();
219 let written = assert_ready_ok!(
220 Pin::new(&mut buffer).poll_write(&mut cx, b"write"),
221 "expected a successful write"
222 );
223 assert_eq!(written, 5);
224 assert_ready_ok!(Pin::new(&mut buffer).poll_flush(&mut cx));
225 assert_ready_ok!(Pin::new(&mut buffer).poll_shutdown(&mut cx));
226 }
227
228 #[test]
229 #[should_panic(expected = "Tried to extend the read buffer")]
230 fn extend_read_buf_after_close_panics() {
231 let mut buffer = TestSeqBuffer::empty();
232 buffer.close_read();
233 buffer.extend_read_buf("data");
234 }
235}