Skip to content

Commit f288641

Browse files
pdcaladoseanmonstar
authored andcommitted
test(server): test server keep alive by counting number of pings
Add `http2_keep_alive_count_server_pings` which tests if 3 pings are received under 5 seconds with keep alive interval set to 1 second.
1 parent fb19f3a commit f288641

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

tests/server.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,6 +1903,94 @@ async fn http2_keep_alive_with_responsive_client() {
19031903
client.send_request(req).await.expect("client.send_request");
19041904
}
19051905

1906+
fn is_ping_frame(buf: &[u8]) -> bool {
1907+
buf[3] == 6
1908+
}
1909+
1910+
fn assert_ping_frame(buf: &[u8], len: usize) {
1911+
// Assert the StreamId is zero
1912+
let mut ubuf = [0; 4];
1913+
ubuf.copy_from_slice(&buf[5..9]);
1914+
let unpacked = u32::from_be_bytes(ubuf);
1915+
assert_eq!(unpacked & !(1 << 31), 0);
1916+
1917+
// Assert ACK flag is unset (only set for PONG).
1918+
let flags = buf[4];
1919+
assert_eq!(flags & 0x1, 0);
1920+
1921+
// Assert total frame size
1922+
assert_eq!(len, 17);
1923+
}
1924+
1925+
async fn write_pong_frame(conn: &mut TkTcpStream) {
1926+
conn.write_all(&[
1927+
0, 0, 8, // len
1928+
6, // kind
1929+
0x1, // flag
1930+
0, 0, 0, 0, // stream id
1931+
0x3b, 0x7c, 0xdb, 0x7a, 0x0b, 0x87, 0x16, 0xb4, // payload
1932+
])
1933+
.await
1934+
.expect("client pong");
1935+
}
1936+
1937+
#[tokio::test]
1938+
async fn http2_keep_alive_count_server_pings() {
1939+
let _ = pretty_env_logger::try_init();
1940+
1941+
let mut listener = tcp_bind(&"127.0.0.1:0".parse().unwrap()).unwrap();
1942+
let addr = listener.local_addr().unwrap();
1943+
1944+
tokio::spawn(async move {
1945+
let (socket, _) = listener.accept().await.expect("accept");
1946+
1947+
Http::new()
1948+
.http2_only(true)
1949+
.http2_keep_alive_interval(Duration::from_secs(1))
1950+
.http2_keep_alive_timeout(Duration::from_secs(1))
1951+
.serve_connection(socket, unreachable_service())
1952+
.await
1953+
.expect("serve_connection");
1954+
});
1955+
1956+
// Spawn a "client" conn that only reads until EOF
1957+
let mut conn = connect_async(addr).await;
1958+
1959+
// write h2 magic preface and settings frame
1960+
conn.write_all(b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
1961+
.await
1962+
.expect("client preface");
1963+
conn.write_all(&[
1964+
0, 0, 0, // len
1965+
4, // kind
1966+
0, // flag
1967+
0, 0, 0, 0, // stream id
1968+
])
1969+
.await
1970+
.expect("client settings");
1971+
1972+
let read_pings = async {
1973+
// read until 3 pings are received
1974+
let mut pings = 0;
1975+
let mut buf = [0u8; 1024];
1976+
while pings < 3 {
1977+
let n = conn.read(&mut buf).await.expect("client.read");
1978+
assert!(n != 0);
1979+
1980+
if is_ping_frame(&buf) {
1981+
assert_ping_frame(&buf, n);
1982+
write_pong_frame(&mut conn).await;
1983+
pings += 1;
1984+
}
1985+
}
1986+
};
1987+
1988+
// Expect all pings to occurs under 5 seconds
1989+
tokio::time::timeout(Duration::from_secs(5), read_pings)
1990+
.await
1991+
.expect("timed out waiting for pings");
1992+
}
1993+
19061994
// -------------------------------------------------
19071995
// the Server that is used to run all the tests with
19081996
// -------------------------------------------------

0 commit comments

Comments
 (0)