Add e2e latency consistency test for WireGuard tunnel

Sends 50 pings at 0.2s intervals through the cell-to-cell tunnel and
asserts that ≤5% exceed 3× the median RTT (floor 15ms). Catches
server-side packet processing regressions on wired paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-07 15:13:27 -04:00
parent b8e57b6e51
commit 7391d7f7a2
+27
View File
@@ -401,6 +401,33 @@ class TestCellToCellRouting:
f'Cell1 web (Caddy) at {url} not reachable via tunnel: {e}' f'Cell1 web (Caddy) at {url} not reachable via tunnel: {e}'
) )
def test_tunnel_latency_consistency(self, wg_setup):
"""WireGuard tunnel has no significant latency spikes on a local wired network.
Sends 50 pings at 0.2s intervals to cell2's WG server IP. Pass condition:
≤ 5% of pings (≤ 2 out of 50) exceed max(3× median RTT, 15ms).
"""
cell2_wg_ip = wg_setup['cell2_wg_ip']
r = _run(['ping', '-c', '50', '-i', '0.2', '-W', '2', cell2_wg_ip], timeout=25)
assert r.returncode == 0, f'All pings to {cell2_wg_ip} failed: {r.stderr}'
rtts = [float(m.group(1)) for m in re.finditer(r'time=([\d.]+) ms', r.stdout)]
assert len(rtts) >= 40, (
f'Too few ping replies ({len(rtts)}/50) — packet loss may mask latency issues'
)
sorted_rtts = sorted(rtts)
median = sorted_rtts[len(sorted_rtts) // 2]
spike_threshold = max(median * 3.0, 15.0)
spikes = [rtt for rtt in rtts if rtt > spike_threshold]
spike_ratio = len(spikes) / len(rtts)
assert spike_ratio <= 0.05, (
f'Latency spikes: {len(spikes)}/{len(rtts)} packets ({spike_ratio:.0%}) '
f'exceeded {spike_threshold:.1f}ms (3× median {median:.1f}ms). '
f'Spike values: {[f"{s:.1f}ms" for s in sorted(spikes)]}'
)
def test_cross_cell_domain_accessible(self, wg_setup): def test_cross_cell_domain_accessible(self, wg_setup):
"""A service domain from cell1 is resolvable via cell2's DNS and HTTP-reachable. """A service domain from cell1 is resolvable via cell2's DNS and HTTP-reachable.