diff --git a/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientPostTest.java b/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientPostTest.java index b58ffce17dc..67fd3d56330 100644 --- a/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientPostTest.java +++ b/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientPostTest.java @@ -18,6 +18,8 @@ import io.fabric8.kubernetes.client.http.AbstractHttpPostTest; import io.fabric8.kubernetes.client.http.HttpClient; +import java.io.IOException; + @SuppressWarnings("java:S2187") public class JdkHttpClientPostTest extends AbstractHttpPostTest { @Override @@ -31,4 +33,9 @@ public void expectContinue() { // Apparently the JDK sets the Expect header to 100-Continue which is not according to spec. // We should consider overriding the header manually instead. } + + @Override + protected Class getConnectionFailedExceptionType() { + return IOException.class; + } } diff --git a/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientPutTest.java b/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientPutTest.java index e7e4054ed5a..a888cab4f13 100644 --- a/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientPutTest.java +++ b/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientPutTest.java @@ -18,10 +18,17 @@ import io.fabric8.kubernetes.client.http.AbstractHttpPutTest; import io.fabric8.kubernetes.client.http.HttpClient; +import java.io.IOException; + @SuppressWarnings("java:S2187") public class JdkHttpClientPutTest extends AbstractHttpPutTest { @Override protected HttpClient.Factory getHttpClientFactory() { return new JdkHttpClientFactory(); } + + @Override + protected Class getConnectionFailedExceptionType() { + return IOException.class; + } } diff --git a/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpPostTest.java b/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpPostTest.java index 33fbe1d6ad9..024631d591a 100644 --- a/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpPostTest.java +++ b/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpPostTest.java @@ -18,10 +18,17 @@ import io.fabric8.kubernetes.client.http.AbstractHttpPostTest; import io.fabric8.kubernetes.client.http.HttpClient; +import java.net.ConnectException; + @SuppressWarnings("java:S2187") public class JettyHttpPostTest extends AbstractHttpPostTest { @Override protected HttpClient.Factory getHttpClientFactory() { return new JettyHttpClientFactory(); } + + @Override + protected Class getConnectionFailedExceptionType() { + return ConnectException.class; + } } diff --git a/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpPutTest.java b/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpPutTest.java index 59283a0c938..aaeae528058 100644 --- a/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpPutTest.java +++ b/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpPutTest.java @@ -18,10 +18,17 @@ import io.fabric8.kubernetes.client.http.AbstractHttpPutTest; import io.fabric8.kubernetes.client.http.HttpClient; +import java.net.ConnectException; + @SuppressWarnings("java:S2187") public class JettyHttpPutTest extends AbstractHttpPutTest { @Override protected HttpClient.Factory getHttpClientFactory() { return new JettyHttpClientFactory(); } + + @Override + protected Class getConnectionFailedExceptionType() { + return ConnectException.class; + } } diff --git a/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpPostTest.java b/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpPostTest.java index b5e8abf0b8a..90753a04a2c 100644 --- a/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpPostTest.java +++ b/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpPostTest.java @@ -18,10 +18,17 @@ import io.fabric8.kubernetes.client.http.AbstractHttpPostTest; import io.fabric8.kubernetes.client.http.HttpClient; +import java.net.ConnectException; + @SuppressWarnings("java:S2187") public class OkHttpPostTest extends AbstractHttpPostTest { @Override protected HttpClient.Factory getHttpClientFactory() { return new OkHttpClientFactory(); } + + @Override + protected Class getConnectionFailedExceptionType() { + return ConnectException.class; + } } diff --git a/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpPutTest.java b/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpPutTest.java index 4f77fa9e05f..34d5ff00356 100644 --- a/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpPutTest.java +++ b/httpclient-okhttp/src/test/java/io/fabric8/kubernetes/client/okhttp/OkHttpPutTest.java @@ -18,10 +18,17 @@ import io.fabric8.kubernetes.client.http.AbstractHttpPutTest; import io.fabric8.kubernetes.client.http.HttpClient; +import java.net.ConnectException; + @SuppressWarnings("java:S2187") public class OkHttpPutTest extends AbstractHttpPutTest { @Override protected HttpClient.Factory getHttpClientFactory() { return new OkHttpClientFactory(); } + + @Override + protected Class getConnectionFailedExceptionType() { + return ConnectException.class; + } } diff --git a/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientPostTest.java b/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientPostTest.java index ef4095a54bd..c243ecc564f 100644 --- a/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientPostTest.java +++ b/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientPostTest.java @@ -18,6 +18,8 @@ import io.fabric8.kubernetes.client.http.AbstractHttpPostTest; import io.fabric8.kubernetes.client.http.HttpClient; +import java.net.ConnectException; + @SuppressWarnings("java:S2187") public class VertxHttpClientPostTest extends AbstractHttpPostTest { @Override @@ -25,4 +27,9 @@ protected HttpClient.Factory getHttpClientFactory() { return new VertxHttpClientFactory(); } + @Override + protected Class getConnectionFailedExceptionType() { + return ConnectException.class; + } + } diff --git a/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientPutTest.java b/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientPutTest.java index 5ede5806444..cc5141efe14 100644 --- a/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientPutTest.java +++ b/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientPutTest.java @@ -18,10 +18,17 @@ import io.fabric8.kubernetes.client.http.AbstractHttpPutTest; import io.fabric8.kubernetes.client.http.HttpClient; +import java.net.ConnectException; + @SuppressWarnings("java:S2187") public class VertxHttpClientPutTest extends AbstractHttpPutTest { @Override protected HttpClient.Factory getHttpClientFactory() { return new VertxHttpClientFactory(); } + + @Override + protected Class getConnectionFailedExceptionType() { + return ConnectException.class; + } } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpPostTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpPostTest.java index 5fe578a871e..4f7e7b3e607 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpPostTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpPostTest.java @@ -23,9 +23,15 @@ import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; @@ -47,6 +53,8 @@ static void afterAll() { protected abstract HttpClient.Factory getHttpClientFactory(); + protected abstract Class getConnectionFailedExceptionType(); + @Test @DisplayName("String body, should send a POST request with body") public void postStringBody() throws Exception { @@ -148,4 +156,34 @@ public void expectContinue() throws Exception { .isEqualTo("100-continue"); } } + + @Test + public void expectFailure() throws IOException, URISyntaxException { + try (final ServerSocket serverSocket = new ServerSocket(0);) { + + try (HttpClient client = getHttpClientFactory().newBuilder().build()) { + final URI uri = uriForPath(serverSocket, "/post-failing"); + serverSocket.close(); + + // When + final CompletableFuture> response = client + .sendAsync(client.newHttpRequestBuilder() + .post("text/plain", new ByteArrayInputStream("A string body".getBytes(StandardCharsets.UTF_8)), -1) + .uri(uri) + .timeout(250, TimeUnit.MILLISECONDS) + .build(), String.class); + + // Then + assertThat(response).failsWithin(30, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseInstanceOf(getConnectionFailedExceptionType()); + } + } + } + + private static URI uriForPath(ServerSocket socket, String path) throws URISyntaxException { + final InetAddress httpServerAddress = socket.getInetAddress(); + return new URI(String.format("http://%s:%s%s", httpServerAddress.getHostName(), socket.getLocalPort(), path)); + } + } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpPutTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpPutTest.java index 31aa8e0ccb3..147ee26e3bd 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpPutTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractHttpPutTest.java @@ -23,7 +23,14 @@ import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; @@ -44,6 +51,8 @@ static void afterAll() { protected abstract HttpClient.Factory getHttpClientFactory(); + protected abstract Class getConnectionFailedExceptionType(); + @Test @DisplayName("String body, should send a PUT request with body") public void putStringBody() throws Exception { @@ -83,4 +92,33 @@ public void putInputStreamBody() throws Exception { .extracting(rr -> rr.getHeader("Content-Type")).asString() .startsWith("text/plain"); } + + @Test + public void expectFailure() throws IOException, URISyntaxException { + try (final ServerSocket serverSocket = new ServerSocket(0);) { + + try (HttpClient client = getHttpClientFactory().newBuilder().build()) { + final URI uri = uriForPath(serverSocket, "/put-failing"); + serverSocket.close(); + + // When + final CompletableFuture> response = client + .sendAsync(client.newHttpRequestBuilder() + .put("text/plain", new ByteArrayInputStream("A string body".getBytes(StandardCharsets.UTF_8)), -1) + .uri(uri) + .timeout(250, TimeUnit.MILLISECONDS) + .build(), String.class); + + // Then + assertThat(response).failsWithin(30, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseInstanceOf(getConnectionFailedExceptionType()); + } + } + } + + private static URI uriForPath(ServerSocket socket, String path) throws URISyntaxException { + final InetAddress httpServerAddress = socket.getInetAddress(); + return new URI(String.format("http://%s:%s%s", httpServerAddress.getHostName(), socket.getLocalPort(), path)); + } }