test(fuzz): measure the recovery probe from the latest tick
Fuzz steps can move the clock backwards, while a peer's idle time counts from its last frame, so advancing from the current tick could stay short of the idle window. Track the latest tick and probe from it; skip the probe when the tick is too close to u64::MAX to advance. A 5-minute nightly run (84k inputs) is clean after the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+15
-1
@@ -318,6 +318,9 @@ pub struct Harness {
|
|||||||
mtu: usize,
|
mtu: usize,
|
||||||
q: Rc<Queues>,
|
q: Rc<Queues>,
|
||||||
now: Tick,
|
now: Tick,
|
||||||
|
/// The latest tick the node has been given. Steps can move `now`
|
||||||
|
/// backwards, but the node's idle clock counts from the latest tick.
|
||||||
|
max_now: Tick,
|
||||||
peers: BTreeMap<Addr, PeerBook>,
|
peers: BTreeMap<Addr, PeerBook>,
|
||||||
/// Drops counted in the overflow slot (`addr: None`).
|
/// Drops counted in the overflow slot (`addr: None`).
|
||||||
overflow_drops: u64,
|
overflow_drops: u64,
|
||||||
@@ -350,6 +353,7 @@ impl Harness {
|
|||||||
mtu,
|
mtu,
|
||||||
q,
|
q,
|
||||||
now: 0,
|
now: 0,
|
||||||
|
max_now: 0,
|
||||||
peers: BTreeMap::new(),
|
peers: BTreeMap::new(),
|
||||||
overflow_drops: 0,
|
overflow_drops: 0,
|
||||||
stored: BTreeMap::new(),
|
stored: BTreeMap::new(),
|
||||||
@@ -511,6 +515,7 @@ impl Harness {
|
|||||||
} else {
|
} else {
|
||||||
self.now.saturating_sub(delta.unsigned_abs())
|
self.now.saturating_sub(delta.unsigned_abs())
|
||||||
};
|
};
|
||||||
|
self.max_now = self.max_now.max(self.now);
|
||||||
}
|
}
|
||||||
Step::Ourselves { size } => {
|
Step::Ourselves { size } => {
|
||||||
let payload = vec![0x5A; *size as usize % (MAX_PAYLOAD + 1)];
|
let payload = vec![0x5A; *size as usize % (MAX_PAYLOAD + 1)];
|
||||||
@@ -773,7 +778,16 @@ impl Harness {
|
|||||||
/// every peer, a frame from a never-seen address still gets a slot, so
|
/// every peer, a frame from a never-seen address still gets a slot, so
|
||||||
/// the node stores the observation it carries.
|
/// the node stores the observation it carries.
|
||||||
pub fn check_peer_table_recovers(&mut self) {
|
pub fn check_peer_table_recovers(&mut self) {
|
||||||
self.now = self.now.saturating_add(conformance::PEER_IDLE_MS + 1);
|
// Idle time counts from each peer's last frame, so measure from the
|
||||||
|
// latest tick, not the current one (a step may have moved `now`
|
||||||
|
// backwards; ages saturate rather than go negative). Ticks this close
|
||||||
|
// to u64::MAX can't advance by PEER_IDLE_MS, so there's nothing to
|
||||||
|
// probe.
|
||||||
|
let Some(now) = self.max_now.checked_add(conformance::PEER_IDLE_MS + 1) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
self.now = now;
|
||||||
|
self.max_now = now;
|
||||||
self.pump();
|
self.pump();
|
||||||
let addr = Addr::MAX;
|
let addr = Addr::MAX;
|
||||||
let obs = Observation::broadcast([0xEE; 16], u64::MAX, b"recovery", b"probe");
|
let obs = Observation::broadcast([0xEE; 16], u64::MAX, b"recovery", b"probe");
|
||||||
|
|||||||
Reference in New Issue
Block a user