Skip to content

Fix double-dilated timeout in ExpectMsgAsync<T>(Func<T, IActorRef, bool>, ...) - #8430

Merged
Aaronontheweb merged 1 commit into
akkadotnet:devfrom
Aaronontheweb:fix/testkit-expectmsg-double-dilation
Jul 29, 2026
Merged

Aaronontheweb merged 1 commit into
akkadotnet:devfrom
Aaronontheweb:fix/testkit-expectmsg-double-dilation

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Member

Problem

TestKitBase_Expect.cs:207 resolves its timeout as:

timeout: RemainingOrDilated(RemainingOrDilated(timeout))

applying akka.test.timefactor twice. Every sibling overload applies it once.

Two consequences:

  • With an explicit duration and timefactor = 3, a 5s wait becomes 45s (5 → 15 → 45).
  • With null it is worse than a simple over-scale: the inner call resolves to RemainingOrDefault — the time actually remaining in the enclosing Within — and the outer call then dilates that remainder, yielding a bound larger than the budget it was derived from.

Found while tracking down MNTR flakes caused by the same class of mistake in test code (pre-dilating a value handed to a TestKit method that dilates internally).

Fix

Apply RemainingOrDilated once, matching every other overload.

Blast radius

This overload — ExpectMsgAsync<T>(Func<T, IActorRef, bool> isMessageAndSender, ...) — has no callers anywhere in this repository, so no existing test was relying on the inflated bound. It affects downstream users of Akka.TestKit only, for whom this restores the documented timefactor semantics.

Note the effective timeout gets shorter for anyone using this overload with a large timefactor, which is the correct behaviour but is a behavioural change worth calling out in review.

Verification

Akka.TestKit.Tests 320/321 (1 pre-existing skip) and Akka.TestKit.Xunit2.Tests 4/4 pass.

…ol>, ...)

This overload resolved its bound as RemainingOrDilated(RemainingOrDilated(timeout)), applying
akka.test.timefactor twice. Every sibling overload applies it once.

With timefactor = 3 an explicit 5s wait became 45s. The null case is worse: the inner call resolves
to RemainingOrDefault - the time actually left in the enclosing Within - and the outer call then
dilates that, producing a bound larger than the remaining budget it was derived from.

Apply RemainingOrDilated once, matching every other overload. No in-repo caller uses this overload,
so nothing here was relying on the inflated bound; Akka.TestKit.Tests (320) and
Akka.TestKit.Xunit2.Tests (4) pass.

@Aaronontheweb Aaronontheweb left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

LGTM

@Aaronontheweb Aaronontheweb added akka-testkit Akka.NET Testkit issues confirmed bug labels Jul 29, 2026
@Aaronontheweb
Aaronontheweb merged commit 3b76168 into akkadotnet:dev Jul 29, 2026
10 of 12 checks passed
@Aaronontheweb
Aaronontheweb deleted the fix/testkit-expectmsg-double-dilation branch July 29, 2026 16:21
Aaronontheweb added a commit to Aaronontheweb/akka.net that referenced this pull request Jul 31, 2026
Aaronontheweb added a commit that referenced this pull request Aug 11, 2026
…ol>, ...) (#8430)

This overload resolved its bound as RemainingOrDilated(RemainingOrDilated(timeout)), applying
akka.test.timefactor twice. Every sibling overload applies it once.

With timefactor = 3 an explicit 5s wait became 45s. The null case is worse: the inner call resolves
to RemainingOrDefault - the time actually left in the enclosing Within - and the outer call then
dilates that, producing a bound larger than the remaining budget it was derived from.

Apply RemainingOrDilated once, matching every other overload. No in-repo caller uses this overload,
so nothing here was relying on the inflated bound; Akka.TestKit.Tests (320) and
Akka.TestKit.Xunit2.Tests (4) pass.
This was referenced Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

akka-testkit Akka.NET Testkit issues confirmed bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant