This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 7dee4a791634 CAMEL-23888: Fix flaky camel-platform-http-vertx surefire 
tests
7dee4a791634 is described below

commit 7dee4a791634dc5e1cad53985f0c74f5632b91c8
Author: Guillaume Nodet <[email protected]>
AuthorDate: Fri Jul 3 09:41:42 2026 +0200

    CAMEL-23888: Fix flaky camel-platform-http-vertx surefire tests
    
    Fix four distinct flaky test patterns observed failing intermittently
    during CI on JDK 25:
    
    - VertxPlatformEventNotifierTest: use Awaitility polling and
      CopyOnWriteArrayList for async event assertions
    - VertxPlatformHttpSharedVertxTest: replace tight CountDownLatch with
      Awaitility polling (5s timeout)
    - VertxPlatformHttpProxyTest: use camelPort.getPort() instead of static
      RestAssured.port to avoid races
    - VertxPlatformHttpOAuthProfileTest: register body handler inside
      response onSuccess callback to prevent body data loss
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .../http/vertx/VertxPlatformEventNotifierTest.java | 26 ++++++++++-----
 .../vertx/VertxPlatformHttpOAuthProfileTest.java   | 37 ++++++++++++++--------
 .../http/vertx/VertxPlatformHttpProxyTest.java     |  6 ++--
 .../vertx/VertxPlatformHttpSharedVertxTest.java    | 13 ++++----
 4 files changed, 52 insertions(+), 30 deletions(-)

diff --git 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformEventNotifierTest.java
 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformEventNotifierTest.java
index 7eb326ca8f9f..d4f3ef66e0e5 100644
--- 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformEventNotifierTest.java
+++ 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformEventNotifierTest.java
@@ -16,8 +16,9 @@
  */
 package org.apache.camel.component.platform.http.vertx;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
@@ -28,10 +29,11 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import static io.restassured.RestAssured.given;
+import static org.awaitility.Awaitility.await;
 import static org.hamcrest.Matchers.is;
 
 public class VertxPlatformEventNotifierTest {
-    private final List<String> events = new ArrayList<>();
+    private final List<String> events = new CopyOnWriteArrayList<>();
 
     @Test
     void testEventNotifierOk() throws Exception {
@@ -57,9 +59,13 @@ public class VertxPlatformEventNotifierTest {
                     .statusCode(200)
                     .body(is("Bye World"));
 
-            Assertions.assertEquals(2, events.size());
-            Assertions.assertEquals("ExchangeCreated (failed:false)", 
events.get(0));
-            Assertions.assertEquals("ExchangeCompleted (failed:false)", 
events.get(1));
+            // Event notification is async — the HTTP response can return 
before
+            // ExchangeCompleted fires, so poll with Awaitility instead of 
asserting immediately.
+            await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+                Assertions.assertEquals(2, events.size());
+                Assertions.assertEquals("ExchangeCreated (failed:false)", 
events.get(0));
+                Assertions.assertEquals("ExchangeCompleted (failed:false)", 
events.get(1));
+            });
         } finally {
             context.stop();
         }
@@ -89,9 +95,13 @@ public class VertxPlatformEventNotifierTest {
                     .statusCode(500)
                     .body(is(""));
 
-            Assertions.assertEquals(2, events.size());
-            Assertions.assertEquals("ExchangeCreated (failed:false)", 
events.get(0));
-            Assertions.assertEquals("ExchangeFailed (failed:true)", 
events.get(1));
+            // Event notification is async — the HTTP response can return 
before
+            // ExchangeFailed fires, so poll with Awaitility instead of 
asserting immediately.
+            await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+                Assertions.assertEquals(2, events.size());
+                Assertions.assertEquals("ExchangeCreated (failed:false)", 
events.get(0));
+                Assertions.assertEquals("ExchangeFailed (failed:true)", 
events.get(1));
+            });
         } finally {
             context.stop();
         }
diff --git 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpOAuthProfileTest.java
 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpOAuthProfileTest.java
index 2f18a2616a7e..bc413147bbe2 100644
--- 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpOAuthProfileTest.java
+++ 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpOAuthProfileTest.java
@@ -21,7 +21,6 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import io.vertx.core.http.HttpClient;
-import io.vertx.core.http.HttpClientResponse;
 import io.vertx.core.http.HttpMethod;
 import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
