refactor(client): correct late-reply docs and drop private counter tests
The counter tests instantiated the private TargetCounters and mirrored its match arms, duplicating outcome-level coverage that already asserts replies_received and late through ManagedTargetOutcome, and coupling a private refactor to persistent test churn. The new counter documentation also defined late replies in timeout-only terms. A reply that arrives behind an already-received sequence is classified late by process_echo_reply even when its own probe has not timed out, so both counters are now described in terms of order and timeout.
This commit is contained in:
1 parent
5506220f67
commit
dd68608d56
3 files changed
+16
-114
No files matched your search
@@ -209,15 +209,19 @@ pub struct ManagedTargetOutcome {
|
||||
pub end_reason: ManagedTargetEndReason,
|
||||
/// Probes the underlying client reported as sent.
|
||||
pub packets_sent: u64,
|
||||
/// On-time unique echo replies.
|
||||
/// Unique echo replies that arrived in order and before their probe timed
|
||||
/// out.
|
||||
///
|
||||
/// A unique reply that arrived after its probe timed out is counted by
|
||||
/// `late` instead, so this is the count of replies that arrived in time.
|
||||
/// A unique reply that arrives behind an already-received sequence, or
|
||||
/// after its own probe timed out, is counted by `late` instead.
|
||||
pub replies_received: u64,
|
||||
/// Replies for a sequence that had already been answered.
|
||||
pub duplicates: u64,
|
||||
/// Replies that arrived after their probe timed out, whether or not the
|
||||
/// client could still match them to retained send state.
|
||||
/// Late replies: those arriving behind an already-received sequence
|
||||
/// (reordering) or after their own probe timed out.
|
||||
///
|
||||
/// This counts every late reply, whether or not the client could still
|
||||
/// match it to retained send state.
|
||||
pub late: u64,
|
||||
/// Warning events observed for this target.
|
||||
pub warning_events: u64,
|
||||
|
||||
@@ -394,15 +394,16 @@ impl TargetState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Eq, PartialEq)]
|
||||
#[derive(Default)]
|
||||
struct TargetCounters {
|
||||
packets_sent: u64,
|
||||
/// On-time unique echo replies.
|
||||
/// Unique echo replies that arrived in order and before their probe timed
|
||||
/// out.
|
||||
///
|
||||
/// A late unique reply is counted by `late` and deliberately not here, so
|
||||
/// `replies_received` stays the count of replies that arrived within their
|
||||
/// probe timeout. These counters are durable, unlike the lossy managed
|
||||
/// presentation events.
|
||||
/// A reply that arrives behind an already-received sequence, or after its
|
||||
/// own probe timed out, is counted by `late` and deliberately not here.
|
||||
/// These counters are durable, unlike the lossy managed presentation
|
||||
/// events.
|
||||
replies_received: u64,
|
||||
duplicates: u64,
|
||||
late: u64,
|
||||
|
||||
@@ -2954,106 +2954,3 @@ fn terminal_subscription_is_closed() {
|
||||
Err(ManagedSubscribeError::Closed)
|
||||
));
|
||||
}
|
||||
|
||||
/// Build the client events target accounting distinguishes.
|
||||
fn accounting_events() -> Vec<ClientEvent> {
|
||||
let remote: std::net::SocketAddr = "127.0.0.1:2112".parse().unwrap();
|
||||
let at = ClientTimestamp {
|
||||
mono: Instant::now(),
|
||||
wall: SystemTime::UNIX_EPOCH,
|
||||
};
|
||||
let rtt = crate::RttSample {
|
||||
raw: Duration::from_millis(1),
|
||||
adjusted: None,
|
||||
effective: crate::SignedDuration::from_nanos(1_000_000),
|
||||
};
|
||||
vec![
|
||||
ClientEvent::EchoSent {
|
||||
seq: 0,
|
||||
remote,
|
||||
scheduled_at: at.mono,
|
||||
sent_at: at,
|
||||
bytes: 64,
|
||||
send_call: Duration::ZERO,
|
||||
timer_error: Duration::ZERO,
|
||||
},
|
||||
ClientEvent::EchoReply {
|
||||
seq: 0,
|
||||
remote,
|
||||
sent_at: at,
|
||||
received_at: at,
|
||||
rtt,
|
||||
server_timing: None,
|
||||
one_way: None,
|
||||
received_stats: None,
|
||||
bytes: 64,
|
||||
packet_meta: crate::PacketMeta::default(),
|
||||
},
|
||||
ClientEvent::DuplicateReply {
|
||||
seq: 0,
|
||||
remote,
|
||||
received_at: at,
|
||||
bytes: 64,
|
||||
},
|
||||
ClientEvent::LateReply {
|
||||
seq: 1,
|
||||
highest_seen: 2,
|
||||
remote,
|
||||
sent_at: Some(at),
|
||||
received_at: at,
|
||||
rtt: Some(rtt),
|
||||
server_timing: None,
|
||||
one_way: None,
|
||||
received_stats: None,
|
||||
bytes: 64,
|
||||
packet_meta: crate::PacketMeta::default(),
|
||||
},
|
||||
ClientEvent::EchoLoss {
|
||||
seq: 2,
|
||||
sent_at: at,
|
||||
timeout_at: at.mono,
|
||||
},
|
||||
ClientEvent::Warning {
|
||||
kind: crate::WarningKind::WrongToken,
|
||||
message: "wrong token".to_owned(),
|
||||
at,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_counters_account_for_each_observed_event_once() {
|
||||
let mut counters = TargetCounters::default();
|
||||
for event in accounting_events() {
|
||||
counters.observe(&event);
|
||||
}
|
||||
|
||||
// A late unique reply is counted as late, not as a received reply, and a
|
||||
// probe send is not accounted here because the client owns packets_sent.
|
||||
assert_eq!(counters.packets_sent, 0);
|
||||
assert_eq!(counters.replies_received, 1);
|
||||
assert_eq!(counters.duplicates, 1);
|
||||
assert_eq!(counters.late, 1);
|
||||
assert_eq!(counters.warning_events, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_counters_ignore_events_without_a_durable_count() {
|
||||
let ignored: Vec<ClientEvent> = accounting_events()
|
||||
.into_iter()
|
||||
.filter(|event| {
|
||||
matches!(
|
||||
event,
|
||||
ClientEvent::EchoSent { .. } | ClientEvent::EchoLoss { .. }
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(ignored.len(), 2);
|
||||
|
||||
let mut counters = TargetCounters::default();
|
||||
for event in ignored {
|
||||
counters.observe(&event);
|
||||
}
|
||||
|
||||
assert_eq!(counters, TargetCounters::default());
|
||||
}
|
||||
Reference in new issue
Block a user