diff --git a/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java b/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java index 2f94de7154c..8f4170add3d 100644 --- a/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java +++ b/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java @@ -40,7 +40,6 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -50,7 +49,6 @@ import static org.elasticsearch.client.RestClientTestUtil.getAllStatusCodes; import static org.elasticsearch.client.RestClientTestUtil.getHttpMethods; import static org.elasticsearch.client.RestClientTestUtil.randomStatusCode; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** @@ -77,8 +75,7 @@ public class RestClientSingleHostIntegTests extends RestClientTestCase { } httpServer = createHttpServer(); - int numHeaders = randomIntBetween(0, 5); - defaultHeaders = generateHeaders("Header-default", "Header-array", numHeaders); + defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); RestClientBuilder restClientBuilder = RestClient.builder( new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())).setDefaultHeaders(defaultHeaders); if (pathPrefix.length() > 0) { @@ -151,17 +148,11 @@ public class RestClientSingleHostIntegTests extends RestClientTestCase { if (method.equals("HEAD") == false) { standardHeaders.add("Content-length"); } - - final int numHeaders = randomIntBetween(1, 5); - final Header[] headers = generateHeaders("Header", "Header-array", numHeaders); - final Map> expectedHeaders = new HashMap<>(); - - addHeaders(expectedHeaders, defaultHeaders, headers); - + final Header[] requestHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header"); final int statusCode = randomStatusCode(getRandom()); Response esResponse; try { - esResponse = restClient.performRequest(method, "/" + statusCode, Collections.emptyMap(), headers); + esResponse = restClient.performRequest(method, "/" + statusCode, Collections.emptyMap(), requestHeaders); } catch(ResponseException e) { esResponse = e.getResponse(); } @@ -169,24 +160,13 @@ public class RestClientSingleHostIntegTests extends RestClientTestCase { assertEquals(method, esResponse.getRequestLine().getMethod()); assertEquals(statusCode, esResponse.getStatusLine().getStatusCode()); assertEquals((pathPrefix.length() > 0 ? pathPrefix : "") + "/" + statusCode, esResponse.getRequestLine().getUri()); - + assertHeaders(defaultHeaders, requestHeaders, esResponse.getHeaders(), standardHeaders); for (final Header responseHeader : esResponse.getHeaders()) { - final String name = responseHeader.getName(); - final String value = responseHeader.getValue(); - if (name.startsWith("Header")) { - final List values = expectedHeaders.get(name); - assertNotNull("found response header [" + name + "] that wasn't originally sent: " + value, values); - assertTrue("found incorrect response header [" + name + "]: " + value, values.remove(value)); - - // we've collected them all - if (values.isEmpty()) { - expectedHeaders.remove(name); - } - } else { + String name = responseHeader.getName(); + if (name.startsWith("Header") == false) { assertTrue("unknown header was returned " + name, standardHeaders.remove(name)); } } - assertTrue("some headers that were sent weren't returned: " + expectedHeaders, expectedHeaders.isEmpty()); assertTrue("some expected standard headers weren't returned: " + standardHeaders, standardHeaders.isEmpty()); } } diff --git a/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java b/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java index ce0d6d0936e..865f9b1817a 100644 --- a/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java +++ b/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java @@ -56,7 +56,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Future; @@ -70,7 +69,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -131,9 +129,7 @@ public class RestClientSingleHostTests extends RestClientTestCase { } }); - - int numHeaders = randomIntBetween(0, 3); - defaultHeaders = generateHeaders("Header-default", "Header-array", numHeaders); + defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); httpHost = new HttpHost("localhost", 9200); failureListener = new HostsTrackingFailureListener(); restClient = new RestClient(httpClient, 10000, defaultHeaders, new HttpHost[]{httpHost}, null, failureListener); @@ -339,33 +335,16 @@ public class RestClientSingleHostTests extends RestClientTestCase { */ public void testHeaders() throws IOException { for (String method : getHttpMethods()) { - final int numHeaders = randomIntBetween(1, 5); - final Header[] headers = generateHeaders("Header", null, numHeaders); - final Map> expectedHeaders = new HashMap<>(); - - addHeaders(expectedHeaders, defaultHeaders, headers); - + final Header[] requestHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header"); final int statusCode = randomStatusCode(getRandom()); Response esResponse; try { - esResponse = restClient.performRequest(method, "/" + statusCode, headers); + esResponse = restClient.performRequest(method, "/" + statusCode, requestHeaders); } catch(ResponseException e) { esResponse = e.getResponse(); } assertThat(esResponse.getStatusLine().getStatusCode(), equalTo(statusCode)); - for (Header responseHeader : esResponse.getHeaders()) { - final String name = responseHeader.getName(); - final String value = responseHeader.getValue(); - final List values = expectedHeaders.get(name); - assertNotNull("found response header [" + name + "] that wasn't originally sent: " + value, values); - assertTrue("found incorrect response header [" + name + "]: " + value, values.remove(value)); - - // we've collected them all - if (values.isEmpty()) { - expectedHeaders.remove(name); - } - } - assertTrue("some headers that were sent weren't returned " + expectedHeaders, expectedHeaders.isEmpty()); + assertHeaders(defaultHeaders, requestHeaders, esResponse.getHeaders(), Collections.emptySet()); } } @@ -424,10 +403,9 @@ public class RestClientSingleHostTests extends RestClientTestCase { } Header[] headers = new Header[0]; - final int numHeaders = randomIntBetween(1, 5); - final Set uniqueNames = new HashSet<>(numHeaders); + final Set uniqueNames = new HashSet<>(); if (randomBoolean()) { - headers = generateHeaders("Header", "Header-array", numHeaders); + headers = RestClientTestUtil.randomHeaders(getRandom(), "Header"); for (Header header : headers) { request.addHeader(header); uniqueNames.add(header.getName()); diff --git a/client/test/src/main/java/org/elasticsearch/client/RestClientTestCase.java b/client/test/src/main/java/org/elasticsearch/client/RestClientTestCase.java index 4296932a002..6a2a45ef281 100644 --- a/client/test/src/main/java/org/elasticsearch/client/RestClientTestCase.java +++ b/client/test/src/main/java/org/elasticsearch/client/RestClientTestCase.java @@ -30,16 +30,19 @@ import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; - import org.apache.http.Header; -import org.apache.http.message.BasicHeader; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + @TestMethodProviders({ JUnit3MethodProvider.class }) @@ -53,70 +56,56 @@ import java.util.Set; public abstract class RestClientTestCase extends RandomizedTest { /** - * Create the specified number of {@link Header}s. - *

- * Generated header names will be the {@code baseName} plus its index or, rarely, the {@code arrayName} if it's supplied. + * Assert that the actual headers are the expected ones given the original default and request headers. Some headers can be ignored, + * for instance in case the http client is adding its own automatically. * - * @param baseName The base name to use for all headers. - * @param arrayName The optional ({@code null}able) array name to use randomly. - * @param headers The number of headers to create. - * @return Never {@code null}. + * @param defaultHeaders the default headers set to the REST client instance + * @param requestHeaders the request headers sent with a particular request + * @param actualHeaders the actual headers as a result of the provided default and request headers + * @param ignoreHeaders header keys to be ignored as they are not part of default nor request headers, yet they + * will be part of the actual ones */ - protected static Header[] generateHeaders(final String baseName, final String arrayName, final int headers) { - final Header[] generated = new Header[headers]; - for (int i = 0; i < headers; i++) { - String headerName = baseName + i; - if (arrayName != null && rarely()) { - headerName = arrayName; - } - - generated[i] = new BasicHeader(headerName, randomAsciiOfLengthBetween(3, 10)); + protected static void assertHeaders(final Header[] defaultHeaders, final Header[] requestHeaders, + final Header[] actualHeaders, final Set ignoreHeaders) { + final Map> expectedHeaders = new HashMap<>(); + final Set requestHeaderKeys = new HashSet<>(); + for (final Header header : requestHeaders) { + final String name = header.getName(); + addValueToListEntry(expectedHeaders, name, header.getValue()); + requestHeaderKeys.add(name); } - return generated; + for (final Header defaultHeader : defaultHeaders) { + final String name = defaultHeader.getName(); + if (requestHeaderKeys.contains(name) == false) { + addValueToListEntry(expectedHeaders, name, defaultHeader.getValue()); + } + } + Set actualIgnoredHeaders = new HashSet<>(); + for (Header responseHeader : actualHeaders) { + final String name = responseHeader.getName(); + if (ignoreHeaders.contains(name)) { + expectedHeaders.remove(name); + actualIgnoredHeaders.add(name); + continue; + } + final String value = responseHeader.getValue(); + final List values = expectedHeaders.get(name); + assertNotNull("found response header [" + name + "] that wasn't originally sent: " + value, values); + assertTrue("found incorrect response header [" + name + "]: " + value, values.remove(value)); + if (values.isEmpty()) { + expectedHeaders.remove(name); + } + } + assertEquals("some headers meant to be ignored were not part of the actual headers", ignoreHeaders, actualIgnoredHeaders); + assertTrue("some headers that were sent weren't returned " + expectedHeaders, expectedHeaders.isEmpty()); } - /** - * Create a new {@link List} within the {@code map} if none exists for {@code name} or append to the existing list. - * - * @param map The map to manipulate. - * @param name The name to create/append the list for. - * @param value The value to add. - */ - private static void createOrAppendList(final Map> map, final String name, final String value) { + private static void addValueToListEntry(final Map> map, final String name, final String value) { List values = map.get(name); - if (values == null) { values = new ArrayList<>(); map.put(name, values); } - values.add(value); } - - /** - * Add the {@code headers} to the {@code map} so that related tests can more easily assert that they exist. - *

- * If both the {@code defaultHeaders} and {@code headers} contain the same {@link Header}, based on its - * {@linkplain Header#getName() name}, then this will only use the {@code Header}(s) from {@code headers}. - * - * @param map The map to build with name/value(s) pairs. - * @param defaultHeaders The headers to add to the map representing default headers. - * @param headers The headers to add to the map representing request-level headers. - * @see #createOrAppendList(Map, String, String) - */ - protected static void addHeaders(final Map> map, final Header[] defaultHeaders, final Header[] headers) { - final Set uniqueHeaders = new HashSet<>(); - for (final Header header : headers) { - final String name = header.getName(); - createOrAppendList(map, name, header.getValue()); - uniqueHeaders.add(name); - } - for (final Header defaultHeader : defaultHeaders) { - final String name = defaultHeader.getName(); - if (uniqueHeaders.contains(name) == false) { - createOrAppendList(map, name, defaultHeader.getValue()); - } - } - } - } diff --git a/client/test/src/main/java/org/elasticsearch/client/RestClientTestUtil.java b/client/test/src/main/java/org/elasticsearch/client/RestClientTestUtil.java index 4d4aa00f492..dbf85578b19 100644 --- a/client/test/src/main/java/org/elasticsearch/client/RestClientTestUtil.java +++ b/client/test/src/main/java/org/elasticsearch/client/RestClientTestUtil.java @@ -19,7 +19,11 @@ package org.elasticsearch.client; +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; import com.carrotsearch.randomizedtesting.generators.RandomPicks; +import com.carrotsearch.randomizedtesting.generators.RandomStrings; +import org.apache.http.Header; +import org.apache.http.message.BasicHeader; import java.util.ArrayList; import java.util.Arrays; @@ -81,4 +85,23 @@ final class RestClientTestUtil { static List getAllStatusCodes() { return ALL_STATUS_CODES; } + + /** + * Create a random number of {@link Header}s. + * Generated header names will either be the {@code baseName} plus its index, or exactly the provided {@code baseName} so that the + * we test also support for multiple headers with same key and different values. + */ + static Header[] randomHeaders(Random random, final String baseName) { + int numHeaders = RandomNumbers.randomIntBetween(random, 0, 5); + final Header[] headers = new Header[numHeaders]; + for (int i = 0; i < numHeaders; i++) { + String headerName = baseName; + //randomly exercise the code path that supports multiple headers with same key + if (random.nextBoolean()) { + headerName = headerName + i; + } + headers[i] = new BasicHeader(headerName, RandomStrings.randomAsciiOfLengthBetween(random, 3, 10)); + } + return headers; + } }