@@ -56,24 +55,36 @@ class VertxPlatformHttpOAuthProfileTest {
             VertxPlatformHttpServer server = 
context.hasService(VertxPlatformHttpServer.class);
             client = server.getVertx().createHttpClient();
 
-            CompletableFuture<HttpClientResponse> responseFuture = new 
CompletableFuture<>();
+            // Collect status code and response body atomically inside the 
response
+            // handler to avoid a race where the body arrives and is discarded 
before
+            // the test registers a body() handler.
+            CompletableFuture<int[]> statusFuture = new CompletableFuture<>();
+            CompletableFuture<String> bodyFuture = new CompletableFuture<>();
             client.request(HttpMethod.POST, server.getPort(), "localhost", 
"/secure")
                     .onSuccess(request -> {
                         request.putHeader("Content-Length", "1024");
                         request.response()
-                                .onSuccess(responseFuture::complete)
-                                
.onFailure(responseFuture::completeExceptionally);
-                        
request.sendHead().onFailure(responseFuture::completeExceptionally);
+                                .onSuccess(response -> {
+                                    statusFuture.complete(new int[] { 
response.statusCode() });
+                                    response.body()
+                                            .onSuccess(buffer -> 
bodyFuture.complete(buffer.toString()))
+                                            
.onFailure(bodyFuture::completeExceptionally);
+                                })
+                                .onFailure(t -> {
+                                    statusFuture.completeExceptionally(t);
+                                    bodyFuture.completeExceptionally(t);
+                                });
+                        request.sendHead().onFailure(t -> {
+                            statusFuture.completeExceptionally(t);
+                            bodyFuture.completeExceptionally(t);
+                        });
                     })
-                    .onFailure(responseFuture::completeExceptionally);
-
-            HttpClientResponse response = responseFuture.get(5, 
TimeUnit.SECONDS);
-            CompletableFuture<String> bodyFuture = new CompletableFuture<>();
-            response.body()
-                    .onSuccess(buffer -> 
bodyFuture.complete(buffer.toString()))
-                    .onFailure(bodyFuture::completeExceptionally);
+                    .onFailure(t -> {
+                        statusFuture.completeExceptionally(t);
+                        bodyFuture.completeExceptionally(t);
+                    });
 
-            assertEquals(401, response.statusCode());
+            assertEquals(401, statusFuture.get(5, TimeUnit.SECONDS)[0]);
             assertEquals("Unauthorized", bodyFuture.get(5, TimeUnit.SECONDS));
 
             assertEquals(0, routeInvocations.get());
diff --git 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpProxyTest.java
 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpProxyTest.java
index 1b087499a690..556afcb2c9bd 100644
--- 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpProxyTest.java
+++ 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpProxyTest.java
@@ -17,7 +17,6 @@
 package org.apache.camel.component.platform.http.vertx;
 
 import com.github.tomakehurst.wiremock.WireMockServer;
-import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
@@ -78,8 +77,9 @@ public class VertxPlatformHttpProxyTest {
 
             context.start();
 
-            // URI of proxy created with platform HTTP component
-            final var proxyURI = "http://localhost:"; + RestAssured.port;
+            // URI of proxy created with platform HTTP component — use 
camelPort directly
+            // instead of the static RestAssured.port to avoid races with 
other tests.
+            final var proxyURI = "http://localhost:"; + camelPort.getPort();
 
             final var originURI = "http://localhost:"; + wireMockServer.port();
 
diff --git 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpSharedVertxTest.java
 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpSharedVertxTest.java
index 0a5d1ea6ae5e..4f05076ff4b8 100644
--- 
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpSharedVertxTest.java
+++ 
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpSharedVertxTest.java
@@ -16,8 +16,8 @@
  */
 package org.apache.camel.component.platform.http.vertx;
 
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import io.vertx.core.Vertx;
 import org.apache.camel.CamelContext;
@@ -28,7 +28,7 @@ import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.awaitility.Awaitility.await;
 
 class VertxPlatformHttpSharedVertxTest {
     @RegisterExtension
@@ -61,9 +61,10 @@ class VertxPlatformHttpSharedVertxTest {
             context.start();
         }
 
-        // Verify shutdown of VertxPlatformHttpServer did not close the shared 
Vertx instance
-        CountDownLatch latch = new CountDownLatch(1);
-        vertx.setTimer(1, event -> latch.countDown());
-        assertTrue(latch.await(1, TimeUnit.SECONDS));
+        // Verify shutdown of VertxPlatformHttpServer did not close the shared 
Vertx instance.
+        // Use Awaitility instead of a tight CountDownLatch timeout to avoid 
flakiness on slow CI.
+        AtomicBoolean timerFired = new AtomicBoolean(false);
+        vertx.setTimer(1, event -> timerFired.set(true));
+        await().atMost(5, TimeUnit.SECONDS).untilTrue(timerFired);
     }
 }

Reply via email to