#![cfg(feature = "reassembler")]
use flowscope::{Reassembler, SegmentBufferReassembler, TcpOverlapPolicy, Timestamp};
fn ts(s: u32) -> Timestamp {
Timestamp::new(s, 0)
}
fn primed(policy: TcpOverlapPolicy) -> SegmentBufferReassembler {
let mut r = SegmentBufferReassembler::new().with_tcp_overlap_policy(policy);
r.segment(1000, b"hello", ts(0));
r
}
fn run_exact_overlap(policy: TcpOverlapPolicy) -> Vec<u8> {
let mut r = primed(policy);
r.segment(1010, b"FIRST", ts(1));
r.segment(1010, b"laTeR", ts(2));
r.segment(1005, b"PAUSE", ts(3));
r.take()
}
#[test]
fn first_policy_keeps_earlier_arrived_bytes() {
let out = run_exact_overlap(TcpOverlapPolicy::First);
assert_eq!(out, b"helloPAUSEFIRST");
}
#[test]
fn last_policy_uses_later_arrived_bytes() {
let out = run_exact_overlap(TcpOverlapPolicy::Last);
assert_eq!(out, b"helloPAUSElaTeR");
}
#[test]
fn lower_seq_policy_with_exact_overlap_keeps_first_inserted() {
let out = run_exact_overlap(TcpOverlapPolicy::LowerSeq);
assert_eq!(out, b"helloPAUSEFIRST");
}
#[test]
fn higher_seq_policy_with_exact_overlap_keeps_first_inserted() {
let out = run_exact_overlap(TcpOverlapPolicy::HigherSeq);
assert_eq!(out, b"helloPAUSEFIRST");
}
#[test]
fn partial_overlap_lower_seq_keeps_lower_starting_segment() {
let mut r = primed(TcpOverlapPolicy::LowerSeq);
r.segment(1010, b"AAAAA", ts(1));
r.segment(1012, b"BBBBB", ts(2));
r.segment(1005, b"-----", ts(3));
let out = r.take();
assert_eq!(out, b"hello-----AAAAABB");
}
#[test]
fn partial_overlap_higher_seq_keeps_higher_starting_segment() {
let mut r = primed(TcpOverlapPolicy::HigherSeq);
r.segment(1010, b"AAAAA", ts(1));
r.segment(1012, b"BBBBB", ts(2));
r.segment(1005, b"-----", ts(3));
let out = r.take();
assert_eq!(out, b"hello-----AABBBBB");
}
#[test]
fn partial_overlap_first_policy_takes_existing_in_overlap() {
let mut r = primed(TcpOverlapPolicy::First);
r.segment(1010, b"AAAAA", ts(1));
r.segment(1012, b"BBBBB", ts(2));
r.segment(1005, b"-----", ts(3));
let out = r.take();
assert_eq!(out, b"hello-----AAAAABB");
}
#[test]
fn partial_overlap_last_policy_takes_new_in_overlap() {
let mut r = primed(TcpOverlapPolicy::Last);
r.segment(1010, b"AAAAA", ts(1));
r.segment(1012, b"BBBBB", ts(2));
r.segment(1005, b"-----", ts(3));
let out = r.take();
assert_eq!(out, b"hello-----AABBBBB");
}
#[test]
fn divergent_overlap_increments_inconsistency_counter() {
for policy in [
TcpOverlapPolicy::First,
TcpOverlapPolicy::Last,
TcpOverlapPolicy::LowerSeq,
TcpOverlapPolicy::HigherSeq,
] {
let mut r = primed(policy);
r.segment(1010, b"FIRST", ts(1));
r.segment(1010, b"laTeR", ts(2));
assert_eq!(
r.rexmit_inconsistencies(),
1,
"policy {policy:?} should still flag divergence"
);
}
}
#[test]
fn identical_overlap_does_not_increment_inconsistency() {
let mut r = primed(TcpOverlapPolicy::First);
r.segment(1010, b"hello", ts(1));
r.segment(1010, b"hello", ts(2));
assert_eq!(r.rexmit_inconsistencies(), 0);
}
#[test]
fn overlap_policy_default_is_first() {
let r = SegmentBufferReassembler::new();
assert_eq!(r.tcp_overlap_policy(), TcpOverlapPolicy::First);
}
#[test]
fn overlap_policy_round_trip_via_with_builder() {
let r = SegmentBufferReassembler::new().with_tcp_overlap_policy(TcpOverlapPolicy::Last);
assert_eq!(r.tcp_overlap_policy(), TcpOverlapPolicy::Last);
}
#[test]
fn slug_vocabulary_locked() {
assert_eq!(TcpOverlapPolicy::First.as_str(), "first");
assert_eq!(TcpOverlapPolicy::Last.as_str(), "last");
assert_eq!(TcpOverlapPolicy::LowerSeq.as_str(), "lower_seq");
assert_eq!(TcpOverlapPolicy::HigherSeq.as_str(), "higher_seq");
}