Add parsing methods to BulkItemResponse (#22859)
This commit adds a parsing method to the BulkItemResponse class. In order to do that, the way DocWriteResponses are parsed has to be changed: ConstructingObjectParser/ObjectParser is removed in favor of a simpler and more readable way to parse these objects. DocWriteResponse now provides the parseInnerToXContent() method that can be used by subclasses (IndexResponse, UpdateReponse and DeleteResponse) to parse the current token/field and potentially update a DocWriteResponseBuilder. The DocWriteResponseBuilder is a simple POJO used to contain parsed values. It can be passed around from one parsing method to another parsing method. For example, this is what is done in IndexResponse: a IndexResponseBuilder is created in IndexResponse.fromXContent(), it get passed to IndexResponse.parseXContentFields() that parses fields specific to IndexResponse (like "created") and updates the context, delegating to DocWriteResponse.parseInnerToXContent() the parsing of any other field. Once all XContent is parsed, IndexResponse.fromXContent() uses the method IndexResponseBuilder.build() to create the new instance of IndexResponse. This behavior allow to reuse parsing code among the class hierarchy while keeping the current behavior. It also allows other objects like BulkItemResponse to reuse the same parsing code to parse DocWriteResponses. Finally, IndexResponseTests, UpdateResponseTests and DeleteResponseTests have been updated to introduce some random shuffling of fields before the XContent is parsed in order to ensure that the parsing code does not rely on field order.
This commit is contained in:
parent
a6389a30f2
commit
e8d669f50c
|
@ -586,7 +586,7 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|||
return new ElasticsearchException(buildMessage("exception", parser.text(), null));
|
||||
}
|
||||
|
||||
ensureExpectedToken(token, XContentParser.Token.START_OBJECT, parser::getTokenLocation);
|
||||
ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation);
|
||||
token = parser.nextToken();
|
||||
|
||||
// Root causes are parsed in the innerFromXContent() and are added as suppressed exceptions.
|
||||
|
|
|
@ -23,15 +23,15 @@ import org.elasticsearch.action.support.WriteRequest;
|
|||
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
||||
import org.elasticsearch.action.support.WriteResponse;
|
||||
import org.elasticsearch.action.support.replication.ReplicationResponse;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.StatusToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.IndexSettings;
|
||||
import org.elasticsearch.index.seqno.SequenceNumbersService;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
|
@ -45,8 +45,9 @@ import java.net.URLEncoder;
|
|||
import java.nio.charset.Charset;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.throwUnknownField;
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.throwUnknownToken;
|
||||
|
||||
/**
|
||||
* A base class for the response of a write operation that involves a single doc
|
||||
|
@ -299,16 +300,113 @@ public abstract class DocWriteResponse extends ReplicationResponse implements Wr
|
|||
}
|
||||
|
||||
/**
|
||||
* Declare the {@link ObjectParser} fields to use when parsing a {@link DocWriteResponse}
|
||||
* Parse the output of the {@link #innerToXContent(XContentBuilder, Params)} method.
|
||||
*
|
||||
* This method is intended to be called by subclasses and must be called multiple times to parse all the information concerning
|
||||
* {@link DocWriteResponse} objects. It always parses the current token, updates the given parsing context accordingly
|
||||
* if needed and then immediately returns.
|
||||
*/
|
||||
protected static void declareParserFields(ConstructingObjectParser<? extends DocWriteResponse, Void> objParser) {
|
||||
objParser.declareString(constructorArg(), new ParseField(_INDEX));
|
||||
objParser.declareString(constructorArg(), new ParseField(_TYPE));
|
||||
objParser.declareString(constructorArg(), new ParseField(_ID));
|
||||
objParser.declareLong(constructorArg(), new ParseField(_VERSION));
|
||||
objParser.declareString(constructorArg(), new ParseField(RESULT));
|
||||
objParser.declareObject(optionalConstructorArg(), (p, c) -> ShardInfo.fromXContent(p), new ParseField(_SHARDS));
|
||||
objParser.declareLong(optionalConstructorArg(), new ParseField(_SEQ_NO));
|
||||
objParser.declareBoolean(DocWriteResponse::setForcedRefresh, new ParseField(FORCED_REFRESH));
|
||||
protected static void parseInnerToXContent(XContentParser parser, DocWriteResponseBuilder context) throws IOException {
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);
|
||||
|
||||
String currentFieldName = parser.currentName();
|
||||
token = parser.nextToken();
|
||||
|
||||
if (token.isValue()) {
|
||||
if (_INDEX.equals(currentFieldName)) {
|
||||
// index uuid and shard id are unknown and can't be parsed back for now.
|
||||
context.setShardId(new ShardId(new Index(parser.text(), IndexMetaData.INDEX_UUID_NA_VALUE), -1));
|
||||
} else if (_TYPE.equals(currentFieldName)) {
|
||||
context.setType(parser.text());
|
||||
} else if (_ID.equals(currentFieldName)) {
|
||||
context.setId(parser.text());
|
||||
} else if (_VERSION.equals(currentFieldName)) {
|
||||
context.setVersion(parser.longValue());
|
||||
} else if (RESULT.equals(currentFieldName)) {
|
||||
String result = parser.text();
|
||||
for (Result r : Result.values()) {
|
||||
if (r.getLowercase().equals(result)) {
|
||||
context.setResult(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (FORCED_REFRESH.equals(currentFieldName)) {
|
||||
context.setForcedRefresh(parser.booleanValue());
|
||||
} else if (_SEQ_NO.equals(currentFieldName)) {
|
||||
context.setSeqNo(parser.longValue());
|
||||
} else {
|
||||
throwUnknownField(currentFieldName, parser.getTokenLocation());
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (_SHARDS.equals(currentFieldName)) {
|
||||
context.setShardInfo(ShardInfo.fromXContent(parser));
|
||||
} else {
|
||||
throwUnknownField(currentFieldName, parser.getTokenLocation());
|
||||
}
|
||||
} else {
|
||||
throwUnknownToken(token, parser.getTokenLocation());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link DocWriteResponseBuilder} is used to build {@link DocWriteResponse} objects during XContent parsing.
|
||||
*/
|
||||
public static abstract class DocWriteResponseBuilder {
|
||||
|
||||
protected ShardId shardId = null;
|
||||
protected String type = null;
|
||||
protected String id = null;
|
||||
protected Long version = null;
|
||||
protected Result result = null;
|
||||
protected boolean forcedRefresh;
|
||||
protected ShardInfo shardInfo = null;
|
||||
protected Long seqNo = SequenceNumbersService.UNASSIGNED_SEQ_NO;
|
||||
|
||||
public ShardId getShardId() {
|
||||
return shardId;
|
||||
}
|
||||
|
||||
public void setShardId(ShardId shardId) {
|
||||
this.shardId = shardId;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setVersion(Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public void setResult(Result result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public void setForcedRefresh(boolean forcedRefresh) {
|
||||
this.forcedRefresh = forcedRefresh;
|
||||
}
|
||||
|
||||
public void setShardInfo(ShardInfo shardInfo) {
|
||||
this.shardInfo = shardInfo;
|
||||
}
|
||||
|
||||
public void setSeqNo(Long seqNo) {
|
||||
this.seqNo = seqNo;
|
||||
}
|
||||
|
||||
public abstract DocWriteResponse build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.elasticsearch.action.DocWriteResponse;
|
|||
import org.elasticsearch.action.delete.DeleteResponse;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.common.CheckedConsumer;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
@ -35,9 +36,14 @@ import org.elasticsearch.common.io.stream.Writeable;
|
|||
import org.elasticsearch.common.xcontent.StatusToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.throwUnknownField;
|
||||
|
||||
/**
|
||||
* Represents a single item response for an action executed as part of the bulk API. Holds the index/type/id
|
||||
|
@ -45,6 +51,12 @@ import java.io.IOException;
|
|||
*/
|
||||
public class BulkItemResponse implements Streamable, StatusToXContentObject {
|
||||
|
||||
private static final String _INDEX = "_index";
|
||||
private static final String _TYPE = "_type";
|
||||
private static final String _ID = "_id";
|
||||
private static final String STATUS = "status";
|
||||
private static final String ERROR = "error";
|
||||
|
||||
@Override
|
||||
public RestStatus status() {
|
||||
return failure == null ? response.status() : failure.getStatus();
|
||||
|
@ -56,13 +68,13 @@ public class BulkItemResponse implements Streamable, StatusToXContentObject {
|
|||
builder.startObject(opType.getLowercase());
|
||||
if (failure == null) {
|
||||
response.innerToXContent(builder, params);
|
||||
builder.field(Fields.STATUS, response.status().getStatus());
|
||||
builder.field(STATUS, response.status().getStatus());
|
||||
} else {
|
||||
builder.field(Fields._INDEX, failure.getIndex());
|
||||
builder.field(Fields._TYPE, failure.getType());
|
||||
builder.field(Fields._ID, failure.getId());
|
||||
builder.field(Fields.STATUS, failure.getStatus().getStatus());
|
||||
builder.startObject(Fields.ERROR);
|
||||
builder.field(_INDEX, failure.getIndex());
|
||||
builder.field(_TYPE, failure.getType());
|
||||
builder.field(_ID, failure.getId());
|
||||
builder.field(STATUS, failure.getStatus().getStatus());
|
||||
builder.startObject(ERROR);
|
||||
ElasticsearchException.generateThrowableXContent(builder, params, failure.getCause());
|
||||
builder.endObject();
|
||||
}
|
||||
|
@ -71,12 +83,73 @@ public class BulkItemResponse implements Streamable, StatusToXContentObject {
|
|||
return builder;
|
||||
}
|
||||
|
||||
static final class Fields {
|
||||
static final String _INDEX = "_index";
|
||||
static final String _TYPE = "_type";
|
||||
static final String _ID = "_id";
|
||||
static final String STATUS = "status";
|
||||
static final String ERROR = "error";
|
||||
/**
|
||||
* Reads a {@link BulkItemResponse} from a {@link XContentParser}.
|
||||
*
|
||||
* @param parser the {@link XContentParser}
|
||||
* @param id the id to assign to the parsed {@link BulkItemResponse}. It is usually the index of
|
||||
* the item in the {@link BulkResponse#getItems} array.
|
||||
*/
|
||||
public static BulkItemResponse fromXContent(XContentParser parser, int id) throws IOException {
|
||||
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser::getTokenLocation);
|
||||
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);
|
||||
|
||||
String currentFieldName = parser.currentName();
|
||||
token = parser.nextToken();
|
||||
|
||||
final OpType opType = OpType.fromString(currentFieldName);
|
||||
ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation);
|
||||
|
||||
DocWriteResponse.DocWriteResponseBuilder builder = null;
|
||||
CheckedConsumer<XContentParser, IOException> itemParser = null;
|
||||
|
||||
if (opType == OpType.INDEX || opType == OpType.CREATE) {
|
||||
final IndexResponse.IndexResponseBuilder indexResponseBuilder = new IndexResponse.IndexResponseBuilder();
|
||||
builder = indexResponseBuilder;
|
||||
itemParser = (indexParser) -> IndexResponse.parseXContentFields(indexParser, indexResponseBuilder);
|
||||
|
||||
} else if (opType == OpType.UPDATE) {
|
||||
final UpdateResponse.UpdateResponseBuilder updateResponseBuilder = new UpdateResponse.UpdateResponseBuilder();
|
||||
builder = updateResponseBuilder;
|
||||
itemParser = (updateParser) -> UpdateResponse.parseXContentFields(updateParser, updateResponseBuilder);
|
||||
|
||||
} else if (opType == OpType.DELETE) {
|
||||
final DeleteResponse.DeleteResponseBuilder deleteResponseBuilder = new DeleteResponse.DeleteResponseBuilder();
|
||||
builder = deleteResponseBuilder;
|
||||
itemParser = (deleteParser) -> DeleteResponse.parseXContentFields(deleteParser, deleteResponseBuilder);
|
||||
} else {
|
||||
throwUnknownField(currentFieldName, parser.getTokenLocation());
|
||||
}
|
||||
|
||||
ElasticsearchException exception = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
}
|
||||
|
||||
if (ERROR.equals(currentFieldName)) {
|
||||
if (token == XContentParser.Token.START_OBJECT) {
|
||||
exception = ElasticsearchException.fromXContent(parser);
|
||||
}
|
||||
} else if (STATUS.equals(currentFieldName) == false) {
|
||||
itemParser.accept(parser);
|
||||
}
|
||||
}
|
||||
|
||||
ensureExpectedToken(XContentParser.Token.END_OBJECT, token, parser::getTokenLocation);
|
||||
token = parser.nextToken();
|
||||
ensureExpectedToken(XContentParser.Token.END_OBJECT, token, parser::getTokenLocation);
|
||||
|
||||
BulkItemResponse bulkItemResponse;
|
||||
if (exception != null) {
|
||||
Failure failure = new Failure(builder.getShardId().getIndexName(), builder.getType(), builder.getId(), exception);
|
||||
bulkItemResponse = new BulkItemResponse(id, opType, failure);
|
||||
} else {
|
||||
bulkItemResponse = new BulkItemResponse(id, opType, builder.build());
|
||||
}
|
||||
return bulkItemResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,19 +20,14 @@
|
|||
package org.elasticsearch.action.delete;
|
||||
|
||||
import org.elasticsearch.action.DocWriteResponse;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.seqno.SequenceNumbersService;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
||||
|
||||
/**
|
||||
* The response of the delete action.
|
||||
|
@ -45,7 +40,6 @@ public class DeleteResponse extends DocWriteResponse {
|
|||
private static final String FOUND = "found";
|
||||
|
||||
public DeleteResponse() {
|
||||
|
||||
}
|
||||
|
||||
public DeleteResponse(ShardId shardId, String type, String id, long seqNo, long version, boolean found) {
|
||||
|
@ -57,37 +51,6 @@ public class DeleteResponse extends DocWriteResponse {
|
|||
return result == Result.DELETED ? super.status() : RestStatus.NOT_FOUND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder innerToXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.field(FOUND, result == Result.DELETED);
|
||||
super.innerToXContent(builder, params);
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static final ConstructingObjectParser<DeleteResponse, Void> PARSER;
|
||||
static {
|
||||
PARSER = new ConstructingObjectParser<>(DeleteResponse.class.getName(),
|
||||
args -> {
|
||||
// index uuid and shard id are unknown and can't be parsed back for now.
|
||||
ShardId shardId = new ShardId(new Index((String) args[0], IndexMetaData.INDEX_UUID_NA_VALUE), -1);
|
||||
String type = (String) args[1];
|
||||
String id = (String) args[2];
|
||||
long version = (long) args[3];
|
||||
ShardInfo shardInfo = (ShardInfo) args[5];
|
||||
long seqNo = (args[6] != null) ? (long) args[6] : SequenceNumbersService.UNASSIGNED_SEQ_NO;
|
||||
boolean found = (boolean) args[7];
|
||||
DeleteResponse deleteResponse = new DeleteResponse(shardId, type, id, seqNo, version, found);
|
||||
deleteResponse.setShardInfo(shardInfo);
|
||||
return deleteResponse;
|
||||
});
|
||||
DocWriteResponse.declareParserFields(PARSER);
|
||||
PARSER.declareBoolean(constructorArg(), new ParseField(FOUND));
|
||||
}
|
||||
|
||||
public static DeleteResponse fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
@ -100,4 +63,56 @@ public class DeleteResponse extends DocWriteResponse {
|
|||
builder.append(",shards=").append(getShardInfo());
|
||||
return builder.append("]").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder innerToXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.field(FOUND, result == Result.DELETED);
|
||||
super.innerToXContent(builder, params);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static DeleteResponse fromXContent(XContentParser parser) throws IOException {
|
||||
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
|
||||
|
||||
DeleteResponseBuilder context = new DeleteResponseBuilder();
|
||||
while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
|
||||
parseXContentFields(parser, context);
|
||||
}
|
||||
return context.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the current token and update the parsing context appropriately.
|
||||
*/
|
||||
public static void parseXContentFields(XContentParser parser, DeleteResponseBuilder context) throws IOException {
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
String currentFieldName = parser.currentName();
|
||||
|
||||
if (FOUND.equals(currentFieldName)) {
|
||||
if (token.isValue()) {
|
||||
context.setFound(parser.booleanValue());
|
||||
}
|
||||
} else {
|
||||
DocWriteResponse.parseInnerToXContent(parser, context);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DeleteResponseBuilder extends DocWriteResponse.DocWriteResponseBuilder {
|
||||
|
||||
private boolean found = false;
|
||||
|
||||
public void setFound(boolean found) {
|
||||
this.found = found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteResponse build() {
|
||||
DeleteResponse deleteResponse = new DeleteResponse(shardId, type, id, seqNo, version, found);
|
||||
deleteResponse.setForcedRefresh(forcedRefresh);
|
||||
if (shardInfo != null) {
|
||||
deleteResponse.setShardInfo(shardInfo);
|
||||
}
|
||||
return deleteResponse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,20 +20,15 @@
|
|||
package org.elasticsearch.action.index;
|
||||
|
||||
import org.elasticsearch.action.DocWriteResponse;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.seqno.SequenceNumbersService;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
||||
|
||||
/**
|
||||
* A response of an index operation,
|
||||
|
@ -78,34 +73,48 @@ public class IndexResponse extends DocWriteResponse {
|
|||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* ConstructingObjectParser used to parse the {@link IndexResponse}. We use a ObjectParser here
|
||||
* because most fields are parsed by the parent abstract class {@link DocWriteResponse} and it's
|
||||
* not easy to parse part of the fields in the parent class and other fields in the children class
|
||||
* using the usual streamed parsing method.
|
||||
*/
|
||||
private static final ConstructingObjectParser<IndexResponse, Void> PARSER;
|
||||
static {
|
||||
PARSER = new ConstructingObjectParser<>(IndexResponse.class.getName(),
|
||||
args -> {
|
||||
// index uuid and shard id are unknown and can't be parsed back for now.
|
||||
ShardId shardId = new ShardId(new Index((String) args[0], IndexMetaData.INDEX_UUID_NA_VALUE), -1);
|
||||
String type = (String) args[1];
|
||||
String id = (String) args[2];
|
||||
long version = (long) args[3];
|
||||
ShardInfo shardInfo = (ShardInfo) args[5];
|
||||
long seqNo = (args[6] != null) ? (long) args[6] : SequenceNumbersService.UNASSIGNED_SEQ_NO;
|
||||
boolean created = (boolean) args[7];
|
||||
public static IndexResponse fromXContent(XContentParser parser) throws IOException {
|
||||
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
|
||||
|
||||
IndexResponse indexResponse = new IndexResponse(shardId, type, id, seqNo, version, created);
|
||||
indexResponse.setShardInfo(shardInfo);
|
||||
return indexResponse;
|
||||
});
|
||||
DocWriteResponse.declareParserFields(PARSER);
|
||||
PARSER.declareBoolean(constructorArg(), new ParseField(CREATED));
|
||||
IndexResponseBuilder context = new IndexResponseBuilder();
|
||||
while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
|
||||
parseXContentFields(parser, context);
|
||||
}
|
||||
return context.build();
|
||||
}
|
||||
|
||||
public static IndexResponse fromXContent(XContentParser parser) throws IOException {
|
||||
return PARSER.apply(parser, null);
|
||||
/**
|
||||
* Parse the current token and update the parsing context appropriately.
|
||||
*/
|
||||
public static void parseXContentFields(XContentParser parser, IndexResponseBuilder context) throws IOException {
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
String currentFieldName = parser.currentName();
|
||||
|
||||
if (CREATED.equals(currentFieldName)) {
|
||||
if (token.isValue()) {
|
||||
context.setCreated(parser.booleanValue());
|
||||
}
|
||||
} else {
|
||||
DocWriteResponse.parseInnerToXContent(parser, context);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IndexResponseBuilder extends DocWriteResponse.DocWriteResponseBuilder {
|
||||
|
||||
private boolean created = false;
|
||||
|
||||
public void setCreated(boolean created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexResponse build() {
|
||||
IndexResponse indexResponse = new IndexResponse(shardId, type, id, seqNo, version, created);
|
||||
indexResponse.setForcedRefresh(forcedRefresh);
|
||||
if (shardInfo != null) {
|
||||
indexResponse.setShardInfo(shardInfo);
|
||||
}
|
||||
return indexResponse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,21 +20,18 @@
|
|||
package org.elasticsearch.action.update;
|
||||
|
||||
import org.elasticsearch.action.DocWriteResponse;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.get.GetResult;
|
||||
import org.elasticsearch.index.seqno.SequenceNumbersService;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
||||
|
||||
public class UpdateResponse extends DocWriteResponse {
|
||||
|
||||
|
@ -114,44 +111,54 @@ public class UpdateResponse extends DocWriteResponse {
|
|||
return builder.append("]").toString();
|
||||
}
|
||||
|
||||
private static final ConstructingObjectParser<UpdateResponse, Void> PARSER;
|
||||
static {
|
||||
PARSER = new ConstructingObjectParser<>(UpdateResponse.class.getName(),
|
||||
args -> {
|
||||
// index uuid and shard id are unknown and can't be parsed back for now.
|
||||
String index = (String) args[0];
|
||||
ShardId shardId = new ShardId(new Index(index, IndexMetaData.INDEX_UUID_NA_VALUE), -1);
|
||||
String type = (String) args[1];
|
||||
String id = (String) args[2];
|
||||
long version = (long) args[3];
|
||||
ShardInfo shardInfo = (ShardInfo) args[5];
|
||||
Long seqNo = (Long) args[6];
|
||||
public static UpdateResponse fromXContent(XContentParser parser) throws IOException {
|
||||
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
|
||||
|
||||
Result result = null;
|
||||
for (Result r : Result.values()) {
|
||||
if (r.getLowercase().equals(args[4])) {
|
||||
result = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateResponse updateResponse = null;
|
||||
if (shardInfo != null && seqNo != null) {
|
||||
updateResponse = new UpdateResponse(shardInfo, shardId, type, id, seqNo, version, result);
|
||||
} else {
|
||||
updateResponse = new UpdateResponse(shardId, type, id, version, result);
|
||||
}
|
||||
return updateResponse;
|
||||
});
|
||||
|
||||
DocWriteResponse.declareParserFields(PARSER);
|
||||
BiConsumer<UpdateResponse, GetResult> setGetResult = (update, get) ->
|
||||
update.setGetResult(new GetResult(update.getIndex(), update.getType(), update.getId(), update.getVersion(),
|
||||
get.isExists(), get.internalSourceRef(), get.getFields()));
|
||||
PARSER.declareObject(setGetResult, (parser, context) -> GetResult.fromXContentEmbedded(parser), new ParseField(GET));
|
||||
UpdateResponseBuilder context = new UpdateResponseBuilder();
|
||||
while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
|
||||
parseXContentFields(parser, context);
|
||||
}
|
||||
return context.build();
|
||||
}
|
||||
|
||||
public static UpdateResponse fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
/**
|
||||
* Parse the current token and update the parsing context appropriately.
|
||||
*/
|
||||
public static void parseXContentFields(XContentParser parser, UpdateResponseBuilder context) throws IOException {
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
String currentFieldName = parser.currentName();
|
||||
|
||||
if (GET.equals(currentFieldName)) {
|
||||
if (token == XContentParser.Token.START_OBJECT) {
|
||||
context.setGetResult(GetResult.fromXContentEmbedded(parser));
|
||||
}
|
||||
} else {
|
||||
DocWriteResponse.parseInnerToXContent(parser, context);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateResponseBuilder extends DocWriteResponse.DocWriteResponseBuilder {
|
||||
|
||||
private GetResult getResult = null;
|
||||
|
||||
public void setGetResult(GetResult getResult) {
|
||||
this.getResult = getResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateResponse build() {
|
||||
UpdateResponse update;
|
||||
if (shardInfo != null && seqNo != null) {
|
||||
update = new UpdateResponse(shardInfo, shardId, type, id, seqNo, version, result);
|
||||
} else {
|
||||
update = new UpdateResponse(shardId, type, id, version, result);
|
||||
}
|
||||
if (getResult != null) {
|
||||
update.setGetResult(new GetResult(update.getIndex(), update.getType(), update.getId(), update.getVersion(),
|
||||
getResult.isExists(),getResult.internalSourceRef(), getResult.getFields()));
|
||||
}
|
||||
update.setForcedRefresh(forcedRefresh);
|
||||
return update;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -859,7 +859,7 @@ public class ElasticsearchExceptionTests extends ESTestCase {
|
|||
} while (expected != null);
|
||||
}
|
||||
|
||||
private static Tuple<Throwable, ElasticsearchException> randomExceptions() {
|
||||
public static Tuple<Throwable, ElasticsearchException> randomExceptions() {
|
||||
Throwable actual;
|
||||
ElasticsearchException expected;
|
||||
|
||||
|
|
|
@ -19,12 +19,32 @@
|
|||
|
||||
package org.elasticsearch.action.bulk;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.DocWriteRequest;
|
||||
import org.elasticsearch.action.bulk.BulkItemResponse.Failure;
|
||||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.ElasticsearchExceptionTests.assertDeepEquals;
|
||||
import static org.elasticsearch.ElasticsearchExceptionTests.randomExceptions;
|
||||
import static org.elasticsearch.action.delete.DeleteResponseTests.assertDeleteResponse;
|
||||
import static org.elasticsearch.action.delete.DeleteResponseTests.randomDeleteResponse;
|
||||
import static org.elasticsearch.action.index.IndexResponseTests.assertIndexResponse;
|
||||
import static org.elasticsearch.action.index.IndexResponseTests.randomIndexResponse;
|
||||
import static org.elasticsearch.action.update.UpdateResponseTests.assertUpdateResponse;
|
||||
import static org.elasticsearch.action.update.UpdateResponseTests.randomUpdateResponse;
|
||||
import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class BulkItemResponseTests extends ESTestCase {
|
||||
|
||||
public void testFailureToString() {
|
||||
Failure failure = new Failure("index", "type", "id", new RuntimeException("test"));
|
||||
String toString = failure.toString();
|
||||
|
@ -32,4 +52,115 @@ public class BulkItemResponseTests extends ESTestCase {
|
|||
assertThat(toString, containsString("\"reason\":\"test\""));
|
||||
assertThat(toString, containsString("\"status\":500"));
|
||||
}
|
||||
|
||||
public void testToAndFromXContent() throws IOException {
|
||||
final XContentType xContentType = randomFrom(XContentType.values());
|
||||
|
||||
for (DocWriteRequest.OpType opType : DocWriteRequest.OpType.values()) {
|
||||
int bulkItemId = randomIntBetween(0, 100);
|
||||
boolean humanReadable = randomBoolean();
|
||||
BytesReference originalBytes = null;
|
||||
BulkItemResponse expectedBulkItemResponse = null;
|
||||
|
||||
if (opType == DocWriteRequest.OpType.INDEX || opType == DocWriteRequest.OpType.CREATE) {
|
||||
expectedBulkItemResponse = new BulkItemResponse(bulkItemId, opType, randomIndexResponse());
|
||||
originalBytes = toXContent(expectedBulkItemResponse, xContentType, humanReadable);
|
||||
|
||||
} else if (opType == DocWriteRequest.OpType.DELETE) {
|
||||
expectedBulkItemResponse = new BulkItemResponse(bulkItemId, opType, randomDeleteResponse());
|
||||
originalBytes = toXContent(expectedBulkItemResponse, xContentType, humanReadable);
|
||||
|
||||
} else if (opType == DocWriteRequest.OpType.UPDATE) {
|
||||
Tuple<UpdateResponse, UpdateResponse> updates = randomUpdateResponse(xContentType);
|
||||
expectedBulkItemResponse = new BulkItemResponse(bulkItemId, opType, updates.v2());
|
||||
originalBytes = toXContent(new BulkItemResponse(bulkItemId, opType, updates.v1()), xContentType, humanReadable);
|
||||
}
|
||||
|
||||
// Shuffle the XContent fields
|
||||
if (randomBoolean()) {
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
|
||||
originalBytes = shuffleXContent(parser, randomBoolean()).bytes();
|
||||
}
|
||||
}
|
||||
|
||||
BulkItemResponse parsedBulkItemResponse;
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
|
||||
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
|
||||
parsedBulkItemResponse = BulkItemResponse.fromXContent(parser, bulkItemId);
|
||||
assertNull(parser.nextToken());
|
||||
}
|
||||
|
||||
assertEquals(expectedBulkItemResponse.getIndex(), parsedBulkItemResponse.getIndex());
|
||||
assertEquals(expectedBulkItemResponse.getType(), parsedBulkItemResponse.getType());
|
||||
assertEquals(expectedBulkItemResponse.getId(), parsedBulkItemResponse.getId());
|
||||
assertEquals(expectedBulkItemResponse.getOpType(), parsedBulkItemResponse.getOpType());
|
||||
assertEquals(expectedBulkItemResponse.getVersion(), parsedBulkItemResponse.getVersion());
|
||||
assertEquals(bulkItemId, parsedBulkItemResponse.getItemId());
|
||||
|
||||
BytesReference finalBytes = toXContent(parsedBulkItemResponse, xContentType, humanReadable);
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), finalBytes)) {
|
||||
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
|
||||
assertEquals(XContentParser.Token.FIELD_NAME, parser.nextToken());
|
||||
assertEquals(opType.getLowercase(), parser.currentName());
|
||||
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
|
||||
|
||||
Map<String, Object> map = parser.map();
|
||||
|
||||
if (opType == DocWriteRequest.OpType.INDEX || opType == DocWriteRequest.OpType.CREATE) {
|
||||
assertIndexResponse(expectedBulkItemResponse.getResponse(), map);
|
||||
} else if (opType == DocWriteRequest.OpType.DELETE) {
|
||||
assertDeleteResponse(expectedBulkItemResponse.getResponse(), map);
|
||||
} else if (opType == DocWriteRequest.OpType.UPDATE) {
|
||||
assertUpdateResponse(expectedBulkItemResponse.getResponse(), parsedBulkItemResponse.getResponse(), map);
|
||||
} else {
|
||||
fail("Test does not support opType [" + opType + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testFailureToAndFromXContent() throws IOException {
|
||||
final XContentType xContentType = randomFrom(XContentType.values());
|
||||
|
||||
final Tuple<Throwable, ElasticsearchException> exceptions = randomExceptions();
|
||||
final Throwable cause = exceptions.v1();
|
||||
final ElasticsearchException expectedCause = exceptions.v2();
|
||||
|
||||
int bulkItemId = randomIntBetween(0, 100);
|
||||
String index = randomAsciiOfLength(5);
|
||||
String type = randomAsciiOfLength(5);
|
||||
String id = randomAsciiOfLength(5);
|
||||
DocWriteRequest.OpType opType = randomFrom(DocWriteRequest.OpType.values());
|
||||
|
||||
BulkItemResponse bulkItemResponse = new BulkItemResponse(bulkItemId, opType, new Failure(index, type, id, (Exception) cause));
|
||||
BytesReference originalBytes = toXContent(bulkItemResponse, xContentType, randomBoolean());
|
||||
|
||||
// Shuffle the XContent fields
|
||||
if (randomBoolean()) {
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
|
||||
originalBytes = shuffleXContent(parser, randomBoolean()).bytes();
|
||||
}
|
||||
}
|
||||
|
||||
BulkItemResponse parsedBulkItemResponse;
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
|
||||
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
|
||||
parsedBulkItemResponse = BulkItemResponse.fromXContent(parser, bulkItemId);
|
||||
assertNull(parser.nextToken());
|
||||
}
|
||||
|
||||
assertNotNull(parsedBulkItemResponse);
|
||||
assertEquals(index, parsedBulkItemResponse.getIndex());
|
||||
assertEquals(type, parsedBulkItemResponse.getType());
|
||||
assertEquals(id, parsedBulkItemResponse.getId());
|
||||
assertEquals(opType, parsedBulkItemResponse.getOpType());
|
||||
assertEquals(bulkItemId, parsedBulkItemResponse.getItemId());
|
||||
|
||||
Failure parsedFailure = parsedBulkItemResponse.getFailure();
|
||||
assertEquals(index, parsedFailure.getIndex());
|
||||
assertEquals(type, parsedFailure.getType());
|
||||
assertEquals(id, parsedFailure.getId());
|
||||
|
||||
assertDeepEquals(expectedCause, (ElasticsearchException) parsedFailure.getCause());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,13 @@ public class DeleteResponseTests extends ESTestCase {
|
|||
boolean humanReadable = randomBoolean();
|
||||
BytesReference deleteResponseBytes = toXContent(deleteResponse, xContentType, humanReadable);
|
||||
|
||||
// Shuffle the XContent fields
|
||||
if (randomBoolean()) {
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), deleteResponseBytes)) {
|
||||
deleteResponseBytes = shuffleXContent(parser, randomBoolean()).bytes();
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the XContent bytes to obtain a parsed
|
||||
DeleteResponse parsedDeleteResponse;
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), deleteResponseBytes)) {
|
||||
|
@ -81,7 +88,7 @@ public class DeleteResponseTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private static void assertDeleteResponse(DeleteResponse expected, Map<String, Object> actual) {
|
||||
public static void assertDeleteResponse(DeleteResponse expected, Map<String, Object> actual) {
|
||||
assertDocWriteResponse(expected, actual);
|
||||
if (expected.getResult() == DocWriteResponse.Result.DELETED) {
|
||||
assertTrue((boolean) actual.get("found"));
|
||||
|
@ -90,7 +97,7 @@ public class DeleteResponseTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private static DeleteResponse randomDeleteResponse() {
|
||||
public static DeleteResponse randomDeleteResponse() {
|
||||
ShardId shardId = new ShardId(randomAsciiOfLength(5), randomAsciiOfLength(5), randomIntBetween(0, 5));
|
||||
String type = randomAsciiOfLength(5);
|
||||
String id = randomAsciiOfLength(5);
|
||||
|
|
|
@ -59,13 +59,20 @@ public class IndexResponseTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testToAndFromXContent() throws IOException {
|
||||
final XContentType xContentType = randomFrom(XContentType.values());
|
||||
final XContentType xContentType = XContentType.JSON;//randomFrom(XContentType.values());
|
||||
|
||||
// Create a random IndexResponse and converts it to XContent in bytes
|
||||
IndexResponse indexResponse = randomIndexResponse();
|
||||
boolean humanReadable = randomBoolean();
|
||||
BytesReference indexResponseBytes = toXContent(indexResponse, xContentType, humanReadable);
|
||||
|
||||
// Shuffle the XContent fields
|
||||
if (randomBoolean()) {
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), indexResponseBytes)) {
|
||||
indexResponseBytes = shuffleXContent(parser, randomBoolean()).bytes();
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the XContent bytes to obtain a parsed
|
||||
IndexResponse parsedIndexResponse;
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), indexResponseBytes)) {
|
||||
|
@ -155,7 +162,7 @@ public class IndexResponseTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private static void assertIndexResponse(IndexResponse expected, Map<String, Object> actual) {
|
||||
public static void assertIndexResponse(IndexResponse expected, Map<String, Object> actual) {
|
||||
assertDocWriteResponse(expected, actual);
|
||||
if (expected.getResult() == DocWriteResponse.Result.CREATED) {
|
||||
assertTrue((boolean) actual.get("created"));
|
||||
|
@ -164,7 +171,7 @@ public class IndexResponseTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private static IndexResponse randomIndexResponse() {
|
||||
public static IndexResponse randomIndexResponse() {
|
||||
ShardId shardId = new ShardId(randomAsciiOfLength(5), randomAsciiOfLength(5), randomIntBetween(0, 5));
|
||||
String type = randomAsciiOfLength(5);
|
||||
String id = randomAsciiOfLength(5);
|
||||
|
|
|
@ -84,21 +84,34 @@ public class UpdateResponseTests extends ESTestCase {
|
|||
final Tuple<UpdateResponse, UpdateResponse> tuple = randomUpdateResponse(xContentType);
|
||||
boolean humanReadable = randomBoolean();
|
||||
|
||||
BytesReference updateResponseBytes = toXContent(tuple.v1(), xContentType, humanReadable);
|
||||
|
||||
// Shuffle the XContent fields
|
||||
if (randomBoolean()) {
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), updateResponseBytes)) {
|
||||
updateResponseBytes = shuffleXContent(parser, randomBoolean()).bytes();
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the XContent bytes to obtain a parsed UpdateResponse
|
||||
UpdateResponse parsedUpdateResponse;
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), toXContent(tuple.v1(), xContentType, humanReadable))) {
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), updateResponseBytes)) {
|
||||
parsedUpdateResponse = UpdateResponse.fromXContent(parser);
|
||||
assertNull(parser.nextToken());
|
||||
}
|
||||
|
||||
final UpdateResponse expectedUpdateResponse = tuple.v2();
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), toXContent(parsedUpdateResponse, xContentType, humanReadable))) {
|
||||
IndexResponseTests.assertDocWriteResponse(expectedUpdateResponse, parser.map());
|
||||
assertUpdateResponse(expectedUpdateResponse, parsedUpdateResponse, parser.map());
|
||||
}
|
||||
assertEquals(expectedUpdateResponse.getGetResult(), parsedUpdateResponse.getGetResult());
|
||||
}
|
||||
|
||||
private static Tuple<UpdateResponse, UpdateResponse> randomUpdateResponse(XContentType xContentType) {
|
||||
public static void assertUpdateResponse(UpdateResponse expected, UpdateResponse parsed, Map<String, Object> actual) throws IOException {
|
||||
IndexResponseTests.assertDocWriteResponse(expected, actual);
|
||||
assertEquals(expected.getGetResult(), parsed.getGetResult());
|
||||
}
|
||||
|
||||
public static Tuple<UpdateResponse, UpdateResponse> randomUpdateResponse(XContentType xContentType) {
|
||||
Tuple<GetResult, GetResult> getResults = GetResultTests.randomGetResult(xContentType);
|
||||
GetResult actualGetResult = getResults.v1();
|
||||
GetResult expectedGetResult = getResults.v2();
|
||||
|
|
Loading…
Reference in New Issue