Skip to content

Commit

Permalink
test: remove integration tests in favor of unit (#1503)
Browse files Browse the repository at this point in the history
  • Loading branch information
camshaft authored Sep 21, 2022
1 parent 08a08af commit b8f38ad
Show file tree
Hide file tree
Showing 37 changed files with 385 additions and 405 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ env:
RUST_BACKTRACE: 1
# Pin the nightly toolchain to prevent breakage.
# This should be occasionally updated.
RUST_NIGHTLY_TOOLCHAIN: nightly-2022-07-10
RUST_NIGHTLY_TOOLCHAIN: nightly-2022-09-15
CDN: https://dnglbrstg7yg.cloudfront.net
# enable unstable features for testing
S2N_UNSTABLE_CRYPTO_OPT_TX: 100
Expand Down Expand Up @@ -647,4 +647,3 @@ jobs:
./scripts/typos --format json | tee /tmp/typos.json | jq -rs '.[] | "::error file=\(.path),line=\(.line_num),col=\(.byte_offset)::\(.typo) should be \"" + (.corrections // [] | join("\" or \"") + "\"")'
cat /tmp/typos.json
! grep -q '[^[:space:]]' /tmp/typos.json
2 changes: 1 addition & 1 deletion .github/workflows/netbench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ env:
RUST_BACKTRACE: 1
# Pin the nightly toolchain to prevent breakage.
# This should be occasionally updated.
RUST_NIGHTLY_TOOLCHAIN: nightly-2022-07-10
RUST_NIGHTLY_TOOLCHAIN: nightly-2022-09-15
CDN: https://dnglbrstg7yg.cloudfront.net
# enable unstable features for testing
S2N_UNSTABLE_CRYPTO_OPT_TX: 100
Expand Down
36 changes: 0 additions & 36 deletions quic/s2n-quic-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,39 +44,3 @@ futures-test = "0.3"
ip_network = "0.4"
plotters = { version = "0.3", default-features = false, features = ["svg_backend", "line_series"] }
s2n-codec = { path = "../../common/s2n-codec", features = ["testing"] }

# TODO remove this once this is fixed: https://github.com/model-checking/kani/issues/473
[target.'cfg(kani)'.dependencies]
bolero = "0.7"
bolero-generator = "0.7"

[[test]]
name = "crypto"
path = "tests/crypto/fuzz_target.rs"
harness = false

[[test]]
name = "frame"
path = "tests/frame/fuzz_target.rs"
harness = false

[[test]]
name = "packet"
path = "tests/packet/fuzz_target.rs"
harness = false
required-features = ["testing"]

[[test]]
name = "transport_parameters"
path = "tests/transport_parameters/fuzz_target.rs"
harness = false

[[test]]
name = "varint"
path = "tests/varint/fuzz_target.rs"
harness = false

[[test]]
name = "recovery-simulation"
path = "tests/recovery/simulation.rs"
required-features = ["testing"]
3 changes: 3 additions & 0 deletions quic/s2n-quic-core/src/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ pub mod retry;
pub mod tls;
pub mod zero_rtt;

#[cfg(test)]
mod tests;

pub use application::*;
pub use error::*;
pub use handshake::*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use bolero::{check, generator::*};
use core::mem::size_of;
use s2n_codec::{DecoderBufferMut, EncoderBuffer};
use s2n_quic_core::{
use crate::{
crypto::{CryptoError, HeaderKey, HeaderProtectionMask, Key, ProtectedPayload},
packet::number::{PacketNumber, PacketNumberSpace},
varint::VarInt,
};
use bolero::{check, generator::*};
use core::mem::size_of;
use s2n_codec::{DecoderBufferMut, EncoderBuffer};
use std::convert::TryInto;

fn main() {
#[test]
#[cfg_attr(miri, ignore)] // This test is too expensive for miri to complete in a reasonable amount of time
fn round_trip() {
check!()
.with_generator((
gen()
Expand Down Expand Up @@ -54,7 +56,7 @@ fn fuzz_unprotect(
let payload = ProtectedPayload::new(header_len, payload.into_less_safe_slice());

let (truncated_packet_number, payload) =
s2n_quic_core::crypto::unprotect(&FuzzCrypto, largest_packet_number.space(), payload)?;
crate::crypto::unprotect(&FuzzCrypto, largest_packet_number.space(), payload)?;

let packet_number = truncated_packet_number.expand(largest_packet_number);

Expand All @@ -64,7 +66,7 @@ fn fuzz_unprotect(
.filter(|actual| truncated_packet_number.eq(actual))
.ok_or(CryptoError::DECODE_ERROR)?;

let (_header, _payload) = s2n_quic_core::crypto::decrypt(&FuzzCrypto, packet_number, payload)?;
let (_header, _payload) = crate::crypto::decrypt(&FuzzCrypto, packet_number, payload)?;

Ok((packet_number, header_len))
}
Expand All @@ -82,15 +84,15 @@ fn fuzz_protect(
let truncated_packet_number = packet_number.truncate(largest_packet_number).unwrap();
let packet_number_len = truncated_packet_number.len();

let (payload, _remaining) = s2n_quic_core::crypto::encrypt(
let (payload, _remaining) = crate::crypto::encrypt(
&FuzzCrypto,
packet_number,
packet_number_len,
header_len,
payload,
)?;

let _payload = s2n_quic_core::crypto::protect(&FuzzCrypto, payload)?;
let _payload = crate::crypto::protect(&FuzzCrypto, payload)?;

Ok(())
}
Expand Down Expand Up @@ -138,8 +140,8 @@ impl Key for FuzzCrypto {
0
}

fn cipher_suite(&self) -> s2n_quic_core::crypto::tls::CipherSuite {
s2n_quic_core::crypto::tls::CipherSuite::Unknown
fn cipher_suite(&self) -> crate::crypto::tls::CipherSuite {
crate::crypto::tls::CipherSuite::Unknown
}
}

Expand Down
3 changes: 3 additions & 0 deletions quic/s2n-quic-core/src/frame/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ pub mod ack_elicitation;
pub mod congestion_controlled;
pub mod path_validation;

#[cfg(test)]
mod tests;

//= https://www.rfc-editor.org/rfc/rfc9000#section-19
//# As described in Section 12.4, packets contain one or more frames.
//# This section describes the format and semantics of the core QUIC
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::frame::FrameRef;
use bolero::check;
use s2n_codec::{assert_codec_round_trip_bytes_mut, Encoder, EncoderLenEstimator, EncoderValue};
use s2n_quic_core::frame::FrameRef;

fn main() {
#[test]
fn round_trip() {
check!().for_each(|input| {
let mut input = input.to_vec();
let frames = assert_codec_round_trip_bytes_mut!(FrameRef, &mut input);
Expand Down
3 changes: 3 additions & 0 deletions quic/s2n-quic-core/src/packet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ pub mod long;
pub mod number;
pub mod stateless_reset;

#[cfg(test)]
mod tests;

pub use key_phase::{KeyPhase, ProtectedKeyPhase};

use connection::id::ConnectionInfo;
Expand Down
143 changes: 3 additions & 140 deletions quic/s2n-quic-core/src/packet/number/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ pub mod map;
#[cfg(feature = "alloc")]
pub use map::Map;

#[cfg(test)]
mod tests;

//= https://www.rfc-editor.org/rfc/rfc9000#section-17.1
//# the sender MUST use a packet number size able to represent more than
//# twice as large a range as the difference between the largest
Expand Down Expand Up @@ -225,143 +228,3 @@ fn decode_packet_number(

PacketNumber::from_varint(candidate_pn, space)
}

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

fn new(value: VarInt) -> PacketNumber {
PacketNumberSpace::Initial.new_packet_number(value)
}

/// This implementation tries to closely follow the RFC pseudo code so it's
/// easier to ensure it matches.
#[allow(clippy::blocks_in_if_conditions)]
fn rfc_decoder(largest_pn: u64, truncated_pn: u64, pn_nbits: usize) -> u64 {
use std::panic::catch_unwind as catch;

//= https://www.rfc-editor.org/rfc/rfc9000#section-A.3
//= type=test
//# DecodePacketNumber(largest_pn, truncated_pn, pn_nbits):
//# expected_pn = largest_pn + 1
//# pn_win = 1 << pn_nbits
//# pn_hwin = pn_win / 2
//# pn_mask = pn_win - 1
//# // The incoming packet number should be greater than
//# // expected_pn - pn_hwin and less than or equal to
//# // expected_pn + pn_hwin
//# //
//# // This means we cannot just strip the trailing bits from
//# // expected_pn and add the truncated_pn because that might
//# // yield a value outside the window.
//# //
//# // The following code calculates a candidate value and
//# // makes sure it's within the packet number window.
//# // Note the extra checks to prevent overflow and underflow.
//# candidate_pn = (expected_pn & ~pn_mask) | truncated_pn
//# if candidate_pn <= expected_pn - pn_hwin and
//# candidate_pn < (1 << 62) - pn_win:
//# return candidate_pn + pn_win
//# if candidate_pn > expected_pn + pn_hwin and
//# candidate_pn >= pn_win:
//# return candidate_pn - pn_win
//# return candidate_pn
let expected_pn = largest_pn + 1;
let pn_win = 1 << pn_nbits;
let pn_hwin = pn_win / 2;
let pn_mask = pn_win - 1;

let candidate_pn = (expected_pn & !pn_mask) | truncated_pn;
if catch(|| {
candidate_pn <= expected_pn.checked_sub(pn_hwin).unwrap()
&& candidate_pn < (1u64 << 62).checked_sub(pn_win).unwrap()
})
.unwrap_or_default()
{
return candidate_pn + pn_win;
}

if catch(|| {
candidate_pn > expected_pn.checked_add(pn_hwin).unwrap() && candidate_pn >= pn_win
})
.unwrap_or_default()
{
return candidate_pn - pn_win;
}

candidate_pn
}

#[test]
fn truncate_expand_test() {
check!()
.with_type()
.cloned()
.for_each(|(largest_pn, expected_pn)| {
let largest_pn = new(largest_pn);
let expected_pn = new(expected_pn);
if let Some(truncated_pn) = expected_pn.truncate(largest_pn) {
assert_eq!(expected_pn, truncated_pn.expand(largest_pn));
}
});
}

#[test]
fn rfc_differential_test() {
check!()
.with_type()
.cloned()
.for_each(|(largest_pn, truncated_pn)| {
let largest_pn = new(largest_pn);
let space = largest_pn.space();
let truncated_pn = TruncatedPacketNumber {
space,
value: truncated_pn,
};
let rfc_value = rfc_decoder(
largest_pn.as_u64(),
truncated_pn.into_u64(),
truncated_pn.bitsize(),
)
.min(VarInt::MAX.as_u64());
let actual_value = truncated_pn.expand(largest_pn).as_u64();

assert_eq!(
actual_value,
rfc_value,
"diff: {}",
actual_value
.checked_sub(rfc_value)
.unwrap_or(rfc_value - actual_value)
);
});
}

#[test]
fn example_test() {
macro_rules! example {
($largest:expr, $truncated:expr, $expected:expr) => {{
let largest = new(VarInt::from_u32($largest));
let truncated = TruncatedPacketNumber::new($truncated, PacketNumberSpace::Initial);
let expected = new(VarInt::from_u32($expected));
assert_eq!(truncated.expand(largest), expected);
}};
}

example!(0xa82e1b31, 0x9b32u16, 0xa82e9b32);
}

#[test]
#[cfg_attr(miri, ignore)] // snapshot tests don't work on miri
fn size_of_snapshots() {
use core::mem::size_of;
use insta::assert_debug_snapshot;

assert_debug_snapshot!("PacketNumber", size_of::<PacketNumber>());
assert_debug_snapshot!("PacketNumberLen", size_of::<PacketNumberLen>());
assert_debug_snapshot!("PacketNumberSpace", size_of::<PacketNumberSpace>());
assert_debug_snapshot!("ProtectedPacketNumber", size_of::<ProtectedPacketNumber>());
assert_debug_snapshot!("TruncatedPacketNumber", size_of::<TruncatedPacketNumber>());
}
}
Loading

0 comments on commit b8f38ad

Please sign in to comment.