From de9432d996f82ad58122cd8f0ed6d8b5fa134b65 Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Sat, 1 Jun 2024 23:30:15 +0200 Subject: [PATCH] 5.4.1 test cases --- crates/httpwg-macros/src/lib.rs | 87 +++++++++++-------- crates/httpwg/src/lib.rs | 22 ++++- .../_5_4_1_connection_error_handling.rs | 38 ++++++++ crates/httpwg/src/rfc9113/mod.rs | 5 +- 4 files changed, 116 insertions(+), 36 deletions(-) create mode 100644 crates/httpwg/src/rfc9113/_5_4_1_connection_error_handling.rs diff --git a/crates/httpwg-macros/src/lib.rs b/crates/httpwg-macros/src/lib.rs index 3ec12a25..dfdb3ef3 100644 --- a/crates/httpwg-macros/src/lib.rs +++ b/crates/httpwg-macros/src/lib.rs @@ -139,40 +139,6 @@ macro_rules! tests { } } - /// Section 5.1.1: Stream Identifiers - mod _5_1_1_stream_identifiers { - use super::__suite::_5_1_1_stream_identifiers as __group; - - /// An endpoint that receives an unexpected stream identifier - /// MUST respond with a connection error (Section 5.4.1) of - /// type PROTOCOL_ERROR. - #[test] - fn sends_even_numbered_stream_identifier() { - use __group::sends_even_numbered_stream_identifier as test; - $body - } - - /// An endpoint that receives an unexpected stream identifier - /// MUST respond with a connection error (Section 5.4.1) of - /// type PROTOCOL_ERROR. - #[test] - fn sends_smaller_stream_identifier() { - use __group::sends_smaller_stream_identifier as test; - $body - } - } - - /// Section 5.1.2: Stream Concurrency - mod _5_1_2_stream_concurrency { - use super::__suite::_5_1_2_stream_concurrency as __group; - - #[test] - fn exceeds_concurrent_stream_limit() { - use __group::exceeds_concurrent_stream_limit as test; - $body - } - } - /// Section 5.1: Stream States mod _5_1_stream_states { use super::__suite::_5_1_stream_states as __group; @@ -311,6 +277,40 @@ macro_rules! tests { } } + /// Section 5.1.1: Stream Identifiers + mod _5_1_1_stream_identifiers { + use super::__suite::_5_1_1_stream_identifiers as __group; + + /// An endpoint that receives an unexpected stream identifier + /// MUST respond with a connection error (Section 5.4.1) of + /// type PROTOCOL_ERROR. + #[test] + fn sends_even_numbered_stream_identifier() { + use __group::sends_even_numbered_stream_identifier as test; + $body + } + + /// An endpoint that receives an unexpected stream identifier + /// MUST respond with a connection error (Section 5.4.1) of + /// type PROTOCOL_ERROR. + #[test] + fn sends_smaller_stream_identifier() { + use __group::sends_smaller_stream_identifier as test; + $body + } + } + + /// Section 5.1.2: Stream Concurrency + mod _5_1_2_stream_concurrency { + use super::__suite::_5_1_2_stream_concurrency as __group; + + #[test] + fn exceeds_concurrent_stream_limit() { + use __group::exceeds_concurrent_stream_limit as test; + $body + } + } + /// Section 5.3: Stream Dependencies mod _5_3_1_stream_dependencies { use super::__suite::_5_3_1_stream_dependencies as __group; @@ -331,6 +331,25 @@ macro_rules! tests { $body } } + + /// Section 5.4.1: Connection Error Handling + mod _5_4_1_connection_error_handling { + use super::__suite::_5_4_1_connection_error_handling as __group; + + /// After sending the GOAWAY frame for an error condition, + /// the endpoint MUST close the TCP connection. + #[test] + fn invalid_ping_frame_for_connection_close() { + use __group::invalid_ping_frame_for_connection_close as test; + $body + } + + #[test] + fn test_invalid_ping_frame_for_goaway() { + use __group::test_invalid_ping_frame_for_goaway as test; + $body + } + } } }; } diff --git a/crates/httpwg/src/lib.rs b/crates/httpwg/src/lib.rs index 2c7632c3..352c069c 100644 --- a/crates/httpwg/src/lib.rs +++ b/crates/httpwg/src/lib.rs @@ -449,6 +449,26 @@ impl Conn { } } + pub async fn verify_connection_close(&mut self) -> eyre::Result<()> { + match self.wait_for_frame(FrameT::GoAway).await { + FrameWaitOutcome::Success(_frame, _payload) => { + // that's what we expected! + Ok(()) + } + FrameWaitOutcome::Timeout { last_frame, .. } => Err(eyre!( + "Timed out while waiting for connection close, last frame: ({last_frame:?})" + )), + FrameWaitOutcome::Eof { .. } => { + // that's fine + Ok(()) + } + FrameWaitOutcome::IoError { .. } => { + // TODO: that's fine if it's a connection reset, we should probably check + Ok(()) + } + } + } + pub async fn verify_stream_close(&mut self, stream_id: StreamId) -> eyre::Result<()> { let mut global_last_frame: Option = None; let deadline = Instant::now() + self.config.timeout; @@ -782,5 +802,5 @@ pub fn dummy_string(len: usize) -> String { // DummyBytes returns an array of bytes with specified length. pub fn dummy_bytes(len: usize) -> Vec { - vec![b'x'; len.into()] + vec![b'x'; len] } diff --git a/crates/httpwg/src/rfc9113/_5_4_1_connection_error_handling.rs b/crates/httpwg/src/rfc9113/_5_4_1_connection_error_handling.rs new file mode 100644 index 00000000..0badfc43 --- /dev/null +++ b/crates/httpwg/src/rfc9113/_5_4_1_connection_error_handling.rs @@ -0,0 +1,38 @@ +//! Section 5.4.1: Connection Error Handling + +use fluke_buffet::IntoHalves; + +use crate::{Conn, ErrorC}; + +/// After sending the GOAWAY frame for an error condition, +/// the endpoint MUST close the TCP connection. +pub async fn invalid_ping_frame_for_connection_close( + mut conn: Conn, +) -> eyre::Result<()> { + conn.handshake().await?; + + // PING frame with invalid stream ID + conn.send(b"\x00\x00\x08\x06\x00\x00\x00\x00\x03").await?; + conn.send(b"\x00\x00\x00\x00\x00\x00\x00\x00").await?; + + conn.verify_connection_close().await?; + + Ok(()) +} + +// An endpoint that encounters a connection error SHOULD first send +// a GOAWAY frame (Section 6.8) with the stream identifier of the last +// stream that it successfully received from its peer. +pub async fn test_invalid_ping_frame_for_goaway( + mut conn: Conn, +) -> eyre::Result<()> { + conn.handshake().await?; + + // PING frame with invalid stream ID + conn.send(b"\x00\x00\x08\x06\x00\x00\x00\x00\x03").await?; + conn.send(b"\x00\x00\x00\x00\x00\x00\x00\x00").await?; + + conn.verify_connection_error(ErrorC::ProtocolError).await?; + + Ok(()) +} diff --git a/crates/httpwg/src/rfc9113/mod.rs b/crates/httpwg/src/rfc9113/mod.rs index 74b1f45e..d24d6d22 100644 --- a/crates/httpwg/src/rfc9113/mod.rs +++ b/crates/httpwg/src/rfc9113/mod.rs @@ -29,8 +29,11 @@ pub mod _4_1_frame_format; pub mod _4_2_frame_size; pub mod _4_3_header_compression_and_decompression; +pub mod _5_1_stream_states; + pub mod _5_1_1_stream_identifiers; pub mod _5_1_2_stream_concurrency; -pub mod _5_1_stream_states; pub mod _5_3_1_stream_dependencies; + +pub mod _5_4_1_connection_error_handling;