#![allow(dead_code, unused_macros)]
use fire::Body;
use fire_http as fire;
use hyper_util::rt::TokioExecutor;
use types::body::BodyHttp;
use std::io;
macro_rules! spawn_server {
(|$builder:ident| $block:block) => {{
use std::net::{Ipv4Addr, SocketAddr};
let socket_addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0);
let mut $builder = fire::build(socket_addr).await.unwrap();
let _ = $block;
let fire = $builder.build().await.unwrap();
let addr = fire.local_addr().unwrap();
tokio::task::spawn(fire.ignite());
addr
}};
}
macro_rules! other_err {
($e:expr) => {
io::Error::new(io::ErrorKind::Other, $e)
};
}
pub async fn send_request(
req: hyper::Request<BodyHttp>,
) -> io::Result<hyper::Response<hyper::body::Incoming>> {
let client =
hyper_util::client::legacy::Client::builder(TokioExecutor::new())
.build_http();
client
.request(req.map(Box::pin))
.await
.map_err(|e| other_err!(e))
}
macro_rules! make_request {
(
$method:expr, $srv_addr:expr, $uri:expr,
|$builder:ident| $block:block
) => {
async {
let addr = $srv_addr.to_string();
let uri = format!("http://{addr}{}", $uri);
let $builder = hyper::Request::builder()
.method($method)
.uri(uri)
.header("host", &addr);
let resp = util::send_request($block)
.await
.expect("failed to send request")
.map(fire::Body::from_hyper);
util::TestResponse::new(resp)
}
};
($method:expr, $srv_addr:expr, $uri:expr, $body:expr) => {
make_request!($method, $srv_addr, $uri, |builder| {
builder
.body(fire::Body::into_http_body($body.into()))
.expect("could not build request")
})
};
($method:expr, $srv_addr:expr, $uri:expr) => {
make_request!($method, $srv_addr, $uri, fire::Body::new())
};
}
#[derive(Debug)]
pub struct TestResponse {
inner: hyper::Response<Body>,
}
impl TestResponse {
pub fn new(inner: hyper::Response<Body>) -> Self {
Self { inner }
}
#[track_caller]
pub fn assert_status(self, other: u16) -> Self {
assert_eq!(
self.inner.status().as_u16(),
other,
"status code doens't match"
);
self
}
#[track_caller]
pub fn assert_header(self, key: &str, value: impl AsRef<str>) -> Self {
let v = self
.inner
.headers()
.get(key)
.expect(&format!("header with key {:?} not found", key))
.to_str()
.expect("header does not only contain visible ASCII chars");
assert_eq!(v, value.as_ref(), "value does not match");
self
}
#[track_caller]
pub fn assert_not_header(self, key: &str) -> Self {
if self.inner.headers().get(key).is_some() {
panic!("expected no header named {}", key);
}
self
}
pub fn header(&self, key: &str) -> Option<&str> {
self.inner.headers().get(key).and_then(|v| v.to_str().ok())
}
pub async fn assert_body_str(mut self, value: &str) -> Self {
let body = self
.inner
.body_mut()
.take()
.into_string()
.await
.expect("could not convert response body to string");
assert_eq!(body, value, "body does not match value");
self
}
pub async fn assert_body_vec(mut self, value: &[u8]) -> Self {
let body = self
.inner
.body_mut()
.take()
.into_bytes()
.await
.expect("could not convert response body to vec");
assert_eq!(body, value, "body does not match value");
self
}
}