Skip to content

Commit

Permalink
Add more unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
iyangsj committed Nov 25, 2023
1 parent 8df58a4 commit 458bb24
Show file tree
Hide file tree
Showing 15 changed files with 248 additions and 40 deletions.
3 changes: 2 additions & 1 deletion src/congestion_control/congestion_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ pub use hystart_plus_plus::HystartPlusPlus;

/// Available congestion control algorithm
#[repr(C)]
#[derive(Eq, PartialEq, Debug, Clone)]
#[derive(Eq, PartialEq, Debug, Clone, Copy, Default)]
pub enum CongestionControlAlgorithm {
/// CUBIC uses a cubic function instead of a linear window increase function
/// of the current TCP standards to improve scalability and stability under
/// fast and long-distance networks..
#[default]
Cubic,

/// BBR uses recent measurements of a transport connection's delivery rate,
Expand Down
2 changes: 1 addition & 1 deletion src/connection/cid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::Result;
const MAX_CIDS_COUNT: u64 = 16;

/// Connection Id and related metadata.
#[derive(Debug, Default)]
#[derive(Default)]
pub struct ConnectionIdItem {
/// The Connection ID.
pub cid: ConnectionId,
Expand Down
1 change: 1 addition & 0 deletions src/connection/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4208,6 +4208,7 @@ pub(crate) mod tests {
conf.set_ack_delay_exponent(3);
conf.set_max_ack_delay(25);
conf.set_reset_token_key([1u8; 64]);
conf.set_address_token_lifetime(3600);
conf.set_send_batch_size(2);
conf.set_max_handshake_timeout(0);
conf.set_multipath(false);
Expand Down
14 changes: 4 additions & 10 deletions src/connection/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,16 +480,6 @@ impl PathMap {
}
}

/// Process a PATH_ABANDON frame on the give path
pub(super) fn on_path_abandon(&mut self, path_id: usize, error_code: u64, reason: Vec<u8>) {
// TODO
}

/// Process a PATH_STATUS frame on the give path
pub(super) fn on_path_status(&mut self, path_id: usize, seq_num: u64, status: u64) {
// TODO
}

/// Handle the sent event of PATH_CHALLENGE.
pub fn on_path_chal_sent(
&mut self,
Expand Down Expand Up @@ -650,6 +640,10 @@ mod tests {
assert_eq!(path_mgr.get_mut(pid)?.state, PathState::Validated);
assert_eq!(path_mgr.get_mut(pid)?.sent_chals.len(), 0);

// Fake receiving of depulicated PATH_RESPONSE
path_mgr.on_path_resp_received(pid, data);
assert_eq!(path_mgr.get_mut(pid)?.validated(), true);

// Timeout event
path_mgr.on_path_chal_timeout(now + time::Duration::from_millis(INITIAL_CHAL_TIMEOUT));
assert_eq!(path_mgr.get_mut(pid)?.lost_chal, 0);
Expand Down
1 change: 0 additions & 1 deletion src/connection/recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ const MAX_PTO_PROBES_COUNT: usize = 2;

/// An implementation of the loss detection mechanisms described in
/// RFC 9002 Section 6 and Appendix A.
#[derive(Debug)]
pub struct Recovery {
/// The maximum amount of time by which the receiver intends to delay
/// acknowledgments for packets in the Application Data packet number space.
Expand Down
1 change: 0 additions & 1 deletion src/connection/rtt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use crate::TIMER_GRANULARITY;

/// RTT estimation for a network path
/// See RFC 9001 Section 5
#[derive(Copy, Clone, Debug)]
pub struct RttEstimator {
/// The most recent RTT sample.
latest_rtt: Duration,
Expand Down
1 change: 0 additions & 1 deletion src/connection/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,6 @@ impl std::fmt::Debug for SentPacket {
}

/// Metadata of acknowledged packet
#[derive(Clone)]
pub struct AckedPacket {
/// The packet number of the sent packet.
pub pkt_num: u64,
Expand Down
57 changes: 52 additions & 5 deletions src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,7 @@ mod tests {
use super::*;
use crate::connection;
use crate::Config;
use crate::CongestionControlAlgorithm;
use crate::Error;
use crate::TlsConfig;
use bytes::Buf;
Expand Down Expand Up @@ -1050,11 +1051,13 @@ mod tests {
}

/// Run client/server endpoint with default config.
fn run_with_test_config(&mut self, hdr_opt: CaseConf) -> Result<()> {
let cli_conf = TestPair::new_test_config(false)?;
let srv_conf = TestPair::new_test_config(true)?;
fn run_with_test_config(&mut self, case_conf: CaseConf) -> Result<()> {
let mut cli_conf = TestPair::new_test_config(false)?;
cli_conf.set_congestion_control_algorithm(case_conf.cc_algor);
let mut srv_conf = TestPair::new_test_config(true)?;
srv_conf.set_congestion_control_algorithm(case_conf.cc_algor);

self.run(cli_conf, srv_conf, hdr_opt)
self.run(cli_conf, srv_conf, case_conf)
}

/// Run event loop for the endpoint.
Expand Down Expand Up @@ -1461,6 +1464,7 @@ mod tests {
token: Option<Vec<u8>>,
request_num: u32,
request_size: usize,
cc_algor: CongestionControlAlgorithm,
packet_loss: u32,
packet_delay: u32,
packet_reorder: u32,
Expand Down Expand Up @@ -2244,13 +2248,56 @@ mod tests {
}

#[test]
fn transfer_single_stream_with_packet_loss() -> Result<()> {
fn transfer_single_stream_cubic_with_packet_loss() -> Result<()> {
let mut t = TestPair::new();

let mut case_conf = CaseConf::default();
case_conf.request_num = 1;
case_conf.request_size = 1024 * 16;
case_conf.packet_loss = 1;
case_conf.cc_algor = CongestionControlAlgorithm::Cubic;

t.run_with_test_config(case_conf)?;
Ok(())
}

#[test]
fn transfer_single_stream_bbr_with_packet_loss() -> Result<()> {
let mut t = TestPair::new();

let mut case_conf = CaseConf::default();
case_conf.request_num = 1;
case_conf.request_size = 1024 * 16;
case_conf.packet_loss = 1;
case_conf.cc_algor = CongestionControlAlgorithm::Bbr;

t.run_with_test_config(case_conf)?;
Ok(())
}

#[test]
fn transfer_single_stream_bbr3_with_packet_loss() -> Result<()> {
let mut t = TestPair::new();

let mut case_conf = CaseConf::default();
case_conf.request_num = 1;
case_conf.request_size = 1024 * 16;
case_conf.packet_loss = 1;
case_conf.cc_algor = CongestionControlAlgorithm::Bbr3;

t.run_with_test_config(case_conf)?;
Ok(())
}

#[test]
fn transfer_single_stream_copa_with_packet_loss() -> Result<()> {
let mut t = TestPair::new();

let mut case_conf = CaseConf::default();
case_conf.request_num = 1;
case_conf.request_size = 1024 * 16;
case_conf.packet_loss = 1;
case_conf.cc_algor = CongestionControlAlgorithm::Copa;

t.run_with_test_config(case_conf)?;
Ok(())
Expand Down
87 changes: 81 additions & 6 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@
use crate::frame::Frame;

use strum::IntoEnumIterator;
use strum_macros::EnumIter;

/// QUIC transport error.
#[allow(clippy::enum_variant_names)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, Default, PartialEq, Eq, EnumIter)]
pub enum Error {
/// An endpoint uses this with CONNECTION_CLOSE to signal that the
/// connection is being closed abruptly in the absence of any error.
#[default]
NoError,

/// The endpoint encountered an internal error and cannot continue with the
Expand Down Expand Up @@ -175,8 +179,7 @@ impl Error {
}
}

#[cfg(feature = "ffi")]
pub(crate) fn to_c(self) -> libc::ssize_t {
pub(crate) fn to_c(&self) -> libc::ssize_t {
match self {
Error::NoError => 0,
Error::InternalError => -1,
Expand Down Expand Up @@ -253,10 +256,82 @@ impl std::fmt::Debug for ConnectionError {
write!(f, "is_app={:?} ", self.is_app)?;
write!(f, "error_code={:?} ", self.error_code)?;
match std::str::from_utf8(&self.reason) {
Ok(v) => write!(f, "reason={:?}", v),
Err(_) => write!(f, "reason={:?}", self.reason),
}?;
Ok(v) => write!(f, "reason={:?}", v)?,
Err(_) => write!(f, "reason={:?}", self.reason)?,
};

Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::Error::IoError;

#[test]
fn error_to_wire() {
let mut found_internal_err = false;
for err in Error::iter() {
if err == Error::NoError {
assert!(err.to_wire() == 0);
continue;
}
if err == Error::Done {
found_internal_err = true;
}
if found_internal_err {
assert_eq!(err.to_wire(), 0);
continue;
}
if let Error::CryptoError(_) = err {
assert_eq!(err.to_wire(), 0);
} else {
assert!(err.to_wire() > 0);
}
}
}

#[test]
fn error_to_c() {
for err in Error::iter() {
if err == Error::NoError {
assert_eq!(err.to_c(), 0);
} else {
assert!(err.to_c() < 0);
}
}
}

#[test]
fn io_error() {
use std::error::Error;
let e = std::io::Error::from(std::io::ErrorKind::UnexpectedEof);
let e = super::Error::from(e);

assert_eq!(format!("{}", e), "IoError(\"unexpected end of file\")");
assert!(e.source().is_none());
}

#[test]
fn connection_error() {
let e = ConnectionError {
is_app: false,
error_code: 0,
frame: None,
reason: vec![],
};
assert_eq!(format!("{:?}", e), "is_app=false error_code=0 reason=\"\"");

let e = ConnectionError {
is_app: true,
error_code: 1,
frame: None,
reason: vec![0x97, 0x61, 0x6C],
};
assert_eq!(
format!("{:?}", e),
"is_app=true error_code=1 reason=[151, 97, 108]"
);
}
}
47 changes: 44 additions & 3 deletions src/h3/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
use std::fmt;
use std::fmt::Write;

use strum::IntoEnumIterator;
use strum_macros::EnumIter;

/// An HTTP/3 error.
/// See RFC 9114 and RFC 9204.
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, EnumIter)]
pub enum Http3Error {
/// This is used when the connection or stream needs to be closed, but there
/// is no error to signal.
Expand Down Expand Up @@ -134,8 +137,7 @@ impl Http3Error {
}
}

#[cfg(feature = "ffi")]
pub(crate) fn to_c(self) -> libc::ssize_t {
pub(crate) fn to_c(&self) -> libc::ssize_t {
match self {
Http3Error::NoError => 0,
Http3Error::Done => -1,
Expand Down Expand Up @@ -186,3 +188,42 @@ impl std::convert::From<crate::error::Error> for Http3Error {
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn error_to_wire() {
let mut found_internal_err = false;
for err in Http3Error::iter() {
assert!(err.to_wire() > 0);
if let Http3Error::TransportError(_) = err {
found_internal_err = true;
}
if found_internal_err {
assert_eq!(err.to_wire(), 0x102);
}
}
}

#[test]
fn error_to_c() {
for err in Http3Error::iter() {
if err == Http3Error::NoError {
assert_eq!(err.to_c(), 0);
} else {
assert!(err.to_c() < 0);
}
}
}

#[test]
fn internal_error() {
let e = Http3Error::InternalError;
assert_eq!(format!("{}", e), "InternalError");

use std::error::Error;
assert!(e.source().is_none());
}
}
23 changes: 23 additions & 0 deletions src/h3/h3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,29 @@ pub trait Http3Handler {
fn on_conn_goaway(&self, stream_id: u64);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn fmt_readable() {
let h = Header::new(b"proto", b"h3");
assert_eq!(format!("{:?}", h), "\"proto: h3\"");

let h = Header::new(b"proto", &vec![0x97, 0x61, 0x6c]);
assert_eq!(format!("{:?}", h), "\"proto: [151, 97, 108]\"");
}

#[test]
fn header_ref() {
let name = b"x-powered-by";
let value = b"tquic";
let h = HeaderRef::new(name, value);
assert_eq!(h.name(), name);
assert_eq!(h.value(), value);
}
}

pub use error::Http3Error;

#[path = "qpack/qpack.rs"]
Expand Down
5 changes: 0 additions & 5 deletions src/h3/qpack/qpack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,6 @@ mod tests {
fn static_table() {
let mut encoded = [0u8; 158];

for (k, v, index) in static_table::STATIC_ENCODE_TABLE {
assert_eq!(static_table::STATIC_DECODE_TABLE[index as usize].0, k);
assert_eq!(static_table::STATIC_DECODE_TABLE[index as usize].1, v);
}

let headers = vec![
h3::Header::new(b":authority", b""),
h3::Header::new(b":path", b"/"),
Expand Down
Loading

0 comments on commit 458bb24

Please sign in to comment.