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);
}
}