From f9db949910c91fab946e9eb49bb9ad0d02541cea Mon Sep 17 00:00:00 2001 From: Christof Weickhardt Date: Wed, 13 Apr 2022 04:29:52 +0200 Subject: [PATCH] test: adding benchmarks (#26) --- Cargo.toml | 3 +- src/lib.rs | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 204 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4cb2770..3798bdd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] \ No newline at end of file +default = ["https"] diff --git a/src/lib.rs b/src/lib.rs index 1d363fd..2a049e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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::().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::(); + 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::(); + 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::(); + 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::(); + 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::(); + 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::(); + 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(); + }); + } +} +