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

davsclaus 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 a15e244af384 CAMEL-26819: camel-http: speed up tests by removing fixed 
waits and slow server shutdowns (#29574)
a15e244af384 is described below

commit a15e244af38431987cc519f836c4c2a734d27f75
Author: AurĂ©lien Pupier <[email protected]>
AuthorDate: Tue Nov 10 21:13:58 2026 +0100

    CAMEL-26819: camel-http: speed up tests by removing fixed waits and slow 
server shutdowns (#29574)
    
    Co-authored-by: IBM Bob 2.2.1
    Signed-off-by: AurĂ©lien Pupier <[email protected]>
---
 .../apache/camel/component/http/BaseHttpTest.java  | 16 ++++++++
 .../camel/component/http/HttpConcurrentTest.java   | 13 +++++-
 .../http/HttpOAuth2CachedTokensKeyTest.java        | 16 +++++---
 .../http/HttpOAuth2RedirectTokenLeakTest.java      |  3 +-
 .../http/HttpOAuth2ResourceIndicatorTest.java      |  2 +-
 .../camel/component/http/HttpOAuth2ScopeTest.java  |  3 +-
 .../component/http/HttpOAuth2TokenCachingTest.java | 46 +++++++++++++---------
 .../component/http/HttpPollingConsumerTest.java    | 19 +++++++--
 .../component/http/HttpProducerRestartTest.java    |  8 ++--
 .../camel/component/http/HttpSOTimeoutTest.java    | 20 ++++++++--
 ...psTwoComponentsSslContextParametersGetTest.java |  4 +-
 ...Handler.java => BlockingValidationHandler.java} | 21 +++++++---
 12 files changed, 121 insertions(+), 50 deletions(-)

diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/BaseHttpTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/BaseHttpTest.java
index d84c1cc6e31e..c3c19d6c4735 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/BaseHttpTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/BaseHttpTest.java
@@ -21,6 +21,8 @@ import java.util.Map;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
+import org.apache.hc.core5.io.CloseMode;
 
 import static org.apache.hc.core5.http.HttpHeaders.CONTENT_LENGTH;
 import static org.apache.hc.core5.http.HttpHeaders.CONTENT_TYPE;
@@ -56,4 +58,18 @@ public abstract class BaseHttpTest extends 
HttpServerTestSupport {
     protected String getExpectedContent() {
         return "camel rocks!";
     }
+
+    /**
+     * Closes the servers without waiting for their open (keep-alive) 
connections: the graceful close of an
+     * {@link HttpServer} waits up to 5 seconds for them to terminate.
+     */
+    protected static AutoCloseable closeImmediately(HttpServer... servers) {
+        return () -> {
+            for (HttpServer server : servers) {
+                if (server != null) {
+                    server.close(CloseMode.IMMEDIATE);
+                }
+            }
+        };
+    }
 }
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpConcurrentTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpConcurrentTest.java
index 8ae558020189..2af7bbebe57a 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpConcurrentTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpConcurrentTest.java
@@ -20,9 +20,11 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.hc.core5.http.HttpStatus;
@@ -37,6 +39,9 @@ public class HttpConcurrentTest extends BaseHttpTest {
 
     private final AtomicInteger counter = new AtomicInteger();
 
+    // released when the expected number of requests are being processed by 
the server at the same time
+    private volatile CountDownLatch concurrentRequests = new CountDownLatch(0);
+
     private HttpServer localServer;
 
     @Override
@@ -46,10 +51,13 @@ public class HttpConcurrentTest extends BaseHttpTest {
                 
.setConnectionReuseStrategy(getConnectionReuseStrategy()).setResponseFactory(getHttpResponseFactory())
                 .setSslContext(getSSLContext())
                 .register("/", (request, response, context) -> {
+                    // wait until the expected number of requests are in 
flight to prove they are concurrent
+                    CountDownLatch latch = concurrentRequests;
+                    latch.countDown();
                     try {
-                        Thread.sleep(1000);
+                        latch.await(10, TimeUnit.SECONDS);
                     } catch (InterruptedException e) {
-                        // ignore
+                        Thread.currentThread().interrupt();
                     }
                     response.setCode(HttpStatus.SC_OK);
                     response.setEntity(new 
StringEntity(Integer.toString(counter.incrementAndGet())));
@@ -76,6 +84,7 @@ public class HttpConcurrentTest extends BaseHttpTest {
     }
 
     private void doSendMessages(int files, int poolSize) throws Exception {
+        concurrentRequests = new CountDownLatch(poolSize);
         ExecutorService executor = Executors.newFixedThreadPool(poolSize);
         // we access the responses Map below only inside the main thread,
         // so no need for a thread-safe Map implementation
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2CachedTokensKeyTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2CachedTokensKeyTest.java
index cb1d30a1ea6c..c6b83a8ac651 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2CachedTokensKeyTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2CachedTokensKeyTest.java
@@ -30,6 +30,7 @@ import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.NoHttpResponseException;
 import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
 import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
+import org.apache.hc.core5.io.CloseMode;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -96,7 +97,7 @@ public class HttpOAuth2CachedTokensKeyTest extends 
BaseHttpTest {
 
     @Test
     public void theEndpointHasTheOptions() throws Exception {
-        try (HttpServer localServer = createLocalServer()) {
+        try (HttpServer localServer = createLocalServer(); AutoCloseable 
shutdown = closeImmediately(localServer)) {
             HttpEndpoint endpoint = context.getEndpoint("http://localhost:"; + 
localServer.getLocalPort()
                                                         + 
"/post?oauth2CachedTokensKey=HOST_AND_PATH",
                     HttpEndpoint.class);
@@ -116,7 +117,8 @@ public class HttpOAuth2CachedTokensKeyTest extends 
BaseHttpTest {
 
     @Test
     public void aClassResolverIsTheSameInstanceOnTheEndpoint() throws 
Exception {
-        try (HttpServer localServer = createLocalServer(); HttpServer 
oauth2Server = createLocalOAuth2Server()) {
+        try (HttpServer localServer = createLocalServer(); HttpServer 
oauth2Server = createLocalOAuth2Server();
+             AutoCloseable shutdown = closeImmediately(localServer, 
oauth2Server)) {
             String uri = uri(localServer, oauth2Server, "/post",
                     "&oauth2CachedTokensKeyResolver=#class:" + 
RecordingResolver.class.getName());
             assertOk(template.request(uri, e -> {
@@ -144,20 +146,22 @@ public class HttpOAuth2CachedTokensKeyTest extends 
BaseHttpTest {
     }
 
     private void assertSecondRequestReusesToken(String first, String second, 
String options) throws Exception {
-        try (HttpServer localServer = createLocalServer(); HttpServer 
oauth2Server = createLocalOAuth2Server()) {
+        try (HttpServer localServer = createLocalServer(); HttpServer 
oauth2Server = createLocalOAuth2Server();
+             AutoCloseable shutdown = closeImmediately(localServer, 
oauth2Server)) {
             assertOk(template.request(uri(localServer, oauth2Server, first, 
options), e -> {
             }));
-            oauth2Server.close();
+            oauth2Server.close(CloseMode.IMMEDIATE);
             assertOk(template.request(uri(localServer, oauth2Server, second, 
options), e -> {
             }));
         }
     }
 
     private void assertSecondRequestRequestsNewToken(String first, String 
second, String options) throws Exception {
-        try (HttpServer localServer = createLocalServer(); HttpServer 
oauth2Server = createLocalOAuth2Server()) {
+        try (HttpServer localServer = createLocalServer(); HttpServer 
oauth2Server = createLocalOAuth2Server();
+             AutoCloseable shutdown = closeImmediately(localServer, 
oauth2Server)) {
             assertOk(template.request(uri(localServer, oauth2Server, first, 
options), e -> {
             }));
-            oauth2Server.close();
+            oauth2Server.close(CloseMode.IMMEDIATE);
             Exchange exchange = template.request(uri(localServer, 
oauth2Server, second, options), e -> {
             });
             // When the token endpoint server is closed, the HTTP client may 
report either
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2RedirectTokenLeakTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2RedirectTokenLeakTest.java
index 13b6b72c5a5e..fab3014e7ab3 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2RedirectTokenLeakTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2RedirectTokenLeakTest.java
@@ -19,7 +19,6 @@ package org.apache.camel.component.http;
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.camel.component.http.handler.OAuth2TokenRequestHandler;
-import org.apache.camel.util.IOHelper;
 import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
 import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
 import org.apache.hc.core5.http.io.entity.StringEntity;
@@ -109,7 +108,7 @@ public class HttpOAuth2RedirectTokenLeakTest extends 
BaseHttpTest {
 
     @Override
     public void cleanupResources() throws Exception {
-        IOHelper.close(localServer, differentHostRedirectTarget, 
differentPortRedirectTarget);
+        closeImmediately(localServer, differentHostRedirectTarget, 
differentPortRedirectTarget).close();
     }
 
     @ParameterizedTest
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2ResourceIndicatorTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2ResourceIndicatorTest.java
index cfdc48edaff4..b52838b65472 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2ResourceIndicatorTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2ResourceIndicatorTest.java
@@ -78,7 +78,7 @@ public class HttpOAuth2ResourceIndicatorTest extends 
BaseHttpTest {
     // Sends a request that needs a token, and returns the parameters of the 
token request
     private Map<String, String> requestWithToken(boolean bodyAuthentication) 
throws Exception {
         tokenRequests.clear();
-        try (HttpServer localServer = createLocalServer()) {
+        try (HttpServer localServer = createLocalServer(); AutoCloseable 
shutdown = closeImmediately(localServer)) {
             String tokenEndpoint = "http://localhost:"; + 
localServer.getLocalPort() + "/token";
             String requestUrl = "http://localhost:"; + 
localServer.getLocalPort() + "/post?httpMethod=POST&oauth2ClientId="
                                 + CLIENT_ID + "&oauth2ClientSecret=" + 
CLIENT_SECRET + "&oauth2TokenEndpoint=" + tokenEndpoint
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2ScopeTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2ScopeTest.java
index 68c4397afca7..992bd93b08cf 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2ScopeTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2ScopeTest.java
@@ -25,6 +25,7 @@ import 
org.apache.camel.component.http.handler.OAuth2ScopeRequestHandler;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
 import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
+import org.apache.hc.core5.io.CloseMode;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -58,7 +59,7 @@ public class HttpOAuth2ScopeTest extends BaseHttpTest {
                             exchange1 -> {
                             });
 
-            localServer.close();
+            localServer.close(CloseMode.IMMEDIATE);
 
             assertExchange(exchange);
         }
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2TokenCachingTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2TokenCachingTest.java
index 9a5736caf96b..9fecd642c66b 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2TokenCachingTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2TokenCachingTest.java
@@ -28,6 +28,7 @@ import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.NoHttpResponseException;
 import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
 import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
+import org.apache.hc.core5.io.CloseMode;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -47,7 +48,8 @@ public class HttpOAuth2TokenCachingTest extends BaseHttpTest {
 
     @Test
     public void tokenIsCached() throws Exception {
-        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server()) {
+        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server();
+             var shutdown = closeImmediately(localServer, localOAuth2Server)) {
             String tokenEndpoint = "http://localhost:"; + 
localOAuth2Server.getLocalPort() + "/token";
             String requestUrl = "http://localhost:"; + 
localServer.getLocalPort() + "/post?httpMethod=POST&oauth2ClientId="
                                 + clientId + "&oauth2ClientSecret=" + 
clientSecret + "&oauth2TokenEndpoint=" + tokenEndpoint +
@@ -56,7 +58,7 @@ public class HttpOAuth2TokenCachingTest extends BaseHttpTest {
             template.request(requestUrl,
                     exchange1 -> {
                     });
-            localOAuth2Server.close();
+            localOAuth2Server.close(CloseMode.IMMEDIATE);
             Exchange exchange
                     = template.request(requestUrl,
                             exchange1 -> {
@@ -75,7 +77,8 @@ public class HttpOAuth2TokenCachingTest extends BaseHttpTest {
      */
     @Test
     public void aDifferentScopeDoesNotReuseACachedToken() throws Exception {
-        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server()) {
+        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server();
+             var shutdown = closeImmediately(localServer, localOAuth2Server)) {
             String tokenEndpoint = "http://localhost:"; + 
localOAuth2Server.getLocalPort() + "/token";
             String base = "http://localhost:"; + localServer.getLocalPort() + 
"/post?httpMethod=POST&oauth2ClientId="
                           + clientId + "&oauth2ClientSecret=" + clientSecret + 
"&oauth2TokenEndpoint=" + tokenEndpoint
@@ -84,7 +87,7 @@ public class HttpOAuth2TokenCachingTest extends BaseHttpTest {
             // caches a token for the narrow scope
             template.request(base + "read", exchange -> {
             });
-            localOAuth2Server.close();
+            localOAuth2Server.close(CloseMode.IMMEDIATE);
 
             // same target and credentials, different scope: the narrow-scope 
token must not be handed out
             Exchange exchange = template.request(base + "read+write", 
exchange1 -> {
@@ -95,7 +98,8 @@ public class HttpOAuth2TokenCachingTest extends BaseHttpTest {
 
     @Test
     public void theSameScopeStillReusesTheCachedToken() throws Exception {
-        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server()) {
+        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server();
+             var shutdown = closeImmediately(localServer, localOAuth2Server)) {
             String tokenEndpoint = "http://localhost:"; + 
localOAuth2Server.getLocalPort() + "/token";
             String requestUrl = "http://localhost:"; + 
localServer.getLocalPort() + "/post?httpMethod=POST&oauth2ClientId="
                                 + clientId + "&oauth2ClientSecret=" + 
clientSecret + "&oauth2TokenEndpoint=" + tokenEndpoint
@@ -103,7 +107,7 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
 
             template.request(requestUrl, exchange -> {
             });
-            localOAuth2Server.close();
+            localOAuth2Server.close(CloseMode.IMMEDIATE);
 
             Exchange exchange = template.request(requestUrl, exchange1 -> {
             });
@@ -169,7 +173,8 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
     }
 
     private void assertDifferentQuery(String keyOption, boolean reused) throws 
Exception {
-        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server()) {
+        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server();
+             var shutdown = closeImmediately(localServer, localOAuth2Server)) {
             String tokenEndpoint = "http://localhost:"; + 
localOAuth2Server.getLocalPort() + "/token";
             String options = "&httpMethod=POST&oauth2ClientId=" + clientId + 
"&oauth2ClientSecret=" + clientSecret
                              + "&oauth2TokenEndpoint=" + tokenEndpoint + 
"&oauth2CacheTokens=true" + keyOption;
@@ -177,7 +182,7 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
 
             assertExchange(template.request(base + "1" + options, exchange -> {
             }));
-            localOAuth2Server.close();
+            localOAuth2Server.close(CloseMode.IMMEDIATE);
 
             Exchange exchange = template.request(base + "2" + options, 
exchange1 -> {
             });
@@ -186,7 +191,8 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
     }
 
     private void assertDifferentPath(String keyOption, boolean reused) throws 
Exception {
-        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server()) {
+        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server();
+             var shutdown = closeImmediately(localServer, localOAuth2Server)) {
             String tokenEndpoint = "http://localhost:"; + 
localOAuth2Server.getLocalPort() + "/token";
             String options = "?httpMethod=POST&oauth2ClientId=" + clientId + 
"&oauth2ClientSecret=" + clientSecret
                              + "&oauth2TokenEndpoint=" + tokenEndpoint + 
"&oauth2CacheTokens=true" + keyOption;
@@ -194,7 +200,7 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
 
             assertExchange(template.request(base + "/post" + options, exchange 
-> {
             }));
-            localOAuth2Server.close();
+            localOAuth2Server.close(CloseMode.IMMEDIATE);
 
             Exchange exchange = template.request(base + "/other" + options, 
exchange1 -> {
             });
@@ -203,7 +209,8 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
     }
 
     private void assertDifferentHttpPathHeader(String keyOption, boolean 
reused) throws Exception {
-        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server()) {
+        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server();
+             var shutdown = closeImmediately(localServer, localOAuth2Server)) {
             String tokenEndpoint = "http://localhost:"; + 
localOAuth2Server.getLocalPort() + "/token";
 
             context.addRoutes(new RouteBuilder() {
@@ -217,7 +224,7 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
             });
 
             assertExchange(template.send("direct:path", e -> 
e.getIn().setHeader(Exchange.HTTP_PATH, "/post")));
-            localOAuth2Server.close();
+            localOAuth2Server.close(CloseMode.IMMEDIATE);
             Exchange exchange = template.send("direct:path", e -> 
e.getIn().setHeader(Exchange.HTTP_PATH, "/other"));
 
             assertTokenReused(exchange, reused);
@@ -237,7 +244,8 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
 
     @Test
     public void tokenIsNotCachedWhenCacheTokensIsFalse() throws Exception {
-        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server()) {
+        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server();
+             var shutdown = closeImmediately(localServer, localOAuth2Server)) {
             String tokenEndpoint = "http://localhost:"; + 
localOAuth2Server.getLocalPort() + "/token";
             String requestUrl = "http://localhost:"; + 
localServer.getLocalPort() + "/post?httpMethod=POST&oauth2ClientId="
                                 + clientId + "&oauth2ClientSecret=" + 
clientSecret + "&oauth2TokenEndpoint=" + tokenEndpoint +
@@ -246,7 +254,7 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
             template.request(requestUrl,
                     exchange1 -> {
                     });
-            localOAuth2Server.close();
+            localOAuth2Server.close(CloseMode.IMMEDIATE);
             Exchange exchange
                     = template.request(requestUrl,
                             exchange1 -> {
@@ -257,7 +265,8 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
 
     @Test
     public void toDTokenIsCached() throws Exception {
-        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server()) {
+        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server();
+             var shutdown = closeImmediately(localServer, localOAuth2Server)) {
             String tokenEndpoint = "http://localhost:"; + 
localOAuth2Server.getLocalPort() + "/token";
 
             context.addRoutes(new RouteBuilder() {
@@ -275,7 +284,7 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
 
             template.send("direct:start", e -> {
             });
-            localOAuth2Server.close();
+            localOAuth2Server.close(CloseMode.IMMEDIATE);
             Exchange exchange = template.send("direct:start", e -> {
             });
 
@@ -285,7 +294,8 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
 
     @Test
     public void toDTokenIsNotCachedWhenCacheTokensIsFalse() throws Exception {
-        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server()) {
+        try (var localServer = createLocalServer(); var localOAuth2Server = 
createLocalOAuth2Server();
+             var shutdown = closeImmediately(localServer, localOAuth2Server)) {
             String tokenEndpoint = "http://localhost:"; + 
localOAuth2Server.getLocalPort() + "/token";
 
             context.addRoutes(new RouteBuilder() {
@@ -303,7 +313,7 @@ public class HttpOAuth2TokenCachingTest extends 
BaseHttpTest {
 
             template.send("direct:start", e -> {
             });
-            localOAuth2Server.close();
+            localOAuth2Server.close(CloseMode.IMMEDIATE);
             Exchange exchange = template.send("direct:start", e -> {
             });
 
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpPollingConsumerTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpPollingConsumerTest.java
index 25bd6d162cb6..b2c9e035d571 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpPollingConsumerTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpPollingConsumerTest.java
@@ -17,9 +17,10 @@
 package org.apache.camel.component.http;
 
 import java.net.SocketTimeoutException;
+import java.util.concurrent.CountDownLatch;
 
 import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.component.http.handler.DelayValidationHandler;
+import org.apache.camel.component.http.handler.BlockingValidationHandler;
 import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
 import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
 import org.junit.jupiter.api.Test;
@@ -32,17 +33,22 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 public class HttpPollingConsumerTest extends BaseHttpTest {
 
     private HttpServer localServer;
+    // the server only answers once the latch is released: the timeout test 
never releases it before the call
+    private CountDownLatch serverResponse;
     private final String user = "camel";
     private final String password = "password";
     private String endpointUrl;
 
     @Override
     public void setupResources() throws Exception {
+        serverResponse = new CountDownLatch(1);
         localServer = ServerBootstrap.bootstrap()
                 
.setCanonicalHostName("localhost").setHttpProcessor(getBasicHttpProcessor())
                 
.setConnectionReuseStrategy(getConnectionReuseStrategy()).setResponseFactory(getHttpResponseFactory())
                 .setSslContext(getSSLContext())
-                .register("/", new DelayValidationHandler(GET.name(), null, 
null, getExpectedContent(), 1000)).create();
+                .register("/",
+                        new BlockingValidationHandler(GET.name(), null, null, 
getExpectedContent(), serverResponse))
+                .create();
         localServer.start();
 
         endpointUrl = "http://localhost:"; + localServer.getLocalPort();
@@ -50,7 +56,8 @@ public class HttpPollingConsumerTest extends BaseHttpTest {
 
     @Override
     public void cleanupResources() throws Exception {
-
+        // unblock any server thread still waiting
+        serverResponse.countDown();
         if (localServer != null) {
             localServer.stop();
         }
@@ -58,6 +65,7 @@ public class HttpPollingConsumerTest extends BaseHttpTest {
 
     @Test
     public void basicAuthenticationShouldSuccess() {
+        serverResponse.countDown();
         String body = consumer.receiveBody(endpointUrl + "/?authUsername=" + 
user + "&authPassword="
                                            + password,
                 String.class);
@@ -67,6 +75,7 @@ public class HttpPollingConsumerTest extends BaseHttpTest {
 
     @Test
     public void basicAuthenticationPreemptiveShouldSuccess() {
+        serverResponse.countDown();
 
         String body = consumer.receiveBody(endpointUrl + "/?authUsername=" + 
user + "&authPassword="
                                            + password + 
"&authenticationPreemptive=true",
@@ -76,12 +85,14 @@ public class HttpPollingConsumerTest extends BaseHttpTest {
 
     @Test
     public void testReceive() {
+        serverResponse.countDown();
         String body = consumer.receiveBody(endpointUrl + "/", String.class);
         assertEquals(getExpectedContent(), body);
     }
 
     @Test
     public void testReceiveTimeout() {
+        serverResponse.countDown();
         String body = consumer.receiveBody(endpointUrl + "/", 5000, 
String.class);
         assertEquals(getExpectedContent(), body);
     }
@@ -89,7 +100,7 @@ public class HttpPollingConsumerTest extends BaseHttpTest {
     @Test
     public void testReceiveTimeoutTriggered() {
         RuntimeCamelException ex = assertThrows(RuntimeCamelException.class,
-                () -> consumer.receiveBody(endpointUrl + "/", 250, 
String.class),
+                () -> consumer.receiveBody(endpointUrl + "/", 100, 
String.class),
                 "Should have thrown exception");
         assertIsInstanceOf(SocketTimeoutException.class, ex.getCause());
     }
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpProducerRestartTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpProducerRestartTest.java
index 9ec68bff7821..4e28832d053b 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpProducerRestartTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpProducerRestartTest.java
@@ -17,7 +17,9 @@
 package org.apache.camel.component.http;
 
 import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
 
+import org.apache.camel.ServiceStatus;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
 import org.apache.hc.core5.http.HttpStatus;
@@ -26,6 +28,7 @@ import 
org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
 import org.apache.hc.core5.http.io.entity.StringEntity;
 import org.junit.jupiter.api.Test;
 
+import static org.awaitility.Awaitility.await;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 public class HttpProducerRestartTest extends BaseHttpTest {
@@ -78,9 +81,8 @@ public class HttpProducerRestartTest extends BaseHttpTest {
         assertEquals("Bye World", out);
 
         context.getRouteController().stopRoute("foo");
-
-        // a little delay before starting again
-        Thread.sleep(1000);
+        await().atMost(10, TimeUnit.SECONDS)
+                .untilAsserted(() -> assertEquals(ServiceStatus.Stopped, 
context.getRouteController().getRouteStatus("foo")));
 
         context.getRouteController().startRoute("foo");
         out = template.requestBody("direct:start", "Hello World", 
String.class);
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpSOTimeoutTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpSOTimeoutTest.java
index c5bd90487d7c..68572d5198b5 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpSOTimeoutTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpSOTimeoutTest.java
@@ -16,8 +16,10 @@
  */
 package org.apache.camel.component.http;
 
+import java.util.concurrent.CountDownLatch;
+
 import org.apache.camel.Exchange;
-import org.apache.camel.component.http.handler.DelayValidationHandler;
+import org.apache.camel.component.http.handler.BlockingValidationHandler;
 import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
 import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
 import org.junit.jupiter.api.Assertions;
@@ -30,18 +32,26 @@ public class HttpSOTimeoutTest extends BaseHttpTest {
 
     private HttpServer localServer;
 
+    // the server only answers once the latch is released: tests expecting a 
timeout never release it before the call
+    private CountDownLatch serverResponse;
+
     @Override
     public void setupResources() throws Exception {
+        serverResponse = new CountDownLatch(1);
         localServer = ServerBootstrap.bootstrap()
                 
.setCanonicalHostName("localhost").setHttpProcessor(getBasicHttpProcessor())
                 
.setConnectionReuseStrategy(getConnectionReuseStrategy()).setResponseFactory(getHttpResponseFactory())
                 .setSslContext(getSSLContext())
-                .register("/", new DelayValidationHandler(GET.name(), null, 
null, getExpectedContent(), 2000)).create();
+                .register("/",
+                        new BlockingValidationHandler(GET.name(), null, null, 
getExpectedContent(), serverResponse))
+                .create();
         localServer.start();
     }
 
     @Override
     public void cleanupResources() {
+        // unblock any server thread still waiting
+        serverResponse.countDown();
         if (localServer != null) {
             localServer.stop();
         }
@@ -49,6 +59,7 @@ public class HttpSOTimeoutTest extends BaseHttpTest {
 
     @Test
     public void httpGet() {
+        serverResponse.countDown();
         Exchange exchange = template.request("http://localhost:";
                                              + localServer.getLocalPort() + 
"?httpClient.responseTimeout=5000",
                 exchange1 -> {
@@ -60,7 +71,7 @@ public class HttpSOTimeoutTest extends BaseHttpTest {
     @Test
     public void httpGetShouldThrowASocketTimeoutException() {
         Exchange reply = template.request("http://localhost:";
-                                          + localServer.getLocalPort() + 
"?httpClient.responseTimeout=1000",
+                                          + localServer.getLocalPort() + 
"?httpClient.responseTimeout=200",
                 exchange -> {
                 });
         Exception e = reply.getException();
@@ -69,6 +80,7 @@ public class HttpSOTimeoutTest extends BaseHttpTest {
 
     @Test
     public void httpGetUriOption() {
+        serverResponse.countDown();
         HttpEndpoint endpoint = context.getEndpoint("http://localhost:";
                                                     + 
localServer.getLocalPort() + "?responseTimeout=5000",
                 HttpEndpoint.class);
@@ -84,7 +96,7 @@ public class HttpSOTimeoutTest extends BaseHttpTest {
     @Test
     public void httpGetUriOptionShouldThrowASocketTimeoutException() {
         Exchange reply = template.request("http://localhost:";
-                                          + localServer.getLocalPort() + 
"?responseTimeout=1000",
+                                          + localServer.getLocalPort() + 
"?responseTimeout=200",
                 exchange -> {
                 });
         Exception e = reply.getException();
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpsTwoComponentsSslContextParametersGetTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpsTwoComponentsSslContextParametersGetTest.java
index 41e630c6abbe..0ce917cd097c 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpsTwoComponentsSslContextParametersGetTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpsTwoComponentsSslContextParametersGetTest.java
@@ -100,11 +100,9 @@ public class HttpsTwoComponentsSslContextParametersGetTest 
extends BaseHttpsTest
             }
         });
 
+        // should be able to startup (start is synchronous)
         context.start();
 
-        // should be able to startup
-        Thread.sleep(500);
-
         context.stop();
     }
 
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/handler/DelayValidationHandler.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/handler/BlockingValidationHandler.java
similarity index 64%
rename from 
components/camel-http/src/test/java/org/apache/camel/component/http/handler/DelayValidationHandler.java
rename to 
components/camel-http/src/test/java/org/apache/camel/component/http/handler/BlockingValidationHandler.java
index 7de5da6405db..1c78e2a20546 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/handler/DelayValidationHandler.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/handler/BlockingValidationHandler.java
@@ -17,20 +17,28 @@
 package org.apache.camel.component.http.handler;
 
 import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.protocol.HttpContext;
 
-public class DelayValidationHandler extends BasicValidationHandler {
+/**
+ * Handler which does not answer until the given latch is released, so tests 
can deterministically trigger client side
+ * timeouts (never release the latch) or get an immediate answer (release the 
latch before sending the request).
+ */
+public class BlockingValidationHandler extends BasicValidationHandler {
+
+    private static final int MAX_WAIT_SECONDS = 30;
 
-    protected final int delay;
+    private final CountDownLatch release;
 
-    public DelayValidationHandler(String expectedMethod, String expectedQuery,
-                                  Object expectedContent, String 
responseContent, int delay) {
+    public BlockingValidationHandler(String expectedMethod, String 
expectedQuery,
+                                     Object expectedContent, String 
responseContent, CountDownLatch release) {
         super(expectedMethod, expectedQuery, expectedContent, responseContent);
-        this.delay = delay;
+        this.release = release;
     }
 
     @Override
@@ -39,7 +47,8 @@ public class DelayValidationHandler extends 
BasicValidationHandler {
             final HttpContext context)
             throws HttpException, IOException {
         try {
-            Thread.sleep(delay);
+            // bounded wait to never hang the server thread forever
+            release.await(MAX_WAIT_SECONDS, TimeUnit.SECONDS);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
         }

Reply via email to