From 37b0d52882801c141ab8d4e06f2fc66bac22e312 Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Fri, 9 Dec 2016 09:07:09 +0100 Subject: [PATCH] Watcher: Remove mock web server from square (elastic/elasticsearch#4221) The latest release of the mock web server requires more security permissions, and we dont need all the functionality anyway. This introduces a small MockWebServer using the JDK internal HttpServer, yet fullfilling all our needs and supporting SSL as well for testing. The MockWebServer allows to enqueue responses and also requires you to enqueue as many responses as you requests will be executed - there is no fallback at the moment. SSL is also supported by passing an SSL context - for which the TestsSSLService is needed, which makes the required methods public. Original commit: elastic/x-pack-elasticsearch@55f4a172a26a60a21b8fa435b7746897881a78c4 --- elasticsearch/build.gradle | 10 - .../org/elasticsearch/test/http/Headers.java | 61 +++++ .../elasticsearch/test/http/MockRequest.java | 76 ++++++ .../elasticsearch/test/http/MockResponse.java | 102 ++++++++ .../test/http/MockWebServer.java | 234 ++++++++++++++++++ .../xpack/common/http/HttpClientTests.java | 230 ++++++----------- .../common/http/HttpReadTimeoutTests.java | 68 +---- .../exporter/http/HttpExporterIT.java | 134 +++++----- .../xpack/ssl/TestsSSLService.java | 33 +++ .../actions/email/EmailAttachmentTests.java | 11 +- .../actions/webhook/WebhookActionTests.java | 34 ++- .../webhook/WebhookHttpsIntegrationTests.java | 37 ++- .../webhook/WebhookIntegrationTests.java | 37 ++- .../HistoryTemplateHttpMappingsTests.java | 22 +- .../HttpSecretsIntegrationTests.java | 22 +- .../action/delete/DeleteWatchTests.java | 16 +- 16 files changed, 731 insertions(+), 396 deletions(-) create mode 100644 elasticsearch/src/test/java/org/elasticsearch/test/http/Headers.java create mode 100644 elasticsearch/src/test/java/org/elasticsearch/test/http/MockRequest.java create mode 100644 elasticsearch/src/test/java/org/elasticsearch/test/http/MockResponse.java create mode 100644 elasticsearch/src/test/java/org/elasticsearch/test/http/MockWebServer.java create mode 100644 elasticsearch/src/test/java/org/elasticsearch/xpack/ssl/TestsSSLService.java diff --git a/elasticsearch/build.gradle b/elasticsearch/build.gradle index 90967497a58..c529ae1a3db 100644 --- a/elasticsearch/build.gradle +++ b/elasticsearch/build.gradle @@ -16,10 +16,6 @@ esplugin { } archivesBaseName = 'x-pack' // for api jar -ext.versions = [ - okhttp: '2.7.5' -] - // TODO: fix this! https://github.com/elastic/x-plugins/issues/1066 ext.compactProfile = 'full' @@ -58,12 +54,6 @@ dependencies { testCompile 'org.elasticsearch:securemock:1.2' testCompile 'org.slf4j:slf4j-log4j12:1.6.2' testCompile 'org.slf4j:slf4j-api:1.6.2' - - // mock web server - testCompile "com.squareup.okhttp:mockwebserver:${versions.okhttp}" - testCompile "com.squareup.okhttp:okhttp:${versions.okhttp}" - testCompile "com.squareup.okhttp:okhttp-ws:${versions.okhttp}" - testCompile 'com.squareup.okio:okio:1.6.0' } // make LicenseSigner available for testing signed licenses diff --git a/elasticsearch/src/test/java/org/elasticsearch/test/http/Headers.java b/elasticsearch/src/test/java/org/elasticsearch/test/http/Headers.java new file mode 100644 index 00000000000..2a5f6f44587 --- /dev/null +++ b/elasticsearch/src/test/java/org/elasticsearch/test/http/Headers.java @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.test.http; + +import org.elasticsearch.common.SuppressForbidden; + +import java.util.Collections; +import java.util.List; + +/** + * A helper class to not leak the internal headers class into our tests + * Currently setting multiple values for a single header is not supported, as it was not needed yet + */ +@SuppressForbidden(reason = "use http server") +public class Headers { + + final com.sun.net.httpserver.Headers headers; + + /** + * Creates a class with empty headers + */ + Headers() { + this.headers = new com.sun.net.httpserver.Headers(); + } + + /** + * Creates a class headers from http + * @param headers The internal sun webserver headers object + */ + Headers(com.sun.net.httpserver.Headers headers) { + this.headers = headers; + } + + /** + * @param name The name of header + * @return A list of values for this header + */ + public List get(String name) { + return headers.get(name); + } + + /** + * Adds a new header to this headers object + * @param name Name of the header + * @param value Value of the header + */ + void add(String name, String value) { + this.headers.put(name, Collections.singletonList(value)); + } + + /** + * @param name Name of the header + * @return Returns the first header value or null if none exists + */ + String getFirst(String name) { + return headers.getFirst(name); + } +} diff --git a/elasticsearch/src/test/java/org/elasticsearch/test/http/MockRequest.java b/elasticsearch/src/test/java/org/elasticsearch/test/http/MockRequest.java new file mode 100644 index 00000000000..7a6a81620ad --- /dev/null +++ b/elasticsearch/src/test/java/org/elasticsearch/test/http/MockRequest.java @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.test.http; + +import org.elasticsearch.common.SuppressForbidden; + +import java.net.URI; +import java.util.Locale; + +/** + * A request parsed by the MockWebServer + */ +public class MockRequest { + + private final String method; + private final URI uri; + private final Headers headers; + private String body = null; + + @SuppressForbidden(reason = "use http server header class") + MockRequest(String method, URI uri, com.sun.net.httpserver.Headers headers) { + this.method = method; + this.uri = uri; + this.headers = new Headers(headers); + } + + /** + * @return The HTTP method of the incoming request + */ + public String getMethod() { + return method; + } + + /** + * @return The URI of the incoming request + */ + public URI getUri() { + return uri; + } + + /** + * @return The specific value of a request header, null if it does not exist + */ + public String getHeader(String name) { + return headers.getFirst(name); + } + + /** + * @return All headers associated with this request + */ + public Headers getHeaders() { + return headers; + } + + /** + * @return The body the incoming request had, null if no body was found + */ + public String getBody() { + return body; + } + + @Override + public String toString() { + return String.format(Locale.ROOT, "%s %s", method, uri); + } + + /** + * @param body Sets the body of the incoming request + */ + void setBody(String body) { + this.body = body; + } +} diff --git a/elasticsearch/src/test/java/org/elasticsearch/test/http/MockResponse.java b/elasticsearch/src/test/java/org/elasticsearch/test/http/MockResponse.java new file mode 100644 index 00000000000..e2d9a41dee3 --- /dev/null +++ b/elasticsearch/src/test/java/org/elasticsearch/test/http/MockResponse.java @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.test.http; + +import org.elasticsearch.common.unit.TimeValue; + +/** + * A response to be sent via the mock webserver. Parts of the response can be configured + */ +public class MockResponse { + + private String body = null; + private int statusCode = 200; + private TimeValue bodyDelay = null; + private Headers headers = new Headers(); + private TimeValue beforeReplyDelay = null; + + /** + * @param body The body to be returned if the response is sent by the webserver + * @return The updated mock response + */ + public MockResponse setBody(String body) { + this.body = body; + return this; + } + + /** + * @param statusCode The status code to be returned if the response is sent by the webserver, defaults to 200 + * @return The updated mock response + */ + public MockResponse setResponseCode(int statusCode) { + this.statusCode = statusCode; + return this; + } + + /** + * @param timeValue Allows to specify a delay between sending of headers and the body to inject artificial latency + * @return The updated mock response + */ + public MockResponse setBodyDelay(TimeValue timeValue) { + this.bodyDelay = timeValue; + return this; + } + + /** + * @param timeValue Allows to specify a delay before anything is sent back to the client + * @return The updated mock response + */ + public MockResponse setBeforeReplyDelay(TimeValue timeValue) { + this.beforeReplyDelay = timeValue; + return this; + } + + /** + * Adds a new header to a response + * @param name Header name + * @param value header value + * @return The updated mock response + */ + public MockResponse addHeader(String name, String value) { + headers.add(name, value); + return this; + } + + /** + * @return the body of the request + */ + String getBody() { + return body; + } + + /** + * @return The HTTP status code + */ + int getStatusCode() { + return statusCode; + } + + /** + * @return The time to delay the between sending the headers and the body + */ + TimeValue getBodyDelay() { + return bodyDelay; + } + + /** + * @return All configured headers for this request + */ + Headers getHeaders() { + return headers; + } + + /** + * @return The time to delay before the first byte is being returned + */ + TimeValue getBeforeReplyDelay() { + return beforeReplyDelay; + } +} diff --git a/elasticsearch/src/test/java/org/elasticsearch/test/http/MockWebServer.java b/elasticsearch/src/test/java/org/elasticsearch/test/http/MockWebServer.java new file mode 100644 index 00000000000..4bed6c5a7f2 --- /dev/null +++ b/elasticsearch/src/test/java/org/elasticsearch/test/http/MockWebServer.java @@ -0,0 +1,234 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.test.http; + +import com.google.common.base.Charsets; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsParameters; +import com.sun.net.httpserver.HttpsServer; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.apache.logging.log4j.util.Supplier; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.SuppressForbidden; +import org.elasticsearch.common.io.Streams; +import org.elasticsearch.common.logging.ESLoggerFactory; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.util.concurrent.ConcurrentCollections; + +import javax.net.ssl.SSLContext; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.elasticsearch.test.ESTestCase.terminate; + +/** + * A MockWebServer to test against. Holds a list of responses, which can be enqueed. + * The webserver has to enqueue at least the amount of responses with the number of requests that happen, otherwise errors + * will be returned. + *

+ * Each response that was executed also contains the request, so you can check if requests happened in the correct order. + */ +@SuppressForbidden(reason = "use http server") +public class MockWebServer implements Closeable { + + private HttpServer server; + private final AtomicInteger index = new AtomicInteger(0); + private final List responses = new ArrayList<>(); + private final List requests = new ArrayList<>(); + private final Logger logger; + private final SSLContext sslContext; + private boolean needClientAuth; + private Set latches = ConcurrentCollections.newConcurrentSet(); + + /** + * Instantiates a webserver without https + */ + public MockWebServer() { + this(null, false); + } + + /** + * Instantiates a webserver with https + * @param sslContext The SSL context to be used for encryption + * @param needClientAuth Should clientAuth be used, which requires a client side certificate + */ + public MockWebServer(SSLContext sslContext, boolean needClientAuth) { + this.needClientAuth = needClientAuth; + this.logger = ESLoggerFactory.getLogger(this.getClass()); + this.sslContext = sslContext; + } + + /** + * Starts the webserver and binds it to an arbitrary ephemeral port + * The webserver will be able to serve requests once this method returns + * + * @throws IOException in case of a binding or other I/O errors + */ + public void start() throws IOException { + InetSocketAddress address = new InetSocketAddress(InetAddress.getLoopbackAddress().getHostAddress(), 0); + if (sslContext != null) { + HttpsServer httpsServer = HttpsServer.create(address, 0); + httpsServer.setHttpsConfigurator(new CustomHttpsConfigurator(sslContext, needClientAuth)); + server = httpsServer; + } else { + server = HttpServer.create(address, 0); + } + + server.start(); + server.createContext("/", s -> { + logger.debug("incoming HTTP request [{} {}]", s.getRequestMethod(), s.getRequestURI()); + + try { + MockResponse response = responses.get(index.getAndAdd(1)); + MockRequest request = createRequest(s); + requests.add(request); + + sleepIfNeeded(response.getBeforeReplyDelay()); + + s.getResponseHeaders().putAll(response.getHeaders().headers); + + if (Strings.isEmpty(response.getBody())) { + s.sendResponseHeaders(response.getStatusCode(), 0); + } else { + byte[] responseAsBytes = response.getBody().getBytes(Charsets.UTF_8); + s.sendResponseHeaders(response.getStatusCode(), responseAsBytes.length); + sleepIfNeeded(response.getBodyDelay()); + try (OutputStream responseBody = s.getResponseBody()) { + responseBody.write(responseAsBytes); + } + } + } catch (Exception e) { + logger.error((Supplier) () -> new ParameterizedMessage("failed to respond to request [{} {}]", + s.getRequestMethod(), s.getRequestURI()), e); + } finally { + s.close(); + } + + }); + logger.info("bound HTTP mock server to [{}:{}]", getHostName(), getPort()); + } + + /** + * A custom HttpsConfigurator that takes the SSL context and the required client authentication into account + * Also configured the protocols and cipher suites to match the security default ones + */ + @SuppressForbidden(reason = "use http server") + private static final class CustomHttpsConfigurator extends HttpsConfigurator { + + private final boolean needClientAuth; + + public CustomHttpsConfigurator(SSLContext sslContext, boolean needClientAuth) { + super(sslContext); + this.needClientAuth = needClientAuth; + } + + @Override + public void configure(HttpsParameters params) { + params.setNeedClientAuth(needClientAuth); + } + } + + /** + * Sleep the specified amount of time, if the time value is not null + */ + private void sleepIfNeeded(TimeValue timeValue) throws InterruptedException { + if (timeValue == null) { + return; + } + + CountDownLatch latch = new CountDownLatch(1); + latches.add(latch); + try { + latch.await(timeValue.millis(), TimeUnit.MILLISECONDS); + } finally { + latches.remove(latch); + } + } + + /** + * Creates a MockRequest from an incoming HTTP request, that can later be checked in your test assertions + */ + private MockRequest createRequest(HttpExchange exchange) throws IOException { + MockRequest request = new MockRequest(exchange.getRequestMethod(), exchange.getRequestURI(), exchange.getRequestHeaders()); + if (exchange.getRequestBody() != null) { + String body = Streams.copyToString(new InputStreamReader(exchange.getRequestBody())); + if (Strings.isEmpty(body) == false) { + request.setBody(body); + } + } + return request; + } + + /** + * @return The hostname the server is bound to. Uses #InetSocketAddress.getHostString() to prevent reverse dns lookups + */ + public String getHostName() { + return server.getAddress().getHostString(); + } + + /** + * @return The tcp port that the server is bound to + */ + public int getPort() { + return server.getAddress().getPort(); + } + + /** + * Adds a response to the response queue that is used when a request comes in + * Note: Every response is only processed once + * @param response The created mock response + */ + public void enqueue(MockResponse response) { + responses.add(response); + } + + /** + * @return The requests that have been made to this mock web server + */ + public List requests() { + return requests; + } + + /** + * Removes the first request in the list of requests and returns it to the caller. + * This can be used as a queue if you know the order of your requests deone. + */ + public MockRequest takeRequest() { + return requests.remove(0); + } + + /** + * Closes down the webserver. Also tries to stop all the currently sleeping requests first by counting down their respective + * latches. + */ + @Override + public void close() { + logger.debug("Counting down all latches before terminating executor"); + latches.forEach(CountDownLatch::countDown); + + if (server.getExecutor() instanceof ExecutorService) { + try { + terminate((ExecutorService) server.getExecutor()); + } catch (InterruptedException e) { + } + } + server.stop(0); + } +} diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/common/http/HttpClientTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/common/http/HttpClientTests.java index 9e9f50804a8..e258f09bcd5 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/common/http/HttpClientTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/common/http/HttpClientTests.java @@ -6,33 +6,32 @@ package org.elasticsearch.xpack.common.http; import com.carrotsearch.randomizedtesting.generators.RandomStrings; -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; -import com.squareup.okhttp.mockwebserver.RecordedRequest; import org.apache.logging.log4j.message.ParameterizedMessage; import org.apache.logging.log4j.util.Supplier; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.env.Environment; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.test.junit.annotations.Network; +import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.xpack.common.http.auth.HttpAuthRegistry; import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth; import org.elasticsearch.xpack.common.http.auth.basic.BasicAuthFactory; import org.elasticsearch.xpack.ssl.SSLService; +import org.elasticsearch.xpack.ssl.TestsSSLService; import org.elasticsearch.xpack.ssl.VerificationMode; import org.junit.After; import org.junit.Before; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.SSLContext; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; -import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.concurrent.ExecutorService; @@ -42,6 +41,7 @@ import java.util.concurrent.atomic.AtomicReference; import static java.util.Collections.singletonMap; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -49,7 +49,7 @@ import static org.hamcrest.core.Is.is; public class HttpClientTests extends ESTestCase { - private MockWebServer webServer; + private MockWebServer webServer = new MockWebServer(); private HttpClient httpClient; private HttpAuthRegistry authRegistry; private Environment environment = new Environment(Settings.builder().put("path.home", createTempDir()).build()); @@ -57,13 +57,13 @@ public class HttpClientTests extends ESTestCase { @Before public void init() throws Exception { authRegistry = new HttpAuthRegistry(singletonMap(BasicAuth.TYPE, new BasicAuthFactory(null))); - webServer = startWebServer(); + webServer.start(); httpClient = new HttpClient(Settings.EMPTY, authRegistry, new SSLService(environment.settings(), environment)); } @After public void shutdown() throws Exception { - webServer.shutdown(); + webServer.close(); } public void testBasics() throws Exception { @@ -71,7 +71,6 @@ public class HttpClientTests extends ESTestCase { String body = randomAsciiOfLengthBetween(2, 8096); webServer.enqueue(new MockResponse().setResponseCode(responseCode).setBody(body)); - HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort()) .method(HttpMethod.POST) .path("/" + randomAsciiOfLength(5)); @@ -90,18 +89,16 @@ public class HttpClientTests extends ESTestCase { HttpRequest request = requestBuilder.build(); HttpResponse response = httpClient.execute(request); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(response.status(), equalTo(responseCode)); assertThat(response.body().utf8ToString(), equalTo(body)); - assertThat(webServer.getRequestCount(), equalTo(1)); - assertThat(recordedRequest.getBody().readString(StandardCharsets.UTF_8), equalTo(request.body())); - assertThat(recordedRequest.getPath().split("\\?")[0], equalTo(request.path())); - assertThat(recordedRequest.getPath().split("\\?")[1], equalTo(paramKey + "=" + paramValue)); - assertThat(recordedRequest.getHeader(headerKey), equalTo(headerValue)); + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getPath(), equalTo(request.path())); + assertThat(webServer.requests().get(0).getUri().getQuery(), equalTo(paramKey + "=" + paramValue)); + assertThat(webServer.requests().get(0).getHeader(headerKey), equalTo(headerValue)); } + @TestLogging("org.elasticsearch.http.test:TRACE") public void testNoQueryString() throws Exception { webServer.enqueue(new MockResponse().setResponseCode(200).setBody("body")); HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort()) @@ -112,9 +109,9 @@ public class HttpClientTests extends ESTestCase { assertThat(response.status(), equalTo(200)); assertThat(response.body().utf8ToString(), equalTo("body")); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/test")); - assertThat(recordedRequest.getBody().readUtf8Line(), nullValue()); + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getPath(), is("/test")); + assertThat(webServer.requests().get(0).getBody(), is(nullValue())); } public void testUrlEncodingWithQueryStrings() throws Exception{ @@ -128,9 +125,10 @@ public class HttpClientTests extends ESTestCase { assertThat(response.status(), equalTo(200)); assertThat(response.body().utf8ToString(), equalTo("body")); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/test?key=value+123%3A123")); - assertThat(recordedRequest.getBody().readUtf8Line(), nullValue()); + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getPath(), is("/test")); + assertThat(webServer.requests().get(0).getUri().getRawQuery(), is("key=value+123%3A123")); + assertThat(webServer.requests().get(0).getBody(), is(nullValue())); } public void testBasicAuth() throws Exception { @@ -143,17 +141,19 @@ public class HttpClientTests extends ESTestCase { HttpResponse response = httpClient.execute(request.build()); assertThat(response.status(), equalTo(200)); assertThat(response.body().utf8ToString(), equalTo("body")); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/test")); - assertThat(recordedRequest.getHeader("Authorization"), equalTo("Basic dXNlcjpwYXNz")); + + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getPath(), is("/test")); + assertThat(webServer.requests().get(0).getHeader("Authorization"), is("Basic dXNlcjpwYXNz")); } public void testNoPathSpecified() throws Exception { webServer.enqueue(new MockResponse().setResponseCode(200).setBody("doesntmatter")); HttpRequest.Builder request = HttpRequest.builder("localhost", webServer.getPort()).method(HttpMethod.GET); httpClient.execute(request.build()); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/")); + + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getPath(), is("/")); } public void testHttps() throws Exception { @@ -171,26 +171,16 @@ public class HttpClientTests extends ESTestCase { .put("xpack.ssl.truststore.password", "truststore-testnode-only") .build(); } - HttpClient httpClient = new HttpClient(settings, authRegistry, new SSLService(settings, environment)); + httpClient = new HttpClient(settings, authRegistry, new SSLService(settings, environment)); // We can't use the client created above for the server since it is only a truststore Settings settings2 = Settings.builder() .put("xpack.ssl.keystore.path", getDataPath("/org/elasticsearch/xpack/security/keystore/testnode.jks")) .put("xpack.ssl.keystore.password", "testnode") .build(); - webServer.useHttps(new SSLService(settings2, environment).sslSocketFactory(Settings.EMPTY), false); - webServer.enqueue(new MockResponse().setResponseCode(200).setBody("body")); - HttpRequest.Builder request = HttpRequest.builder("localhost", webServer.getPort()) - .scheme(Scheme.HTTPS) - .path("/test") - .body("body"); - HttpResponse response = httpClient.execute(request.build()); - assertThat(response.status(), equalTo(200)); - assertThat(response.body().utf8ToString(), equalTo("body")); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/test")); - assertThat(recordedRequest.getBody().readUtf8Line(), equalTo("body")); + TestsSSLService sslService = new TestsSSLService(settings2, environment); + testSslMockWebserver(sslService.sslContext(), false); } public void testHttpsDisableHostnameVerification() throws Exception { @@ -210,7 +200,7 @@ public class HttpClientTests extends ESTestCase { .put("xpack.ssl.verification_mode", randomFrom(VerificationMode.NONE, VerificationMode.CERTIFICATE)) .build(); } - HttpClient httpClient = new HttpClient(settings, authRegistry, new SSLService(settings, environment)); + httpClient = new HttpClient(settings, authRegistry, new SSLService(settings, environment)); // We can't use the client created above for the server since it only defines a truststore Settings settings2 = Settings.builder() @@ -218,52 +208,38 @@ public class HttpClientTests extends ESTestCase { getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode-no-subjaltname.jks")) .put("xpack.ssl.keystore.password", "testnode-no-subjaltname") .build(); - webServer.useHttps(new SSLService(settings2, environment).sslSocketFactory(Settings.EMPTY), false); - webServer.enqueue(new MockResponse().setResponseCode(200).setBody("body")); - HttpRequest.Builder request = HttpRequest.builder("localhost", webServer.getPort()) - .scheme(Scheme.HTTPS) - .path("/test") - .body("body"); - HttpResponse response = httpClient.execute(request.build()); - assertThat(response.status(), equalTo(200)); - assertThat(response.body().utf8ToString(), equalTo("body")); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/test")); - assertThat(recordedRequest.getBody().readUtf8Line(), equalTo("body")); + TestsSSLService sslService = new TestsSSLService(settings2, environment); + testSslMockWebserver(sslService.sslContext(), false); } public void testHttpsClientAuth() throws Exception { Path resource = getDataPath("/org/elasticsearch/xpack/security/keystore/testnode.jks"); - Settings settings; - if (randomBoolean()) { - settings = Settings.builder() - .put("xpack.http.ssl.keystore.path", resource.toString()) - .put("xpack.http.ssl.keystore.password", "testnode") - .build(); - } else { - settings = Settings.builder() + Settings settings = Settings.builder() .put("xpack.ssl.keystore.path", resource.toString()) .put("xpack.ssl.keystore.password", "testnode") .build(); + + TestsSSLService sslService = new TestsSSLService(settings, environment); + httpClient = new HttpClient(settings, authRegistry, sslService); + testSslMockWebserver(sslService.sslContext(), true); + } + + private void testSslMockWebserver(SSLContext sslContext, boolean needClientAuth) throws IOException { + try (MockWebServer mockWebServer = new MockWebServer(sslContext, needClientAuth)) { + mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody("body")); + mockWebServer.start(); + + HttpRequest.Builder request = HttpRequest.builder("localhost", mockWebServer.getPort()) + .scheme(Scheme.HTTPS) + .path("/test"); + HttpResponse response = httpClient.execute(request.build()); + assertThat(response.status(), equalTo(200)); + assertThat(response.body().utf8ToString(), equalTo("body")); + + assertThat(mockWebServer.requests(), hasSize(1)); + assertThat(mockWebServer.requests().get(0).getUri().getPath(), is("/test")); } - - final SSLService sslService = new SSLService(settings, environment); - HttpClient httpClient = new HttpClient(settings, authRegistry, sslService); - webServer.useHttps( - new ClientAuthRequiringSSLSocketFactory(sslService.sslSocketFactory(settings.getByPrefix("xpack.http.ssl."))), false); - - webServer.enqueue(new MockResponse().setResponseCode(200).setBody("body")); - HttpRequest.Builder request = HttpRequest.builder("localhost", webServer.getPort()) - .scheme(Scheme.HTTPS) - .path("/test") - .body("body"); - HttpResponse response = httpClient.execute(request.build()); - assertThat(response.status(), equalTo(200)); - assertThat(response.body().utf8ToString(), equalTo("body")); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/test")); - assertThat(recordedRequest.getBody().readUtf8Line(), equalTo("body")); } public void testHttpResponseWithAnyStatusCodeCanReturnBody() throws Exception { @@ -304,10 +280,9 @@ public class HttpClientTests extends ESTestCase { public void testThatProxyCanBeConfigured() throws Exception { // this test fakes a proxy server that sends a response instead of forwarding it to the mock web server - MockWebServer proxyServer = startWebServer(); - proxyServer.enqueue(new MockResponse().setResponseCode(200).setBody("fullProxiedContent")); - - try { + try (MockWebServer proxyServer = new MockWebServer()) { + proxyServer.enqueue(new MockResponse().setResponseCode(200).setBody("fullProxiedContent")); + proxyServer.start(); Settings settings = Settings.builder() .put(HttpClient.SETTINGS_PROXY_HOST, "localhost") .put(HttpClient.SETTINGS_PROXY_PORT, proxyServer.getPort()) @@ -323,19 +298,16 @@ public class HttpClientTests extends ESTestCase { assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent")); // ensure we hit the proxyServer and not the webserver - assertThat(webServer.getRequestCount(), equalTo(0)); - assertThat(proxyServer.getRequestCount(), equalTo(1)); - } finally { - proxyServer.shutdown(); + assertThat(webServer.requests(), hasSize(0)); + assertThat(proxyServer.requests(), hasSize(1)); } } public void testThatProxyCanBeOverriddenByRequest() throws Exception { // this test fakes a proxy server that sends a response instead of forwarding it to the mock web server - MockWebServer proxyServer = startWebServer(); - proxyServer.enqueue(new MockResponse().setResponseCode(200).setBody("fullProxiedContent")); - - try { + try (MockWebServer proxyServer = new MockWebServer()) { + proxyServer.enqueue(new MockResponse().setResponseCode(200).setBody("fullProxiedContent")); + proxyServer.start(); Settings settings = Settings.builder() .put(HttpClient.SETTINGS_PROXY_HOST, "localhost") .put(HttpClient.SETTINGS_PROXY_PORT, proxyServer.getPort() + 1) @@ -352,26 +324,24 @@ public class HttpClientTests extends ESTestCase { assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent")); // ensure we hit the proxyServer and not the webserver - assertThat(webServer.getRequestCount(), equalTo(0)); - assertThat(proxyServer.getRequestCount(), equalTo(1)); - } finally { - proxyServer.shutdown(); + assertThat(webServer.requests(), hasSize(0)); + assertThat(proxyServer.requests(), hasSize(1)); } } public void testThatUrlPathIsNotEncoded() throws Exception { // %2F is a slash that needs to be encoded to not be misinterpreted as a path - String path = "//_search"; + String path = "/%3Clogstash-%7Bnow%2Fd%7D%3E/_search"; webServer.enqueue(new MockResponse().setResponseCode(200).setBody("foo")); HttpRequest request = HttpRequest.builder("localhost", webServer.getPort()).path(path).build(); httpClient.execute(request); - assertThat(webServer.getRequestCount(), is(1)); + assertThat(webServer.requests(), hasSize(1)); - RecordedRequest recordedRequest = webServer.takeRequest(); // under no circumstances have a double encode of %2F => %25 (percent sign) - assertThat(recordedRequest.getPath(), not(containsString("%25"))); - assertThat(recordedRequest.getPath(), equalTo(path)); + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getRawPath(), not(containsString("%25"))); + assertThat(webServer.requests().get(0).getUri().getPath(), is("//_search")); } public void testThatHttpClientFailsOnNonHttpResponse() throws Exception { @@ -397,64 +367,4 @@ public class HttpClientTests extends ESTestCase { terminate(executor); } } - - private MockWebServer startWebServer() throws IOException { - MockWebServer mockWebServer = new MockWebServer(); - mockWebServer.setProtocolNegotiationEnabled(false); - mockWebServer.start(); - return mockWebServer; - } - - static class ClientAuthRequiringSSLSocketFactory extends SSLSocketFactory { - final SSLSocketFactory delegate; - - ClientAuthRequiringSSLSocketFactory(SSLSocketFactory delegate) { - this.delegate = delegate; - } - - @Override - public String[] getDefaultCipherSuites() { - return delegate.getDefaultCipherSuites(); - } - - @Override - public String[] getSupportedCipherSuites() { - return delegate.getSupportedCipherSuites(); - } - - @Override - public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException { - SSLSocket sslSocket = (SSLSocket) delegate.createSocket(socket, s, i, b); - sslSocket.setNeedClientAuth(true); - return sslSocket; - } - - @Override - public Socket createSocket(String s, int i) throws IOException, UnknownHostException { - SSLSocket sslSocket = (SSLSocket) delegate.createSocket(s, i); - sslSocket.setNeedClientAuth(true); - return sslSocket; - } - - @Override - public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException { - SSLSocket sslSocket = (SSLSocket) delegate.createSocket(s, i, inetAddress, i1); - sslSocket.setNeedClientAuth(true); - return sslSocket; - } - - @Override - public Socket createSocket(InetAddress inetAddress, int i) throws IOException { - SSLSocket sslSocket = (SSLSocket) delegate.createSocket(inetAddress, i); - sslSocket.setNeedClientAuth(true); - return sslSocket; - } - - @Override - public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException { - SSLSocket sslSocket = (SSLSocket) delegate.createSocket(inetAddress, i, inetAddress1, i1); - sslSocket.setNeedClientAuth(true); - return sslSocket; - } - } } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/common/http/HttpReadTimeoutTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/common/http/HttpReadTimeoutTests.java index 787855bc322..eba15f63104 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/common/http/HttpReadTimeoutTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/common/http/HttpReadTimeoutTests.java @@ -5,40 +5,35 @@ */ package org.elasticsearch.xpack.common.http; -import com.squareup.okhttp.mockwebserver.Dispatcher; -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; -import com.squareup.okhttp.mockwebserver.RecordedRequest; import org.elasticsearch.ElasticsearchTimeoutException; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.env.Environment; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.common.http.auth.HttpAuthRegistry; import org.elasticsearch.xpack.ssl.SSLService; import org.junit.After; import org.junit.Before; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.lessThan; import static org.mockito.Mockito.mock; public class HttpReadTimeoutTests extends ESTestCase { - private MockWebServer webServer; + private MockWebServer webServer = new MockWebServer(); @Before public void init() throws Exception { - webServer = new MockWebServer(); webServer.start(); + webServer.enqueue(new MockResponse().setBeforeReplyDelay(TimeValue.timeValueSeconds(20))); } @After public void cleanup() throws Exception { - webServer.shutdown(); + webServer.close(); } public void testDefaultTimeout() throws Exception { @@ -46,11 +41,9 @@ public class HttpReadTimeoutTests extends ESTestCase { HttpClient httpClient = new HttpClient(Settings.EMPTY, mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment)); - // we're not going to enqueue an response... so the server will just hang - HttpRequest request = HttpRequest.builder("localhost", webServer.getPort()) .method(HttpMethod.POST) - .path("/" + randomAsciiOfLength(5)) + .path("/") .build(); long start = System.nanoTime(); @@ -61,9 +54,6 @@ public class HttpReadTimeoutTests extends ESTestCase { // it's supposed to be 10, but we'll give it an error margin of 2 seconds assertThat(timeout.seconds(), greaterThan(8L)); assertThat(timeout.seconds(), lessThan(12L)); - - // lets enqueue a response to relese the server. - webServer.enqueue(new MockResponse()); } public void testDefaultTimeoutCustom() throws Exception { @@ -73,14 +63,9 @@ public class HttpReadTimeoutTests extends ESTestCase { .put("xpack.http.default_read_timeout", "3s").build() , mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment)); - final String path = '/' + randomAsciiOfLength(5); - final CountDownLatch latch = new CountDownLatch(1); - final TimeValue sleepTime = TimeValue.timeValueSeconds(10); - webServer.setDispatcher(new CountDownLatchDispatcher(path, latch, sleepTime)); - HttpRequest request = HttpRequest.builder("localhost", webServer.getPort()) .method(HttpMethod.POST) - .path(path) + .path("/") .build(); long start = System.nanoTime(); @@ -91,11 +76,6 @@ public class HttpReadTimeoutTests extends ESTestCase { // it's supposed to be 3, but we'll give it an error margin of 2 seconds assertThat(timeout.seconds(), greaterThan(1L)); assertThat(timeout.seconds(), lessThan(5L)); - - if (!latch.await(sleepTime.seconds(), TimeUnit.SECONDS)) { - // should never happen - fail("waited too long for the response to be returned"); - } } public void testTimeoutCustomPerRequest() throws Exception { @@ -105,15 +85,10 @@ public class HttpReadTimeoutTests extends ESTestCase { .put("xpack.http.default_read_timeout", "10s").build() , mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment)); - final String path = '/' + randomAsciiOfLength(5); - final CountDownLatch latch = new CountDownLatch(1); - final TimeValue sleepTime = TimeValue.timeValueSeconds(10); - webServer.setDispatcher(new CountDownLatchDispatcher(path, latch, sleepTime)); - HttpRequest request = HttpRequest.builder("localhost", webServer.getPort()) .readTimeout(TimeValue.timeValueSeconds(5)) .method(HttpMethod.POST) - .path(path) + .path("/") .build(); long start = System.nanoTime(); @@ -124,32 +99,5 @@ public class HttpReadTimeoutTests extends ESTestCase { // it's supposed to be 5, but we'll give it an error margin of 2 seconds assertThat(timeout.seconds(), greaterThan(3L)); assertThat(timeout.seconds(), lessThan(7L)); - - if (!latch.await(sleepTime.seconds(), TimeUnit.SECONDS)) { - // should never happen - fail("waited too long for the response to be returned"); - } - } - - private class CountDownLatchDispatcher extends Dispatcher { - - private final String path; - private final CountDownLatch latch; - private TimeValue sleepTime; - - public CountDownLatchDispatcher(String path, CountDownLatch latch, TimeValue sleepTime) { - this.path = path; - this.latch = latch; - this.sleepTime = sleepTime; - } - - @Override - public MockResponse dispatch(RecordedRequest request) throws InterruptedException { - if (path.equals(request.getPath())) { - Thread.sleep(sleepTime.millis()); - latch.countDown(); - } - return new MockResponse().setStatus("200"); - } } } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java index f6d30ac3342..9316d863cfb 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java @@ -5,11 +5,6 @@ */ package org.elasticsearch.xpack.monitoring.exporter.http; -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; -import com.squareup.okhttp.mockwebserver.QueueDispatcher; -import com.squareup.okhttp.mockwebserver.RecordedRequest; -import okio.Buffer; import org.elasticsearch.Version; import org.elasticsearch.action.DocWriteRequest; import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse; @@ -20,6 +15,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.settings.Settings; @@ -29,6 +25,9 @@ import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase.Scope; +import org.elasticsearch.test.http.MockRequest; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.monitoring.MonitoredSystem; import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.collector.cluster.ClusterStateMonitoringDoc; @@ -45,8 +44,7 @@ import org.junit.After; import org.junit.Before; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -79,7 +77,7 @@ public class HttpExporterIT extends MonitoringIntegTestCase { @After public void stopWebServer() throws Exception { - webServer.shutdown(); + webServer.close(); } @Override @@ -223,8 +221,7 @@ public class HttpExporterIT extends MonitoringIntegTestCase { assertMonitorResources(webServer, templatesExistsAlready, pipelineExistsAlready, bwcIndexesExist, bwcAliasesExist); assertBulk(webServer); - final MockWebServer secondWebServer = createMockWebServer(); - try { + try (MockWebServer secondWebServer = createMockWebServer()) { assertAcked(client().admin().cluster().prepareUpdateSettings().setTransientSettings( Settings.builder().putArray("xpack.monitoring.exporters._http.host", getFormattedAddress(secondWebServer)))); @@ -249,22 +246,22 @@ public class HttpExporterIT extends MonitoringIntegTestCase { assertMonitorVersion(secondWebServer); for (Tuple template : monitoringTemplates()) { - RecordedRequest recordedRequest = secondWebServer.takeRequest(); + MockRequest recordedRequest = secondWebServer.takeRequest(); assertThat(recordedRequest.getMethod(), equalTo("GET")); - assertThat(recordedRequest.getPath(), equalTo("/_template/" + template.v1() + resourceQueryString())); + assertThat(recordedRequest.getUri().getPath(), equalTo("/_template/" + template.v1())); + assertThat(recordedRequest.getUri().getQuery(), equalTo(resourceQueryString())); if (template.v1().contains(MonitoringBulkTimestampedResolver.Data.DATA) == false) { recordedRequest = secondWebServer.takeRequest(); assertThat(recordedRequest.getMethod(), equalTo("PUT")); - assertThat(recordedRequest.getPath(), equalTo("/_template/" + template.v1() + resourceQueryString())); - assertThat(recordedRequest.getBody().readUtf8(), equalTo(template.v2())); + assertThat(recordedRequest.getUri().getPath(), equalTo("/_template/" + template.v1())); + assertThat(recordedRequest.getUri().getQuery(), equalTo(resourceQueryString())); + assertThat(recordedRequest.getBody(), equalTo(template.v2())); } } assertMonitorPipelines(secondWebServer, !pipelineExistsAlready, null, null); assertMonitorBackwardsCompatibilityAliases(secondWebServer, false, null, null); assertBulk(secondWebServer); - } finally { - secondWebServer.shutdown(); } } @@ -282,7 +279,7 @@ public class HttpExporterIT extends MonitoringIntegTestCase { // fire off what should be an unsuccessful request assertNull(getExporter(agentNode).openBulk()); - assertThat(webServer.getRequestCount(), equalTo(1)); + assertThat(webServer.requests(), hasSize(1)); assertMonitorVersion(webServer); } @@ -307,12 +304,12 @@ public class HttpExporterIT extends MonitoringIntegTestCase { export(Collections.singletonList(doc)); assertMonitorResources(webServer, templatesExistsAlready, pipelineExistsAlready, bwcIndexesExist, bwcAliasesExist); - RecordedRequest recordedRequest = assertBulk(webServer); + MockRequest recordedRequest = assertBulk(webServer); @SuppressWarnings("unchecked") String indexName = new ResolversRegistry(Settings.EMPTY).getResolver(doc).index(doc); - byte[] bytes = recordedRequest.getBody().readByteArray(); + byte[] bytes = recordedRequest.getBody().getBytes(StandardCharsets.UTF_8); Map data = XContentHelper.convertToMap(new BytesArray(bytes), false).v2(); @SuppressWarnings("unchecked") Map index = (Map) data.get("index"); @@ -335,7 +332,7 @@ public class HttpExporterIT extends MonitoringIntegTestCase { assertMonitorResources(webServer, true, true, false, false); recordedRequest = assertBulk(webServer); - bytes = recordedRequest.getBody().readByteArray(); + bytes = recordedRequest.getBody().getBytes(StandardCharsets.UTF_8); data = XContentHelper.convertToMap(new BytesArray(bytes), false).v2(); @SuppressWarnings("unchecked") final Map newIndex = (Map) data.get("index"); @@ -348,11 +345,14 @@ public class HttpExporterIT extends MonitoringIntegTestCase { private void assertMonitorVersion(final MockWebServer webServer, @Nullable final Map customHeaders, @Nullable final String basePath) throws Exception { - final String pathPrefix = basePathToAssertablePrefix(basePath); - final RecordedRequest request = webServer.takeRequest(); + final MockRequest request = webServer.takeRequest(); assertThat(request.getMethod(), equalTo("GET")); - assertThat(request.getPath(), equalTo(pathPrefix + "/?filter_path=version.number")); + final String pathPrefix = basePathToAssertablePrefix(basePath); + if (Strings.isEmpty(pathPrefix) == false) { + assertThat(request.getUri().getPath(), equalTo(pathPrefix + "/")); + } + assertThat(request.getUri().getQuery(), equalTo("filter_path=version.number")); assertHeaders(request, customHeaders); } @@ -373,21 +373,23 @@ public class HttpExporterIT extends MonitoringIntegTestCase { private void assertMonitorTemplates(final MockWebServer webServer, final boolean alreadyExists, @Nullable final Map customHeaders, @Nullable final String basePath) throws Exception { final String pathPrefix = basePathToAssertablePrefix(basePath); - RecordedRequest request; + MockRequest request; for (Tuple template : monitoringTemplates()) { request = webServer.takeRequest(); assertThat(request.getMethod(), equalTo("GET")); - assertThat(request.getPath(), equalTo(pathPrefix + "/_template/" + template.v1() + resourceQueryString())); + assertThat(request.getUri().getPath(), equalTo(pathPrefix + "/_template/" + template.v1())); + assertThat(request.getUri().getQuery(), equalTo(resourceQueryString())); assertHeaders(request, customHeaders); if (alreadyExists == false) { request = webServer.takeRequest(); assertThat(request.getMethod(), equalTo("PUT")); - assertThat(request.getPath(), equalTo(pathPrefix + "/_template/" + template.v1() + resourceQueryString())); - assertThat(request.getBody().readUtf8(), equalTo(template.v2())); + assertThat(request.getUri().getPath(), equalTo(pathPrefix + "/_template/" + template.v1())); + assertThat(request.getUri().getQuery(), equalTo(resourceQueryString())); + assertThat(request.getBody(), equalTo(template.v2())); assertHeaders(request, customHeaders); } } @@ -396,19 +398,20 @@ public class HttpExporterIT extends MonitoringIntegTestCase { private void assertMonitorPipelines(final MockWebServer webServer, final boolean alreadyExists, @Nullable final Map customHeaders, @Nullable final String basePath) throws Exception { final String pathPrefix = basePathToAssertablePrefix(basePath); - RecordedRequest request = webServer.takeRequest(); + MockRequest request = webServer.takeRequest(); assertThat(request.getMethod(), equalTo("GET")); - assertThat(request.getPath(), equalTo(pathPrefix + "/_ingest/pipeline/" + Exporter.EXPORT_PIPELINE_NAME + resourceQueryString())); + assertThat(request.getUri().getPath(), equalTo(pathPrefix + "/_ingest/pipeline/" + Exporter.EXPORT_PIPELINE_NAME)); + assertThat(request.getUri().getQuery(), equalTo(resourceQueryString())); assertHeaders(request, customHeaders); if (alreadyExists == false) { request = webServer.takeRequest(); assertThat(request.getMethod(), equalTo("PUT")); - assertThat(request.getPath(), - equalTo(pathPrefix + "/_ingest/pipeline/" + Exporter.EXPORT_PIPELINE_NAME + resourceQueryString())); - assertThat(request.getBody().readUtf8(), equalTo(Exporter.emptyPipeline(XContentType.JSON).string())); + assertThat(request.getUri().getPath(), equalTo(pathPrefix + "/_ingest/pipeline/" + Exporter.EXPORT_PIPELINE_NAME)); + assertThat(request.getUri().getQuery(), equalTo(resourceQueryString())); + assertThat(request.getBody(), equalTo(Exporter.emptyPipeline(XContentType.JSON).string())); assertHeaders(request, customHeaders); } } @@ -416,40 +419,42 @@ public class HttpExporterIT extends MonitoringIntegTestCase { private void assertMonitorBackwardsCompatibilityAliases(final MockWebServer webServer, final boolean expectPost, @Nullable final Map customHeaders, @Nullable final String basePath) throws Exception { final String pathPrefix = basePathToAssertablePrefix(basePath); - RecordedRequest request = webServer.takeRequest(); + MockRequest request = webServer.takeRequest(); assertThat(request.getMethod(), equalTo("GET")); - assertThat(request.getPath(), startsWith(pathPrefix + "/.marvel-es-1-*")); - assertThat(request.getPath(), containsString("filter_path=*.aliases")); + assertThat(request.getUri().getPath(), startsWith(pathPrefix + "/.marvel-es-1-*")); + assertThat(request.getUri().getQuery(), containsString("filter_path=*.aliases")); assertHeaders(request, customHeaders); if (expectPost) { request = webServer.takeRequest(); assertThat(request.getMethod(), equalTo("POST")); - assertThat(request.getPath(), startsWith(pathPrefix + "/_aliases")); - assertThat(request.getPath(), containsString("master_timeout=30s")); - assertThat(request.getBody().readUtf8(), containsString("add")); + assertThat(request.getUri().getPath(), startsWith(pathPrefix + "/_aliases")); + assertThat(request.getUri().getQuery(), containsString("master_timeout=30s")); + assertThat(request.getBody(), containsString("add")); assertHeaders(request, customHeaders); } } - private RecordedRequest assertBulk(final MockWebServer webServer) throws Exception { + private MockRequest assertBulk(final MockWebServer webServer) throws Exception { return assertBulk(webServer, -1); } - private RecordedRequest assertBulk(final MockWebServer webServer, final int docs) throws Exception { + private MockRequest assertBulk(final MockWebServer webServer, final int docs) throws Exception { return assertBulk(webServer, docs, null, null); } - private RecordedRequest assertBulk(final MockWebServer webServer, final int docs, @Nullable final Map customHeaders, - @Nullable final String basePath) throws Exception { + private MockRequest assertBulk(final MockWebServer webServer, final int docs, + @Nullable final Map customHeaders, @Nullable final String basePath) + throws Exception { final String pathPrefix = basePathToAssertablePrefix(basePath); - final RecordedRequest request = webServer.takeRequest(); + final MockRequest request = webServer.takeRequest(); assertThat(request.getMethod(), equalTo("POST")); - assertThat(request.getPath(), equalTo(pathPrefix + "/_bulk" + bulkQueryString())); + assertThat(request.getUri().getPath(), equalTo(pathPrefix + "/_bulk")); + assertThat(request.getUri().getQuery(), equalTo(bulkQueryString())); assertHeaders(request, customHeaders); if (docs != -1) { @@ -459,16 +464,18 @@ public class HttpExporterIT extends MonitoringIntegTestCase { return request; } - private void assertHeaders(final RecordedRequest request, final Map customHeaders) { + private void assertHeaders(final MockRequest request, final Map customHeaders) { if (customHeaders != null) { for (final Map.Entry entry : customHeaders.entrySet()) { final String header = entry.getKey(); final String[] values = entry.getValue(); - final List headerValues = request.getHeaders().values(header); + final List headerValues = request.getHeaders().get(header); - assertThat(header, headerValues, hasSize(values.length)); - assertThat(header, headerValues, containsInAnyOrder(values)); + if (values.length > 0) { + assertThat(headerValues, hasSize(values.length)); + assertThat(headerValues, containsInAnyOrder(values)); + } } } } @@ -514,29 +521,20 @@ public class HttpExporterIT extends MonitoringIntegTestCase { return docs; } - private String basePathToAssertablePrefix(@Nullable final String basePath) { + private String basePathToAssertablePrefix(@Nullable String basePath) { if (basePath == null) { return ""; } - - return basePath.startsWith("/") == false ? "/" + basePath : basePath; + basePath = basePath.startsWith("/")? basePath : "/" + basePath; + return basePath; } private String resourceQueryString() { - return "?filter_path=" + urlEncode(FILTER_PATH_NONE); + return "filter_path=" + FILTER_PATH_NONE; } private String bulkQueryString() { - return "?pipeline=" + urlEncode(Exporter.EXPORT_PIPELINE_NAME) + "&filter_path=" + urlEncode("errors,items.*.error"); - } - - private String urlEncode(final String value) { - try { - return URLEncoder.encode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - // whelp, our JVM is broken - throw new RuntimeException(e); - } + return "pipeline=" + Exporter.EXPORT_PIPELINE_NAME + "&filter_path=" + "errors,items.*.error"; } private void enqueueGetClusterVersionResponse(Version v) throws IOException { @@ -544,8 +542,9 @@ public class HttpExporterIT extends MonitoringIntegTestCase { } private void enqueueGetClusterVersionResponse(MockWebServer mockWebServer, Version v) throws IOException { - mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody(jsonBuilder().startObject().startObject("version") - .field("number", v.toString()).endObject().endObject().bytes().utf8ToString())); + mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody( + jsonBuilder().startObject().startObject("version") + .field("number", v.toString()).endObject().endObject().bytes().utf8ToString())); } private void enqueueSetupResponses(MockWebServer webServer, boolean templatesAlreadyExists, boolean pipelineAlreadyExists, @@ -633,8 +632,8 @@ public class HttpExporterIT extends MonitoringIntegTestCase { mockWebServer.enqueue(new MockResponse().setResponseCode(responseCode).setBody(body)); } - private void assertBulkRequest(Buffer requestBody, int numberOfActions) throws Exception { - BulkRequest bulkRequest = Requests.bulkRequest().add(new BytesArray(requestBody.readByteArray()), null, null); + private void assertBulkRequest(String requestBody, int numberOfActions) throws Exception { + BulkRequest bulkRequest = Requests.bulkRequest().add(new BytesArray(requestBody.getBytes(StandardCharsets.UTF_8)), null, null); assertThat(bulkRequest.numberOfActions(), equalTo(numberOfActions)); for (DocWriteRequest actionRequest : bulkRequest.requests()) { assertThat(actionRequest, instanceOf(IndexRequest.class)); @@ -648,9 +647,6 @@ public class HttpExporterIT extends MonitoringIntegTestCase { private MockWebServer createMockWebServer() throws IOException { MockWebServer server = new MockWebServer(); server.start(); - final QueueDispatcher dispatcher = new QueueDispatcher(); - dispatcher.setFailFast(true); - server.setDispatcher(dispatcher); return server; } } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/ssl/TestsSSLService.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/ssl/TestsSSLService.java new file mode 100644 index 00000000000..7942d10c35e --- /dev/null +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/ssl/TestsSSLService.java @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.ssl; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; + +import javax.net.ssl.SSLContext; + +/** + * Extending SSLService to make helper methods public to access in tests + */ +public class TestsSSLService extends SSLService { + + public TestsSSLService(Settings settings, Environment environment) { + super(settings, environment); + } + + @Override + public SSLContext sslContext() { + return super.sslContext(); + } + + /** + * Allows to get alternative ssl context, like for the http client + */ + public SSLContext sslContext(Settings settings) { + return sslContextHolder(super.sslConfiguration(settings)).sslContext(); + } +} diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/email/EmailAttachmentTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/email/EmailAttachmentTests.java index 626d49aeae6..ce9e1ad580c 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/email/EmailAttachmentTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/email/EmailAttachmentTests.java @@ -5,14 +5,13 @@ */ package org.elasticsearch.xpack.watcher.actions.email; -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; -import com.squareup.okhttp.mockwebserver.QueueDispatcher; import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.Streams; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.common.http.HttpRequestTemplate; import org.elasticsearch.xpack.common.http.Scheme; import org.elasticsearch.xpack.notification.email.DataAttachment; @@ -61,7 +60,6 @@ import static org.hamcrest.Matchers.startsWith; public class EmailAttachmentTests extends AbstractWatcherIntegrationTestCase { private MockWebServer webServer = new MockWebServer(); - private QueueDispatcher dispatcher = new QueueDispatcher(); private MockResponse mockResponse = new MockResponse().setResponseCode(200) .addHeader("Content-Type", "application/foo").setBody("This is the content"); private EmailServer server; @@ -69,9 +67,6 @@ public class EmailAttachmentTests extends AbstractWatcherIntegrationTestCase { @Override public void setUp() throws Exception { super.setUp(); - - dispatcher.setFailFast(true); - webServer.setDispatcher(dispatcher); webServer.enqueue(mockResponse); webServer.start(); @@ -81,7 +76,7 @@ public class EmailAttachmentTests extends AbstractWatcherIntegrationTestCase { @After public void cleanup() throws Exception { server.stop(); - webServer.shutdown(); + webServer.close(); } @Override diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionTests.java index a942f138089..04abec30f95 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionTests.java @@ -5,8 +5,6 @@ */ package org.elasticsearch.xpack.watcher.actions.webhook; -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.ToXContent; @@ -15,12 +13,8 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.env.Environment; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.common.text.TextTemplateEngine; -import org.elasticsearch.xpack.ssl.SSLService; -import org.elasticsearch.xpack.watcher.actions.Action; -import org.elasticsearch.xpack.watcher.actions.Action.Result.Status; -import org.elasticsearch.xpack.watcher.execution.TriggeredExecutionContext; -import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.common.http.HttpClient; import org.elasticsearch.xpack.common.http.HttpMethod; import org.elasticsearch.xpack.common.http.HttpProxy; @@ -29,8 +23,18 @@ import org.elasticsearch.xpack.common.http.HttpRequestTemplate; import org.elasticsearch.xpack.common.http.HttpResponse; import org.elasticsearch.xpack.common.http.auth.HttpAuthRegistry; import org.elasticsearch.xpack.common.http.auth.basic.BasicAuthFactory; -import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy; import org.elasticsearch.xpack.common.text.TextTemplate; +import org.elasticsearch.xpack.common.text.TextTemplateEngine; +import org.elasticsearch.xpack.notification.email.Attachment; +import org.elasticsearch.xpack.notification.email.Authentication; +import org.elasticsearch.xpack.notification.email.Email; +import org.elasticsearch.xpack.notification.email.Profile; +import org.elasticsearch.xpack.ssl.SSLService; +import org.elasticsearch.xpack.watcher.actions.Action; +import org.elasticsearch.xpack.watcher.actions.Action.Result.Status; +import org.elasticsearch.xpack.watcher.execution.TriggeredExecutionContext; +import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext; +import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy; import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService; import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase; import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine; @@ -38,10 +42,6 @@ import org.elasticsearch.xpack.watcher.test.WatcherTestUtils; import org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTriggerEvent; import org.elasticsearch.xpack.watcher.watch.Payload; import org.elasticsearch.xpack.watcher.watch.Watch; -import org.elasticsearch.xpack.notification.email.Attachment; -import org.elasticsearch.xpack.notification.email.Authentication; -import org.elasticsearch.xpack.notification.email.Email; -import org.elasticsearch.xpack.notification.email.Profile; import org.hamcrest.Matchers; import org.joda.time.DateTime; import org.junit.Before; @@ -58,6 +58,7 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.hamcrest.core.Is.is; import static org.joda.time.DateTimeZone.UTC; @@ -225,8 +226,7 @@ public class WebhookActionTests extends ESTestCase { HttpClient httpClient = new HttpClient(Settings.EMPTY, authRegistry, new SSLService(environment.settings(), environment)); - MockWebServer proxyServer = new MockWebServer(); - try { + try (MockWebServer proxyServer = new MockWebServer()) { proxyServer.start(); proxyServer.enqueue(new MockResponse().setResponseCode(200).setBody("fullProxiedContent")); @@ -241,9 +241,7 @@ public class WebhookActionTests extends ESTestCase { new ScheduleTriggerEvent(watchId, new DateTime(UTC), new DateTime(UTC)), timeValueSeconds(5)); executable.execute("_id", ctx, new Payload.Simple()); - assertThat(proxyServer.getRequestCount(), is(1)); - } finally { - proxyServer.shutdown(); + assertThat(proxyServer.requests(), hasSize(1)); } } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java index 4d2ad15157a..a391e3f3b07 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java @@ -5,18 +5,17 @@ */ package org.elasticsearch.xpack.watcher.actions.webhook; -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; -import com.squareup.okhttp.mockwebserver.QueueDispatcher; -import com.squareup.okhttp.mockwebserver.RecordedRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.common.http.HttpRequestTemplate; import org.elasticsearch.xpack.common.http.Scheme; import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth; import org.elasticsearch.xpack.common.text.TextTemplate; -import org.elasticsearch.xpack.ssl.SSLService; +import org.elasticsearch.xpack.ssl.TestsSSLService; import org.elasticsearch.xpack.watcher.actions.ActionBuilders; import org.elasticsearch.xpack.watcher.condition.AlwaysCondition; import org.elasticsearch.xpack.watcher.history.WatchRecord; @@ -34,6 +33,7 @@ import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.xContentSour import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -53,20 +53,15 @@ public class WebhookHttpsIntegrationTests extends AbstractWatcherIntegrationTest @Before public void startWebservice() throws Exception { - webServer = new MockWebServer(); - webServer.setProtocolNegotiationEnabled(false); - QueueDispatcher dispatcher = new QueueDispatcher(); - dispatcher.setFailFast(true); - webServer.setDispatcher(dispatcher); - webServer.start(); - SSLService sslService = getInstanceFromMaster(SSLService.class); Settings settings = getInstanceFromMaster(Settings.class); - webServer.useHttps(sslService.sslSocketFactory(settings.getByPrefix("xpack.http.ssl.")), false); + TestsSSLService sslService = new TestsSSLService(settings, getInstanceFromMaster(Environment.class)); + webServer = new MockWebServer(sslService.sslContext(settings.getByPrefix("xpack.http.ssl.")), false); + webServer.start(); } @After public void stopWebservice() throws Exception { - webServer.shutdown(); + webServer.close(); } public void testHttps() throws Exception { @@ -90,9 +85,9 @@ public class WebhookHttpsIntegrationTests extends AbstractWatcherIntegrationTest } assertWatchWithMinimumPerformedActionsCount("_id", 1, false); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/test/_id")); - assertThat(recordedRequest.getBody().readUtf8Line(), equalTo("{key=value}")); + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getPath(), equalTo("/test/_id")); + assertThat(webServer.requests().get(0).getBody(), equalTo("{key=value}")); SearchResponse response = searchWatchRecords(b -> b.setQuery(QueryBuilders.termQuery(WatchRecord.Field.STATE.getPreferredName(), "executed"))); @@ -129,9 +124,9 @@ public class WebhookHttpsIntegrationTests extends AbstractWatcherIntegrationTest } assertWatchWithMinimumPerformedActionsCount("_id", 1, false); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/test/_id")); - assertThat(recordedRequest.getBody().readUtf8Line(), equalTo("{key=value}")); - assertThat(recordedRequest.getHeader("Authorization"), equalTo("Basic X3VzZXJuYW1lOl9wYXNzd29yZA==")); + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getPath(), equalTo("/test/_id")); + assertThat(webServer.requests().get(0).getBody(), equalTo("{key=value}")); + assertThat(webServer.requests().get(0).getHeader("Authorization"), equalTo("Basic X3VzZXJuYW1lOl9wYXNzd29yZA==")); } } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java index 4b073a8a2eb..2027c297f6f 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java @@ -5,13 +5,10 @@ */ package org.elasticsearch.xpack.watcher.actions.webhook; - -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; -import com.squareup.okhttp.mockwebserver.QueueDispatcher; -import com.squareup.okhttp.mockwebserver.RecordedRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.common.http.HttpRequestTemplate; import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth; import org.elasticsearch.xpack.common.text.TextTemplate; @@ -31,25 +28,22 @@ import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval; import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; public class WebhookIntegrationTests extends AbstractWatcherIntegrationTestCase { - private MockWebServer webServer; + private MockWebServer webServer = new MockWebServer();; @Before public void startWebservice() throws Exception { - webServer = new MockWebServer(); - QueueDispatcher dispatcher = new QueueDispatcher(); - dispatcher.setFailFast(true); - webServer.setDispatcher(dispatcher); webServer.start(); } @After public void stopWebservice() throws Exception { - webServer.shutdown(); + webServer.close(); } public void testWebhook() throws Exception { @@ -74,10 +68,12 @@ public class WebhookIntegrationTests extends AbstractWatcherIntegrationTestCase } assertWatchWithMinimumPerformedActionsCount("_id", 1, false); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), - anyOf(equalTo("/test/_id?watch_id=_id¶m1=value1"), equalTo("/test/_id?param1=value1&watch_id=_id"))); - assertThat(recordedRequest.getBody().readUtf8Line(), equalTo("_body")); + + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getQuery(), + anyOf(equalTo("watch_id=_id¶m1=value1"), equalTo("param1=value1&watch_id=_id"))); + + assertThat(webServer.requests().get(0).getBody(), is("_body")); SearchResponse response = searchWatchRecords(b -> QueryBuilders.termQuery(WatchRecord.Field.STATE.getPreferredName(), "executed")); @@ -114,10 +110,11 @@ public class WebhookIntegrationTests extends AbstractWatcherIntegrationTestCase } assertWatchWithMinimumPerformedActionsCount("_id", 1, false); - RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), - anyOf(equalTo("/test/_id?watch_id=_id¶m1=value1"), equalTo("/test/_id?param1=value1&watch_id=_id"))); - assertThat(recordedRequest.getBody().readUtf8Line(), equalTo("_body")); - assertThat(recordedRequest.getHeader("Authorization"), equalTo("Basic X3VzZXJuYW1lOl9wYXNzd29yZA==")); + + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getUri().getQuery(), + anyOf(equalTo("watch_id=_id¶m1=value1"), equalTo("param1=value1&watch_id=_id"))); + assertThat(webServer.requests().get(0).getBody(), is("_body")); + assertThat(webServer.requests().get(0).getHeader("Authorization"), is(("Basic X3VzZXJuYW1lOl9wYXNzd29yZA=="))); } } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/history/HistoryTemplateHttpMappingsTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/history/HistoryTemplateHttpMappingsTests.java index 38f119d2c3d..63cf9e34155 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/history/HistoryTemplateHttpMappingsTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/history/HistoryTemplateHttpMappingsTests.java @@ -5,12 +5,12 @@ */ package org.elasticsearch.xpack.watcher.history; -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; -import com.squareup.okhttp.mockwebserver.QueueDispatcher; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.search.aggregations.Aggregations; import org.elasticsearch.search.aggregations.bucket.terms.Terms; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; +import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.xpack.common.http.HttpRequestTemplate; import org.elasticsearch.xpack.watcher.condition.AlwaysCondition; import org.elasticsearch.xpack.watcher.execution.ExecutionState; @@ -26,6 +26,7 @@ import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBu import static org.elasticsearch.xpack.watcher.input.InputBuilders.httpInput; import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -35,20 +36,16 @@ import static org.hamcrest.Matchers.notNullValue; */ public class HistoryTemplateHttpMappingsTests extends AbstractWatcherIntegrationTestCase { - private MockWebServer webServer; + private MockWebServer webServer = new MockWebServer(); @Before public void init() throws Exception { - QueueDispatcher dispatcher = new QueueDispatcher(); - dispatcher.setFailFast(true); - webServer = new MockWebServer(); - webServer.setDispatcher(dispatcher); webServer.start(); } @After public void cleanup() throws Exception { - webServer.shutdown(); + webServer.close(); } @Override @@ -61,6 +58,7 @@ public class HistoryTemplateHttpMappingsTests extends AbstractWatcherIntegration return false; // remove security noise from this test } + @TestLogging("org.elasticsearch.test.http:TRACE") public void testHttpFields() throws Exception { PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id").setSource(watchBuilder() .trigger(schedule(interval("5s"))) @@ -72,6 +70,8 @@ public class HistoryTemplateHttpMappingsTests extends AbstractWatcherIntegration .get(); + // one for the input, one for the webhook + webServer.enqueue(new MockResponse().setResponseCode(200).setBody("{}")); webServer.enqueue(new MockResponse().setResponseCode(200).setBody("{}")); assertThat(putWatchResponse.isCreated(), is(true)); @@ -104,5 +104,9 @@ public class HistoryTemplateHttpMappingsTests extends AbstractWatcherIntegration assertThat(terms.getBuckets().size(), is(1)); assertThat(terms.getBucketByKey("/webhook/path"), notNullValue()); assertThat(terms.getBucketByKey("/webhook/path").getDocCount(), is(1L)); + + assertThat(webServer.requests(), hasSize(2)); + assertThat(webServer.requests().get(0).getUri().getPath(), is("/input/path")); + assertThat(webServer.requests().get(1).getUri().getPath(), is("/webhook/path")); } } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java index bf809080afa..83aabd7930b 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java @@ -5,12 +5,11 @@ */ package org.elasticsearch.xpack.watcher.test.integration; -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; -import com.squareup.okhttp.mockwebserver.RecordedRequest; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.support.XContentMapValues; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.common.http.HttpRequestTemplate; import org.elasticsearch.xpack.common.http.auth.basic.ApplicableBasicAuth; import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth; @@ -39,7 +38,7 @@ import static org.elasticsearch.xpack.watcher.input.InputBuilders.httpInput; import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput; import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.cron; -import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; @@ -52,18 +51,17 @@ public class HttpSecretsIntegrationTests extends AbstractWatcherIntegrationTestC static final String USERNAME = "_user"; static final String PASSWORD = "_passwd"; - private MockWebServer webServer; + private MockWebServer webServer = new MockWebServer();; private static Boolean encryptSensitiveData; @Before public void init() throws Exception { - webServer = new MockWebServer(); webServer.start(); } @After public void cleanup() throws Exception { - webServer.shutdown(); + webServer.close(); } @Override @@ -139,8 +137,9 @@ public class HttpSecretsIntegrationTests extends AbstractWatcherIntegrationTestC assertThat(value, notNullValue()); assertThat(value, is((Object) 200)); - RecordedRequest request = webServer.takeRequest(); - assertThat(request.getHeader("Authorization"), equalTo(ApplicableBasicAuth.headerValue(USERNAME, PASSWORD.toCharArray()))); + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getHeader("Authorization"), + is(ApplicableBasicAuth.headerValue(USERNAME, PASSWORD.toCharArray()))); } public void testWebhookAction() throws Exception { @@ -216,7 +215,8 @@ public class HttpSecretsIntegrationTests extends AbstractWatcherIntegrationTestC value = contentSource.getValue("result.actions.0.webhook.request.auth.basic.password"); assertThat(value, nullValue()); // but the auth password was filtered out - RecordedRequest request = webServer.takeRequest(); - assertThat(request.getHeader("Authorization"), equalTo(ApplicableBasicAuth.headerValue(USERNAME, PASSWORD.toCharArray()))); + assertThat(webServer.requests(), hasSize(1)); + assertThat(webServer.requests().get(0).getHeader("Authorization"), + is(ApplicableBasicAuth.headerValue(USERNAME, PASSWORD.toCharArray()))); } } diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/transport/action/delete/DeleteWatchTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/transport/action/delete/DeleteWatchTests.java index 83c5dbd3161..5a20e3a5c51 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/transport/action/delete/DeleteWatchTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/watcher/transport/action/delete/DeleteWatchTests.java @@ -5,10 +5,11 @@ */ package org.elasticsearch.xpack.watcher.transport.action.delete; -import com.squareup.okhttp.mockwebserver.MockResponse; -import com.squareup.okhttp.mockwebserver.MockWebServer; import org.elasticsearch.action.ListenableActionFuture; import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.test.http.MockResponse; +import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.common.http.HttpRequestTemplate; import org.elasticsearch.xpack.watcher.condition.AlwaysCondition; import org.elasticsearch.xpack.watcher.history.HistoryStore; @@ -21,7 +22,6 @@ import org.elasticsearch.xpack.watcher.transport.actions.get.GetWatchResponse; import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchResponse; import java.util.Map; -import java.util.concurrent.TimeUnit; import static com.carrotsearch.randomizedtesting.RandomizedTest.sleep; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; @@ -76,12 +76,10 @@ public class DeleteWatchTests extends AbstractWatcherIntegrationTestCase { MockResponse response = new MockResponse(); response.setBody("foo"); response.setResponseCode(200); - response.setBodyDelay(5, TimeUnit.SECONDS); + response.setBodyDelay(TimeValue.timeValueSeconds(5)); - MockWebServer server = new MockWebServer(); - server.enqueue(response); - - try { + try (MockWebServer server = new MockWebServer()) { + server.enqueue(response); server.start(); HttpRequestTemplate template = HttpRequestTemplate.builder(server.getHostName(), server.getPort()).path("/").build(); @@ -119,8 +117,6 @@ public class DeleteWatchTests extends AbstractWatcherIntegrationTestCase { assertThat(state, is("executed")); // no exception occured assertThat(source, not(hasKey("exception"))); - } finally { - server.shutdown(); } } }