[Testing] Fix flaky unit tests - #8626
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughChangesVote collector expectations
Asynchronous test synchronization
Deterministic test inputs and assertions
Estimated code review effort: 4 (Complex) | ~45 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@engine/common/follower/compliance_engine_test.go`:
- Line 220: Correct the inline comment on the block.View assignment to state
that newFinalizedBlock.View equals s.finalized.View + 2, distinguishing it from
the child block’s view at s.finalized.View + 1.
In `@engine/common/synchronization/engine_spam_test.go`:
- Around line 350-374: Update the probability-factor comments for each loadGroup
in the synchronization test to use the batch-size formula 0.1 or 0.01 * (n + 1)
/ 64, where n matches the corresponding BlockIDs count (1, 10, 99, or 999/1000
as described). Remove the height-difference expressions and ensure each
comment’s calculated probability matches its batch size before stating the
bounds.
In `@module/executiondatasync/optimistic_sync/pipeline/pipeline_test_utils.go`:
- Around line 96-109: Update waitForStateUpdatesAndNoError to synchronize with
the producer before checking errChan, replacing the non-blocking probe with an
explicit worker-result or phase acknowledgement that confirms pipeline.Run has
reached the relevant completion point. Ensure the helper cannot return before an
immediately produced error is observable, while preserving waitForStateUpdates
behavior for callers that expect concurrent errors.
In `@network/test/cohort1/network_test.go`:
- Around line 550-556: Replace the fixed one-second sleep in the rate-limit test
with deterministic synchronization by calling EnsureNotConnectedBetweenGroups
and EnsureNoStreamCreationBetweenGroups before asserting callCount. Keep the
uint64(2) assertion after both checks so asynchronous pruning and queued
delivery have completed before validating that no third message was delivered.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: dfed4eca-70bc-44f5-9ee9-ccc0146a7b57
📒 Files selected for processing (14)
consensus/hotstuff/votecollector/statemachine_test.goengine/common/follower/compliance_engine_test.goengine/common/stop/stop_control_test.goengine/common/synchronization/engine_spam_test.gofvm/evm/evm_test.gomodule/builder/collection/builder_test.gomodule/executiondatasync/optimistic_sync/pipeline/pipeline_functional_test.gomodule/executiondatasync/optimistic_sync/pipeline/pipeline_test_utils.gomodule/util/log_test.gonetwork/p2p/builder/libp2pscaler_test.gonetwork/p2p/inspector/validation/control_message_validation_inspector_test.gonetwork/test/cohort1/network_test.gostate/cluster/badger/mutator_test.gostorage/migration/validation_test.go
Kay-Zee
left a comment
There was a problem hiding this comment.
LGTM. I went through the full diff and ran everything this touches: all the packages pass go test -race repeatedly on my end (count=5 for the core ones), including the reworked sync spam load tests and the newly enabled TestRegisterVoteConsumer. I also spot-checked the new statistical bounds numerically — all the groups are within 1e-9 per tail of Binomial(1000, p), so the "a correct implementation practically can't flake" claim in the comments checks out.
A few small things, none blocking:
- In the sync load tests,
HandleHeight/WithinToleranceare registered without.Maybe(), but they're invoked by the async request workers.AssertExpectationsright after the load loop therefore technically depends on a worker having dequeued at least one request by then. In practice that's a non-issue — the test goroutine does a thousand rounds of crypto-RNG and mock matching before it gets there — so I'd leave it. Just mentioning it in case it ever shows up in CI, so nobody has to rediscover the mechanism. - On the CodeRabbit thread about
waitForStateUpdatesAndNoError: I agree with your call to defer. At all three call sites the only thing that can produce an error is the next test action (SetSealed/cancel), so nothing can be sitting onerrChanat probe time. The stronger producer-phase synchronization would be nice eventually but isn't buying correctness here. - The EVM
Len(13)→NotEmptyrelaxation is a fair trade given the random block ID, and it's disclosed as a known gap with a follow-up planned. Fine by me.
The mock-expectation hoisting out of the load loops is a nice win on its own — quadratic call matching explains a lot about how slow those tests had gotten.
Reviewed in collaboration with an AI agent (kimi).
|
Two things I ran into while running this stack — both pre-existing on master, neither caused by these PRs. Passing them along rather than filing, since they're squarely in the territory you've been cleaning up: 1. Real production race in the follower cache. 2. One side effect worth knowing: when that mock failure fires inside an inspector worker goroutine, the Written in collaboration with an AI agent (kimi). |
Fixes a batch of flaky unit tests. The flakiness fell into a few categories:
with waits, registered mock expectations upfront instead of lazily, and stopped
engines/workers before test teardown.
Binomial(1000, p) quantiles with 1e-9 tail probability, and register loop-invariant
mock expectations once instead of per iteration (the accumulated expectations made
call matching quadratic and the tests extremely slow).
resource-limit overrides are guaranteed distinct from defaults, and an exact EVM
register count assertion (dependent on a random block ID) was relaxed.
TestLogProgressNoDataForAWhilenow runs undertesting/synctestwith a fake clock.Also fixes latent data races surfaced while testing: an unsynchronized mock in the
pipeline test utils, a captured
errshared across goroutines in the bandwidth ratelimit test, and enables
TestRegisterVoteConsumer, which was never running due to amissing
Testprefix.Tests touched
consensus/hotstuff/votecollector:TestStateMachinesuite (all subtests viaprepareMockedProcessor); enabledTestRegisterVoteConsumerengine/common/follower:TestProcessFinalizedBlockengine/common/stop:TestStopControl_OnProcessedBlockengine/common/synchronization:TestLoad_Process_SyncRequest_HigherThanReceiver_OutsideTolerance_AlwaysReportSpam,TestLoad_Process_SyncRequest_HigherThanReceiver_OutsideTolerance_SometimesReportSpam,TestLoad_Process_RangeRequest_SometimesReportSpam,TestLoad_Process_BatchRequest_SometimesReportSpamfvm/evm:TestCadenceOwnedAccountFunctionalities(dryCall,dryCallWithSigAndArgs)module/builder/collection:TestBuildOn_WithOrphanedReferenceBlockmodule/executiondatasync/optimistic_sync/pipeline: shared test utils(
waitForStateUpdates,mockStateProvider) + happy-path/error functional testsmodule/util:TestLogProgressNoDataForAWhilenetwork/p2p/builder:TestBuildLibp2pResourceManagerLimitsnetwork/p2p/inspector/validation:TestNewControlMsgValidationInspector_validateClusterPrefixedTopicnetwork/test/cohort1:TestUnicastRateLimit_Bandwidthstate/cluster/badger:TestExtend_WithOrphanedReferenceBlockstorage/migration:TestCompareKeyValuePairsFromChannelsAll touched packages pass
go test -racelocally (repeated runs).Known coverage gaps introduced (follow-up PRs planned)
Some fixes deliberately trade assertion strength for determinism. The remaining gaps
will be addressed in follow-up PRs:
with p ≤ ~0.02, so those subtests alone can no longer detect an implementation that
never reports misbehavior (higher-p groups still catch it). Follow-up: extract the
probabilistic decision into a pure helper and table-test the boundary exactly, then
slim the statistical groups down to wiring smoke tests.
assert.Len(..., 13)→NotEmptycan no longer catch awrite-amplification regression. Follow-up: pin the test env's random block ID (or
assert a sampled tight range) and restore an exact/bounded count.
dissemination behavior (1..N notifications past the hard threshold) is untested.
✅ Addressed in [Testing] Fix data race in cluster-prefix RecordCache #8627 (which also fixes a production data race in
RecordCachethat the new multi-worker test exposed).
non-positive overrides ("keep default") are no longer exercised end-to-end through
BuildLibp2pResourceManagerLimits(unit coverage exists inTestApplyResourceLimitOverride). ✅ Addressed in [Testing] Fix data race in cluster-prefix RecordCache #8627.TestRegisterVoteConsumer: the enabled test covers the caching state only;consumer delivery across the caching→verifying transition is not covered at the
collector level (cache-level coverage exists in
TestVotesCache_RegisterVoteConsumer).✅ Addressed in [Testing] Fix data race in cluster-prefix RecordCache #8627.
This PR was produced in collaboration with claude.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by CodeRabbit