#![cfg(all(test, feature = "compio"))]
#[cfg(all(test, feature = "compio"))]
mod compio_tests {
use crate::client::HttpEngineLocal;
use crate::runtime::compio_rt::{CompioIo, CompioRuntime, TcpConnector};
fn make_local_engine() -> HttpEngineLocal<CompioRuntime, TcpConnector> {
HttpEngineLocal::<CompioRuntime, TcpConnector>::new()
}
fn make_h2_local_engine() -> HttpEngineLocal<CompioRuntime, TcpConnector> {
HttpEngineLocal::<CompioRuntime, TcpConnector>::builder()
.build_local()
.unwrap()
}
#[test]
fn connect_h1_local_succeeds() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
listener.set_nonblocking(true).unwrap();
let async_listener = async_io::Async::new(listener).unwrap();
compio_runtime::Runtime::new().unwrap().block_on(async {
let client_tcp = async_io::Async::<std::net::TcpStream>::connect(addr)
.await
.unwrap();
let (server_tcp, _) = async_listener.accept().await.unwrap();
compio_runtime::spawn(async move {
use futures_io::AsyncRead;
let mut server = server_tcp;
let mut buf = [0u8; 4096];
while std::future::poll_fn(|cx| {
std::pin::Pin::new(&mut server).poll_read(cx, &mut buf)
})
.await
.unwrap_or(0)
> 0
{}
})
.detach();
let io = CompioIo::new(client_tcp);
let engine = make_local_engine();
let result = engine.connect_h1_local(io).await;
assert!(result.is_ok());
let pooled = result.unwrap();
assert!(matches!(pooled.conn, crate::pool::HttpConnection::H1(_)));
});
}
#[test]
fn connect_h2_prior_knowledge_local_succeeds() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
listener.set_nonblocking(true).unwrap();
let async_listener = async_io::Async::new(listener).unwrap();
compio_runtime::Runtime::new().unwrap().block_on(async {
let client_tcp = async_io::Async::<std::net::TcpStream>::connect(addr)
.await
.unwrap();
let (server_tcp, _) = async_listener.accept().await.unwrap();
compio_runtime::spawn(async move {
let io = CompioIo::new(server_tcp);
let builder = hyper::server::conn::http2::Builder::new(
crate::runtime::executor::completion_executor::<CompioRuntime>(),
);
let _ = builder
.serve_connection(
io,
hyper::service::service_fn(|_req| async {
Ok::<_, std::convert::Infallible>(hyper::Response::new(
http_body_util::Empty::<bytes::Bytes>::new(),
))
}),
)
.await;
})
.detach();
let io = CompioIo::new(client_tcp);
let engine = make_local_engine();
let result = engine.connect_h2_prior_knowledge_local(io).await;
assert!(result.is_ok());
let pooled = result.unwrap();
assert!(matches!(pooled.conn, crate::pool::HttpConnection::H2(_)));
});
}
#[test]
fn connect_plaintext_local_defaults_to_h1() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
listener.set_nonblocking(true).unwrap();
let async_listener = async_io::Async::new(listener).unwrap();
compio_runtime::Runtime::new().unwrap().block_on(async {
let client_tcp = async_io::Async::<std::net::TcpStream>::connect(addr)
.await
.unwrap();
let (server_tcp, _) = async_listener.accept().await.unwrap();
compio_runtime::spawn(async move {
use futures_io::AsyncRead;
let mut server = server_tcp;
let mut buf = [0u8; 4096];
while std::future::poll_fn(|cx| {
std::pin::Pin::new(&mut server).poll_read(cx, &mut buf)
})
.await
.unwrap_or(0)
> 0
{}
})
.detach();
let io = CompioIo::new(client_tcp);
let engine = make_local_engine();
let result = engine.connect_plaintext_local_with_hint(io, false).await;
assert!(result.is_ok());
let pooled = result.unwrap();
assert!(matches!(pooled.conn, crate::pool::HttpConnection::H1(_)));
});
}
#[test]
fn connect_plaintext_local_with_hint_false_uses_h1() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
listener.set_nonblocking(true).unwrap();
let async_listener = async_io::Async::new(listener).unwrap();
compio_runtime::Runtime::new().unwrap().block_on(async {
let client_tcp = async_io::Async::<std::net::TcpStream>::connect(addr)
.await
.unwrap();
let (server_tcp, _) = async_listener.accept().await.unwrap();
compio_runtime::spawn(async move {
use futures_io::AsyncRead;
let mut server = server_tcp;
let mut buf = [0u8; 4096];
while std::future::poll_fn(|cx| {
std::pin::Pin::new(&mut server).poll_read(cx, &mut buf)
})
.await
.unwrap_or(0)
> 0
{}
})
.detach();
let io = CompioIo::new(client_tcp);
let engine = make_local_engine();
let result = engine.connect_plaintext_local_with_hint(io, false).await;
assert!(result.is_ok());
let pooled = result.unwrap();
assert!(matches!(pooled.conn, crate::pool::HttpConnection::H1(_)));
});
}
#[test]
fn connect_plaintext_local_with_hint_true_uses_h2() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
listener.set_nonblocking(true).unwrap();
let async_listener = async_io::Async::new(listener).unwrap();
compio_runtime::Runtime::new().unwrap().block_on(async {
let client_tcp = async_io::Async::<std::net::TcpStream>::connect(addr)
.await
.unwrap();
let (server_tcp, _) = async_listener.accept().await.unwrap();
compio_runtime::spawn(async move {
let io = CompioIo::new(server_tcp);
let builder = hyper::server::conn::http2::Builder::new(
crate::runtime::executor::completion_executor::<CompioRuntime>(),
);
let _ = builder
.serve_connection(
io,
hyper::service::service_fn(|_req| async {
Ok::<_, std::convert::Infallible>(hyper::Response::new(
http_body_util::Empty::<bytes::Bytes>::new(),
))
}),
)
.await;
})
.detach();
let io = CompioIo::new(client_tcp);
let engine = make_local_engine();
let result = engine.connect_plaintext_local_with_hint(io, true).await;
assert!(result.is_ok());
let pooled = result.unwrap();
assert!(matches!(pooled.conn, crate::pool::HttpConnection::H2(_)));
});
}
#[test]
fn connect_plaintext_local_with_http2_prior_knowledge_uses_h2() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
listener.set_nonblocking(true).unwrap();
let async_listener = async_io::Async::new(listener).unwrap();
compio_runtime::Runtime::new().unwrap().block_on(async {
let client_tcp = async_io::Async::<std::net::TcpStream>::connect(addr)
.await
.unwrap();
let (server_tcp, _) = async_listener.accept().await.unwrap();
compio_runtime::spawn(async move {
let io = CompioIo::new(server_tcp);
let builder = hyper::server::conn::http2::Builder::new(
crate::runtime::executor::completion_executor::<CompioRuntime>(),
);
let _ = builder
.serve_connection(
io,
hyper::service::service_fn(|_req| async {
Ok::<_, std::convert::Infallible>(hyper::Response::new(
http_body_util::Empty::<bytes::Bytes>::new(),
))
}),
)
.await;
})
.detach();
let io = CompioIo::new(client_tcp);
let engine = make_h2_local_engine();
let result = engine.connect_plaintext_local_with_hint(io, true).await;
assert!(result.is_ok());
let pooled = result.unwrap();
assert!(matches!(pooled.conn, crate::pool::HttpConnection::H2(_)));
});
}
#[test]
fn connect_h1_local_server_closes_immediately() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
listener.set_nonblocking(true).unwrap();
let async_listener = async_io::Async::new(listener).unwrap();
compio_runtime::Runtime::new().unwrap().block_on(async {
let client_tcp = async_io::Async::<std::net::TcpStream>::connect(addr)
.await
.unwrap();
let (server_tcp, _) = async_listener.accept().await.unwrap();
drop(server_tcp);
let io = CompioIo::new(client_tcp);
let engine = make_local_engine();
let result = engine.connect_h1_local(io).await;
assert!(result.is_ok());
});
}
#[test]
fn connect_h2_local_server_closes_immediately_fails() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
listener.set_nonblocking(true).unwrap();
let async_listener = async_io::Async::new(listener).unwrap();
compio_runtime::Runtime::new().unwrap().block_on(async {
let client_tcp = async_io::Async::<std::net::TcpStream>::connect(addr)
.await
.unwrap();
let (server_tcp, _) = async_listener.accept().await.unwrap();
drop(server_tcp);
let io = CompioIo::new(client_tcp);
let engine = make_local_engine();
let result = engine.connect_h2_prior_knowledge_local(io).await;
match result {
Ok(pooled) => {
assert!(matches!(pooled.conn, crate::pool::HttpConnection::H2(_)));
}
Err(_) => {
}
}
});
}
#[cfg(feature = "rustls")]
#[test]
fn connect_tls_local_on_plain_stream_fails() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
compio_runtime::Runtime::new().unwrap().block_on(async {
let accept_handle = std::thread::spawn(move || {
let (mut conn, _) = listener.accept().unwrap();
use std::io::Read;
let mut buf = [0u8; 4096];
let _ = conn.read(&mut buf);
});
crate::tls::install_default_crypto_provider();
let engine = HttpEngineLocal::<CompioRuntime, TcpConnector>::builder()
.tls(crate::tls::RustlsConnector::with_webpki_roots())
.build_local()
.unwrap();
let connector = TcpConnector;
let stream = crate::runtime::ConnectorLocal::connect(&connector, addr)
.await
.unwrap();
let result = engine.connect_tls_local(stream, "example.com").await;
assert!(result.is_err());
drop(accept_handle);
});
}
}