Skip to content

Commit f9f8f44

Browse files
authored
tests(client): port tests to in-memory socket (#3947)
see #3896. this commit ports an assortment of test cases for the client to an in-memory socket using `tokio::io::duplex()`. this should help reduce test flakes related to TCP close behavior. this supersedes #3946. Signed-off-by: katelyn martin <[email protected]>
1 parent 5803a9c commit f9f8f44

File tree

1 file changed

+40
-30
lines changed

1 file changed

+40
-30
lines changed

tests/client.rs

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@ mod conn {
14981498
use futures_util::future::{self, poll_fn, FutureExt, TryFutureExt};
14991499
use http_body_util::{BodyExt, Empty, Full, StreamBody};
15001500
use hyper::rt::Timer;
1501-
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
1501+
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _, DuplexStream};
15021502
use tokio::net::{TcpListener as TkTcpListener, TcpStream};
15031503

15041504
use hyper::body::{Body, Frame};
@@ -1530,6 +1530,21 @@ mod conn {
15301530
(listener, addr)
15311531
}
15321532

1533+
fn setup_duplex_test_server() -> (DuplexStream, DuplexStream, SocketAddr) {
1534+
use std::net::{IpAddr, Ipv6Addr};
1535+
setup_logger();
1536+
1537+
const BUF_SIZE: usize = 1024;
1538+
let (ioa, iob) = tokio::io::duplex(BUF_SIZE);
1539+
1540+
/// A test address inside the 'documentation' address range.
1541+
/// See: <https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml>
1542+
const TEST_ADDR: IpAddr = IpAddr::V6(Ipv6Addr::new(0x3fff, 0, 0, 0, 0, 0, 0, 1));
1543+
const TEST_SOCKET: SocketAddr = SocketAddr::new(TEST_ADDR, 8080);
1544+
1545+
(ioa, iob, TEST_SOCKET)
1546+
}
1547+
15331548
#[tokio::test]
15341549
async fn get() {
15351550
let (listener, addr) = setup_tk_test_server().await;
@@ -2307,16 +2322,14 @@ mod conn {
23072322
// Regression test for failure to fully close connections when using HTTP2 CONNECT
23082323
// We send 2 requests and then drop them. We should see the connection gracefully close.
23092324
use futures_util::future;
2310-
let (listener, addr) = setup_tk_test_server().await;
2325+
let (client_io, server_io, addr) = setup_duplex_test_server();
23112326
let (tx, rxx) = oneshot::channel::<()>();
23122327

23132328
tokio::task::spawn(async move {
23142329
use hyper::server::conn::http2;
23152330
use hyper::service::service_fn;
23162331

2317-
let res = listener.accept().await;
2318-
let (stream, _) = res.unwrap();
2319-
let stream = TokioIo::new(stream);
2332+
let stream = TokioIo::new(server_io);
23202333

23212334
let service = service_fn(move |req: Request<hyper::body::Incoming>| {
23222335
tokio::task::spawn(async move {
@@ -2334,7 +2347,7 @@ mod conn {
23342347
});
23352348
});
23362349

2337-
let io = tcp_connect(&addr).await.expect("tcp connect");
2350+
let io = TokioIo::new(client_io);
23382351
let (mut client, conn) = conn::http2::Builder::new(TokioExecutor)
23392352
.handshake(io)
23402353
.await
@@ -2380,11 +2393,11 @@ mod conn {
23802393

23812394
#[tokio::test]
23822395
async fn http2_keep_alive_detects_unresponsive_server() {
2383-
let (listener, addr) = setup_tk_test_server().await;
2396+
let (client_io, server_io, _) = setup_duplex_test_server();
23842397

23852398
// spawn a server that reads but doesn't write
23862399
tokio::spawn(async move {
2387-
let mut sock = listener.accept().await.unwrap().0;
2400+
let mut sock = server_io;
23882401
let mut buf = [0u8; 1024];
23892402
loop {
23902403
let n = sock.read(&mut buf).await.expect("server read");
@@ -2395,7 +2408,7 @@ mod conn {
23952408
}
23962409
});
23972410

2398-
let io = tcp_connect(&addr).await.expect("tcp connect");
2411+
let io = TokioIo::new(client_io);
23992412
let (_client, conn) = conn::http2::Builder::new(TokioExecutor)
24002413
.timer(TokioTimer)
24012414
.keep_alive_interval(Duration::from_secs(1))
@@ -2415,15 +2428,14 @@ mod conn {
24152428
// will use the default behavior which will NOT detect the server
24162429
// is unresponsive while no streams are active.
24172430

2418-
let (listener, addr) = setup_tk_test_server().await;
2431+
let (client_io, server_io, _) = setup_duplex_test_server();
24192432

24202433
// spawn a server that reads but doesn't write
24212434
tokio::spawn(async move {
2422-
let sock = listener.accept().await.unwrap().0;
2423-
drain_til_eof(sock).await.expect("server read");
2435+
drain_til_eof(server_io).await.expect("server read");
24242436
});
24252437

2426-
let io = tcp_connect(&addr).await.expect("tcp connect");
2438+
let io = TokioIo::new(client_io);
24272439
let (mut client, conn) = conn::http2::Builder::new(TokioExecutor)
24282440
.timer(TokioTimer)
24292441
.keep_alive_interval(Duration::from_secs(1))
@@ -2446,15 +2458,14 @@ mod conn {
24462458

24472459
#[tokio::test]
24482460
async fn http2_keep_alive_closes_open_streams() {
2449-
let (listener, addr) = setup_tk_test_server().await;
2461+
let (client_io, server_io, _addr) = setup_duplex_test_server();
24502462

24512463
// spawn a server that reads but doesn't write
24522464
tokio::spawn(async move {
2453-
let sock = listener.accept().await.unwrap().0;
2454-
drain_til_eof(sock).await.expect("server read");
2465+
drain_til_eof(server_io).await.expect("server read");
24552466
});
24562467

2457-
let io = tcp_connect(&addr).await.expect("tcp connect");
2468+
let io = TokioIo::new(client_io);
24582469
let (mut client, conn) = conn::http2::Builder::new(TokioExecutor)
24592470
.timer(TokioTimer)
24602471
.keep_alive_interval(Duration::from_secs(1))
@@ -2491,11 +2502,11 @@ mod conn {
24912502
// alive is enabled
24922503
use hyper::service::service_fn;
24932504

2494-
let (listener, addr) = setup_tk_test_server().await;
2505+
let (client_io, server_io, _addr) = setup_duplex_test_server();
24952506

24962507
// Spawn an HTTP2 server that reads the whole body and responds
24972508
tokio::spawn(async move {
2498-
let sock = TokioIo::new(listener.accept().await.unwrap().0);
2509+
let sock = TokioIo::new(server_io);
24992510
hyper::server::conn::http2::Builder::new(TokioExecutor)
25002511
.timer(TokioTimer)
25012512
.serve_connection(
@@ -2513,7 +2524,7 @@ mod conn {
25132524
.expect("serve_connection");
25142525
});
25152526

2516-
let io = tcp_connect(&addr).await.expect("tcp connect");
2527+
let io = TokioIo::new(client_io);
25172528
let (mut client, conn) = conn::http2::Builder::new(TokioExecutor)
25182529
.timer(TokioTimer)
25192530
.keep_alive_interval(Duration::from_secs(1))
@@ -2598,11 +2609,11 @@ mod conn {
25982609

25992610
#[tokio::test]
26002611
async fn h2_connect() {
2601-
let (listener, addr) = setup_tk_test_server().await;
2612+
let (client_io, server_io, _) = setup_duplex_test_server();
26022613

26032614
// Spawn an HTTP2 server that asks for bread and responds with baguette.
26042615
tokio::spawn(async move {
2605-
let sock = listener.accept().await.unwrap().0;
2616+
let sock = server_io;
26062617
let mut h2 = h2::server::handshake(sock).await.unwrap();
26072618

26082619
let (req, mut respond) = h2.accept().await.unwrap().unwrap();
@@ -2624,7 +2635,7 @@ mod conn {
26242635
assert!(body.data().await.is_none());
26252636
});
26262637

2627-
let io = tcp_connect(&addr).await.expect("tcp connect");
2638+
let io = TokioIo::new(client_io);
26282639
let (mut client, conn) = conn::http2::Builder::new(TokioExecutor)
26292640
.handshake(io)
26302641
.await
@@ -2653,11 +2664,11 @@ mod conn {
26532664

26542665
#[tokio::test]
26552666
async fn h2_connect_rejected() {
2656-
let (listener, addr) = setup_tk_test_server().await;
2667+
let (client_io, server_io, _) = setup_duplex_test_server();
26572668
let (done_tx, done_rx) = oneshot::channel();
26582669

26592670
tokio::spawn(async move {
2660-
let sock = listener.accept().await.unwrap().0;
2671+
let sock = server_io;
26612672
let mut h2 = h2::server::handshake(sock).await.unwrap();
26622673

26632674
let (req, mut respond) = h2.accept().await.unwrap().unwrap();
@@ -2674,7 +2685,7 @@ mod conn {
26742685
done_rx.await.unwrap();
26752686
});
26762687

2677-
let io = tcp_connect(&addr).await.expect("tcp connect");
2688+
let io = TokioIo::new(client_io);
26782689
let (mut client, conn) = conn::http2::Builder::new(TokioExecutor)
26792690
.handshake::<_, Empty<Bytes>>(io)
26802691
.await
@@ -2703,16 +2714,15 @@ mod conn {
27032714

27042715
#[tokio::test]
27052716
async fn test_body_panics() {
2706-
let (listener, addr) = setup_tk_test_server().await;
2717+
let (client_io, server_io, _) = setup_duplex_test_server();
27072718

27082719
// spawn a server that reads but doesn't write
27092720
tokio::spawn(async move {
2710-
let sock = listener.accept().await.unwrap().0;
2721+
let sock = server_io;
27112722
drain_til_eof(sock).await.expect("server read");
27122723
});
27132724

2714-
let io = tcp_connect(&addr).await.expect("tcp connect");
2715-
2725+
let io = TokioIo::new(client_io);
27162726
let (mut client, conn) = conn::http1::Builder::new()
27172727
.handshake(io)
27182728
.await

0 commit comments

Comments
 (0)