Skip to content

test(auth): run the outage grant test on the real clock - #4291

Merged
kixelated merged 1 commit into
mainfrom
fix/auth-outage-clock-race
Sep 26, 2026
Merged

kixelated merged 1 commit into
mainfrom
fix/auth-outage-clock-race

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Problem

an_outage_keeps_the_grant_until_expires (rs/moq-auth) ran on a paused tokio clock against a real loopback server. When the runtime idles while the 1s re-check is still on the socket, tokio auto-advances the clock past the sleep(1500ms) and log.revalidates() >= 1 fails. Linux delivers loopback inside the send syscall so CI rarely hits it; macOS does.

Reproduced on Linux by delaying the server's revalidate handling 20ms on an OS thread: fails every run.

Approach

Run the test on the real clock, the same way #4244 fixed an_outage_keeps_the_session_until_expires: expire at a whole second about 3s out, answer re-checks with 503, wait for the close, and assert lower bounds (closed as Expired, not before expires, at least one re-check seen). It now uses the wiremock server helper since nothing needs the paused clock. Adds ~3s of wall time.

Waiting on the log instead of the fixed sleep was tried first and is not sound: the clock then jumps to the 3s expiry timer, the driver drops the in-flight re-check, and the server never logs it (the repro hangs). Any virtual timer can outrun real loopback I/O here.

With a 200ms server-side delay the new test still passes.

Impact

  • Public API: none.
  • Wire: none.

Alternatives

  • Keep the paused clock and wait on log.until(...): hangs under the repro, see above.

Follow-ups

An audit of every other paused-clock test that uses real sockets found no other instance of this race. Two are safe today but would break if a connect or handshake timeout were added on their paths:

  • fixed_addresses_keep_tls_name_and_request_host (rs/moq-tokio/src/websocket.rs:709)
  • a_grant_within_clock_skew_stays_live (rs/moq-auth/src/client.rs:496)

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-26T20:42:14.869958Z 85f5cc5 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated
kixelated enabled auto-merge (squash) September 26, 2026 20:40
@coderabbitai

coderabbitai Bot commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 30 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 8ae7e431-f7be-494b-9197-e8bcc8b47c23

📥 Commits

Reviewing files that changed from the base of the PR and between 42959bd and 85f5cc5.

📒 Files selected for processing (1)
  • rs/moq-auth/src/client.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kixelated

Copy link
Copy Markdown
Collaborator Author

MERGE

Positive improvement: yes. The old test mixed a paused tokio clock with a real loopback server, so idle waits on the socket let the clock jump past the mid-lease sleep and miss the re-check assertion—especially on macOS, and reproducible on Linux with a short server-side delay. Moving this onto the wall clock matches the race that actually happens in production-shaped I/O.

Worth the complexity: yes. The change is small (one test, ~3s wall time), drops clock_server where it was the wrong tool, and keeps the useful lower-bound checks (closed as Expired, not before expires, at least one re-check seen, grant still stands). That is a fair trade for killing a flaky auth-path regression.

Different approach: no. Waiting on the log under a paused clock was already tried and is unsound here—the virtual expiry timer can outrun real loopback and drop the in-flight re-check. Keeping the paused clock would just reintroduce the race. Aligning with the merged pattern from #4244 (an_outage_keeps_the_session_until_expires) is the right call; the follow-up notes on the other paused-clock + socket tests are useful but out of scope for this PR.

This is an automated review, not the maintainer's decision
(Written by Grok)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85f5cc595b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-auth/src/client.rs
Comment on lines +524 to +525
let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let expires = SystemTime::UNIX_EPOCH + Duration::from_secs(now.as_secs() + 3);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the expiry test on Tokio's paused clock

This makes an explicitly time-dependent test wait 2 to 3 real seconds and depend on the adjustable system clock. Every run now slows the suite, a backward clock adjustment can fail the post-close comparison, and a setup stall beyond the expiry plus five-second skew makes connect(...).unwrap() fail before the behavior is tested. Please remove the socket/virtual-clock coupling at its source, such as by isolating the driver's HTTP transport, rather than moving this test to wall-clock time; the scoped testing convention requires time-dependent async tests to pause Tokio time.

AGENTS.md reference: rs/AGENTS.md:L51-L54

Useful? React with 👍 / 👎.

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.

1 participant