test(connlib): fix off-by-1 second error in NAT table test (#10912)

A CI failure uncovered that we have an off-by-1 second error in our NAT
table test. The mapping only expires after the last packet seen + the
protocol TTL, not after the first sent one + protocol TTL.

---------

Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Thomas Eizinger
2025-11-19 17:32:13 +11:00
committed by GitHub
parent 01e16e87d6
commit ea5e734254
3 changed files with 21 additions and 23 deletions

View File

@@ -0,0 +1,12 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 1e03c37afda9f91fb4bf23e693921b59530eaefdb95094db03ac8d1e448b68d4
cc 95107af217cd84a6eacda3264751e15825f7fb92d7cc70378baaf2f7a0958b1c
cc 6937709663669c298021f536f9f921964928d1ab8640068da13db6e1cde363a4
cc 483e1d1fa3f453bd4890de5449f284490511e59c9a206cfbc051204a41323495
cc 9937e167496adf2b059df0c2b48c103de8f338b401c585299ae51f7db3e7706e
cc a1b5199cddab4b12b527bd0bf32f33375ce109bc2a2a71bc88e5dce6bdf97de4

View File

@@ -1,11 +0,0 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 1e03c37afda9f91fb4bf23e693921b59530eaefdb95094db03ac8d1e448b68d4 # shrinks to input = _TranslatesBackAndForthUdpPacketArgs { packet: Ipv4(ConvertibleIpv4Packet { buf: Owned([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 28, 0, 0, 0, 0, 64, 17, 122, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 255, 222]) }), outside_dst: 0.0.0.0, response_delay: 9223372036854758677.681955028s }
cc 95107af217cd84a6eacda3264751e15825f7fb92d7cc70378baaf2f7a0958b1c # shrinks to input = _TranslatesBackAndForthUdpPacketArgs { packet: Ipv4(ConvertibleIpv4Packet { buf: Owned([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 28, 0, 0, 0, 0, 64, 17, 122, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 255, 222]) }), outside_dst: ::ffff:0.0.0.0, response_delay: 0 }
cc 6937709663669c298021f536f9f921964928d1ab8640068da13db6e1cde363a4 # shrinks to input = _TranslatesBackAndForthUdpPacketArgs { packet: Ipv4(ConvertibleIpv4Packet { buf: Owned([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 28, 0, 0, 0, 0, 64, 17, 122, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 255, 222]) }), outside_dst: 0.0.0.0, response_delay: 60 }
cc 483e1d1fa3f453bd4890de5449f284490511e59c9a206cfbc051204a41323495 # shrinks to input = _TranslatesBackAndForthPacketArgs { packet: Ipv6(ConvertibleIpv6Packet { buf: Owned([96, 0, 0, 0, 0, 20, 6, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 128, 175, 101, 0, 0]) }), outside_dst: ::ffff:0.0.0.0, response_delay: 0 }
cc 9937e167496adf2b059df0c2b48c103de8f338b401c585299ae51f7db3e7706e # shrinks to input = _CanHandleMultiplePacketsArgs { packet1: Ipv4(ConvertibleIpv4Packet { buf: Owned([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 28, 0, 0, 192, 0, 64, 17, 186, 209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 255, 222]) }), outside_dst1: 0.0.0.0, packet2: Ipv4(ConvertibleIpv4Packet { buf: Owned([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 28, 0, 0, 192, 0, 64, 17, 186, 209, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 8, 255, 222]) }), outside_dst2: 0.0.0.0 }

View File

@@ -349,7 +349,7 @@ mod tests {
) {
proptest::prop_assume!(packet.destination().is_ipv4() == outside_dst.is_ipv4()); // Required for our test to simulate a response.
let sent_at = Instant::now();
let mut now = Instant::now();
let mut table = NatTable::default();
let response_delay = Duration::from_secs(response_delay);
@@ -358,9 +358,8 @@ mod tests {
let dst = packet.destination();
// Translate out
let (new_source_protocol, new_dst_ip) = table
.translate_outgoing(&packet, outside_dst, sent_at)
.unwrap();
let (new_source_protocol, new_dst_ip) =
table.translate_outgoing(&packet, outside_dst, now).unwrap();
// Pretend we are getting a response.
let mut response = packet.clone();
@@ -368,18 +367,16 @@ mod tests {
response.set_src(new_dst_ip).unwrap();
// Update time.
table.handle_timeout(sent_at + Duration::from_secs(1));
now += Duration::from_secs(1);
table.handle_timeout(now);
// Confirm mapping
table
.translate_incoming(&response.clone(), sent_at + Duration::from_secs(1))
.unwrap();
table.translate_incoming(&response.clone(), now).unwrap();
// Simulate another packet after _response_delay_
table.handle_timeout(sent_at + response_delay);
let translate_incoming = table
.translate_incoming(&response, sent_at + response_delay)
.unwrap();
now += response_delay;
table.handle_timeout(now);
let translate_incoming = table.translate_incoming(&response, now).unwrap();
let ttl = match src {
Protocol::Tcp(_) => 7200,