in quic/s2n-quic-core/src/packet/number/map.rs [662:764]
fn model(ops: &[Operation]) {
let mut current = PacketNumberSpace::ApplicationData.new_packet_number(VarInt::from_u8(0));
/// Tracks the subject against an oracle to ensure differential equivalency
#[derive(Debug, Default)]
struct Model {
subject: TestMap,
oracle: BTreeMap<PacketNumber, u64>,
}
impl Model {
pub fn insert(&mut self, packet_number: PacketNumber) {
let value = packet_number.as_u64();
self.subject.insert(packet_number, value);
self.oracle.insert(packet_number, value);
self.check_consistency();
}
pub fn remove(&mut self, packet_number: PacketNumber) {
assert_eq!(
self.subject.remove(packet_number),
self.oracle.remove(&packet_number)
);
self.check_consistency();
}
pub fn remove_range(&mut self, range: PacketNumberRange) {
// trim range so we're not slamming the BTreeMap
let range = if self.subject.is_empty() {
PacketNumberRange::new(range.start(), range.start())
} else {
let start = range.start().max(self.subject.start);
let end = range.end().min(self.subject.end);
if start > end {
PacketNumberRange::new(start, start)
} else {
PacketNumberRange::new(start, end)
}
};
let actual: Vec<_> = self.subject.remove_range(range).collect();
let mut expected = vec![];
for pn in range {
if let Some(value) = self.oracle.remove(&pn) {
expected.push((pn, value));
}
}
assert_eq!(expected, actual);
self.check_consistency();
}
fn check_consistency(&self) {
let mut subject = self.subject.iter();
let mut oracle = self.oracle.iter();
loop {
match (subject.next(), oracle.next()) {
(Some(actual), Some((expected_pn, expected_info))) => {
assert_eq!((*expected_pn, expected_info), actual);
}
(None, None) => break,
(actual, expected) => {
panic!("expected: {:?}, actual: {:?}", expected, actual);
}
}
}
}
}
let mut model = Model::default();
for op in ops.iter().copied() {
match op {
Operation::Insert => {
model.insert(current);
current = current.next().unwrap();
}
Operation::Skip => {
current = current.next().unwrap();
}
Operation::Remove(pn) => {
let pn = PacketNumberSpace::ApplicationData.new_packet_number(pn);
model.remove(pn);
}
Operation::RemoveRange(start, end) => {
let (start, end) = if start > end {
(end, start)
} else {
(start, end)
};
let start = PacketNumberSpace::ApplicationData.new_packet_number(start);
let end = PacketNumberSpace::ApplicationData.new_packet_number(end);
let range = PacketNumberRange::new(start, end);
model.remove_range(range);
}
}
}
}