Skip to content

Commit

Permalink
test: improve test coverage for frames
Browse files Browse the repository at this point in the history
  • Loading branch information
huster-zhangpeng committed Dec 19, 2024
1 parent d0b07ff commit 44417b8
Show file tree
Hide file tree
Showing 23 changed files with 432 additions and 26 deletions.
4 changes: 2 additions & 2 deletions h3-shim/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ async fn h3_test() {
};

let client = async move {
client_example::run(client_opt)
_ = client_example::run(client_opt)
.await
.expect("client failed");
.inspect_err(|e| println!("Error occur: {}", e.to_string()));
};

let server = async move {
Expand Down
29 changes: 27 additions & 2 deletions qbase/src/frame/ack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl super::BeFrame for AckFrame {
}

fn max_encoding_size(&self) -> usize {
1 + 8 + 8 + 8 + self.ranges.len() * 16 + if self.ecn.is_some() { 24 } else { 0 }
1 + 8 + 8 + 8 + 8 + self.ranges.len() * 16 + if self.ecn.is_some() { 24 } else { 0 }
}

fn encoding_size(&self) -> usize {
Expand Down Expand Up @@ -191,10 +191,35 @@ mod tests {

use super::{ack_frame_with_flag, be_ecn_counts, AckFrame, EcnCounts, ACK_FRAME_TYPE};
use crate::{
frame::io::WriteFrame,
frame::{io::WriteFrame, BeFrame, FrameType},
varint::{be_varint, VarInt},
};

#[test]
fn test_ack_frame() {
// test frame type, encoding size, and max encoding size
let mut frame = AckFrame {
largest: VarInt::from_u32(0x1234),
delay: VarInt::from_u32(0x1234),
first_range: VarInt::from_u32(0x1234),
ranges: vec![(VarInt::from_u32(3), VarInt::from_u32(20))],
ecn: None,
};
assert_eq!(frame.frame_type(), FrameType::Ack(0));
assert_eq!(frame.encoding_size(), 1 + 2 * 3 + 1 + 2);
assert_eq!(frame.max_encoding_size(), 1 + 4 * 8 + 2 * 8);

// test set_ecn and take_ecn
let ecn = EcnCounts {
ect0: VarInt::from_u32(0x1234),
ect1: VarInt::from_u32(0x1234),
ce: VarInt::from_u32(0x1234),
};
frame.set_ecn(ecn);
assert!(frame.ecn.is_some());
assert_eq!(frame.take_ecn(), Some(ecn));
}

#[test]
fn test_read_ecn_count() {
let input = vec![0x52, 0x34, 0x52, 0x34, 0x52, 0x34];
Expand Down
20 changes: 19 additions & 1 deletion qbase/src/frame/connection_close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,25 @@ impl<T: bytes::BufMut> super::io::WriteFrame<ConnectionCloseFrame> for T {

#[cfg(test)]
mod tests {
use crate::{error::ErrorKind, frame::io::WriteFrame};
use crate::{
error::ErrorKind,
frame::{io::WriteFrame, BeFrame, FrameType},
};

#[test]
fn test_connection_close_frame() {
let frame = super::ConnectionCloseFrame {
error_kind: ErrorKind::Application,
frame_type: None,
reason: "wrong".into(),
};
assert_eq!(
frame.frame_type(),
FrameType::ConnectionClose(super::APP_LAYER)
);
assert_eq!(frame.max_encoding_size(), 1 + 8 + 2 + 5);
assert_eq!(frame.encoding_size(), 1 + 1 + 1 + 5);
}

#[test]
fn test_read_connection_close_frame() {
Expand Down
21 changes: 17 additions & 4 deletions qbase/src/frame/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ impl super::BeFrame for CryptoFrame {
}

fn encoding_size(&self) -> usize {
1 + self.offset.encoding_size()
+ self.length.encoding_size()
+ self.length.into_inner() as usize
1 + self.offset.encoding_size() + self.length.encoding_size()
}
}

Expand Down Expand Up @@ -113,7 +111,22 @@ where
#[cfg(test)]
mod tests {
use super::{CryptoFrame, CRYPTO_FRAME_TYPE};
use crate::{frame::io::WriteDataFrame, varint::VarInt};
use crate::{
frame::{io::WriteDataFrame, BeFrame},
varint::VarInt,
};

#[test]
fn test_crypto_frame() {
let frame = CryptoFrame {
offset: VarInt::from_u32(0),
length: VarInt::from_u32(500),
};
assert_eq!(frame.frame_type(), super::super::FrameType::Crypto);
assert_eq!(frame.max_encoding_size(), 1 + 8 + 8);
assert_eq!(frame.encoding_size(), 1 + 1 + 2);
assert_eq!(frame.range(), 0..500);
}

#[test]
fn test_read_crypto_frame() {
Expand Down
12 changes: 11 additions & 1 deletion qbase/src/frame/data_blocked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,17 @@ impl<T: bytes::BufMut> super::io::WriteFrame<DataBlockedFrame> for T {
#[cfg(test)]
mod tests {
use super::{DataBlockedFrame, DATA_BLOCKED_FRAME_TYPE};
use crate::frame::io::WriteFrame;
use crate::frame::{io::WriteFrame, BeFrame};

#[test]
fn test_data_blocked_frame() {
let frame = DataBlockedFrame {
limit: crate::varint::VarInt::from_u32(0x1234),
};
assert_eq!(frame.frame_type(), super::super::FrameType::Crypto);
assert_eq!(frame.max_encoding_size(), 1 + 8);
assert_eq!(frame.encoding_size(), 1 + 2);
}

#[test]
fn test_read_data_blocked_frame() {
Expand Down
10 changes: 10 additions & 0 deletions qbase/src/frame/datagram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ mod tests {
use super::*;
use crate::frame::io::WriteDataFrame;

#[test]
fn test_datagram_frame() {
let frame = DatagramFrame {
length: Some(VarInt::from_u32(3)),
};
assert_eq!(frame.frame_type(), FrameType::Datagram(1));
assert_eq!(frame.max_encoding_size(), 1 + 8);
assert_eq!(frame.encoding_size(), 1 + 1);
}

#[test]
fn test_datagram_frame_with_flag() {
let input = [0x05, 0x00, 0x00, 0x00, 0x00, 0x00];
Expand Down
80 changes: 80 additions & 0 deletions qbase/src/frame/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,83 @@ impl nom::error::ParseError<&[u8]> for Error {
}

// TODO: conver DecodingError to quic error

#[cfg(test)]
mod tests {
use nom::error::ParseError;

use super::*;
use crate::packet::r#type::{
long::{Type::V1, Ver1},
Type,
};

#[test]
fn test_error_conversion_to_transport_error() {
let cases = vec![
(Error::NoFrames, TransportErrorKind::ProtocolViolation),
(
Error::IncompleteType("test".to_string()),
TransportErrorKind::FrameEncoding,
),
(
Error::InvalidType(VarInt::from_u32(0x1f)),
TransportErrorKind::FrameEncoding,
),
(
Error::WrongType(FrameType::Ping, Type::Long(V1(Ver1::INITIAL))),
TransportErrorKind::FrameEncoding,
),
(
Error::IncompleteFrame(FrameType::Ping, "incomplete".to_string()),
TransportErrorKind::FrameEncoding,
),
(
Error::ParseError(FrameType::Ping, "parse error".to_string()),
TransportErrorKind::FrameEncoding,
),
];

for (error, expected_kind) in cases {
let transport_error: TransportError = error.into();
assert_eq!(transport_error.kind(), expected_kind);
}
}

#[test]
fn test_nom_error_conversion() {
let error = Error::NoFrames;
let nom_error = nom::Err::Error(error.clone());
let converted: Error = nom_error.into();
assert_eq!(converted, error);

let nom_failure = nom::Err::Failure(error.clone());
let converted: Error = nom_failure.into();
assert_eq!(converted, error);
}

#[test]
fn test_parse_error_impl() {
let error = Error::ParseError(FrameType::Ping, "test error".to_string());
let appended = Error::append(&[], NomErrorKind::ManyTill, error.clone());
assert_eq!(appended, error);
}

#[test]
#[should_panic(expected = "QUIC frame parser must always consume")]
fn test_parse_error_unreachable() {
Error::from_error_kind(&[], NomErrorKind::ManyTill);
}

#[test]
fn test_error_display() {
let error = Error::NoFrames;
assert_eq!(error.to_string(), "A packet containing no frames");

let error = Error::IncompleteType("test".to_string());
assert_eq!(error.to_string(), "Incomplete frame type: test");

let error = Error::InvalidType(VarInt::from_u32(0x1f));
assert_eq!(error.to_string(), "Invalid frame type from 31");
}
}
9 changes: 8 additions & 1 deletion qbase/src/frame/handshake_done.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ impl<T: bytes::BufMut> super::io::WriteFrame<HandshakeDoneFrame> for T {

#[cfg(test)]
mod tests {
use crate::frame::{io::WriteFrame, HandshakeDoneFrame};
use crate::frame::{io::WriteFrame, BeFrame, FrameType, HandshakeDoneFrame};

#[test]
fn test_handshake_done_frame() {
assert_eq!(HandshakeDoneFrame.frame_type(), FrameType::HandshakeDone);
assert_eq!(HandshakeDoneFrame.max_encoding_size(), 1);
assert_eq!(HandshakeDoneFrame.encoding_size(), 1);
}

#[test]
fn test_read_handshake_done_frame() {
Expand Down
15 changes: 14 additions & 1 deletion qbase/src/frame/max_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,20 @@ impl<T: bytes::BufMut> super::io::WriteFrame<MaxDataFrame> for T {
#[cfg(test)]
mod tests {
use super::{MaxDataFrame, MAX_DATA_FRAME_TYPE};
use crate::{frame::io::WriteFrame, varint::VarInt};
use crate::{
frame::{io::WriteFrame, BeFrame, FrameType},
varint::VarInt,
};

#[test]
fn test_max_data_frame() {
let frame = MaxDataFrame {
max_data: VarInt::from_u32(0x1234),
};
assert_eq!(frame.frame_type(), FrameType::MaxData);
assert_eq!(frame.max_encoding_size(), 1 + 8);
assert_eq!(frame.encoding_size(), 1 + 2);
}

#[test]
fn test_read_max_data_frame() {
Expand Down
16 changes: 15 additions & 1 deletion qbase/src/frame/max_stream_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,21 @@ impl<T: bytes::BufMut> super::io::WriteFrame<MaxStreamDataFrame> for T {
#[cfg(test)]
mod tests {
use super::{MaxStreamDataFrame, MAX_STREAM_DATA_FRAME_TYPE};
use crate::{frame::io::WriteFrame, varint::VarInt};
use crate::{
frame::{io::WriteFrame, BeFrame, FrameType},
varint::VarInt,
};

#[test]
fn test_max_stream_data_frame() {
let frame = MaxStreamDataFrame {
stream_id: VarInt::from_u32(0x1234).into(),
max_stream_data: VarInt::from_u32(0x5678),
};
assert_eq!(frame.frame_type(), FrameType::MaxStreamData);
assert_eq!(frame.max_encoding_size(), 1 + 8 + 8);
assert_eq!(frame.encoding_size(), 1 + 2 + 4);
}

#[test]
fn test_read_max_stream_data_frame() {
Expand Down
15 changes: 14 additions & 1 deletion qbase/src/frame/max_streams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,23 @@ impl<T: bytes::BufMut> super::io::WriteFrame<MaxStreamsFrame> for T {
mod tests {
use super::{MaxStreamsFrame, MAX_STREAMS_FRAME_TYPE};
use crate::{
frame::io::WriteFrame,
frame::{io::WriteFrame, BeFrame, FrameType},
varint::{be_varint, VarInt},
};

#[test]
fn test_max_streams_frame() {
let frame = MaxStreamsFrame::Bi(VarInt::from_u32(0x1234));
assert_eq!(frame.frame_type(), FrameType::MaxStreams(0));
assert_eq!(frame.max_encoding_size(), 1 + 8);
assert_eq!(frame.encoding_size(), 1 + 2);

let frame = MaxStreamsFrame::Uni(VarInt::from_u32(0x1236));
assert_eq!(frame.frame_type(), FrameType::MaxStreams(1));
assert_eq!(frame.max_encoding_size(), 1 + 8);
assert_eq!(frame.encoding_size(), 1 + 2);
}

#[test]
fn test_read_max_streams_frame() {
use nom::combinator::flat_map;
Expand Down
70 changes: 70 additions & 0 deletions qbase/src/frame/new_connection_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,73 @@ impl<T: bytes::BufMut> super::io::WriteFrame<NewConnectionIdFrame> for T {
self.put_slice(&frame.reset_token);
}
}

#[cfg(test)]
mod tests {
use bytes::{BufMut, BytesMut};

use super::*;
use crate::frame::{io::WriteFrame, BeFrame, FrameType};

#[test]
fn test_new_connection_id_frame() {
let new_cid_frame = NewConnectionIdFrame::new(
ConnectionId::from_slice(&[1, 2, 3, 4][..]),
VarInt::from_u32(1),
VarInt::from_u32(0),
);
assert_eq!(new_cid_frame.sequence, VarInt::from_u32(1));
assert_eq!(new_cid_frame.retire_prior_to, VarInt::from_u32(0));
assert_eq!(
new_cid_frame.id,
ConnectionId::from_slice(&[1, 2, 3, 4][..])
);

assert_eq!(new_cid_frame.frame_type(), FrameType::NewConnectionId);
assert_eq!(
new_cid_frame.max_encoding_size(),
1 + 8 + 8 + 21 + RESET_TOKEN_SIZE
);
assert_eq!(new_cid_frame.encoding_size(), 1 + 1 + 1 + 1 + 4 + 16);
}

#[test]
fn test_frame_parsing() {
let mut buf = BytesMut::new();
let original_cid = ConnectionId::from_slice(&[1, 2, 3, 4][..]);
let original_frame =
NewConnectionIdFrame::new(original_cid, VarInt::from_u32(1), VarInt::from_u32(0));

// Write frame to buffer
buf.put_frame(&original_frame);

// Skip frame type byte
let (_, parsed_frame) = be_new_connection_id_frame(&buf[1..]).unwrap();

assert_eq!(parsed_frame.sequence, original_frame.sequence);
assert_eq!(parsed_frame.retire_prior_to, original_frame.retire_prior_to);
assert_eq!(parsed_frame.id, original_frame.id);
assert_eq!(parsed_frame.reset_token, original_frame.reset_token);
}

#[test]
fn test_invalid_retire_prior_to() {
let mut buf = BytesMut::new();
buf.put_u8(NEW_CONNECTION_ID_FRAME_TYPE);
buf.put_varint(&VarInt::from_u32(1)); // sequence
buf.put_varint(&VarInt::from_u32(2)); // retire_prior_to > sequence

assert!(be_new_connection_id_frame(&buf[1..]).is_err());
}

#[test]
fn test_zero_length_connection_id() {
let mut buf = BytesMut::new();
buf.put_u8(NEW_CONNECTION_ID_FRAME_TYPE);
buf.put_varint(&VarInt::from_u32(1));
buf.put_varint(&VarInt::from_u32(0));
buf.put_u8(0); // zero length CID

assert!(be_new_connection_id_frame(&buf[1..]).is_err());
}
}
Loading

0 comments on commit 44417b8

Please sign in to comment.