1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 16:02:59 +01:00

update tests

This commit is contained in:
Nikolay Kim 2017-12-14 20:29:49 -08:00
parent a2dff8a0b9
commit 2b0994e448
4 changed files with 59 additions and 41 deletions

View File

@ -74,14 +74,14 @@ As a testing tool i used `wrk` and following commands
I ran all tests on localhost on MacBook Pro late 2017. It has 4 cpu and 8 logical cpus. I ran all tests on localhost on MacBook Pro late 2017. It has 4 cpu and 8 logical cpus.
Each result is best of five runs. All measurements are req/sec. Each result is best of five runs. All measurements are req/sec.
Name | 1 thread | 1 pipeline | 3 thread | 3 pipeline | 8 thread | 8 pipeline | Name | 1 thread | 1 pipeline | 3 thread | 3 pipeline | 8 thread | 8 pipeline
--- | --- | --- | --- | --- | --- | ---- | -------- | ---------- | -------- | ---------- | -------- | ----------
Actix | 81400 | 710200 | 121000 | 1684000 | 106300 | 2206000 | Actix | 81400 | 710200 | 121000 | 1684000 | 106300 | 2206000
Gotham | 61000 | 178000 | | | | | Gotham | 61000 | 178000 | | | |
Iron | | | | | 94500 | 78000 | Iron | | | | | 94500 | 78000
Rocket | | | | | 95500 | failed | Rocket | | | | | 95500 | failed
Shio | 71800 | 317800 | | | | | Shio | 71800 | 317800 | | | | |
tokio-minihttp | 106900 | 1047000 | | | | | tokio-minihttp | 106900 | 1047000 | | | |
Some notes on results. Iron and Rocket got tested with 8 threads, Some notes on results. Iron and Rocket got tested with 8 threads,
which showed best results. Gothan and tokio-minihttp seem does not support which showed best results. Gothan and tokio-minihttp seem does not support

View File

