Skip to content

CAMEL-23889: Fix flaky camel-vertx-websocket surefire tests#24393

Merged
gnodet merged 4 commits into
apache:mainfrom
gnodet:fix-flaky-camel-vertx-websocket-surefire-tests-on
Jul 4, 2026
Merged

CAMEL-23889: Fix flaky camel-vertx-websocket surefire tests#24393
gnodet merged 4 commits into
apache:mainfrom
gnodet:fix-flaky-camel-vertx-websocket-surefire-tests-on

Conversation

@gnodet

@gnodet gnodet commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix intermittent surefire test failures in camel-vertx-websocket observed on both JDK 17 and JDK 25 CI runs (see PR #22300 CI failures).

JIRA: CAMEL-23889

Root causes

  1. Stale WebSocket cache after server stop: VertxWebsocketEndpoint.getWebSocket() caches the WebSocket connection. After stopRoute("server"), isClosed() may still return false until the Vert.x event loop processes the TCP close frame. This causes two race conditions:

    • The "verify that we cannot send messages" assertion fails because template.send() silently drops the message through the stale WebSocket instead of throwing ConnectException.
    • The reconnect verification with template.sendBody() silently loses messages through the stale cache.
  2. Thread.sleep(300) for async operations: Both reconnect tests used Thread.sleep(300) to wait for asynchronous Vert.x operations (close handler, reconnect timer), which is inherently unreliable.

  3. Incorrect timeout value: VertxWebSocketEventTest used webSocketFuture.get(5000, TimeUnit.SECONDS) — a 83-minute timeout that could mask test failures.

Fixes

  • VertxWebsocketConsumerAsClientReconnectTest: Replaced Thread.sleep(300) with Awaitility. Wrapped the "verify send fails" check in await().untilAsserted() to handle the stale WebSocket race. Used await().ignoreExceptions().untilAsserted() for reconnection verification, retrying through transient failures while both the producer and client consumer re-establish their connections. Tests full end-to-end Camel message flow.
  • VertxWebsocketConsumerAsClientMaxReconnectTest: Same "verify send fails" Awaitility fix. Replaced Thread.sleep(300) with await().pollDelay(2, SECONDS).untilAsserted() to reliably wait for reconnect attempts to exhaust before verifying the mock stays at 0 messages.
  • VertxWebSocketEventTest: Fixed timeout from 5000 seconds to 5 seconds.
  • Added awaitility as a test dependency to camel-vertx-websocket.

Test plan

  • All 84 tests in camel-vertx-websocket pass with rerunFailingTestsCount=0
  • Reconnect test passes 5/5 consecutive runs without flakes
  • MaxReconnect test passes 3/3 consecutive runs
  • EventTest passes with corrected timeout
  • Code formatted with mvn formatter:format impsort:sort

Claude Code on behalf of Guillaume Nodet

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-vertx/camel-vertx-websocket

🔬 Scalpel shadow comparison — Scalpel: 10 tested, 29 compile-only — current: 10 all tested

Maveniverse Scalpel detected 39 affected modules (current approach: 10).

⚠️ Modules only in Scalpel (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

Skip-tests mode would test 10 modules (1 direct + 9 downstream), skip tests for 29 (generated code, meta-modules)

Modules Scalpel would test (10)
  • camel-ibm-watsonx-ai
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-launcher-container
  • camel-vertx-websocket
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
Modules with tests skipped (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (39 modules)
  • Camel :: All Components Sync point
  • Camel :: Assembly
  • Camel :: Catalog :: CSimple Maven Plugin (deprecated)
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Catalog :: Camel Report Maven Plugin
  • Camel :: Catalog :: Camel Route Parser
  • Camel :: Catalog :: Console
  • Camel :: Catalog :: Dummy Component
  • Camel :: Catalog :: Lucene (deprecated)
  • Camel :: Catalog :: Maven
  • Camel :: Catalog :: Suggest
  • Camel :: Component DSL
  • Camel :: Coverage
  • Camel :: Docs
  • Camel :: Endpoint DSL
  • Camel :: Endpoint DSL :: Support
  • Camel :: IBM :: watsonx.ai
  • Camel :: Integration Tests
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: Kamelet Main
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: Vert.x :: WebSocket
  • Camel :: YAML DSL
  • Camel :: YAML DSL :: Deserializers
  • Camel :: YAML DSL :: Maven Plugins
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin

⚙️ View full build and test results

@gnodet gnodet changed the title Fix flaky camel-vertx-websocket surefire tests CAMEL-23889: Fix flaky camel-vertx-websocket surefire tests Jul 3, 2026
@gnodet gnodet requested a review from Copilot July 3, 2026 21:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR targets intermittent surefire flakiness in the camel-vertx-websocket module by making asynchronous WebSocket/reconnect assertions deterministic and correcting an overly-long test timeout.

Changes:

  • Replaced Thread.sleep(...)-based timing with Awaitility-based polling in reconnect-related tests.
  • Corrected VertxWebSocketEventTest timeout from 5000 seconds to 5 seconds.
  • Added Awaitility as a test-scoped dependency for camel-vertx-websocket.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebSocketEventTest.java Fixes an incorrectly large CompletableFuture.get(...) timeout to avoid masking failures.
components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientReconnectTest.java Replaces sleeps with Awaitility to stabilize “server down” and reconnect assertions.
components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumerAsClientMaxReconnectTest.java Uses Awaitility instead of sleep around reconnect exhaustion, but the final “no messages after restart” check still needs a stronger assertion window.
components/camel-vertx/camel-vertx-websocket/pom.xml Adds Awaitility as a test dependency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

gnodet and others added 3 commits July 4, 2026 05:25
Replace Thread.sleep() calls with Awaitility-based async assertions
in the vertx-websocket reconnect tests, and fix an incorrect timeout
value in VertxWebSocketEventTest.

Changes:
- VertxWebsocketConsumerAsClientReconnectTest: Replace Thread.sleep(300)
  with Awaitility await().untilAsserted() using fresh WebSocket
  connections to bypass stale producer endpoint cache after server
  restart.
- VertxWebsocketConsumerAsClientMaxReconnectTest: Replace
  Thread.sleep(300) with Awaitility during(2, SECONDS) pattern to
  reliably verify reconnect attempts are exhausted.
- VertxWebSocketEventTest: Fix timeout from 5000 seconds (83 minutes)
  to 5 seconds in webSocketFuture.get() call.
- Add Awaitility test dependency to camel-vertx-websocket pom.xml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The during().untilAsserted() pattern was correct but misleading — with
expectedMessageCount(0), assertIsSatisfied() passes immediately on every
poll, so during() was effectively just a timed wait. Use pollDelay()
instead which more clearly expresses the intent: wait for reconnect
attempts to exhaust, then verify.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After stopRoute("server"), the producer endpoint's cached WebSocket may
still appear open (isClosed() returns false) until the Vert.x event loop
processes the TCP close frame. Wrap the "verify that we cannot send
messages" assertion in Awaitility to wait until the close propagates,
and restore full end-to-end Camel flow in the reconnect test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet gnodet force-pushed the fix-flaky-camel-vertx-websocket-surefire-tests-on branch from 665d667 to f0d4776 Compare July 4, 2026 05:25
@gnodet gnodet marked this pull request as ready for review July 4, 2026 05:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

- ReconnectTest: assertIsSatisfied(500) timeout was silently ignored
  when expectedCount > 0 (defaults to 10s latch wait). Use
  setResultWaitTime(500) to control the actual wait time.
- MaxReconnectTest: Replace Awaitility pollDelay wrapper with direct
  assertIsSatisfied(2000) for the zero-count wait (simpler, equivalent).
  Use setAssertPeriod(1000) for final assertion to re-verify after a
  delay and catch late deliveries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet

gnodet commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Claude Code on behalf of Guillaume Nodet

Addressed all three Copilot review comments:

ReconnectTest assertIsSatisfied(500): Good catch — the 500 timeout was silently ignored when expectedCount > 0, because doAssertIsSatisfied() calls waitForCompleteLatch() which uses resultWaitTime (defaulting to a 10-second wait). Fixed by calling setResultWaitTime(500) after each reset().

MaxReconnectTest Awaitility wrapper (line 69): Agreed the Awaitility pollDelay wrapper was unnecessary for a zero-count mock. Replaced with a direct mockEndpoint.assertIsSatisfied(2000).

MaxReconnectTest final assertion (line 76): Replaced assertIsSatisfied(1000) with setAssertPeriod(1000) + assertIsSatisfied() to re-verify after the delay and catch late deliveries.

@gnodet gnodet merged commit 1aaaa37 into apache:main Jul 4, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants