diff --git a/docs/src/test/java/org/elasticsearch/smoketest/DocsClientYamlTestSuiteIT.java b/docs/src/test/java/org/elasticsearch/smoketest/DocsClientYamlTestSuiteIT.java index a79730339e3..628c364d455 100644 --- a/docs/src/test/java/org/elasticsearch/smoketest/DocsClientYamlTestSuiteIT.java +++ b/docs/src/test/java/org/elasticsearch/smoketest/DocsClientYamlTestSuiteIT.java @@ -48,5 +48,10 @@ public class DocsClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { logger.error("This failing test was generated by documentation starting at {}. It may include many snippets. " + "See docs/README.asciidoc for an explanation of test generation.", name); } + + @Override + protected boolean randomizeContentType() { + return false; + } } diff --git a/qa/backwards-5.0/src/test/java/org/elasticsearch/backwards/Backwards50ClientYamlTestSuiteIT.java b/qa/backwards-5.0/src/test/java/org/elasticsearch/backwards/Backwards50ClientYamlTestSuiteIT.java index cac063fce78..f6cb67f92fb 100644 --- a/qa/backwards-5.0/src/test/java/org/elasticsearch/backwards/Backwards50ClientYamlTestSuiteIT.java +++ b/qa/backwards-5.0/src/test/java/org/elasticsearch/backwards/Backwards50ClientYamlTestSuiteIT.java @@ -39,5 +39,10 @@ public class Backwards50ClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase public static Iterable parameters() throws IOException { return createParameters(); } + + @Override + protected boolean randomizeContentType() { + return false; + } } diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ClientYamlTestExecutionContext.java b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ClientYamlTestExecutionContext.java index fe397f512c5..a2e03a063cf 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ClientYamlTestExecutionContext.java +++ b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ClientYamlTestExecutionContext.java @@ -18,15 +18,21 @@ */ package org.elasticsearch.test.rest.yaml; +import com.carrotsearch.randomizedtesting.RandomizedTest; import org.apache.http.HttpEntity; +import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; import org.apache.logging.log4j.Logger; +import org.apache.lucene.util.BytesRef; import org.elasticsearch.Version; import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -41,13 +47,18 @@ public class ClientYamlTestExecutionContext { private static final Logger logger = Loggers.getLogger(ClientYamlTestExecutionContext.class); + private static final XContentType[] STREAMING_CONTENT_TYPES = new XContentType[]{XContentType.JSON, XContentType.SMILE}; + private final Stash stash = new Stash(); private final ClientYamlTestClient clientYamlTestClient; private ClientYamlTestResponse response; - public ClientYamlTestExecutionContext(ClientYamlTestClient clientYamlTestClient) { + private final boolean randomizeContentType; + + public ClientYamlTestExecutionContext(ClientYamlTestClient clientYamlTestClient, boolean randomizeContentType) { this.clientYamlTestClient = clientYamlTestClient; + this.randomizeContentType = randomizeContentType; } /** @@ -65,7 +76,7 @@ public class ClientYamlTestExecutionContext { } } - HttpEntity entity = createEntity(bodies); + HttpEntity entity = createEntity(bodies, headers); try { response = callApiInternal(apiName, requestParams, entity, headers); return response; @@ -80,23 +91,56 @@ public class ClientYamlTestExecutionContext { } } - private HttpEntity createEntity(List> bodies) throws IOException { + private HttpEntity createEntity(List> bodies, Map headers) throws IOException { if (bodies.isEmpty()) { return null; } if (bodies.size() == 1) { - String bodyAsString = bodyAsString(stash.replaceStashedValues(bodies.get(0))); - return new StringEntity(bodyAsString, ContentType.APPLICATION_JSON); + XContentType xContentType = getContentType(headers, XContentType.values()); + BytesRef bytesRef = bodyAsBytesRef(bodies.get(0), xContentType); + return new ByteArrayEntity(bytesRef.bytes, bytesRef.offset, bytesRef.length, + ContentType.create(xContentType.mediaTypeWithoutParameters(), StandardCharsets.UTF_8)); + } else { + XContentType xContentType = getContentType(headers, STREAMING_CONTENT_TYPES); + List bytesRefList = new ArrayList<>(); + int totalBytesLength = 0; + for (Map body : bodies) { + BytesRef bytesRef = bodyAsBytesRef(body, xContentType); + bytesRefList.add(bytesRef); + totalBytesLength += bytesRef.length - bytesRef.offset + 1; + } + byte[] bytes = new byte[totalBytesLength]; + int position = 0; + for (BytesRef bytesRef : bytesRefList) { + for (int i = bytesRef.offset; i < bytesRef.length; i++) { + bytes[position++] = bytesRef.bytes[i]; + } + bytes[position++] = xContentType.xContent().streamSeparator(); + } + return new ByteArrayEntity(bytes, ContentType.create(xContentType.mediaTypeWithoutParameters(), StandardCharsets.UTF_8)); } - StringBuilder bodyBuilder = new StringBuilder(); - for (Map body : bodies) { - bodyBuilder.append(bodyAsString(stash.replaceStashedValues(body))).append("\n"); - } - return new StringEntity(bodyBuilder.toString(), ContentType.APPLICATION_JSON); } - private String bodyAsString(Map body) throws IOException { - return XContentFactory.jsonBuilder().map(body).string(); + private XContentType getContentType(Map headers, XContentType[] supportedContentTypes) { + XContentType xContentType = null; + String contentType = headers.get("Content-Type"); + if (contentType != null) { + xContentType = XContentType.fromMediaType(contentType); + } + if (xContentType != null) { + return xContentType; + } + if (randomizeContentType) { + return RandomizedTest.randomFrom(supportedContentTypes); + } + return XContentType.JSON; + } + + private BytesRef bodyAsBytesRef(Map bodyAsMap, XContentType xContentType) throws IOException { + Map finalBodyAsMap = stash.replaceStashedValues(bodyAsMap); + try (XContentBuilder builder = XContentFactory.contentBuilder(xContentType)) { + return builder.map(finalBodyAsMap).bytes().toBytesRef(); + } } private ClientYamlTestResponse callApiInternal(String apiName, Map params, diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java index b64f12e9f02..32436515fe8 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java @@ -145,8 +145,8 @@ public abstract class ESClientYamlSuiteTestCase extends ESRestTestCase { } ClientYamlTestClient clientYamlTestClient = new ClientYamlTestClient(restSpec, restClient, hosts, esVersion); - restTestExecutionContext = new ClientYamlTestExecutionContext(clientYamlTestClient); - adminExecutionContext = new ClientYamlTestExecutionContext(clientYamlTestClient); + restTestExecutionContext = new ClientYamlTestExecutionContext(clientYamlTestClient, randomizeContentType()); + adminExecutionContext = new ClientYamlTestExecutionContext(clientYamlTestClient, false); String[] blacklist = resolvePathsProperty(REST_TESTS_BLACKLIST, null); blacklistPathMatchers = new ArrayList<>(); for (String entry : blacklist) { @@ -381,4 +381,8 @@ public abstract class ESClientYamlSuiteTestCase extends ESRestTestCase { private String errorMessage(ExecutableSection executableSection, Throwable t) { return "Failure at [" + testCandidate.getSuitePath() + ":" + executableSection.getLocation().lineNumber + "]: " + t.getMessage(); } + + protected boolean randomizeContentType() { + return true; + } }