[TEST] make sure that fromXContent doesn't rely on keys ordering (#23901)

We shuffle the keys before we parse our responses for the high level client so that we make sure we never rely on keys ordering.
This commit is contained in:
Luca Cavanna 2017-04-05 11:12:34 +02:00 committed by GitHub
parent afd45c1432
commit 318d365b12
27 changed files with 82 additions and 86 deletions

View File

@ -445,7 +445,8 @@ public class XContentHelper {
/** /**
* Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided * Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided
* {@link XContentType}. Wraps the output into a new anonymous object. * {@link XContentType}. Wraps the output into a new anonymous object according to the value returned
* by the {@link ToXContent#isFragment()} method returns.
*/ */
public static BytesReference toXContent(ToXContent toXContent, XContentType xContentType, boolean humanReadable) throws IOException { public static BytesReference toXContent(ToXContent toXContent, XContentType xContentType, boolean humanReadable) throws IOException {
return toXContent(toXContent, xContentType, ToXContent.EMPTY_PARAMS, humanReadable); return toXContent(toXContent, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
@ -453,7 +454,8 @@ public class XContentHelper {
/** /**
* Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided * Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided
* {@link XContentType}. Wraps the output into a new anonymous object. * {@link XContentType}. Wraps the output into a new anonymous object according to the value returned
* by the {@link ToXContent#isFragment()} method returns.
*/ */
public static BytesReference toXContent(ToXContent toXContent, XContentType xContentType, Params params, boolean humanReadable) throws IOException { public static BytesReference toXContent(ToXContent toXContent, XContentType xContentType, Params params, boolean humanReadable) throws IOException {
try (XContentBuilder builder = XContentBuilder.builder(xContentType.xContent())) { try (XContentBuilder builder = XContentBuilder.builder(xContentType.xContent())) {

View File

@ -58,7 +58,6 @@ import org.elasticsearch.search.SearchShardTarget;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.TestSearchContext; import org.elasticsearch.test.TestSearchContext;
import org.elasticsearch.transport.RemoteTransportException; import org.elasticsearch.transport.RemoteTransportException;
import org.hamcrest.Matcher;
import java.io.EOFException; import java.io.EOFException;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -427,6 +426,7 @@ public class ElasticsearchExceptionTests extends ESTestCase {
.field("stack_trace", "...") .field("stack_trace", "...")
.endObject(); .endObject();
builder = shuffleXContent(builder);
ElasticsearchException parsed; ElasticsearchException parsed;
try (XContentParser parser = createParser(xContent, builder.bytes())) { try (XContentParser parser = createParser(xContent, builder.bytes())) {
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken()); assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
@ -447,6 +447,7 @@ public class ElasticsearchExceptionTests extends ESTestCase {
final XContent xContent = randomFrom(XContentType.values()).xContent(); final XContent xContent = randomFrom(XContentType.values()).xContent();
XContentBuilder builder = XContentBuilder.builder(xContent).startObject().value(e).endObject(); XContentBuilder builder = XContentBuilder.builder(xContent).startObject().value(e).endObject();
builder = shuffleXContent(builder);
ElasticsearchException parsed; ElasticsearchException parsed;
try (XContentParser parser = createParser(builder)) { try (XContentParser parser = createParser(builder)) {
@ -491,6 +492,7 @@ public class ElasticsearchExceptionTests extends ESTestCase {
final XContent xContent = randomFrom(XContentType.values()).xContent(); final XContent xContent = randomFrom(XContentType.values()).xContent();
XContentBuilder builder = XContentBuilder.builder(xContent).startObject().value(foo).endObject(); XContentBuilder builder = XContentBuilder.builder(xContent).startObject().value(foo).endObject();
builder = shuffleXContent(builder);
ElasticsearchException parsed; ElasticsearchException parsed;
try (XContentParser parser = createParser(builder)) { try (XContentParser parser = createParser(builder)) {
@ -570,8 +572,9 @@ public class ElasticsearchExceptionTests extends ESTestCase {
.field("object_field", "value") .field("object_field", "value")
.endObject() .endObject()
.endObject(); .endObject();
try (XContentBuilder shuffledBuilder = shuffleXContent(builder)) {
originalBytes = builder.bytes(); originalBytes = shuffledBuilder.bytes();
}
} }
ElasticsearchException parsedException; ElasticsearchException parsedException;
@ -597,10 +600,10 @@ public class ElasticsearchExceptionTests extends ESTestCase {
final Tuple<Throwable, ElasticsearchException> exceptions = randomExceptions(); final Tuple<Throwable, ElasticsearchException> exceptions = randomExceptions();
final Throwable throwable = exceptions.v1(); final Throwable throwable = exceptions.v1();
BytesReference throwableBytes = XContentHelper.toXContent((builder, params) -> { BytesReference throwableBytes = toShuffledXContent((builder, params) -> {
ElasticsearchException.generateThrowableXContent(builder, params, throwable); ElasticsearchException.generateThrowableXContent(builder, params, throwable);
return builder; return builder;
}, xContent.type(), randomBoolean()); }, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean());
ElasticsearchException parsedException; ElasticsearchException parsedException;
try (XContentParser parser = createParser(xContent, throwableBytes)) { try (XContentParser parser = createParser(xContent, throwableBytes)) {
@ -615,11 +618,11 @@ public class ElasticsearchExceptionTests extends ESTestCase {
public void testUnknownFailureToAndFromXContent() throws IOException { public void testUnknownFailureToAndFromXContent() throws IOException {
final XContent xContent = randomFrom(XContentType.values()).xContent(); final XContent xContent = randomFrom(XContentType.values()).xContent();
BytesReference failureBytes = XContentHelper.toXContent((builder, params) -> { BytesReference failureBytes = toShuffledXContent((builder, params) -> {
// Prints a null failure using generateFailureXContent() // Prints a null failure using generateFailureXContent()
ElasticsearchException.generateFailureXContent(builder, params, null, randomBoolean()); ElasticsearchException.generateFailureXContent(builder, params, null, randomBoolean());
return builder; return builder;
}, xContent.type(), randomBoolean()); }, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean());
ElasticsearchException parsedFailure; ElasticsearchException parsedFailure;
try (XContentParser parser = createParser(xContent, failureBytes)) { try (XContentParser parser = createParser(xContent, failureBytes)) {
@ -640,10 +643,10 @@ public class ElasticsearchExceptionTests extends ESTestCase {
final XContent xContent = randomFrom(XContentType.values()).xContent(); final XContent xContent = randomFrom(XContentType.values()).xContent();
final Exception failure = (Exception) randomExceptions().v1(); final Exception failure = (Exception) randomExceptions().v1();
BytesReference failureBytes = XContentHelper.toXContent((builder, params) -> { BytesReference failureBytes = toShuffledXContent((builder, params) -> {
ElasticsearchException.generateFailureXContent(builder, params, failure, false); ElasticsearchException.generateFailureXContent(builder, params, failure, false);
return builder; return builder;
}, xContent.type(), randomBoolean()); }, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean());
try (XContentParser parser = createParser(xContent, failureBytes)) { try (XContentParser parser = createParser(xContent, failureBytes)) {
failureBytes = shuffleXContent(parser, randomBoolean()).bytes(); failureBytes = shuffleXContent(parser, randomBoolean()).bytes();
@ -785,10 +788,10 @@ public class ElasticsearchExceptionTests extends ESTestCase {
} }
Exception finalFailure = failure; Exception finalFailure = failure;
BytesReference failureBytes = XContentHelper.toXContent((builder, params) -> { BytesReference failureBytes = toShuffledXContent((builder, params) -> {
ElasticsearchException.generateFailureXContent(builder, params, finalFailure, true); ElasticsearchException.generateFailureXContent(builder, params, finalFailure, true);
return builder; return builder;
}, xContent.type(), randomBoolean()); }, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean());
try (XContentParser parser = createParser(xContent, failureBytes)) { try (XContentParser parser = createParser(xContent, failureBytes)) {
failureBytes = shuffleXContent(parser, randomBoolean()).bytes(); failureBytes = shuffleXContent(parser, randomBoolean()).bytes();
@ -807,7 +810,7 @@ public class ElasticsearchExceptionTests extends ESTestCase {
} }
/** /**
* Builds a {@link ToXContent} using a JSON XContentBuilder and check the resulting string with the given {@link Matcher}. * Builds a {@link ToXContent} using a JSON XContentBuilder and compares the result to the given json in string format.
* *
* By default, the stack trace of the exception is not rendered. The parameter `errorTrace` forces the stack trace to * By default, the stack trace of the exception is not rendered. The parameter `errorTrace` forces the stack trace to
* be rendered like the REST API does when the "error_trace" parameter is set to true. * be rendered like the REST API does when the "error_trace" parameter is set to true.

View File

@ -29,6 +29,7 @@ import org.elasticsearch.action.index.IndexResponseTests;
import org.elasticsearch.action.update.UpdateResponseTests; import org.elasticsearch.action.update.UpdateResponseTests;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
@ -37,7 +38,6 @@ import java.io.IOException;
import static org.elasticsearch.ElasticsearchExceptionTests.assertDeepEquals; import static org.elasticsearch.ElasticsearchExceptionTests.assertDeepEquals;
import static org.elasticsearch.ElasticsearchExceptionTests.randomExceptions; import static org.elasticsearch.ElasticsearchExceptionTests.randomExceptions;
import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
public class BulkItemResponseTests extends ESTestCase { public class BulkItemResponseTests extends ESTestCase {
@ -70,14 +70,7 @@ public class BulkItemResponseTests extends ESTestCase {
BulkItemResponse bulkItemResponse = new BulkItemResponse(bulkItemId, opType, randomDocWriteResponses.v1()); BulkItemResponse bulkItemResponse = new BulkItemResponse(bulkItemId, opType, randomDocWriteResponses.v1());
BulkItemResponse expectedBulkItemResponse = new BulkItemResponse(bulkItemId, opType, randomDocWriteResponses.v2()); BulkItemResponse expectedBulkItemResponse = new BulkItemResponse(bulkItemId, opType, randomDocWriteResponses.v2());
BytesReference originalBytes = toXContent(bulkItemResponse, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(bulkItemResponse, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
// Shuffle the XContent fields
if (randomBoolean()) {
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
originalBytes = shuffleXContent(parser, randomBoolean()).bytes();
}
}
BulkItemResponse parsedBulkItemResponse; BulkItemResponse parsedBulkItemResponse;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
@ -105,7 +98,7 @@ public class BulkItemResponseTests extends ESTestCase {
BulkItemResponse bulkItemResponse = new BulkItemResponse(itemId, opType, bulkItemFailure); BulkItemResponse bulkItemResponse = new BulkItemResponse(itemId, opType, bulkItemFailure);
Failure expectedBulkItemFailure = new Failure(index, type, id, exceptions.v2(), ExceptionsHelper.status(bulkItemCause)); Failure expectedBulkItemFailure = new Failure(index, type, id, exceptions.v2(), ExceptionsHelper.status(bulkItemCause));
BulkItemResponse expectedBulkItemResponse = new BulkItemResponse(itemId, opType, expectedBulkItemFailure); BulkItemResponse expectedBulkItemResponse = new BulkItemResponse(itemId, opType, expectedBulkItemFailure);
BytesReference originalBytes = toXContent(bulkItemResponse, xContentType, randomBoolean()); BytesReference originalBytes = toShuffledXContent(bulkItemResponse, xContentType, ToXContent.EMPTY_PARAMS, randomBoolean());
// Shuffle the XContent fields // Shuffle the XContent fields
if (randomBoolean()) { if (randomBoolean()) {

View File

@ -28,6 +28,7 @@ import org.elasticsearch.action.index.IndexResponseTests;
import org.elasticsearch.action.update.UpdateResponseTests; import org.elasticsearch.action.update.UpdateResponseTests;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
@ -86,13 +87,7 @@ public class BulkResponseTests extends ESTestCase {
} }
BulkResponse bulkResponse = new BulkResponse(bulkItems, took, ingestTook); BulkResponse bulkResponse = new BulkResponse(bulkItems, took, ingestTook);
BytesReference originalBytes = toXContent(bulkResponse, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(bulkResponse, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
if (randomBoolean()) {
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
originalBytes = shuffleXContent(parser, randomBoolean()).bytes();
}
}
BulkResponse parsedBulkResponse; BulkResponse parsedBulkResponse;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {

View File

@ -23,6 +23,7 @@ import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.seqno.SequenceNumbersService; import org.elasticsearch.index.seqno.SequenceNumbersService;
@ -34,7 +35,6 @@ import java.io.IOException;
import static org.elasticsearch.action.index.IndexResponseTests.assertDocWriteResponse; import static org.elasticsearch.action.index.IndexResponseTests.assertDocWriteResponse;
import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_UUID_NA_VALUE; import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_UUID_NA_VALUE;
import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
public class DeleteResponseTests extends ESTestCase { public class DeleteResponseTests extends ESTestCase {
@ -62,16 +62,8 @@ public class DeleteResponseTests extends ESTestCase {
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
final XContentType xContentType = randomFrom(XContentType.values()); final XContentType xContentType = randomFrom(XContentType.values());
BytesReference deleteResponseBytes = toXContent(deleteResponse, xContentType, humanReadable); BytesReference deleteResponseBytes = toShuffledXContent(deleteResponse, xContentType, ToXContent.EMPTY_PARAMS, 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
DeleteResponse parsedDeleteResponse; DeleteResponse parsedDeleteResponse;
try (XContentParser parser = createParser(xContentType.xContent(), deleteResponseBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), deleteResponseBytes)) {
parsedDeleteResponse = DeleteResponse.fromXContent(parser); parsedDeleteResponse = DeleteResponse.fromXContent(parser);

View File

@ -23,6 +23,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.get.GetField; import org.elasticsearch.index.get.GetField;
@ -46,7 +47,7 @@ public class GetResponseTests extends ESTestCase {
GetResponse getResponse = new GetResponse(tuple.v1()); GetResponse getResponse = new GetResponse(tuple.v1());
GetResponse expectedGetResponse = new GetResponse(tuple.v2()); GetResponse expectedGetResponse = new GetResponse(tuple.v2());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(getResponse, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(getResponse, xContentType, ToXContent.EMPTY_PARAMS, humanReadable, "_source");
//test that we can parse what we print out //test that we can parse what we print out
GetResponse parsedGetResponse; GetResponse parsedGetResponse;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {

View File

@ -24,6 +24,7 @@ import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.seqno.SequenceNumbersService; import org.elasticsearch.index.seqno.SequenceNumbersService;
@ -35,7 +36,6 @@ import java.io.IOException;
import static org.elasticsearch.action.support.replication.ReplicationResponseTests.assertShardInfo; import static org.elasticsearch.action.support.replication.ReplicationResponseTests.assertShardInfo;
import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_UUID_NA_VALUE; import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_UUID_NA_VALUE;
import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
public class IndexResponseTests extends ESTestCase { public class IndexResponseTests extends ESTestCase {
@ -63,16 +63,8 @@ public class IndexResponseTests extends ESTestCase {
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
BytesReference indexResponseBytes = toXContent(indexResponse, xContentType, humanReadable); BytesReference indexResponseBytes = toShuffledXContent(indexResponse, xContentType, ToXContent.EMPTY_PARAMS, 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; IndexResponse parsedIndexResponse;
try (XContentParser parser = createParser(xContentType.xContent(), indexResponseBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), indexResponseBytes)) {
parsedIndexResponse = IndexResponse.fromXContent(parser); parsedIndexResponse = IndexResponse.fromXContent(parser);

View File

@ -54,7 +54,7 @@ public class MainResponseTests extends ESTestCase {
MainResponse mainResponse = createTestItem(); MainResponse mainResponse = createTestItem();
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(mainResponse, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(mainResponse, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
MainResponse parsed; MainResponse parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
parsed = MainResponse.fromXContent(parser); parsed = MainResponse.fromXContent(parser);

View File

@ -27,7 +27,6 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContent; import org.elasticsearch.common.xcontent.XContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.Index; import org.elasticsearch.index.Index;
@ -157,7 +156,7 @@ public class SearchPhaseExecutionExceptionTests extends ESTestCase {
final String phase = randomFrom("query", "search", "other"); final String phase = randomFrom("query", "search", "other");
SearchPhaseExecutionException actual = new SearchPhaseExecutionException(phase, "unexpected failures", shardSearchFailures); SearchPhaseExecutionException actual = new SearchPhaseExecutionException(phase, "unexpected failures", shardSearchFailures);
BytesReference exceptionBytes = XContentHelper.toXContent(actual, xContent.type(), randomBoolean()); BytesReference exceptionBytes = toShuffledXContent(actual, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean());
ElasticsearchException parsedException; ElasticsearchException parsedException;
try (XContentParser parser = createParser(xContent, exceptionBytes)) { try (XContentParser parser = createParser(xContent, exceptionBytes)) {

View File

@ -25,6 +25,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.breaker.CircuitBreakingException; import org.elasticsearch.common.breaker.CircuitBreakingException;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.shard.ShardId;
@ -76,7 +77,7 @@ public class ReplicationResponseTests extends ESTestCase {
final XContentType xContentType = randomFrom(XContentType.values()); final XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(shardInfo, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(shardInfo, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
// Shuffle the XContent fields // Shuffle the XContent fields
if (randomBoolean()) { if (randomBoolean()) {

View File

@ -26,6 +26,7 @@ import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.Streamable; import org.elasticsearch.common.io.stream.Streamable;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
@ -459,7 +460,7 @@ public class UpdateRequestTests extends ESTestCase {
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = XContentHelper.toXContent(updateRequest, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(updateRequest, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
if (randomBoolean()) { if (randomBoolean()) {
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {

View File

@ -26,6 +26,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.get.GetField; import org.elasticsearch.index.get.GetField;
@ -44,7 +45,6 @@ import static org.elasticsearch.action.DocWriteResponse.Result.DELETED;
import static org.elasticsearch.action.DocWriteResponse.Result.NOT_FOUND; import static org.elasticsearch.action.DocWriteResponse.Result.NOT_FOUND;
import static org.elasticsearch.action.DocWriteResponse.Result.UPDATED; import static org.elasticsearch.action.DocWriteResponse.Result.UPDATED;
import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_UUID_NA_VALUE; import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_UUID_NA_VALUE;
import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
public class UpdateResponseTests extends ESTestCase { public class UpdateResponseTests extends ESTestCase {
@ -87,16 +87,8 @@ public class UpdateResponseTests extends ESTestCase {
UpdateResponse expectedUpdateResponse = tuple.v2(); UpdateResponse expectedUpdateResponse = tuple.v2();
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference updateResponseBytes = toXContent(updateResponse, xContentType, humanReadable); BytesReference updateResponseBytes = toShuffledXContent(updateResponse, xContentType, ToXContent.EMPTY_PARAMS, 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; UpdateResponse parsedUpdateResponse;
try (XContentParser parser = createParser(xContentType.xContent(), updateResponseBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), updateResponseBytes)) {
parsedUpdateResponse = UpdateResponse.fromXContent(parser); parsedUpdateResponse = UpdateResponse.fromXContent(parser);

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.get;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.mapper.ParentFieldMapper; import org.elasticsearch.index.mapper.ParentFieldMapper;
@ -58,7 +59,7 @@ public class GetFieldTests extends ESTestCase {
GetField getField = tuple.v1(); GetField getField = tuple.v1();
GetField expectedGetField = tuple.v2(); GetField expectedGetField = tuple.v2();
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(getField, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(getField, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
//test that we can parse what we print out //test that we can parse what we print out
GetField parsedGetField; GetField parsedGetField;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {

View File

@ -23,6 +23,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
@ -53,7 +54,7 @@ public class GetResultTests extends ESTestCase {
GetResult getResult = tuple.v1(); GetResult getResult = tuple.v1();
GetResult expectedGetResult = tuple.v2(); GetResult expectedGetResult = tuple.v2();
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(getResult, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(getResult, xContentType, ToXContent.EMPTY_PARAMS, humanReadable, "_source");
//test that we can parse what we print out //test that we can parse what we print out
GetResult parsedGetResult; GetResult parsedGetResult;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {

View File

@ -137,7 +137,7 @@ public class SearchHitTests extends ESTestCase {
SearchHit searchHit = createTestItem(true); SearchHit searchHit = createTestItem(true);
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
BytesReference originalBytes = toXContent(searchHit, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(searchHit, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
SearchHit parsed; SearchHit parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {

View File

@ -51,7 +51,7 @@ public class SearchHitsTests extends ESTestCase {
SearchHits searchHits = createTestItem(); SearchHits searchHits = createTestItem();
XContentType xcontentType = randomFrom(XContentType.values()); XContentType xcontentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(searchHits, xcontentType, humanReadable); BytesReference originalBytes = toShuffledXContent(searchHits, xcontentType, ToXContent.EMPTY_PARAMS, humanReadable);
SearchHits parsed; SearchHits parsed;
try (XContentParser parser = createParser(xcontentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xcontentType.xContent(), originalBytes)) {
parsed = SearchHits.fromXContent(parser); parsed = SearchHits.fromXContent(parser);

View File

@ -67,7 +67,7 @@ public class SearchSortValuesTests extends ESTestCase {
SearchSortValues sortValues = createTestItem(); SearchSortValues sortValues = createTestItem();
XContentType xcontentType = randomFrom(XContentType.values()); XContentType xcontentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(sortValues, xcontentType, humanReadable); BytesReference originalBytes = toShuffledXContent(sortValues, xcontentType, ToXContent.EMPTY_PARAMS, humanReadable);
SearchSortValues parsed; SearchSortValues parsed;
try (XContentParser parser = createParser(xcontentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xcontentType.xContent(), originalBytes)) {

View File

@ -65,7 +65,7 @@ public class ProfileResultTests extends ESTestCase {
ProfileResult profileResult = createTestItem(2); ProfileResult profileResult = createTestItem(2);
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(profileResult, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(profileResult, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
ProfileResult parsed; ProfileResult parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation); ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);

View File

@ -20,6 +20,7 @@
package org.elasticsearch.search.profile; package org.elasticsearch.search.profile;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.profile.aggregation.AggregationProfileShardResult; import org.elasticsearch.search.profile.aggregation.AggregationProfileShardResult;
@ -60,7 +61,7 @@ public class SearchProfileShardResultsTests extends ESTestCase {
SearchProfileShardResults shardResult = createTestItem(); SearchProfileShardResults shardResult = createTestItem();
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(shardResult, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(shardResult, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
SearchProfileShardResults parsed = null; SearchProfileShardResults parsed = null;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
ensureExpectedToken(parser.nextToken(), XContentParser.Token.START_OBJECT, parser::getTokenLocation); ensureExpectedToken(parser.nextToken(), XContentParser.Token.START_OBJECT, parser::getTokenLocation);

View File

@ -20,6 +20,7 @@
package org.elasticsearch.search.profile.aggregation; package org.elasticsearch.search.profile.aggregation;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParserUtils; import org.elasticsearch.common.xcontent.XContentParserUtils;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
@ -52,7 +53,7 @@ public class AggregationProfileShardResultTests extends ESTestCase {
AggregationProfileShardResult profileResult = createTestItem(2); AggregationProfileShardResult profileResult = createTestItem(2);
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(profileResult, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(profileResult, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
AggregationProfileShardResult parsed; AggregationProfileShardResult parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {

View File

@ -60,7 +60,7 @@ public class CollectorResultTests extends ESTestCase {
CollectorResult collectorResult = createTestItem(1); CollectorResult collectorResult = createTestItem(1);
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(collectorResult, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(collectorResult, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
CollectorResult parsed; CollectorResult parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {

View File

@ -20,6 +20,7 @@
package org.elasticsearch.search.profile.query; package org.elasticsearch.search.profile.query;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParserUtils; import org.elasticsearch.common.xcontent.XContentParserUtils;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
@ -54,7 +55,7 @@ public class QueryProfileShardResultTests extends ESTestCase {
QueryProfileShardResult profileResult = createTestItem(); QueryProfileShardResult profileResult = createTestItem();
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(profileResult, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(profileResult, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
QueryProfileShardResult parsed; QueryProfileShardResult parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {

View File

@ -21,6 +21,7 @@ package org.elasticsearch.search.suggest;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.text.Text; import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
@ -69,7 +70,7 @@ public class CompletionSuggestionOptionTests extends ESTestCase {
Option option = createTestItem(); Option option = createTestItem();
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(option, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(option, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
if (randomBoolean()) { if (randomBoolean()) {
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
originalBytes = shuffleXContent(parser, randomBoolean()).bytes(); originalBytes = shuffleXContent(parser, randomBoolean()).bytes();

View File

@ -21,6 +21,7 @@ package org.elasticsearch.search.suggest;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.text.Text; import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry; import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry;
@ -85,7 +86,7 @@ public class SuggestionEntryTests extends ESTestCase {
Entry<Option> entry = createTestItem(entryType); Entry<Option> entry = createTestItem(entryType);
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(entry, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(entry, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
Entry<Option> parsed; Entry<Option> parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation); ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);

View File

@ -21,6 +21,7 @@ package org.elasticsearch.search.suggest;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.text.Text; import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry.Option; import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry.Option;
@ -46,7 +47,7 @@ public class SuggestionOptionTests extends ESTestCase {
Option option = createTestItem(); Option option = createTestItem();
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(option, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(option, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
Option parsed; Option parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation); ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);

View File

@ -21,6 +21,7 @@ package org.elasticsearch.search.suggest;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.text.Text; import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.suggest.term.TermSuggestion.Entry.Option; import org.elasticsearch.search.suggest.term.TermSuggestion.Entry.Option;
@ -45,7 +46,7 @@ public class TermSuggestionOptionTests extends ESTestCase {
Option option = createTestItem(); Option option = createTestItem();
XContentType xContentType = randomFrom(XContentType.values()); XContentType xContentType = randomFrom(XContentType.values());
boolean humanReadable = randomBoolean(); boolean humanReadable = randomBoolean();
BytesReference originalBytes = toXContent(option, xContentType, humanReadable); BytesReference originalBytes = toShuffledXContent(option, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
Option parsed; Option parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation); ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);

View File

@ -886,13 +886,28 @@ public abstract class ESTestCase extends LuceneTestCase {
} }
} }
/**
* Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided
* {@link XContentType}. Wraps the output into a new anonymous object according to the value returned
* by the {@link ToXContent#isFragment()} method returns. Shuffles the keys to make sure that parsing never relies on keys ordering.
*/
protected final BytesReference toShuffledXContent(ToXContent toXContent, XContentType xContentType, ToXContent.Params params,
boolean humanReadable, String... exceptFieldNames) throws IOException{
BytesReference bytes = XContentHelper.toXContent(toXContent, xContentType, params, humanReadable);
try (XContentParser parser = createParser(xContentType.xContent(), bytes)) {
try (XContentBuilder builder = shuffleXContent(parser, rarely(), exceptFieldNames)) {
return builder.bytes();
}
}
}
/** /**
* Randomly shuffles the fields inside objects in the {@link XContentBuilder} passed in. * Randomly shuffles the fields inside objects in the {@link XContentBuilder} passed in.
* Recursively goes through inner objects and also shuffles them. Exceptions for this * Recursively goes through inner objects and also shuffles them. Exceptions for this
* recursive shuffling behavior can be made by passing in the names of fields which * recursive shuffling behavior can be made by passing in the names of fields which
* internally should stay untouched. * internally should stay untouched.
*/ */
public XContentBuilder shuffleXContent(XContentBuilder builder, String... exceptFieldNames) throws IOException { protected final XContentBuilder shuffleXContent(XContentBuilder builder, String... exceptFieldNames) throws IOException {
try (XContentParser parser = createParser(builder)) { try (XContentParser parser = createParser(builder)) {
return shuffleXContent(parser, builder.isPrettyPrint(), exceptFieldNames); return shuffleXContent(parser, builder.isPrettyPrint(), exceptFieldNames);
} }
@ -904,8 +919,8 @@ public abstract class ESTestCase extends LuceneTestCase {
* recursive shuffling behavior can be made by passing in the names of fields which * recursive shuffling behavior can be made by passing in the names of fields which
* internally should stay untouched. * internally should stay untouched.
*/ */
public XContentBuilder shuffleXContent(XContentParser parser, boolean prettyPrint, String... exceptFieldNames) throws IOException { protected static XContentBuilder shuffleXContent(XContentParser parser, boolean prettyPrint, String... exceptFieldNames) throws IOException {
// use ordered maps for reproducibility //TODO why do we need sorted map if we later sort the keys right before shuffling them? That should be enough?
Map<String, Object> shuffledMap = shuffleMap(parser.mapOrdered(), new HashSet<>(Arrays.asList(exceptFieldNames))); Map<String, Object> shuffledMap = shuffleMap(parser.mapOrdered(), new HashSet<>(Arrays.asList(exceptFieldNames)));
XContentBuilder xContentBuilder = XContentFactory.contentBuilder(parser.contentType()); XContentBuilder xContentBuilder = XContentFactory.contentBuilder(parser.contentType());
if (prettyPrint) { if (prettyPrint) {
@ -916,7 +931,6 @@ public abstract class ESTestCase extends LuceneTestCase {
private static Map<String, Object> shuffleMap(Map<String, Object> map, Set<String> exceptFields) { private static Map<String, Object> shuffleMap(Map<String, Object> map, Set<String> exceptFields) {
List<String> keys = new ArrayList<>(map.keySet()); List<String> keys = new ArrayList<>(map.keySet());
// even though we shuffle later, we need this to make tests reproduce on different jvms // even though we shuffle later, we need this to make tests reproduce on different jvms
Collections.sort(keys); Collections.sort(keys);
Map<String, Object> targetMap = new TreeMap<>(); Map<String, Object> targetMap = new TreeMap<>();
@ -924,7 +938,9 @@ public abstract class ESTestCase extends LuceneTestCase {
for (String key : keys) { for (String key : keys) {
Object value = map.get(key); Object value = map.get(key);
if (value instanceof Map && exceptFields.contains(key) == false) { if (value instanceof Map && exceptFields.contains(key) == false) {
targetMap.put(key, shuffleMap((Map) value, exceptFields)); @SuppressWarnings("unchecked")
Map<String, Object> valueMap = (Map<String, Object>) value;
targetMap.put(key, shuffleMap(valueMap, exceptFields));
} else { } else {
targetMap.put(key, value); targetMap.put(key, value);
} }