@ -11,7 +11,7 @@ use middlewares::Middleware;
use server::ServerSettings; use server::ServerSettings;
/// Application /// Application
pub struct HttpApplication<S> { pub struct HttpApplication<S=()> {
state: Rc<S>, state: Rc<S>,
prefix: String, prefix: String,
default: Resource<S>, default: Resource<S>,

View File

@ -959,6 +959,8 @@ mod tests {
use tokio_io::AsyncRead; use tokio_io::AsyncRead;
use http::{Version, Method}; use http::{Version, Method};
use super::*; use super::*;
use application::HttpApplication;
use server::WorkerSettings;
struct Buffer { struct Buffer {
buf: Bytes, buf: Bytes,
@ -1006,13 +1008,14 @@ mod tests {
} }
macro_rules! parse_ready { macro_rules! parse_ready {
($e:expr) => ( ($e:expr) => ({
match Reader::new().parse($e, &mut BytesMut::new()) { let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
match Reader::new().parse($e, &mut BytesMut::new(), &settings) {
Ok(Async::Ready(Item::Http1(req))) => req, Ok(Async::Ready(Item::Http1(req))) => req,
Ok(_) => panic!("Eof during parsing http request"), Ok(_) => panic!("Eof during parsing http request"),
Err(err) => panic!("Error during parsing http request: {:?}", err), Err(err) => panic!("Error during parsing http request: {:?}", err),
} }
) })
} }
macro_rules! reader_parse_ready { macro_rules! reader_parse_ready {
@ -1028,7 +1031,9 @@ mod tests {
macro_rules! expect_parse_err { macro_rules! expect_parse_err {
($e:expr) => ({ ($e:expr) => ({
let mut buf = BytesMut::new(); let mut buf = BytesMut::new();
match Reader::new().parse($e, &mut buf) { let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
match Reader::new().parse($e, &mut buf, &settings) {
Err(err) => match err { Err(err) => match err {
ReaderError::Error(_) => (), ReaderError::Error(_) => (),
_ => panic!("Parse error expected"), _ => panic!("Parse error expected"),
@ -1044,9 +1049,10 @@ mod tests {
fn test_parse() { fn test_parse() {
let mut buf = Buffer::new("GET /test HTTP/1.1\r\n\r\n"); let mut buf = Buffer::new("GET /test HTTP/1.1\r\n\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::Ready(Item::Http1(req))) => { Ok(Async::Ready(Item::Http1(req))) => {
assert_eq!(req.version(), Version::HTTP_11); assert_eq!(req.version(), Version::HTTP_11);
assert_eq!(*req.method(), Method::GET); assert_eq!(*req.method(), Method::GET);
@ -1061,15 +1067,16 @@ mod tests {
fn test_parse_partial() { fn test_parse_partial() {
let mut buf = Buffer::new("PUT /test HTTP/1"); let mut buf = Buffer::new("PUT /test HTTP/1");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::NotReady) => (), Ok(Async::NotReady) => (),
_ => panic!("Error"), _ => panic!("Error"),
} }
buf.feed_data(".1\r\n\r\n"); buf.feed_data(".1\r\n\r\n");
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::Ready(Item::Http1(req))) => { Ok(Async::Ready(Item::Http1(req))) => {
assert_eq!(req.version(), Version::HTTP_11); assert_eq!(req.version(), Version::HTTP_11);
assert_eq!(*req.method(), Method::PUT); assert_eq!(*req.method(), Method::PUT);
@ -1084,9 +1091,10 @@ mod tests {
fn test_parse_post() { fn test_parse_post() {
let mut buf = Buffer::new("POST /test2 HTTP/1.0\r\n\r\n"); let mut buf = Buffer::new("POST /test2 HTTP/1.0\r\n\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::Ready(Item::Http1(req))) => { Ok(Async::Ready(Item::Http1(req))) => {
assert_eq!(req.version(), Version::HTTP_10); assert_eq!(req.version(), Version::HTTP_10);
assert_eq!(*req.method(), Method::POST); assert_eq!(*req.method(), Method::POST);
@ -1101,9 +1109,10 @@ mod tests {
fn test_parse_body() { fn test_parse_body() {
let mut buf = Buffer::new("GET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody"); let mut buf = Buffer::new("GET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::Ready(Item::Http1(mut req))) => { Ok(Async::Ready(Item::Http1(mut req))) => {
assert_eq!(req.version(), Version::HTTP_11); assert_eq!(req.version(), Version::HTTP_11);
assert_eq!(*req.method(), Method::GET); assert_eq!(*req.method(), Method::GET);
@ -1119,9 +1128,10 @@ mod tests {
let mut buf = Buffer::new( let mut buf = Buffer::new(
"\r\nGET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody"); "\r\nGET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::Ready(Item::Http1(mut req))) => { Ok(Async::Ready(Item::Http1(mut req))) => {
assert_eq!(req.version(), Version::HTTP_11); assert_eq!(req.version(), Version::HTTP_11);
assert_eq!(*req.method(), Method::GET); assert_eq!(*req.method(), Method::GET);
@ -1136,12 +1146,13 @@ mod tests {
fn test_parse_partial_eof() { fn test_parse_partial_eof() {
let mut buf = Buffer::new("GET /test HTTP/1.1\r\n"); let mut buf = Buffer::new("GET /test HTTP/1.1\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
not_ready!{ reader.parse(&mut buf, &mut readbuf) } not_ready!{ reader.parse(&mut buf, &mut readbuf, &settings) }
buf.feed_data("\r\n"); buf.feed_data("\r\n");
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::Ready(Item::Http1(req))) => { Ok(Async::Ready(Item::Http1(req))) => {
assert_eq!(req.version(), Version::HTTP_11); assert_eq!(req.version(), Version::HTTP_11);
assert_eq!(*req.method(), Method::GET); assert_eq!(*req.method(), Method::GET);
@ -1156,18 +1167,19 @@ mod tests {
fn test_headers_split_field() { fn test_headers_split_field() {
let mut buf = Buffer::new("GET /test HTTP/1.1\r\n"); let mut buf = Buffer::new("GET /test HTTP/1.1\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
not_ready!{ reader.parse(&mut buf, &mut readbuf) } not_ready!{ reader.parse(&mut buf, &mut readbuf, &settings) }
buf.feed_data("t"); buf.feed_data("t");
not_ready!{ reader.parse(&mut buf, &mut readbuf) } not_ready!{ reader.parse(&mut buf, &mut readbuf, &settings) }
buf.feed_data("es"); buf.feed_data("es");
not_ready!{ reader.parse(&mut buf, &mut readbuf) } not_ready!{ reader.parse(&mut buf, &mut readbuf, &settings) }
buf.feed_data("t: value\r\n\r\n"); buf.feed_data("t: value\r\n\r\n");
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::Ready(Item::Http1(req))) => { Ok(Async::Ready(Item::Http1(req))) => {
assert_eq!(req.version(), Version::HTTP_11); assert_eq!(req.version(), Version::HTTP_11);
assert_eq!(*req.method(), Method::GET); assert_eq!(*req.method(), Method::GET);
@ -1186,9 +1198,10 @@ mod tests {
Set-Cookie: c1=cookie1\r\n\ Set-Cookie: c1=cookie1\r\n\
Set-Cookie: c2=cookie2\r\n\r\n"); Set-Cookie: c2=cookie2\r\n\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::Ready(Item::Http1(req))) => { Ok(Async::Ready(Item::Http1(req))) => {
let val: Vec<_> = req.headers().get_all("Set-Cookie") let val: Vec<_> = req.headers().get_all("Set-Cookie")
.iter().map(|v| v.to_str().unwrap().to_owned()).collect(); .iter().map(|v| v.to_str().unwrap().to_owned()).collect();
@ -1420,14 +1433,15 @@ mod tests {
"GET /test HTTP/1.1\r\n\ "GET /test HTTP/1.1\r\n\
transfer-encoding: chunked\r\n\r\n"); transfer-encoding: chunked\r\n\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
let mut req = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf)); let mut req = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
assert!(req.chunked().unwrap()); assert!(req.chunked().unwrap());
assert!(!req.payload().unwrap().eof()); assert!(!req.payload().unwrap().eof());
buf.feed_data("4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); buf.feed_data("4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n");
not_ready!(reader.parse(&mut buf, &mut readbuf)); not_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
assert!(!req.payload().unwrap().eof()); assert!(!req.payload().unwrap().eof());
assert_eq!(req.payload_mut().unwrap().readall().unwrap().as_ref(), b"dataline"); assert_eq!(req.payload_mut().unwrap().readall().unwrap().as_ref(), b"dataline");
assert!(req.payload().unwrap().eof()); assert!(req.payload().unwrap().eof());
@ -1439,10 +1453,11 @@ mod tests {
"GET /test HTTP/1.1\r\n\ "GET /test HTTP/1.1\r\n\
transfer-encoding: chunked\r\n\r\n"); transfer-encoding: chunked\r\n\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
let mut req = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf)); let mut req = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
assert!(req.chunked().unwrap()); assert!(req.chunked().unwrap());
assert!(!req.payload().unwrap().eof()); assert!(!req.payload().unwrap().eof());
@ -1451,7 +1466,7 @@ mod tests {
POST /test2 HTTP/1.1\r\n\ POST /test2 HTTP/1.1\r\n\
transfer-encoding: chunked\r\n\r\n"); transfer-encoding: chunked\r\n\r\n");
let req2 = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf)); let req2 = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
assert_eq!(*req2.method(), Method::POST); assert_eq!(*req2.method(), Method::POST);
assert!(req2.chunked().unwrap()); assert!(req2.chunked().unwrap());
assert!(!req2.payload().unwrap().eof()); assert!(!req2.payload().unwrap().eof());
@ -1466,28 +1481,29 @@ mod tests {
"GET /test HTTP/1.1\r\n\ "GET /test HTTP/1.1\r\n\
transfer-encoding: chunked\r\n\r\n"); transfer-encoding: chunked\r\n\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
let mut req = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf)); let mut req = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
assert!(req.chunked().unwrap()); assert!(req.chunked().unwrap());
assert!(!req.payload().unwrap().eof()); assert!(!req.payload().unwrap().eof());
buf.feed_data("4\r\ndata\r"); buf.feed_data("4\r\ndata\r");
not_ready!(reader.parse(&mut buf, &mut readbuf)); not_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
buf.feed_data("\n4"); buf.feed_data("\n4");
not_ready!(reader.parse(&mut buf, &mut readbuf)); not_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
buf.feed_data("\r"); buf.feed_data("\r");
not_ready!(reader.parse(&mut buf, &mut readbuf)); not_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
buf.feed_data("\n"); buf.feed_data("\n");
not_ready!(reader.parse(&mut buf, &mut readbuf)); not_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
buf.feed_data("li"); buf.feed_data("li");
not_ready!(reader.parse(&mut buf, &mut readbuf)); not_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
buf.feed_data("ne\r\n0\r\n"); buf.feed_data("ne\r\n0\r\n");
not_ready!(reader.parse(&mut buf, &mut readbuf)); not_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
//buf.feed_data("test: test\r\n"); //buf.feed_data("test: test\r\n");
//not_ready!(reader.parse(&mut buf, &mut readbuf)); //not_ready!(reader.parse(&mut buf, &mut readbuf));
@ -1496,7 +1512,7 @@ mod tests {
assert!(!req.payload().unwrap().eof()); assert!(!req.payload().unwrap().eof());
buf.feed_data("\r\n"); buf.feed_data("\r\n");
not_ready!(reader.parse(&mut buf, &mut readbuf)); not_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
assert!(req.payload().unwrap().eof()); assert!(req.payload().unwrap().eof());
} }
@ -1506,14 +1522,15 @@ mod tests {
"GET /test HTTP/1.1\r\n\ "GET /test HTTP/1.1\r\n\
transfer-encoding: chunked\r\n\r\n"); transfer-encoding: chunked\r\n\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
let mut req = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf)); let mut req = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
assert!(req.chunked().unwrap()); assert!(req.chunked().unwrap());
assert!(!req.payload().unwrap().eof()); assert!(!req.payload().unwrap().eof());
buf.feed_data("4;test\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); // test: test\r\n\r\n") buf.feed_data("4;test\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); // test: test\r\n\r\n")
not_ready!(reader.parse(&mut buf, &mut readbuf)); not_ready!(reader.parse(&mut buf, &mut readbuf, &settings));
assert!(!req.payload().unwrap().eof()); assert!(!req.payload().unwrap().eof());
assert_eq!(req.payload_mut().unwrap().readall().unwrap().as_ref(), b"dataline"); assert_eq!(req.payload_mut().unwrap().readall().unwrap().as_ref(), b"dataline");
assert!(req.payload().unwrap().eof()); assert!(req.payload().unwrap().eof());
@ -1540,9 +1557,10 @@ mod tests {
fn test_http2_prefix() { fn test_http2_prefix() {
let mut buf = Buffer::new("PRI * HTTP/2.0\r\n\r\n"); let mut buf = Buffer::new("PRI * HTTP/2.0\r\n\r\n");
let mut readbuf = BytesMut::new(); let mut readbuf = BytesMut::new();
let settings = WorkerSettings::<HttpApplication>::new(Vec::new(), None);
let mut reader = Reader::new(); let mut reader = Reader::new();
match reader.parse(&mut buf, &mut readbuf) { match reader.parse(&mut buf, &mut readbuf, &settings) {
Ok(Async::Ready(Item::Http2)) => (), Ok(Async::Ready(Item::Http2)) => (),
Ok(_) | Err(_) => panic!("Error during parsing http request"), Ok(_) | Err(_) => panic!("Error during parsing http request"),
} }

View File

@ -418,7 +418,7 @@ pub(crate) struct WorkerSettings<H> {
} }
impl<H> WorkerSettings<H> { impl<H> WorkerSettings<H> {
fn new(h: Vec<H>, keep_alive: Option<u64>) -> WorkerSettings<H> { pub(crate) fn new(h: Vec<H>, keep_alive: Option<u64>) -> WorkerSettings<H> {
WorkerSettings { WorkerSettings {
h: h, h: h,
enabled: if let Some(ka) = keep_alive { ka > 0 } else { false }, enabled: if let Some(ka) = keep_alive { ka > 0 } else { false },