Skip to content

test(wifi): one generous D-Bus reply budget for nm_agent's system tests, not 12 tight ones (#676) - #677

Merged
vibechoom merged 1 commit into
mainfrom
test/nm-agent-dbus-budget-676
Jul 31, 2026
Merged

test(wifi): one generous D-Bus reply budget for nm_agent's system tests, not 12 tight ones (#676)#677
vibechoom merged 1 commit into
mainfrom
test/nm-agent-dbus-budget-676

Conversation

@vibechoom

Copy link
Copy Markdown
Contributor

What

wifi/nm_agent.rs's system_tests module wrapped every real D-Bus round trip in tokio::time::timeout(Duration::from_secs(3), …) — 12 copies of the same literal. One of them (non_wireless_setting_is_rejected) flaked CI on a markdown-only PR (#672) with GetSecrets did not return in time: Elapsed(()). Nothing was wrong; something was slow, because nix flake check runs this suite in the same invocation as two nixosTest VM builds, full workspace clippy, and package builds — CPU contention there is the normal condition, not an edge case.

This replaces all 12 literals with one shared const DBUS_REPLY_BUDGET: Duration = Duration::from_secs(30);, doc-commented with the framing that made the fix obvious:

These timeouts are liveness guards, not latency assertions. No test in this file is trying to prove a D-Bus round trip completes within some duration — that would be a meaningless claim about a sandboxed builder under load. Their only job is to stop a genuinely hung call from wedging the suite (and nix flake check) forever. A real regression still fails, just later rather than sooner. Raising the budget weakens no assertion; it only reduces how often the suite lies about a real regression. The doc comment on the const spells this out explicitly so the next person who looks at 30 and thinks "that seems excessive" reads the reasoning before tightening it back down.

Why 30s

Comfortably above worst-case CI contention (the failing run needed more than 3s but the timeout, not the call, was the bug — 30s gives an order of magnitude of headroom over a budget that was already demonstrably too tight under load), comfortably below "painful to notice" if a call is genuinely hung (a wedged test still fails within half a minute, not hangs indefinitely). Not a precisely-derived number — the doc comment says as much and invites raising it further if it ever flakes again.

Count verification — 12 replaced, 0 left alone

I checked each of the 12 occurrences individually rather than blanket-replacing:

  • 1× — ephemeral_bus()'s wait for the spawned dbus-daemon to print its listen address on stdout (startup handshake, itself subject to the same CPU contention as everything else in the suite).
  • 4× — await_prompt() deadlines (polls NmAgent's prompts Mutable until the agent surfaces a PromptRequest, across happy_path, vpn_happy_path, wep_hint, and cancel_resolves).
  • 7× — tokio::time::timeout(...) around an actual GetSecrets/CancelGetSecrets D-Bus call or its JoinHandle.

All 12 are "did this eventually happen" liveness guards over real D-Bus/process I/O — none are latency assertions, and none are unrelated sleeps. Nothing was left alone because nothing in this file's Duration::from_secs(3) occurrences was the wrong shape for this fix.

Also updated the module-level doc comment above mod system_tests (previously said a marshalling regression "fails fast" — now says it fails bounded, not fast, and points at the const for the reasoning) so it doesn't contradict the new budget.

Stability evidence

Ran the actual gated bucket (cargo test --workspace --features system-tests) under xvfb-run (needed for hytte-ui's GTK unit tests — see below) three times back to back after the change: 53/53 test binaries green, 0 failures, all 6 wifi::nm_agent::system_tests::* passing every run. cargo clippy --workspace --all-targets --features system-tests -- -D warnings (with RUSTC_WRAPPER unset) is clean. nix fmt made zero changes.

(Note for anyone reproducing locally: a plain cargo test --workspace --features system-tests without xvfb-run fails early in hytte-reactive's GTK bind tests with "Failed to initialize GTK" — no display server — and never reaches hytte-services. That's expected per this repo's own docs, not a regression; wrap in xvfb-run as CLAUDE.md says.)

Sibling-bucket sweep (#676 asked for this) — report only, no fix

Grepped crates/hytte-bus/tests/, crates/hytte-reactive/, and crates/hytte-ui/ for the same shape (timeout(...)/sleep(...) wrapping real I/O in a gated system-test bucket). hytte-reactive and hytte-ui have no matches — their gated tests are the GTK mod tests blocks compiled under system-tests but don't wrap D-Bus/process I/O in a fixed budget. hytte-bus/tests/ does have the same class, un-fixed by #451:

  • crates/hytte-bus/tests/common/mod.rs:87 — the shared ephemeral_bus() helper (used by every hytte-bus integration test file) has the exact same tokio::time::timeout(Duration::from_secs(3), lines.next_line()) waiting on the spawned dbus-daemon's startup handshake that this PR just fixed in nm_agent.rs's copy of the same helper. Since it's shared, one fix here would cover own.rs, property.rs, proxy.rs, signals.rs, export.rs, connection_reconnect.rs, and call_fd.rs at once.
  • Several files use short poll-loop-with-sub-timeout patterns (an outer 1-5s deadline, an inner 20-200ms timeout on stream.next()), e.g. own.rs:168/324, property.rs:61-381, proxy.rs:29-157, signals.rs:108. These retry within their deadline so they're more resilient than a flat single-shot timeout, but the outer deadlines (Duration::from_secs(1)/(2)/(5)) are tighter than what this PR just judged necessary for nm_agent's flat timeouts, and under the same nix flake check contention they're plausibly exposed to the same flake class.
  • proxy.rs:100 (tokio::time::sleep(Duration::from_secs(3)) inside a Slowpoke::slow() test double) is a deliberately-slow method the test uses to prove a real proxy timeout fires — not a liveness guard, and not in scope for this class of fix.

I did not touch any of these files — the issue asked for a report so you can decide whether a follow-up is worth filing, and keeping this PR to the one file it names keeps it obviously safe to review.

Closes #676

…ts, not 12 tight ones (#676)

Replace 12 duplicated `Duration::from_secs(3)` literals in
wifi/nm_agent.rs's system_tests module with one shared
DBUS_REPLY_BUDGET const (30s), doc-commented with the reasoning so the
next person who thinks "30s seems excessive" reads it before tightening.

These timeouts are liveness guards, not latency assertions: nothing in
this file claims a GetSecrets round trip should complete within any
particular time, only that a hung call must not wedge nix flake check
forever. That check runs the same clippy/test invocation alongside two
nixosTest VMs and package builds, so CPU contention is the normal
condition, not an edge case. A tight budget buys nothing there and
costs false reds, as #676 demonstrated on a markdown-only PR.

Closes #676
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test(wifi): nm_agent's 12 three-second D-Bus timeouts flake under nix flake check load — they're liveness guards, not latency assertions

1 participant