Files
reqwest-impersonate/tests/support/server.rs
Sean McArthur f4100e4148 Rewrite tests with a hyper server instead of raw TCP
This makes the tests much less brittle, by not depending on the exact
order of the HTTP headers, nor always requiring to check for every
single header.
2019-09-23 14:06:01 -07:00

81 lines
2.1 KiB
Rust

use std::convert::Infallible;
use std::future::Future;
use std::net;
use std::sync::mpsc as std_mpsc;
use std::thread;
use std::time::Duration;
use tokio::sync::oneshot;
pub use http::Response;
pub struct Server {
addr: net::SocketAddr,
panic_rx: std_mpsc::Receiver<()>,
shutdown_tx: Option<oneshot::Sender<()>>,
}
impl Server {
pub fn addr(&self) -> net::SocketAddr {
self.addr
}
}
impl Drop for Server {
fn drop(&mut self) {
if let Some(tx) = self.shutdown_tx.take() {
let _ = tx.send(());
}
if !::std::thread::panicking() {
self.panic_rx
.recv_timeout(Duration::from_secs(3))
.expect("test server should not panic");
}
}
}
pub fn http<F, Fut>(func: F) -> Server
where
F: Fn(http::Request<hyper::Body>) -> Fut + Clone + Send + 'static,
Fut: Future<Output = http::Response<hyper::Body>> + Send + 'static,
{
let srv = hyper::Server::bind(&([127, 0, 0, 1], 0).into()).serve(
hyper::service::make_service_fn(move |_| {
let func = func.clone();
async move {
Ok::<_, Infallible>(hyper::service::service_fn(move |req| {
let fut = func(req);
async move { Ok::<_, Infallible>(fut.await) }
}))
}
}),
);
let addr = srv.local_addr();
let (shutdown_tx, shutdown_rx) = oneshot::channel();
let srv = srv.with_graceful_shutdown(async move {
let _ = shutdown_rx.await;
});
let (panic_tx, panic_rx) = std_mpsc::channel();
let tname = format!(
"test({})-support-server",
thread::current().name().unwrap_or("<unknown>")
);
thread::Builder::new()
.name(tname)
.spawn(move || {
let mut rt = tokio::runtime::current_thread::Runtime::new().expect("rt new");
rt.block_on(srv).unwrap();
let _ = panic_tx.send(());
})
.expect("thread spawn");
Server {
addr,
panic_rx,
shutdown_tx: Some(shutdown_tx),
}
}