[TEST] add support for binary responses to REST tests infra

This commit is contained in:
javanna 2017-02-17 22:38:10 +01:00 committed by Luca Cavanna
parent 2f6a6090b8
commit 9a2dba3036
5 changed files with 69 additions and 52 deletions

View File

@ -19,20 +19,17 @@
package org.elasticsearch.rest;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.http.HttpTransportSettings;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.yaml.ObjectPath;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
@ -46,10 +43,7 @@ public class Netty4BadRequestIT extends ESRestTestCase {
public void testBadRequest() throws IOException {
final Response response = client().performRequest("GET", "/_nodes/settings", Collections.emptyMap());
final String body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
final String contentType = response.getHeader("Content-Type");
final XContentType xContentType = XContentType.fromMediaTypeOrFormat(contentType);
final ObjectPath objectPath = ObjectPath.createFromXContent(xContentType.xContent(), body);
final ObjectPath objectPath = ObjectPath.createFromResponse(response);
final Map<String, Object> map = objectPath.evaluate("nodes");
int maxMaxInitialLineLength = Integer.MIN_VALUE;
final Setting<ByteSizeValue> httpMaxInitialLineLength = HttpTransportSettings.SETTING_HTTP_MAX_INITIAL_LINE_LENGTH;
@ -80,5 +74,4 @@ public class Netty4BadRequestIT extends ESRestTestCase {
assertThat(e, hasToString(containsString("too_long_frame_exception")));
assertThat(e, hasToString(matches("An HTTP line is larger than \\d+ bytes")));
}
}

View File

@ -21,14 +21,12 @@ package org.elasticsearch.backwards;
import org.apache.http.HttpHost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.Version;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.seqno.SeqNoStats;
import org.elasticsearch.index.seqno.SequenceNumbersService;
@ -36,7 +34,6 @@ import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.yaml.ObjectPath;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -51,13 +48,6 @@ import static org.hamcrest.Matchers.equalTo;
public class IndexingIT extends ESRestTestCase {
private ObjectPath objectPath(Response response) throws IOException {
String body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
String contentType = response.getHeader("Content-Type");
XContentType xContentType = XContentType.fromMediaTypeOrFormat(contentType);
return ObjectPath.createFromXContent(xContentType.xContent(), body);
}
private void assertOK(Response response) {
assertThat(response.getStatusLine().getStatusCode(), anyOf(equalTo(200), equalTo(201)));
}
@ -272,7 +262,7 @@ public class IndexingIT extends ESRestTestCase {
private void assertCount(final String index, final String preference, final int expectedCount) throws IOException {
final Response response = client().performRequest("GET", index + "/_count", Collections.singletonMap("preference", preference));
assertOK(response);
final int actualCount = Integer.parseInt(objectPath(response).evaluate("count").toString());
final int actualCount = Integer.parseInt(ObjectPath.createFromResponse(response).evaluate("count").toString());
assertThat(actualCount, equalTo(expectedCount));
}
@ -280,7 +270,7 @@ public class IndexingIT extends ESRestTestCase {
final Response response = client().performRequest("GET", index + "/test/" + docId,
Collections.singletonMap("preference", preference));
assertOK(response);
final int actualVersion = Integer.parseInt(objectPath(response).evaluate("_version").toString());
final int actualVersion = Integer.parseInt(ObjectPath.createFromResponse(response).evaluate("_version").toString());
assertThat("version mismatch for doc [" + docId + "] preference [" + preference + "]", actualVersion, equalTo(expectedVersion));
}
@ -323,7 +313,7 @@ public class IndexingIT extends ESRestTestCase {
private List<Shard> buildShards(Nodes nodes, RestClient client) throws IOException {
Response response = client.performRequest("GET", "test/_stats", singletonMap("level", "shards"));
List<Object> shardStats = objectPath(response).evaluate("indices.test.shards.0");
List<Object> shardStats = ObjectPath.createFromResponse(response).evaluate("indices.test.shards.0");
ArrayList<Shard> shards = new ArrayList<>();
for (Object shard : shardStats) {
final String nodeId = ObjectPath.evaluate(shard, "routing.node");
@ -345,7 +335,7 @@ public class IndexingIT extends ESRestTestCase {
private Nodes buildNodeAndVersions() throws IOException {
Response response = client().performRequest("GET", "_nodes");
ObjectPath objectPath = objectPath(response);
ObjectPath objectPath = ObjectPath.createFromResponse(response);
Map<String, Object> nodesAsMap = objectPath.evaluate("nodes");
Nodes nodes = new Nodes();
for (String id : nodesAsMap.keySet()) {
@ -356,7 +346,7 @@ public class IndexingIT extends ESRestTestCase {
HttpHost.create(objectPath.evaluate("nodes." + id + ".http.publish_address"))));
}
response = client().performRequest("GET", "_cluster/state");
nodes.setMasterNodeId(objectPath(response).evaluate("master_node"));
nodes.setMasterNodeId(ObjectPath.createFromResponse(response).evaluate("master_node"));
return nodes;
}

View File

@ -22,9 +22,15 @@ import org.apache.http.Header;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Response;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@ -36,32 +42,30 @@ import java.util.List;
public class ClientYamlTestResponse {
private final Response response;
private final String body;
private final byte[] body;
private final XContentType bodyContentType;
private ObjectPath parsedResponse;
private String bodyAsString;
ClientYamlTestResponse(Response response) throws IOException {
this.response = response;
if (response.getEntity() != null) {
String contentType = response.getHeader("Content-Type");
this.bodyContentType = XContentType.fromMediaTypeOrFormat(contentType);
try {
this.body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
byte[] bytes = EntityUtils.toByteArray(response.getEntity());
//skip parsing if we got text back (e.g. if we called _cat apis)
if (bodyContentType != null) {
this.parsedResponse = ObjectPath.createFromXContent(bodyContentType.xContent(), new BytesArray(bytes));
}
this.body = bytes;
} catch (IOException e) {
EntityUtils.consumeQuietly(response.getEntity());
throw new RuntimeException(e);
throw e;
}
} else {
this.body = null;
}
parseResponseBody();
}
private void parseResponseBody() throws IOException {
if (body != null) {
String contentType = response.getHeader("Content-Type");
XContentType xContentType = XContentType.fromMediaTypeOrFormat(contentType);
//skip parsing if we got text back (e.g. if we called _cat apis)
if (xContentType == XContentType.JSON || xContentType == XContentType.YAML) {
this.parsedResponse = ObjectPath.createFromXContent(xContentType.xContent(), body);
}
this.bodyContentType = null;
}
}
@ -94,14 +98,32 @@ public class ClientYamlTestResponse {
if (parsedResponse != null) {
return parsedResponse.evaluate("");
}
return body;
//we only get here if there is no response body or the body is text
assert bodyContentType == null;
return getBodyAsString();
}
/**
* Returns the body as a string
*/
public String getBodyAsString() {
return body;
if (bodyAsString == null && body != null) {
//content-type null means that text was returned
if (bodyContentType == null || bodyContentType == XContentType.JSON || bodyContentType == XContentType.YAML) {
bodyAsString = new String(body, StandardCharsets.UTF_8);
} else {
//if the body is in a binary format and gets requested as a string (e.g. to log a test failure), we convert it to json
try (XContentBuilder jsonBuilder = XContentFactory.jsonBuilder()) {
try (XContentParser parser = bodyContentType.xContent().createParser(NamedXContentRegistry.EMPTY, body)) {
jsonBuilder.copyCurrentStructure(parser);
}
bodyAsString = jsonBuilder.string();
} catch (IOException e) {
throw new UncheckedIOException("unable to convert response body to a string format", e);
}
}
}
return bodyAsString;
}
public boolean isError() {

View File

@ -18,9 +18,14 @@
*/
package org.elasticsearch.test.rest.yaml;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Response;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContent;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;
import java.util.ArrayList;
@ -34,7 +39,14 @@ public class ObjectPath {
private final Object object;
public static ObjectPath createFromXContent(XContent xContent, String input) throws IOException {
public static ObjectPath createFromResponse(Response response) throws IOException {
byte[] bytes = EntityUtils.toByteArray(response.getEntity());
String contentType = response.getHeader("Content-Type");
XContentType xContentType = XContentType.fromMediaTypeOrFormat(contentType);
return ObjectPath.createFromXContent(xContentType.xContent(), new BytesArray(bytes));
}
public static ObjectPath createFromXContent(XContent xContent, BytesReference input) throws IOException {
try (XContentParser parser = xContent.createParser(NamedXContentRegistry.EMPTY, input)) {
if (parser.nextToken() == XContentParser.Token.START_ARRAY) {
return new ObjectPath(parser.listOrderedMap());

View File

@ -39,8 +39,7 @@ import static org.hamcrest.Matchers.nullValue;
public class ObjectPathTests extends ESTestCase {
private static XContentBuilder randomXContentBuilder() throws IOException {
//only string based formats are supported, no cbor nor smile
XContentType xContentType = randomFrom(XContentType.JSON, XContentType.YAML);
XContentType xContentType = randomFrom(XContentType.values());
return XContentBuilder.builder(XContentFactory.xContent(xContentType));
}
@ -51,7 +50,7 @@ public class ObjectPathTests extends ESTestCase {
xContentBuilder.field("field2.field3", "value2");
xContentBuilder.endObject();
xContentBuilder.endObject();
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.string());
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.bytes());
Object object = objectPath.evaluate("field1.field2\\.field3");
assertThat(object, instanceOf(String.class));
assertThat(object, equalTo("value2"));
@ -64,7 +63,7 @@ public class ObjectPathTests extends ESTestCase {
xContentBuilder.field("field2", "value2");
xContentBuilder.endObject();
xContentBuilder.endObject();
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.string());
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.bytes());
Object object = objectPath.evaluate("field1..field2");
assertThat(object, instanceOf(String.class));
assertThat(object, equalTo("value2"));
@ -83,7 +82,7 @@ public class ObjectPathTests extends ESTestCase {
xContentBuilder.field("field2", 333);
xContentBuilder.endObject();
xContentBuilder.endObject();
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.string());
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.bytes());
Object object = objectPath.evaluate("field1.field2");
assertThat(object, instanceOf(Integer.class));
assertThat(object, equalTo(333));
@ -96,7 +95,7 @@ public class ObjectPathTests extends ESTestCase {
xContentBuilder.field("field2", 3.55);
xContentBuilder.endObject();
xContentBuilder.endObject();
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.string());
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.bytes());
Object object = objectPath.evaluate("field1.field2");
assertThat(object, instanceOf(Double.class));
assertThat(object, equalTo(3.55));
@ -109,7 +108,7 @@ public class ObjectPathTests extends ESTestCase {
xContentBuilder.array("array1", "value1", "value2");
xContentBuilder.endObject();
xContentBuilder.endObject();
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.string());
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.bytes());
Object object = objectPath.evaluate("field1.array1");
assertThat(object, instanceOf(List.class));
List list = (List) object;
@ -138,7 +137,7 @@ public class ObjectPathTests extends ESTestCase {
xContentBuilder.endArray();
xContentBuilder.endObject();
xContentBuilder.endObject();
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.string());
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.bytes());
Object object = objectPath.evaluate("field1.array1.1.element");
assertThat(object, instanceOf(String.class));
assertThat(object, equalTo("value2"));
@ -165,7 +164,7 @@ public class ObjectPathTests extends ESTestCase {
xContentBuilder.endObject();
xContentBuilder.endObject();
xContentBuilder.endObject();
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.string());
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.bytes());
Object object = objectPath.evaluate("metadata.templates");
assertThat(object, instanceOf(Map.class));
Map<String, Object> map = (Map<String, Object>)object;
@ -183,7 +182,7 @@ public class ObjectPathTests extends ESTestCase {
xContentBuilder.endObject();
xContentBuilder.endObject();
xContentBuilder.endObject();
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.string());
ObjectPath objectPath = ObjectPath.createFromXContent(xContentBuilder.contentType().xContent(), xContentBuilder.bytes());
try {
objectPath.evaluate("field1.$placeholder.element1");
fail("evaluate should have failed due to unresolved placeholder");
@ -246,7 +245,8 @@ public class ObjectPathTests extends ESTestCase {
xContentBuilder.field("index", "test2");
xContentBuilder.endObject();
xContentBuilder.endArray();
ObjectPath objectPath = ObjectPath.createFromXContent(XContentFactory.xContent(XContentType.YAML), xContentBuilder.string());
ObjectPath objectPath = ObjectPath.createFromXContent(
XContentFactory.xContent(xContentBuilder.contentType()), xContentBuilder.bytes());
Object object = objectPath.evaluate("");
assertThat(object, notNullValue());
assertThat(object, instanceOf(List.class));