Skip to content

Backport unit and persistence test hardening to v1.5 - #8744

Merged
Aaronontheweb merged 4 commits into
akkadotnet:v1.5from
Aaronontheweb:backport/v1.5-unit-test-hardening
Oct 3, 2026
Merged

Aaronontheweb merged 4 commits into
akkadotnet:v1.5from
Aaronontheweb:backport/v1.5-unit-test-hardening

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Member

Changes

Backports transport-independent test hardening to v1.5:

No production runtime behavior and no Artery code are changed.

Validation

Targeted .NET 10 tests passed:

  • ActorSystemSpec.Log_dead_letters: 1/1
  • scheduler cancellation class: 6/6
  • core TestKit timing tests: 3/3
  • Hosting TestKit timing tests: 5/5
  • SQLite snapshot-store save TCK: 3/3

Build output contained only the existing package target-support warnings.

…tartup (akkadotnet#8428)

The test intermittently failed with 'Only received 0/1 messages that matched filter [Info when
Message contains "not delivered"]' (Azure build 129444, Windows unit lane) — zero matches, not a
late one, which no timeout increase would fix.

Root cause is a genuine startup race. ActorSystemImpl.Start() creates the listener fire-and-forget
(ActorSystemImpl.cs:219 'SystemActorOf<DeadLetterListener>("deadLetterListener")'), and the
EventStream subscription itself happens inside DeadLetterListener.PreStart()
(DeadLetterListener.cs:40). Unlike the configured akka.loggers, that startup has no synchronous
handshake before ActorSystem.Create returns, so a dead letter published in the window before PreStart
runs has no subscriber, is dropped, and never produces a 'not delivered' log at all.

Resolve /system/deadLetterListener before exercising the dead letter. An actor always processes its
Create system message (which runs PreStart) before any user message, so a successful Identify reply
is proof the DeadLetter subscription is in place — a real happens-before, not a padded wait.

Verified: full ActorSystemSpec green; the dead-letter test 12/12 at 2x core saturation (a
non-regression check — the race is too rare to reproduce locally on demand).

(cherry picked from commit d5993ab)
…adioSilence reset) in Akka.TestKit and Akka.Hosting.TestKit (akkadotnet#8615)

* TestFSMRefSpec: time the state timeout from before it is set, drop the 500 ms cap

A_TestFSMRef_must_allow_access_to_internal_state failed in the Akka.Hosting
copy with "Block took 00:00:01.82, exceeding 00:00:00.50" on a 2-vCPU Linux
agent. The StateTimeout travels scheduler -> mailbox -> ThreadPool-backed
dispatcher, and the synchronous Within/AwaitCondition blocked a pool thread
while it waited, so a starved agent easily needs more than 500 ms.

Both copies (Akka.Hosting.TestKit.Tests and Akka.TestKit.Tests) now await
the condition with a Dilated(5s) bound and assert the 80 ms lower bound with
a Stopwatch started before SetStateTimeout. Within's clock started after it,
so a stall between the two calls could have made the timeout look early.

* ReceiveTests: prove the radio-silence reset with a stopwatch instead of a 1.5 s margin

WaitForRadioSilenceAsync_should_reset_timer_twice_only returned {1} instead
of {1,2} in the Akka.Hosting copy on a 2-vCPU Windows agent. Message 2 was
sent 1.5 s after message 1 into a 3 s window that message 1 had just opened,
so a 1.5 s oversleep on the test thread pushed it out.

Both copies now send 2 only 400 ms after 1, in a 4 s window, and prove the
reset from the elapsed time: the silence cannot end before max after 2 was
sent, while without a reset it would end about 400 ms sooner. Delays only
lengthen the measured time. Renamed to what it tests; the maxMessages
violation is already covered by WaitForRadioSilenceAsync_should_fail_immediately_with_bad_input.

(cherry picked from commit 0ea28f8)
…et#8712)

TaskBasedScheduler_TellScheduler_Cancellation_Tests: a repeater tick that fires before Cancel() runs (test thread stalled past the 150ms interval) sits in the TestActor queue and tripped ExpectNoMsg. Drain in-flight ticks, then require two intervals of silence, bounded by a deadline so a broken cancel still fails.

Akka.Hosting.TestKit AwaitAssertTests: convert to AwaitAssertAsync and WithinAsync, and raise the upper bound from 1s (dilated to 2s) to 10s so a starved host cannot trip it.

(cherry picked from commit c01ec35)
The spec stopped an actor, waited for Terminated and recreated it under the same
name. The parent frees the name only after the watcher saw Terminated, so the
recreate failed with InvalidActorNameException in roughly one run in three.

(cherry picked from commit 84461de)
@Aaronontheweb
Aaronontheweb merged commit bfe4e35 into akkadotnet:v1.5 Oct 3, 2026
12 checks passed
@Aaronontheweb
Aaronontheweb deleted the backport/v1.5-unit-test-hardening branch October 3, 2026 22:07
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