diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index cca181c99..cf39b8232 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -815,76 +815,21 @@ where #[cfg(test)] mod tests { - use std::{cmp, io}; - - use actix_codec::{AsyncRead, AsyncWrite}; use actix_service::IntoService; - use bytes::{Buf, Bytes, BytesMut}; use futures::future::{lazy, ok}; use super::*; use crate::error::Error; use crate::h1::{ExpectHandler, UpgradeHandler}; - - struct Buffer { - buf: Bytes, - write_buf: BytesMut, - err: Option, - } - - impl Buffer { - fn new(data: &'static str) -> Buffer { - Buffer { - buf: Bytes::from(data), - write_buf: BytesMut::new(), - err: None, - } - } - } - - impl AsyncRead for Buffer {} - impl io::Read for Buffer { - fn read(&mut self, dst: &mut [u8]) -> Result { - if self.buf.is_empty() { - if self.err.is_some() { - Err(self.err.take().unwrap()) - } else { - Err(io::Error::new(io::ErrorKind::WouldBlock, "")) - } - } else { - let size = cmp::min(self.buf.len(), dst.len()); - let b = self.buf.split_to(size); - dst[..size].copy_from_slice(&b); - Ok(size) - } - } - } - - impl io::Write for Buffer { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.write_buf.extend(buf); - Ok(buf.len()) - } - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } - } - impl AsyncWrite for Buffer { - fn shutdown(&mut self) -> Poll<(), io::Error> { - Ok(Async::Ready(())) - } - fn write_buf(&mut self, _: &mut B) -> Poll { - Ok(Async::NotReady) - } - } + use crate::test::TestBuffer; #[test] fn test_req_parse_err() { let mut sys = actix_rt::System::new("test"); let _ = sys.block_on(lazy(|| { - let buf = Buffer::new("GET /test HTTP/1\r\n\r\n"); + let buf = TestBuffer::new("GET /test HTTP/1\r\n\r\n"); - let mut h1 = Dispatcher::<_, _, _, _, UpgradeHandler>::new( + let mut h1 = Dispatcher::<_, _, _, _, UpgradeHandler>::new( buf, ServiceConfig::default(), CloneableService::new( diff --git a/actix-http/src/test.rs b/actix-http/src/test.rs index 2c5dc502b..3d948ebd4 100644 --- a/actix-http/src/test.rs +++ b/actix-http/src/test.rs @@ -1,8 +1,11 @@ //! Test Various helpers for Actix applications to use during testing. use std::fmt::Write as FmtWrite; +use std::io; use std::str::FromStr; -use bytes::Bytes; +use actix_codec::{AsyncRead, AsyncWrite}; +use bytes::{Buf, Bytes, BytesMut}; +use futures::{Async, Poll}; use http::header::{self, HeaderName, HeaderValue}; use http::{HttpTryFrom, Method, Uri, Version}; use percent_encoding::{percent_encode, USERINFO_ENCODE_SET}; @@ -181,3 +184,67 @@ impl TestRequest { fn parts(parts: &mut Option) -> &mut Inner { parts.as_mut().expect("cannot reuse test request builder") } + +/// Async io buffer +pub struct TestBuffer { + pub read_buf: BytesMut, + pub write_buf: BytesMut, + pub err: Option, +} + +impl TestBuffer { + /// Create new TestBuffer instance + pub fn new(data: T) -> TestBuffer + where + BytesMut: From, + { + TestBuffer { + read_buf: BytesMut::from(data), + write_buf: BytesMut::new(), + err: None, + } + } + + /// Add extra data to read buffer. + pub fn extend_read_buf>(&mut self, data: T) { + self.read_buf.extend_from_slice(data.as_ref()) + } +} + +impl io::Read for TestBuffer { + fn read(&mut self, dst: &mut [u8]) -> Result { + if self.read_buf.is_empty() { + if self.err.is_some() { + Err(self.err.take().unwrap()) + } else { + Err(io::Error::new(io::ErrorKind::WouldBlock, "")) + } + } else { + let size = std::cmp::min(self.read_buf.len(), dst.len()); + let b = self.read_buf.split_to(size); + dst[..size].copy_from_slice(&b); + Ok(size) + } + } +} + +impl io::Write for TestBuffer { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.write_buf.extend(buf); + Ok(buf.len()) + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl AsyncRead for TestBuffer {} + +impl AsyncWrite for TestBuffer { + fn shutdown(&mut self) -> Poll<(), io::Error> { + Ok(Async::Ready(())) + } + fn write_buf(&mut self, _: &mut B) -> Poll { + Ok(Async::NotReady) + } +}