Skip to content

test: fix flaky FusingSpec activeStage assertion - #3496

Open
pjfanning wants to merge 1 commit into
apache:mainfrom
pjfanning:fix/fusingspec-activestage-flaky
Open

test: fix flaky FusingSpec activeStage assertion#3496
pjfanning wants to merge 1 commit into
apache:mainfrom
pjfanning:fix/fusingspec-activestage-flaky

Conversation

@pjfanning

Copy link
Copy Markdown
Member

Motivation

FusingSpec — "leave activeStage cleared when a stage actor callback completes its stage" (added in #3461) — is intermittently failing (#3494), observing the downstream IgnoreSink as activeStage rather than null.

The invariant #3461 introduced is holding: the async source stage the test guards against leaking was cleared. The reported activeStage is the downstream Sink.ignore, which the interpreter is still finalizing. done (Sink.ignore's materialized future) is completed from within IgnoreSink.onUpstreamFinish, at which point activeStage still references the sink, and only afterwards does the interpreter run releaseStage to clear it (GraphInterpreter.scala:821). The test thread, woken by done, read the non-volatile activeStage in a race with that clear — usually saw null, occasionally the sink.

So this is a test-synchronization race, not a product bug.

Modification

Poll the final assertion with awaitAssert, so it settles once the interpreter reaches idle, instead of reading activeStage once and racing the clear. Also rename the local from interpreter to completedInterpreter to avoid shadowing GraphStageLogic.interpreter inside the inner stage (a fatal warning under the project's -Wconf).

Result

The test asserts the same invariant — activeStage ends up null after the callback completes its stage — without the timing race.

Tests

  • sbt "stream-tests/testOnly org.apache.pekko.stream.FusingSpec" — 24 passed

References

Fixes #3494

Motivation:
FusingSpec "leave activeStage cleared when a stage actor callback completes its
stage" (added in apache#3461) intermittently failed observing the downstream IgnoreSink
as activeStage. The stage the test guards against leaking - the async source - was
cleared correctly; the sink was still being finalized. The completion future the
test awaits (Sink.ignore's materialized value) is completed from within the sink's
own onUpstreamFinish, while activeStage still references the sink, before the
interpreter runs releaseStage to clear it. The test thread then read the
non-volatile activeStage in a race with that clear.

Modification:
Poll the final assertion with awaitAssert so it settles once the interpreter goes
idle, instead of reading activeStage once and racing the clear. Rename the local
to avoid shadowing GraphStageLogic.interpreter in the inner stage.

Result:
The test asserts the same invariant without the timing race.

Tests:
- sbt "stream-tests/testOnly org.apache.pekko.stream.FusingSpec" - 24 passed

References:
Fixes apache#3494
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.

[flaky] FusingSpec: must leave activeStage cleared when a stage actor callback completes its stage

1 participant