Skip to main content

actix_http/test/
test_buffer.rs

1use std::{
2    cell::{Ref, RefCell, RefMut},
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/// Async I/O test buffer.
13#[derive(Debug)]
14pub struct TestBuffer {
15    pub read_buf: Rc<RefCell<BytesMut>>,
16    pub write_buf: Rc<RefCell<BytesMut>>,
17    pub err: Option<Rc<io::Error>>,
18}
19
20impl TestBuffer {
21    /// Create new `TestBuffer` instance with initial read buffer.
22    pub fn new<T>(data: T) -> Self
23    where
24        T: Into<BytesMut>,
25    {
26        Self {
27            read_buf: Rc::new(RefCell::new(data.into())),
28            write_buf: Rc::new(RefCell::new(BytesMut::new())),
29            err: None,
30        }
31    }
32
33    // intentionally not using Clone trait
34    #[allow(dead_code)]
35    pub(crate) fn clone(&self) -> Self {
36        Self {
37            read_buf: Rc::clone(&self.read_buf),
38            write_buf: Rc::clone(&self.write_buf),
39            err: self.err.clone(),
40        }
41    }
42
43    /// Create new empty `TestBuffer` instance.
44    pub fn empty() -> Self {
45        Self::new("")
46    }
47
48    #[allow(dead_code)]
49    pub(crate) fn read_buf_slice(&self) -> Ref<'_, [u8]> {
50        Ref::map(self.read_buf.borrow(), |b| b.as_ref())
51    }
52
53    #[allow(dead_code)]
54    pub(crate) fn read_buf_slice_mut(&self) -> RefMut<'_, [u8]> {
55        RefMut::map(self.read_buf.borrow_mut(), |b| b.as_mut())
56    }
57
58    #[allow(dead_code)]
59    pub(crate) fn write_buf_slice(&self) -> Ref<'_, [u8]> {
60        Ref::map(self.write_buf.borrow(), |b| b.as_ref())
61    }
62
63    #[allow(dead_code)]
64    pub(crate) fn write_buf_slice_mut(&self) -> RefMut<'_, [u8]> {
65        RefMut::map(self.write_buf.borrow_mut(), |b| b.as_mut())
66    }
67
68    #[allow(dead_code)]
69    pub(crate) fn take_write_buf(&self) -> Bytes {
70        self.write_buf.borrow_mut().split().freeze()
71    }
72
73    /// Add data to read buffer.
74    pub fn extend_read_buf<T: AsRef<[u8]>>(&mut self, data: T) {
75        self.read_buf.borrow_mut().extend_from_slice(data.as_ref())
76    }
77}
78
79impl io::Read for TestBuffer {
80    fn read(&mut self, dst: &mut [u8]) -> Result<usize, io::Error> {
81        if self.read_buf.borrow().is_empty() {
82            if self.err.is_some() {
83                Err(Rc::try_unwrap(self.err.take().unwrap()).unwrap())
84            } else {
85                Err(io::Error::new(io::ErrorKind::WouldBlock, ""))
86            }
87        } else {
88            let size = std::cmp::min(self.read_buf.borrow().len(), dst.len());
89            let b = self.read_buf.borrow_mut().split_to(size);
90            dst[..size].copy_from_slice(&b);
91            Ok(size)
92        }
93    }
94}
95
96impl io::Write for TestBuffer {
97    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
98        self.write_buf.borrow_mut().extend(buf);
99        Ok(buf.len())
100    }
101
102    fn flush(&mut self) -> io::Result<()> {
103        Ok(())
104    }
105}
106
107impl AsyncRead for TestBuffer {
108    fn poll_read(
109        self: Pin<&mut Self>,
110        _: &mut Context<'_>,
111        buf: &mut ReadBuf<'_>,
112    ) -> Poll<io::Result<()>> {
113        let dst = buf.initialize_unfilled();
114        match self.get_mut().read(dst) {
115            Ok(n) => {
116                buf.advance(n);
117                Poll::Ready(Ok(()))
118            }
119            Err(err) if err.kind() == io::ErrorKind::WouldBlock => Poll::Pending,
120            Err(err) => Poll::Ready(Err(err)),
121        }
122    }
123}
124
125impl AsyncWrite for TestBuffer {
126    fn poll_write(
127        self: Pin<&mut Self>,
128        _: &mut Context<'_>,
129        buf: &[u8],
130    ) -> Poll<io::Result<usize>> {
131        Poll::Ready(self.get_mut().write(buf))
132    }
133
134    fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
135        Poll::Ready(Ok(()))
136    }
137
138    fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
139        Poll::Ready(Ok(()))
140    }
141}
142
143#[cfg(test)]
144mod tests {
145    use std::{io, task::Context};
146
147    use futures_util::task::noop_waker_ref;
148    use tokio_test::{assert_pending, assert_ready_err, assert_ready_ok};
149
150    use super::*;
151
152    #[test]
153    fn buffer_read_write() {
154        let mut buffer = TestBuffer::new("read");
155        let clone = buffer.clone();
156
157        assert_eq!(&*buffer.read_buf_slice(), b"read");
158        buffer.read_buf_slice_mut()[0] = b'R';
159        assert_eq!(&*buffer.read_buf_slice(), b"Read");
160
161        io::Write::write_all(&mut buffer, b"write").unwrap();
162        assert_eq!(&*buffer.write_buf_slice(), b"write");
163        buffer.write_buf_slice_mut()[0] = b'W';
164        assert_eq!(&*buffer.write_buf_slice(), b"Write");
165        io::Write::flush(&mut buffer).unwrap();
166        assert_eq!(clone.take_write_buf(), Bytes::from_static(b"Write"));
167        assert!(buffer.write_buf_slice().is_empty());
168
169        buffer.extend_read_buf("!");
170        let mut read = [0; 5];
171        assert_eq!(io::Read::read(&mut buffer, &mut read).unwrap(), 5);
172        assert_eq!(&read, b"Read!");
173        assert_eq!(
174            io::Read::read(&mut buffer, &mut read).unwrap_err().kind(),
175            io::ErrorKind::WouldBlock
176        );
177
178        let mut empty = TestBuffer::empty();
179        empty.err = Some(Rc::new(io::Error::other("error")));
180        assert_eq!(
181            io::Read::read(&mut empty, &mut []).unwrap_err().to_string(),
182            "error"
183        );
184    }
185
186    #[test]
187    fn buffer_async_io() {
188        let mut cx = Context::from_waker(noop_waker_ref());
189        let mut buffer = TestBuffer::new("read");
190        let mut read = [0; 4];
191        let mut read_buf = ReadBuf::new(&mut read);
192
193        assert_ready_ok!(Pin::new(&mut buffer).poll_read(&mut cx, &mut read_buf));
194        assert_eq!(read_buf.filled(), b"read");
195
196        let mut empty = TestBuffer::empty();
197        let mut read = [];
198        let mut read_buf = ReadBuf::new(&mut read);
199        assert_pending!(Pin::new(&mut empty).poll_read(&mut cx, &mut read_buf));
200
201        let mut error = TestBuffer::empty();
202        error.err = Some(Rc::new(io::Error::other("error")));
203        let mut read = [];
204        let mut read_buf = ReadBuf::new(&mut read);
205        let error = assert_ready_err!(
206            Pin::new(&mut error).poll_read(&mut cx, &mut read_buf),
207            "expected a ready error"
208        );
209        assert_eq!(error.to_string(), "error");
210
211        let mut buffer = TestBuffer::empty();
212        let written = assert_ready_ok!(
213            Pin::new(&mut buffer).poll_write(&mut cx, b"write"),
214            "expected a successful write"
215        );
216        assert_eq!(written, 5);
217        assert_ready_ok!(Pin::new(&mut buffer).poll_flush(&mut cx));
218        assert_ready_ok!(Pin::new(&mut buffer).poll_shutdown(&mut cx));
219    }
220}