Skip to content

Commit

Permalink
5.4.1 test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
fasterthanlime committed Jun 1, 2024
1 parent 21aa817 commit de9432d
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 36 deletions.
87 changes: 53 additions & 34 deletions crates/httpwg-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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
}
}
}
};
}
22 changes: 21 additions & 1 deletion crates/httpwg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,26 @@ impl<IO: IntoHalves> Conn<IO> {
}
}

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<Frame> = None;
let deadline = Instant::now() + self.config.timeout;
Expand Down Expand Up @@ -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<u8> {
vec![b'x'; len.into()]
vec![b'x'; len]
}
38 changes: 38 additions & 0 deletions crates/httpwg/src/rfc9113/_5_4_1_connection_error_handling.rs
Original file line number Diff line number Diff line change
@@ -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<IO: IntoHalves + 'static>(
mut conn: Conn<IO>,
) -> 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<IO: IntoHalves + 'static>(
mut conn: Conn<IO>,
) -> 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(())
}
5 changes: 4 additions & 1 deletion crates/httpwg/src/rfc9113/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

0 comments on commit de9432d

Please sign in to comment.