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.
This commit is contained in:
		
				
					committed by
					
						 Sean McArthur
						Sean McArthur
					
				
			
			
				
	
			
			
			
						parent
						
							fb19f3a869
						
					
				
				
					commit
					f288641792
				
			| @@ -1903,6 +1903,94 @@ async fn http2_keep_alive_with_responsive_client() { | |||||||
|     client.send_request(req).await.expect("client.send_request"); |     client.send_request(req).await.expect("client.send_request"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | fn is_ping_frame(buf: &[u8]) -> bool { | ||||||
|  |     buf[3] == 6 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn assert_ping_frame(buf: &[u8], len: usize) { | ||||||
|  |     // Assert the StreamId is zero | ||||||
|  |     let mut ubuf = [0; 4]; | ||||||
|  |     ubuf.copy_from_slice(&buf[5..9]); | ||||||
|  |     let unpacked = u32::from_be_bytes(ubuf); | ||||||
|  |     assert_eq!(unpacked & !(1 << 31), 0); | ||||||
|  |  | ||||||
|  |     // Assert ACK flag is unset (only set for PONG). | ||||||
|  |     let flags = buf[4]; | ||||||
|  |     assert_eq!(flags & 0x1, 0); | ||||||
|  |  | ||||||
|  |     // Assert total frame size | ||||||
|  |     assert_eq!(len, 17); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async fn write_pong_frame(conn: &mut TkTcpStream) { | ||||||
|  |     conn.write_all(&[ | ||||||
|  |         0, 0, 8,   // len | ||||||
|  |         6,   // kind | ||||||
|  |         0x1, // flag | ||||||
|  |         0, 0, 0, 0, // stream id | ||||||
|  |         0x3b, 0x7c, 0xdb, 0x7a, 0x0b, 0x87, 0x16, 0xb4, // payload | ||||||
|  |     ]) | ||||||
|  |     .await | ||||||
|  |     .expect("client pong"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[tokio::test] | ||||||
|  | async fn http2_keep_alive_count_server_pings() { | ||||||
|  |     let _ = pretty_env_logger::try_init(); | ||||||
|  |  | ||||||
|  |     let mut listener = tcp_bind(&"127.0.0.1:0".parse().unwrap()).unwrap(); | ||||||
|  |     let addr = listener.local_addr().unwrap(); | ||||||
|  |  | ||||||
|  |     tokio::spawn(async move { | ||||||
|  |         let (socket, _) = listener.accept().await.expect("accept"); | ||||||
|  |  | ||||||
|  |         Http::new() | ||||||
|  |             .http2_only(true) | ||||||
|  |             .http2_keep_alive_interval(Duration::from_secs(1)) | ||||||
|  |             .http2_keep_alive_timeout(Duration::from_secs(1)) | ||||||
|  |             .serve_connection(socket, unreachable_service()) | ||||||
|  |             .await | ||||||
|  |             .expect("serve_connection"); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     // Spawn a "client" conn that only reads until EOF | ||||||
|  |     let mut conn = connect_async(addr).await; | ||||||
|  |  | ||||||
|  |     // write h2 magic preface and settings frame | ||||||
|  |     conn.write_all(b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n") | ||||||
|  |         .await | ||||||
|  |         .expect("client preface"); | ||||||
|  |     conn.write_all(&[ | ||||||
|  |         0, 0, 0, // len | ||||||
|  |         4, // kind | ||||||
|  |         0, // flag | ||||||
|  |         0, 0, 0, 0, // stream id | ||||||
|  |     ]) | ||||||
|  |     .await | ||||||
|  |     .expect("client settings"); | ||||||
|  |  | ||||||
|  |     let read_pings = async { | ||||||
|  |         // read until 3 pings are received | ||||||
|  |         let mut pings = 0; | ||||||
|  |         let mut buf = [0u8; 1024]; | ||||||
|  |         while pings < 3 { | ||||||
|  |             let n = conn.read(&mut buf).await.expect("client.read"); | ||||||
|  |             assert!(n != 0); | ||||||
|  |  | ||||||
|  |             if is_ping_frame(&buf) { | ||||||
|  |                 assert_ping_frame(&buf, n); | ||||||
|  |                 write_pong_frame(&mut conn).await; | ||||||
|  |                 pings += 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     // Expect all pings to occurs under 5 seconds | ||||||
|  |     tokio::time::timeout(Duration::from_secs(5), read_pings) | ||||||
|  |         .await | ||||||
|  |         .expect("timed out waiting for pings"); | ||||||
|  | } | ||||||
|  |  | ||||||
| // ------------------------------------------------- | // ------------------------------------------------- | ||||||
| // the Server that is used to run all the tests with | // the Server that is used to run all the tests with | ||||||
| // ------------------------------------------------- | // ------------------------------------------------- | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user