diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/doc/RestTestsFromSnippetsTask.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/doc/RestTestsFromSnippetsTask.groovy
index ba7311fee6f..c7f4316ee04 100644
--- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/doc/RestTestsFromSnippetsTask.groovy
+++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/doc/RestTestsFromSnippetsTask.groovy
@@ -131,8 +131,9 @@ public class RestTestsFromSnippetsTask extends SnippetsTask {
}
private void response(Snippet response) {
- current.println(" - response_body: |")
- response.contents.eachLine { current.println(" $it") }
+ current.println(" - match: ")
+ current.println(" \$body: ")
+ response.contents.eachLine { current.println(" $it") }
}
void emitDo(String method, String pathAndQuery,
diff --git a/buildSrc/src/main/resources/checkstyle_suppressions.xml b/buildSrc/src/main/resources/checkstyle_suppressions.xml
index 51215ba6ce9..2a361980a8e 100644
--- a/buildSrc/src/main/resources/checkstyle_suppressions.xml
+++ b/buildSrc/src/main/resources/checkstyle_suppressions.xml
@@ -1263,26 +1263,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/reference/ingest/ingest-node.asciidoc b/docs/reference/ingest/ingest-node.asciidoc
index b03ed641de7..ec4f9c30e66 100644
--- a/docs/reference/ingest/ingest-node.asciidoc
+++ b/docs/reference/ingest/ingest-node.asciidoc
@@ -46,7 +46,6 @@ PUT _ingest/pipeline/my-pipeline-id
"value": "bar"
}
}
- // other processors
]
}
--------------------------------------------------
@@ -83,7 +82,6 @@ Example response:
"value": "bar"
}
}
- // other processors
]
}
} ]
diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.aliases/20_headers.yaml b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.aliases/20_headers.yaml
index b814856144b..16260151a31 100644
--- a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.aliases/20_headers.yaml
+++ b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.aliases/20_headers.yaml
@@ -17,12 +17,8 @@
headers:
Accept: application/yaml
- - match:
- $body: |
- /^---\n
- -\s+alias:\s+"test_alias"\s+
- index:\s+"test"\s+
- filter:\s+"-"\s+
- routing.index:\s+"-"\s+
- routing.search:\s+"-"\s+$/
-
+ - match: {0.alias: test_alias}
+ - match: {0.index: test}
+ - match: {0.filter: "-"}
+ - match: {0.routing\.index: "-"}
+ - match: {0.routing\.search: "-"}
diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.aliases/30_yaml.yaml b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.aliases/30_yaml.yaml
index c892891f08f..178b77ce60d 100644
--- a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.aliases/30_yaml.yaml
+++ b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.aliases/30_yaml.yaml
@@ -1,8 +1,5 @@
---
-"Simple alias with yaml body through format argument":
-
- - skip:
- features: yaml
+"Simple alias with json body through format argument":
- do:
indices.create:
@@ -15,15 +12,10 @@
- do:
cat.aliases:
- format: yaml
-
- - match:
- $body: |
- /^---\n
- -\s+alias:\s+"test_alias"\s+
- index:\s+"test"\s+
- filter:\s+"-"\s+
- routing.index:\s+"-"\s+
- routing.search:\s+"-"\s+$/
-
+ format: json
+ - match: {0.alias: test_alias}
+ - match: {0.index: test}
+ - match: {0.filter: "-"}
+ - match: {0.routing\.index: "-"}
+ - match: {0.routing\.search: "-"}
diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/get/50_with_headers.yaml b/rest-api-spec/src/main/resources/rest-api-spec/test/get/50_with_headers.yaml
index 1bb031f0878..ed9a5b7c99f 100644
--- a/rest-api-spec/src/main/resources/rest-api-spec/test/get/50_with_headers.yaml
+++ b/rest-api-spec/src/main/resources/rest-api-spec/test/get/50_with_headers.yaml
@@ -18,13 +18,9 @@
type: _all
id: 1
- - match:
- $body: |
- /^---\n
- _index:\s+\"test_1"\n
- _type:\s+"test"\n
- _id:\s+"1"\n
- _version:\s+1\n
- found:\s+true\n
- _source:\n
- \s+body:\s+"foo"\n$/
+ - match: {_index: "test_1"}
+ - match: {_type: "test"}
+ - match: {_id: "1"}
+ - match: {_version: 1}
+ - match: {found: true}
+ - match: { _source: { body: foo }}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/json/JsonPath.java b/test/framework/src/main/java/org/elasticsearch/test/rest/ObjectPath.java
similarity index 79%
rename from test/framework/src/main/java/org/elasticsearch/test/rest/json/JsonPath.java
rename to test/framework/src/main/java/org/elasticsearch/test/rest/ObjectPath.java
index b338d76d985..77de0f30f0c 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/json/JsonPath.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/ObjectPath.java
@@ -16,11 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.elasticsearch.test.rest.json;
+package org.elasticsearch.test.rest;
+import org.elasticsearch.common.xcontent.XContent;
import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.common.xcontent.json.JsonXContent;
-import org.elasticsearch.test.rest.Stash;
import java.io.IOException;
import java.util.ArrayList;
@@ -28,22 +27,23 @@ import java.util.List;
import java.util.Map;
/**
- * Holds a json object and allows to extract specific values from it
+ * Holds an object and allows to extract specific values from it given their path
*/
-public class JsonPath {
+public class ObjectPath {
- final String json;
- final Map jsonMap;
+ private final Object object;
- public JsonPath(String json) throws IOException {
- this.json = json;
- this.jsonMap = convertToMap(json);
+ public static ObjectPath createFromXContent(XContent xContent, String input) throws IOException {
+ try (XContentParser parser = xContent.createParser(input)) {
+ if (parser.nextToken() == XContentParser.Token.START_ARRAY) {
+ return new ObjectPath(parser.listOrderedMap());
+ }
+ return new ObjectPath(parser.mapOrdered());
+ }
}
- private static Map convertToMap(String json) throws IOException {
- try (XContentParser parser = JsonXContent.jsonXContent.createParser(json)) {
- return parser.mapOrdered();
- }
+ public ObjectPath(Object object) {
+ this.object = object;
}
/**
@@ -58,7 +58,7 @@ public class JsonPath {
*/
public Object evaluate(String path, Stash stash) throws IOException {
String[] parts = parsePath(path);
- Object object = jsonMap;
+ Object object = this.object;
for (String part : parts) {
object = evaluate(part, object, stash);
if (object == null) {
@@ -71,7 +71,7 @@ public class JsonPath {
@SuppressWarnings("unchecked")
private Object evaluate(String key, Object object, Stash stash) throws IOException {
if (stash.isStashedValue(key)) {
- key = stash.unstashValue(key).toString();
+ key = stash.getValue(key).toString();
}
if (object instanceof Map) {
@@ -84,7 +84,8 @@ public class JsonPath {
} catch (NumberFormatException e) {
throw new IllegalArgumentException("element was a list, but [" + key + "] was not numeric", e);
} catch (IndexOutOfBoundsException e) {
- throw new IllegalArgumentException("element was a list with " + list.size() + " elements, but [" + key + "] was out of bounds", e);
+ throw new IllegalArgumentException("element was a list with " + list.size() +
+ " elements, but [" + key + "] was out of bounds", e);
}
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/RestTestExecutionContext.java b/test/framework/src/main/java/org/elasticsearch/test/rest/RestTestExecutionContext.java
index 34397f03d94..6d95c7e893f 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/RestTestExecutionContext.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/RestTestExecutionContext.java
@@ -67,7 +67,7 @@ public class RestTestExecutionContext implements Closeable {
HashMap requestParams = new HashMap<>(params);
for (Map.Entry entry : requestParams.entrySet()) {
if (stash.isStashedValue(entry.getValue())) {
- entry.setValue(stash.unstashValue(entry.getValue()).toString());
+ entry.setValue(stash.getValue(entry.getValue()).toString());
}
}
@@ -76,7 +76,7 @@ public class RestTestExecutionContext implements Closeable {
try {
response = callApiInternal(apiName, requestParams, body, headers);
//we always stash the last response body
- stash.stashResponse(response);
+ stash.stashValue("body", response.getBody());
return response;
} catch(ResponseException e) {
response = new RestTestResponse(e);
@@ -90,12 +90,12 @@ public class RestTestExecutionContext implements Closeable {
}
if (bodies.size() == 1) {
- return bodyAsString(stash.unstashMap(bodies.get(0)));
+ return bodyAsString(stash.replaceStashedValues(bodies.get(0)));
}
StringBuilder bodyBuilder = new StringBuilder();
for (Map body : bodies) {
- bodyBuilder.append(bodyAsString(stash.unstashMap(body))).append("\n");
+ bodyBuilder.append(bodyAsString(stash.replaceStashedValues(body))).append("\n");
}
return bodyBuilder.toString();
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/Stash.java b/test/framework/src/main/java/org/elasticsearch/test/rest/Stash.java
index 885df395c2b..13c5b9ff563 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/Stash.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/Stash.java
@@ -24,7 +24,6 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.test.rest.client.RestTestResponse;
import java.io.IOException;
import java.util.HashMap;
@@ -42,7 +41,7 @@ public class Stash implements ToXContent {
public static final Stash EMPTY = new Stash();
private final Map stash = new HashMap<>();
- private RestTestResponse response;
+ private final ObjectPath stashObjectPath = new ObjectPath(stash);
/**
* Allows to saved a specific field in the stash as key-value pair
@@ -55,12 +54,6 @@ public class Stash implements ToXContent {
}
}
- public void stashResponse(RestTestResponse response) throws IOException {
- // TODO we can almost certainly save time by lazily evaluating the body
- stashValue("body", response.getBody());
- this.response = response;
- }
-
/**
* Clears the previously stashed values
*/
@@ -69,7 +62,8 @@ public class Stash implements ToXContent {
}
/**
- * Tells whether a particular value needs to be looked up in the stash
+ * Tells whether a particular key needs to be looked up in the stash based on its name.
+ * Returns true if the string representation of the key starts with "$", false otherwise
* The stash contains fields eventually extracted from previous responses that can be reused
* as arguments for following requests (e.g. scroll_id)
*/
@@ -82,28 +76,23 @@ public class Stash implements ToXContent {
}
/**
- * Extracts a value from the current stash
+ * Retrieves a value from the current stash.
* The stash contains fields eventually extracted from previous responses that can be reused
* as arguments for following requests (e.g. scroll_id)
*/
- public Object unstashValue(String value) throws IOException {
- if (value.startsWith("$body.")) {
- if (response == null) {
- return null;
- }
- return response.evaluate(value.substring("$body".length()), this);
- }
- Object stashedValue = stash.get(value.substring(1));
+ public Object getValue(String key) throws IOException {
+ Object stashedValue = stashObjectPath.evaluate(key.substring(1));
if (stashedValue == null) {
- throw new IllegalArgumentException("stashed value not found for key [" + value + "]");
+ throw new IllegalArgumentException("stashed value not found for key [" + key + "]");
}
return stashedValue;
}
/**
- * Recursively unstashes map values if needed
+ * Goes recursively against each map entry and replaces any string value starting with "$" with its
+ * corresponding value retrieved from the stash
*/
- public Map unstashMap(Map map) throws IOException {
+ public Map replaceStashedValues(Map map) throws IOException {
Map copy = new HashMap<>(map);
unstashObject(copy);
return copy;
@@ -116,7 +105,7 @@ public class Stash implements ToXContent {
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
if (isStashedValue(o)) {
- list.set(i, unstashValue(o.toString()));
+ list.set(i, getValue(o.toString()));
} else {
unstashObject(o);
}
@@ -126,7 +115,7 @@ public class Stash implements ToXContent {
Map map = (Map) obj;
for (Map.Entry entry : map.entrySet()) {
if (isStashedValue(entry.getValue())) {
- entry.setValue(unstashValue(entry.getValue().toString()));
+ entry.setValue(getValue(entry.getValue().toString()));
} else {
unstashObject(entry.getValue());
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/client/RestTestResponse.java b/test/framework/src/main/java/org/elasticsearch/test/rest/client/RestTestResponse.java
index 5b5773d6fdc..4644b87b8e7 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/client/RestTestResponse.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/client/RestTestResponse.java
@@ -23,23 +23,24 @@ import org.apache.http.util.EntityUtils;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.test.rest.ObjectPath;
import org.elasticsearch.test.rest.Stash;
-import org.elasticsearch.test.rest.json.JsonPath;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* Response obtained from a REST call, eagerly reads the response body into a string for later optional parsing.
- * Supports parsing the response body as json when needed and returning specific values extracted from it.
+ * Supports parsing the response body when needed and returning specific values extracted from it.
*/
public class RestTestResponse {
private final Response response;
private final String body;
- private JsonPath parsedResponse;
+ private ObjectPath parsedResponse;
- public RestTestResponse(Response response) {
+ public RestTestResponse(Response response) throws IOException {
this.response = response;
if (response.getEntity() != null) {
try {
@@ -53,11 +54,24 @@ public class RestTestResponse {
} else {
this.body = null;
}
+ parseResponseBody();
}
- public RestTestResponse(ResponseException responseException) {
+ public RestTestResponse(ResponseException responseException) throws IOException {
this.response = responseException.getResponse();
this.body = responseException.getResponseBody();
+ 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);
+ }
+ }
}
public int getStatusCode() {
@@ -73,11 +87,7 @@ public class RestTestResponse {
* Might be a string or a json object parsed as a map.
*/
public Object getBody() throws IOException {
- if (isJson()) {
- JsonPath parsedResponse = parsedResponse();
- if (parsedResponse == null) {
- return null;
- }
+ if (parsedResponse != null) {
return parsedResponse.evaluate("");
}
return body;
@@ -95,23 +105,21 @@ public class RestTestResponse {
}
/**
- * Parses the response body as json and extracts a specific value from it (identified by the provided path)
+ * Parses the response body and extracts a specific value from it (identified by the provided path)
*/
public Object evaluate(String path) throws IOException {
return evaluate(path, Stash.EMPTY);
}
/**
- * Parses the response body as json and extracts a specific value from it (identified by the provided path)
+ * Parses the response body and extracts a specific value from it (identified by the provided path)
*/
public Object evaluate(String path, Stash stash) throws IOException {
if (response == null) {
return null;
}
- JsonPath jsonPath = parsedResponse();
-
- if (jsonPath == null) {
+ if (parsedResponse == null) {
//special case: api that don't support body (e.g. exists) return true if 200, false if 404, even if no body
//is_true: '' means the response had no body but the client returned true (caused by 200)
//is_false: '' means the response had no body but the client returned false (caused by 404)
@@ -121,21 +129,6 @@ public class RestTestResponse {
return null;
}
- return jsonPath.evaluate(path, stash);
- }
-
- private boolean isJson() {
- String contentType = response.getHeader("Content-Type");
- return contentType != null && contentType.contains("application/json");
- }
-
- private JsonPath parsedResponse() throws IOException {
- if (parsedResponse != null) {
- return parsedResponse;
- }
- if (response == null || body == null) {
- return null;
- }
- return parsedResponse = new JsonPath(body);
+ return parsedResponse.evaluate(path, stash);
}
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/GreaterThanEqualToParser.java b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/GreaterThanEqualToParser.java
index 68f833d35c7..7a4cd0f316a 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/GreaterThanEqualToParser.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/GreaterThanEqualToParser.java
@@ -33,7 +33,8 @@ public class GreaterThanEqualToParser implements RestTestFragmentParser stringObjectTuple = parseContext.parseTuple();
if (! (stringObjectTuple.v2() instanceof Comparable) ) {
- throw new RestTestParseException("gte section can only be used with objects that support natural ordering, found " + stringObjectTuple.v2().getClass().getSimpleName());
+ throw new RestTestParseException("gte section can only be used with objects that support natural ordering, found "
+ + stringObjectTuple.v2().getClass().getSimpleName());
}
return new GreaterThanEqualToAssertion(stringObjectTuple.v1(), stringObjectTuple.v2());
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/GreaterThanParser.java b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/GreaterThanParser.java
index a66122138c1..7e1ca1ece7f 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/GreaterThanParser.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/GreaterThanParser.java
@@ -32,7 +32,8 @@ public class GreaterThanParser implements RestTestFragmentParser stringObjectTuple = parseContext.parseTuple();
if (! (stringObjectTuple.v2() instanceof Comparable) ) {
- throw new RestTestParseException("gt section can only be used with objects that support natural ordering, found " + stringObjectTuple.v2().getClass().getSimpleName());
+ throw new RestTestParseException("gt section can only be used with objects that support natural ordering, found "
+ + stringObjectTuple.v2().getClass().getSimpleName());
}
return new GreaterThanAssertion(stringObjectTuple.v1(), stringObjectTuple.v2());
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/LessThanOrEqualToParser.java b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/LessThanOrEqualToParser.java
index f2d53d05a56..a30979c6a3c 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/LessThanOrEqualToParser.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/LessThanOrEqualToParser.java
@@ -33,7 +33,8 @@ public class LessThanOrEqualToParser implements RestTestFragmentParser stringObjectTuple = parseContext.parseTuple();
if (! (stringObjectTuple.v2() instanceof Comparable) ) {
- throw new RestTestParseException("lte section can only be used with objects that support natural ordering, found " + stringObjectTuple.v2().getClass().getSimpleName());
+ throw new RestTestParseException("lte section can only be used with objects that support natural ordering, found "
+ + stringObjectTuple.v2().getClass().getSimpleName());
}
return new LessThanOrEqualToAssertion(stringObjectTuple.v1(), stringObjectTuple.v2());
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/LessThanParser.java b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/LessThanParser.java
index 065dd19d6a1..fc31f221758 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/LessThanParser.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/LessThanParser.java
@@ -32,7 +32,8 @@ public class LessThanParser implements RestTestFragmentParser
public LessThanAssertion parse(RestTestSuiteParseContext parseContext) throws IOException, RestTestParseException {
Tuple stringObjectTuple = parseContext.parseTuple();
if (! (stringObjectTuple.v2() instanceof Comparable) ) {
- throw new RestTestParseException("lt section can only be used with objects that support natural ordering, found " + stringObjectTuple.v2().getClass().getSimpleName());
+ throw new RestTestParseException("lt section can only be used with objects that support natural ordering, found "
+ + stringObjectTuple.v2().getClass().getSimpleName());
}
return new LessThanAssertion(stringObjectTuple.v1(), stringObjectTuple.v2());
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/RestTestSuiteParseContext.java b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/RestTestSuiteParseContext.java
index e972aea641a..f7325443deb 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/RestTestSuiteParseContext.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/RestTestSuiteParseContext.java
@@ -18,22 +18,21 @@
*/
package org.elasticsearch.test.rest.parser;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.XContentLocation;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import org.elasticsearch.test.rest.section.DoSection;
import org.elasticsearch.test.rest.section.ExecutableSection;
-import org.elasticsearch.test.rest.section.ResponseBodyAssertion;
import org.elasticsearch.test.rest.section.SetupSection;
import org.elasticsearch.test.rest.section.SkipSection;
import org.elasticsearch.test.rest.section.TeardownSection;
import org.elasticsearch.test.rest.section.TestSection;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Context shared across the whole tests parse phase.
* Provides shared parse methods and holds information needed to parse the test sections (e.g. es version)
@@ -57,7 +56,6 @@ public class RestTestSuiteParseContext {
EXECUTABLE_SECTIONS_PARSERS.put("lt", new LessThanParser());
EXECUTABLE_SECTIONS_PARSERS.put("lte", new LessThanOrEqualToParser());
EXECUTABLE_SECTIONS_PARSERS.put("length", new LengthParser());
- EXECUTABLE_SECTIONS_PARSERS.put("response_body", ResponseBodyAssertion.PARSER);
}
private final String api;
@@ -160,7 +158,8 @@ public class RestTestSuiteParseContext {
token = parser.nextToken();
}
if (token != XContentParser.Token.FIELD_NAME) {
- throw new RestTestParseException("malformed test section: field name expected but found " + token + " at " + parser.getTokenLocation());
+ throw new RestTestParseException("malformed test section: field name expected but found " + token + " at "
+ + parser.getTokenLocation());
}
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/RestTestSuiteParser.java b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/RestTestSuiteParser.java
index c6986d3eac8..f22f0109594 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/parser/RestTestSuiteParser.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/parser/RestTestSuiteParser.java
@@ -71,7 +71,8 @@ public class RestTestSuiteParser implements RestTestFragmentParser map = (Map) expectedValue;
- return executionContext.stash().unstashMap(map);
+ return executionContext.stash().replaceStashedValues(map);
}
if (executionContext.stash().isStashedValue(expectedValue)) {
- return executionContext.stash().unstashValue(expectedValue.toString());
+ return executionContext.stash().getValue(expectedValue.toString());
}
return expectedValue;
}
protected final Object getActualValue(RestTestExecutionContext executionContext) throws IOException {
if (executionContext.stash().isStashedValue(field)) {
- return executionContext.stash().unstashValue(field);
+ return executionContext.stash().getValue(field);
}
return executionContext.response(field);
}
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/section/GreaterThanAssertion.java b/test/framework/src/main/java/org/elasticsearch/test/rest/section/GreaterThanAssertion.java
index ade7fbd59ca..63f69696653 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/section/GreaterThanAssertion.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/section/GreaterThanAssertion.java
@@ -43,8 +43,10 @@ public class GreaterThanAssertion extends Assertion {
@SuppressWarnings("unchecked")
protected void doAssert(Object actualValue, Object expectedValue) {
logger.trace("assert that [{}] is greater than [{}] (field: [{}])", actualValue, expectedValue, getField());
- assertThat("value of [" + getField() + "] is not comparable (got [" + safeClass(actualValue) + "])", actualValue, instanceOf(Comparable.class));
- assertThat("expected value of [" + getField() + "] is not comparable (got [" + expectedValue.getClass() + "])", expectedValue, instanceOf(Comparable.class));
+ assertThat("value of [" + getField() + "] is not comparable (got [" + safeClass(actualValue) + "])",
+ actualValue, instanceOf(Comparable.class));
+ assertThat("expected value of [" + getField() + "] is not comparable (got [" + expectedValue.getClass() + "])",
+ expectedValue, instanceOf(Comparable.class));
try {
assertThat(errorMessage(), (Comparable) actualValue, greaterThan((Comparable) expectedValue));
} catch (ClassCastException e) {
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/section/GreaterThanEqualToAssertion.java b/test/framework/src/main/java/org/elasticsearch/test/rest/section/GreaterThanEqualToAssertion.java
index cfdca7bc338..297eecf2d2a 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/section/GreaterThanEqualToAssertion.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/section/GreaterThanEqualToAssertion.java
@@ -43,8 +43,10 @@ public class GreaterThanEqualToAssertion extends Assertion {
@Override
protected void doAssert(Object actualValue, Object expectedValue) {
logger.trace("assert that [{}] is greater than or equal to [{}] (field: [{}])", actualValue, expectedValue, getField());
- assertThat("value of [" + getField() + "] is not comparable (got [" + safeClass(actualValue) + "])", actualValue, instanceOf(Comparable.class));
- assertThat("expected value of [" + getField() + "] is not comparable (got [" + expectedValue.getClass() + "])", expectedValue, instanceOf(Comparable.class));
+ assertThat("value of [" + getField() + "] is not comparable (got [" + safeClass(actualValue) + "])",
+ actualValue, instanceOf(Comparable.class));
+ assertThat("expected value of [" + getField() + "] is not comparable (got [" + expectedValue.getClass() + "])",
+ expectedValue, instanceOf(Comparable.class));
try {
assertThat(errorMessage(), (Comparable) actualValue, greaterThanOrEqualTo((Comparable) expectedValue));
} catch (ClassCastException e) {
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/section/LengthAssertion.java b/test/framework/src/main/java/org/elasticsearch/test/rest/section/LengthAssertion.java
index 265487a0388..eb28ba01a94 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/section/LengthAssertion.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/section/LengthAssertion.java
@@ -44,7 +44,8 @@ public class LengthAssertion extends Assertion {
@Override
protected void doAssert(Object actualValue, Object expectedValue) {
logger.trace("assert that [{}] has length [{}] (field: [{}])", actualValue, expectedValue, getField());
- assertThat("expected value of [" + getField() + "] is not numeric (got [" + expectedValue.getClass() + "]", expectedValue, instanceOf(Number.class));
+ assertThat("expected value of [" + getField() + "] is not numeric (got [" + expectedValue.getClass() + "]",
+ expectedValue, instanceOf(Number.class));
int length = ((Number) expectedValue).intValue();
if (actualValue instanceof String) {
assertThat(errorMessage(), ((String) actualValue).length(), equalTo(length));
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/section/LessThanAssertion.java b/test/framework/src/main/java/org/elasticsearch/test/rest/section/LessThanAssertion.java
index 89387ff8952..153a7824569 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/section/LessThanAssertion.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/section/LessThanAssertion.java
@@ -44,8 +44,10 @@ public class LessThanAssertion extends Assertion {
@SuppressWarnings("unchecked")
protected void doAssert(Object actualValue, Object expectedValue) {
logger.trace("assert that [{}] is less than [{}] (field: [{}])", actualValue, expectedValue, getField());
- assertThat("value of [" + getField() + "] is not comparable (got [" + safeClass(actualValue) + "])", actualValue, instanceOf(Comparable.class));
- assertThat("expected value of [" + getField() + "] is not comparable (got [" + expectedValue.getClass() + "])", expectedValue, instanceOf(Comparable.class));
+ assertThat("value of [" + getField() + "] is not comparable (got [" + safeClass(actualValue) + "])",
+ actualValue, instanceOf(Comparable.class));
+ assertThat("expected value of [" + getField() + "] is not comparable (got [" + expectedValue.getClass() + "])",
+ expectedValue, instanceOf(Comparable.class));
try {
assertThat(errorMessage(), (Comparable) actualValue, lessThan((Comparable) expectedValue));
} catch (ClassCastException e) {
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/section/LessThanOrEqualToAssertion.java b/test/framework/src/main/java/org/elasticsearch/test/rest/section/LessThanOrEqualToAssertion.java
index 99cbf1155d5..1eb3a9fc2b2 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/section/LessThanOrEqualToAssertion.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/section/LessThanOrEqualToAssertion.java
@@ -43,8 +43,10 @@ public class LessThanOrEqualToAssertion extends Assertion {
@Override
protected void doAssert(Object actualValue, Object expectedValue) {
logger.trace("assert that [{}] is less than or equal to [{}] (field: [{}])", actualValue, expectedValue, getField());
- assertThat("value of [" + getField() + "] is not comparable (got [" + safeClass(actualValue) + "])", actualValue, instanceOf(Comparable.class));
- assertThat("expected value of [" + getField() + "] is not comparable (got [" + expectedValue.getClass() + "])", expectedValue, instanceOf(Comparable.class));
+ assertThat("value of [" + getField() + "] is not comparable (got [" + safeClass(actualValue) + "])",
+ actualValue, instanceOf(Comparable.class));
+ assertThat("expected value of [" + getField() + "] is not comparable (got [" + expectedValue.getClass() + "])",
+ expectedValue, instanceOf(Comparable.class));
try {
assertThat(errorMessage(), (Comparable) actualValue, lessThanOrEqualTo((Comparable) expectedValue));
} catch (ClassCastException e) {
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/section/MatchAssertion.java b/test/framework/src/main/java/org/elasticsearch/test/rest/section/MatchAssertion.java
index e00fbbea01c..3a96d4532a0 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/section/MatchAssertion.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/section/MatchAssertion.java
@@ -18,15 +18,21 @@
*/
package org.elasticsearch.test.rest.section;
+import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.TreeMap;
import java.util.regex.Pattern;
import static org.elasticsearch.test.hamcrest.RegexMatcher.matches;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
/**
@@ -45,12 +51,12 @@ public class MatchAssertion extends Assertion {
@Override
protected void doAssert(Object actualValue, Object expectedValue) {
-
//if the value is wrapped into / it is a regexp (e.g. /s+d+/)
if (expectedValue instanceof String) {
String expValue = ((String) expectedValue).trim();
if (expValue.length() > 2 && expValue.startsWith("/") && expValue.endsWith("/")) {
- assertThat("field [" + getField() + "] was expected to be of type String but is an instanceof [" + safeClass(actualValue) + "]", actualValue, instanceOf(String.class));
+ assertThat("field [" + getField() + "] was expected to be of type String but is an instanceof [" +
+ safeClass(actualValue) + "]", actualValue, instanceOf(String.class));
String stringValue = (String) actualValue;
String regex = expValue.substring(1, expValue.length() - 1);
logger.trace("assert that [{}] matches [{}]", stringValue, regex);
@@ -60,20 +66,131 @@ public class MatchAssertion extends Assertion {
}
}
- assertThat(errorMessage(), actualValue, notNullValue());
+ assertNotNull("field [" + getField() + "] is null", actualValue);
logger.trace("assert that [{}] matches [{}] (field [{}])", actualValue, expectedValue, getField());
- if (!actualValue.getClass().equals(safeClass(expectedValue))) {
+ if (actualValue.getClass().equals(safeClass(expectedValue)) == false) {
if (actualValue instanceof Number && expectedValue instanceof Number) {
//Double 1.0 is equal to Integer 1
- assertThat(errorMessage(), ((Number) actualValue).doubleValue(), equalTo(((Number) expectedValue).doubleValue()));
+ assertThat("field [" + getField() + "] doesn't match the expected value",
+ ((Number) actualValue).doubleValue(), equalTo(((Number) expectedValue).doubleValue()));
return;
}
}
- assertThat(errorMessage(), actualValue, equalTo(expectedValue));
+ if (expectedValue.equals(actualValue) == false) {
+ FailureMessage message = new FailureMessage(getField());
+ message.compare(getField(), actualValue, expectedValue);
+ throw new AssertionError(message.message);
+ }
}
- private String errorMessage() {
- return "field [" + getField() + "] doesn't match the expected value";
+ private static class FailureMessage {
+ private final StringBuilder message;
+ private int indent = 0;
+
+ private FailureMessage(String field) {
+ this.message = new StringBuilder(field + " didn't match the expected value:\n");
+ }
+
+ private void compareMaps(Map actual, Map expected) {
+ actual = new TreeMap<>(actual);
+ expected = new TreeMap<>(expected);
+ for (Map.Entry expectedEntry : expected.entrySet()) {
+ compare(expectedEntry.getKey(), actual.remove(expectedEntry.getKey()), expectedEntry.getValue());
+ }
+ for (Map.Entry unmatchedEntry : actual.entrySet()) {
+ field(unmatchedEntry.getKey(), "unexpected but found [" + unmatchedEntry.getValue() + "]");
+ }
+ }
+
+ private void compareLists(List