test: adding benchmarks (#26)

This commit is contained in:
Christof Weickhardt 2022-04-13 04:29:52 +02:00 committed by GitHub
parent c25de2e313
commit f9db949910
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 204 additions and 2 deletions

View File

@ -22,6 +22,7 @@ include = [
hyper = { version = "0.14", features = ["full"] }
lazy_static = "1.4"
hyper-tls = { version = "0.5", optional = true }
rand = "0.8.5"
[dev-dependencies]
tokio = { version = "1", features = ["full"] }
@ -33,4 +34,4 @@ tokiotest-httpserver = "0.2.0"
[features]
https = ["hyper-tls"]
default = ["https"]
default = ["https"]

View File

@ -94,7 +94,10 @@
//! }
//! }
//! ```
//!
#![cfg_attr(all(not(stable), test), feature(test))]
#[cfg(all(not(stable), test))]
extern crate test;
use hyper::client::{connect::dns::GaiResolver, HttpConnector};
use hyper::header::{HeaderMap, HeaderValue, HeaderName, HOST};
@ -253,3 +256,201 @@ pub async fn call(
let proxied_response = create_proxied_response(response);
Ok(proxied_response)
}
#[cfg(all(not(stable), test))]
mod tests {
use rand::distributions::Alphanumeric;
use rand::prelude::*;
use hyper::header::HeaderName;
use hyper::Uri;
use hyper::{HeaderMap, Request, Response};
use std::net::Ipv4Addr;
use std::str::FromStr;
use test::Bencher;
use test_context::AsyncTestContext;
use tokiotest_httpserver::HttpTestContext;
fn generate_string() -> String {
let take = rand::thread_rng().gen::<u8>().into();
rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(take)
.map(char::from)
.collect()
}
fn build_headers() -> HeaderMap {
let mut headers_map: HeaderMap = (&*super::HOP_HEADERS)
.iter()
.map(|el: &'static HeaderName| (el.clone(), generate_string().parse().unwrap()))
.collect();
for _i in 0..20 {
'inserted: loop {
if let Ok(value) =
hyper::header::HeaderName::from_str(&generate_string().to_lowercase())
{
headers_map.insert(value, generate_string().parse().unwrap());
break 'inserted;
}
}
}
headers_map
}
#[bench]
fn proxy_call(b: &mut Bencher) {
use tokio::runtime::Runtime;
let rt = Runtime::new().unwrap();
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world");
let http_context: HttpTestContext = rt.block_on(async { AsyncTestContext::setup().await });
let forward_url = &format!("http://0.0.0.0:{}", http_context.port);
let headers_map = build_headers();
let client_ip = std::net::IpAddr::from(Ipv4Addr::from_str("0.0.0.0").unwrap());
b.iter(|| {
rt.block_on(async {
let mut request = Request::builder().uri(uri.clone());
*request.headers_mut().unwrap() = headers_map.clone();
super::call(
client_ip,
forward_url,
request.body(hyper::Body::from("")).unwrap(),
)
.await
.unwrap();
})
});
}
#[bench]
fn create_proxied_response(b: &mut Bencher) {
let headers_map = build_headers();
b.iter(|| {
let mut response = Response::builder().status(200);
*response.headers_mut().unwrap() = headers_map.clone();
super::create_proxied_response(response.body(()).unwrap(), hyper::header::HeaderValue::from_static("me"));
});
}
#[bench]
fn forward_url_with_str_ending_slash(b: &mut Bencher) {
let uri = Uri::from_static("http://0.0.0.0:8080/me");
let port = rand::thread_rng().gen::<u8>();
let forward_url = &format!("http://0.0.0.0:{}/", port);
b.iter(|| {
let request = Request::builder().uri(uri.clone()).body(());
super::forward_uri(forward_url, &request.unwrap());
});
}
#[bench]
fn forward_url_with_str_ending_slash_and_query(b: &mut Bencher) {
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world");
let port = rand::thread_rng().gen::<u8>();
let forward_url = &format!("http://0.0.0.0:{}/", port);
b.iter(|| {
let request = Request::builder().uri(uri.clone()).body(());
super::forward_uri(forward_url, &request.unwrap());
});
}
#[bench]
fn forward_url_no_ending_slash(b: &mut Bencher) {
let uri = Uri::from_static("http://0.0.0.0:8080/me");
let port = rand::thread_rng().gen::<u8>();
let forward_url = &format!("http://0.0.0.0:{}", port);
b.iter(|| {
let request = Request::builder().uri(uri.clone()).body(());
super::forward_uri(forward_url, &request.unwrap());
});
}
#[bench]
fn forward_url_with_query(b: &mut Bencher) {
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world");
let port = rand::thread_rng().gen::<u8>();
let forward_url = &format!("http://0.0.0.0:{}", port);
b.iter(|| {
let request = Request::builder().uri(uri.clone()).body(());
super::forward_uri(forward_url, &request.unwrap());
});
}
#[bench]
fn create_proxied_request_forwarded_for_occupied(b: &mut Bencher) {
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world");
let port = rand::thread_rng().gen::<u8>();
let forward_url = &format!("http://0.0.0.0:{}", port);
let mut headers_map = build_headers();
headers_map.insert(
HeaderName::from_static("x-forwarded-for"),
"0.0.0.0".parse().unwrap(),
);
let client_ip = std::net::IpAddr::from(Ipv4Addr::from_str("0.0.0.0").unwrap());
b.iter(|| {
let mut request = Request::builder().uri(uri.clone());
*request.headers_mut().unwrap() = headers_map.clone();
super::create_proxied_request(
client_ip,
forward_url,
request.body(()).unwrap(),
)
.unwrap();
});
}
#[bench]
fn create_proxied_request_forwarded_for_vacant(b: &mut Bencher) {
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world");
let port = rand::thread_rng().gen::<u8>();
let forward_url = &format!("http://0.0.0.0:{}", port);
let headers_map = build_headers();
let client_ip = std::net::IpAddr::from(Ipv4Addr::from_str("0.0.0.0").unwrap());
b.iter(|| {
let mut request = Request::builder().uri(uri.clone());
*request.headers_mut().unwrap() = headers_map.clone();
super::create_proxied_request(
client_ip,
forward_url,
request.body(()).unwrap(),
)
.unwrap();
});
}
}