Fix flaky HazelcastReplicatedmapConsumerTest (18% failure rate)#24590
Conversation
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
gnodet
left a comment
There was a problem hiding this comment.
Clean fix for the flaky test. The root cause analysis is correct — async REMOVED events from map.clear() in resetState() were bleeding into the next test's mock expectations.
All three changes look good:
- Route stop/start around
map.clear()— deregisters the Hazelcast entry listener soclear()doesn't fire events into the mock testEvict()— correctly replacedAwaitility.await().untilAsserted(() -> MockEndpoint.assertIsSatisfied(...))with the nativeMockEndpoint.assertIsSatisfied(context, 30000, TimeUnit.MILLISECONDS)— avoids polling-on-top-of-latch per project conventionstestRemove()— Awaitility wait for ADDED event counter before removing is the right pattern (mid-test condition that MockEndpoint can't express natively)
LGTM.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
|
🧪 CI tested the following changed modules:
🔬 Scalpel shadow comparison — Scalpel: 1 tested, 0 compile-only — current: 9 all testedMaveniverse Scalpel detected 1 affected modules (current approach: 9). Modules only in current approach (8)
Skip-tests mode would test 1 modules (1 direct + 0 downstream), skip tests for 0 (generated code, meta-modules) Modules Scalpel would test (1)
All tested modules (9 modules)
|
Root cause: map.clear() in @beforeeach fires async REMOVED events that bleed between tests because the Hazelcast entry listener is still active. Additionally, testRemove() calls map.remove() immediately after put() without waiting for the ADDED event, creating a race condition. Fix: - Stop routes before clearing the map to deregister the entry listener, preventing stale REMOVED events from reaching mock endpoints - Restart routes after clearing and resetting mocks - In testRemove(), wait for the ADDED event before calling remove() - Replace redundant Awaitility-wrapped MockEndpoint assertion in testEvict() with the native latch-based timed assertion Validated with 100 consecutive runs (0 failures). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
c771ae5 to
fa10df6
Compare
Summary
Claude Code on behalf of gnodet
Fixes the persistent flakiness of
HazelcastReplicatedmapConsumerTest(18% failure rate on Develocity — 35/194 runs failing). The prior fix (CAMEL-22506) addedmap.clear()+ mock reset in@BeforeEach, but that approach itself introduces the flakiness becauseclear()fires async REMOVED events through the still-active Hazelcast entry listener.Root cause:
map.clear()in@BeforeEachfires async REMOVED events that bleed between tests because the HazelcastEntryListeneris still registered. Additionally,testRemove()callsmap.remove()immediately aftermap.put()without waiting for the ADDED event to be processed, creating a race condition.Fix:
@BeforeEach: Stop routes before clearing the map to deregister the entry listener (viaHazelcastReplicatedmapConsumer.doStop()), preventing stale REMOVED events from reaching mock endpoints. Restart routes after clearing and resetting mocks.testRemove(): Wait for the ADDED event to be delivered before callingremove(), eliminating the put/remove race.testEvict(): Replace redundant Awaitility-wrappedMockEndpoint.assertIsSatisfied()with the native latch-based timed assertion (per project conventions — Awaitility polls on top of an already-waiting mechanism).Test plan
mvn formatter:format impsort:sort