diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/AbstractChallengeRestTest.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/AbstractChallengeRestTest.java index 60c7d07115ef2..4b22e518307d0 100644 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/AbstractChallengeRestTest.java +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/AbstractChallengeRestTest.java @@ -14,7 +14,6 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.core.CheckedConsumer; -import org.elasticsearch.core.Tuple; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.test.cluster.ElasticsearchCluster; @@ -221,44 +220,16 @@ private XContentBuilder createContenderMappings() throws IOException { public abstract void contenderMappings(XContentBuilder builder) throws IOException; - public void baselineSettings(Settings.Builder builder) {} + public abstract void baselineSettings(Settings.Builder builder); - public void contenderSettings(Settings.Builder builder) {} + public abstract void contenderSettings(Settings.Builder builder); public void commonSettings(Settings.Builder builder) {} - private Response indexDocuments( - final String dataStreamName, - final CheckedSupplier, IOException> documentsSupplier - ) throws IOException { - final StringBuilder sb = new StringBuilder(); - int id = 0; - for (var document : documentsSupplier.get()) { - sb.append(Strings.format("{ \"create\": { \"_id\" : \"%d\" } }", id)).append("\n"); - sb.append(Strings.toString(document)).append("\n"); - id++; - } - var request = new Request("POST", "/" + dataStreamName + "/_bulk"); - request.setJsonEntity(sb.toString()); - request.addParameter("refresh", "true"); - return client.performRequest(request); - } - - public Response indexBaselineDocuments(final CheckedSupplier, IOException> documentsSupplier) throws IOException { - return indexDocuments(getBaselineDataStreamName(), documentsSupplier); - } - - public Response indexContenderDocuments(final CheckedSupplier, IOException> documentsSupplier) - throws IOException { - return indexDocuments(getContenderDataStreamName(), documentsSupplier); - } - - public Tuple indexDocuments( - final CheckedSupplier, IOException> baselineSupplier, - final CheckedSupplier, IOException> contenderSupplier - ) throws IOException { - return new Tuple<>(indexBaselineDocuments(baselineSupplier), indexContenderDocuments(contenderSupplier)); - } + public abstract void indexDocuments( + CheckedSupplier, IOException> baselineSupplier, + CheckedSupplier, IOException> contenderSupplier + ) throws IOException; public Response queryBaseline(final SearchSourceBuilder search) throws IOException { return query(search, this::getBaselineDataStreamName); diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkChallengeRestIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkChallengeRestIT.java new file mode 100644 index 0000000000000..3f5b69c170f51 --- /dev/null +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkChallengeRestIT.java @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.logsdb.qa; + +import org.elasticsearch.common.CheckedSupplier; +import org.elasticsearch.common.Strings; +import org.elasticsearch.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + * Challenge test that uses bulk indexing for both baseline and contender sides. + * We index same documents into an index with standard index mode and an index with logsdb index mode. + * Then we verify that results of common operations are the same modulo knows differences like synthetic source + * modifications. + */ +public class BulkChallengeRestIT extends StandardVersusLogsIndexModeChallengeRestIT { + + public BulkChallengeRestIT() {} + + protected BulkChallengeRestIT(DataGenerationHelper dataGenerationHelper) { + super(dataGenerationHelper); + } + + @Override + public void indexDocuments( + final CheckedSupplier, IOException> baselineSupplier, + final CheckedSupplier, IOException> contenderSupplier + ) throws IOException { + var contenderResponseEntity = indexContenderDocuments(contenderSupplier); + indexBaselineDocuments(baselineSupplier, contenderResponseEntity); + } + + private Map indexContenderDocuments(final CheckedSupplier, IOException> documentsSupplier) + throws IOException { + final StringBuilder sb = new StringBuilder(); + int id = 0; + for (var document : documentsSupplier.get()) { + if (autoGenerateId()) { + sb.append("{ \"create\": { } }\n"); + } else { + sb.append(Strings.format("{ \"create\": { \"_id\" : \"%d\" } }\n", id)); + } + sb.append(Strings.toString(document)).append("\n"); + id++; + } + return performBulkRequest(sb.toString(), false); + } + + @SuppressWarnings("unchecked") + private void indexBaselineDocuments( + final CheckedSupplier, IOException> documentsSupplier, + final Map contenderResponseEntity + ) throws IOException { + final StringBuilder sb = new StringBuilder(); + int id = 0; + final List> items = (List>) contenderResponseEntity.get("items"); + for (var document : documentsSupplier.get()) { + if (autoGenerateId()) { + var contenderId = ((Map) items.get(id).get("create")).get("_id"); + sb.append(Strings.format("{ \"create\": { \"_id\" : \"%s\" } }\n", contenderId)); + } else { + sb.append(Strings.format("{ \"create\": { \"_id\" : \"%d\" } }\n", id)); + } + sb.append(Strings.toString(document)).append("\n"); + id++; + } + performBulkRequest(sb.toString(), true); + } +} diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeRandomDataDynamicMappingChallengeRestIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkDynamicMappingChallengeRestIT.java similarity index 76% rename from x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeRandomDataDynamicMappingChallengeRestIT.java rename to x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkDynamicMappingChallengeRestIT.java index c1f97823b963a..d9870ed054b28 100644 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeRandomDataDynamicMappingChallengeRestIT.java +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkDynamicMappingChallengeRestIT.java @@ -9,9 +9,8 @@ import org.elasticsearch.common.settings.Settings; -public class StandardVersusLogsIndexModeRandomDataDynamicMappingChallengeRestIT extends - StandardVersusLogsIndexModeRandomDataChallengeRestIT { - public StandardVersusLogsIndexModeRandomDataDynamicMappingChallengeRestIT() { +public class BulkDynamicMappingChallengeRestIT extends BulkChallengeRestIT { + public BulkDynamicMappingChallengeRestIT() { super(new DataGenerationHelper(builder -> builder.withFullyDynamicMapping(true))); } diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkStaticMappingChallengeRestIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkStaticMappingChallengeRestIT.java new file mode 100644 index 0000000000000..20d2d91977080 --- /dev/null +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkStaticMappingChallengeRestIT.java @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.logsdb.qa; + +import org.elasticsearch.common.time.DateFormatter; +import org.elasticsearch.common.time.FormatNames; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentFactory; + +import java.io.IOException; +import java.time.Instant; + +/** + * This test uses simple mapping and document structure in order to allow easier debugging of the test itself. + */ +public class BulkStaticMappingChallengeRestIT extends BulkChallengeRestIT { + public BulkStaticMappingChallengeRestIT() {} + + @Override + public void baselineMappings(XContentBuilder builder) throws IOException { + if (fullyDynamicMapping == false) { + builder.startObject() + .startObject("properties") + + .startObject("@timestamp") + .field("type", "date") + .endObject() + + .startObject("host.name") + .field("type", "keyword") + .field("ignore_above", randomIntBetween(1000, 1200)) + .endObject() + + .startObject("message") + .field("type", "keyword") + .field("ignore_above", randomIntBetween(1000, 1200)) + .endObject() + + .startObject("method") + .field("type", "keyword") + .field("ignore_above", randomIntBetween(1000, 1200)) + .endObject() + + .startObject("memory_usage_bytes") + .field("type", "long") + .field("ignore_malformed", randomBoolean()) + .endObject() + + .endObject() + + .endObject(); + } else { + // We want dynamic mapping, but we need host.name to be a keyword instead of text to support aggregations. + builder.startObject() + .startObject("properties") + + .startObject("host.name") + .field("type", "keyword") + .field("ignore_above", randomIntBetween(1000, 1200)) + .endObject() + + .endObject() + .endObject(); + } + } + + @Override + public void contenderMappings(XContentBuilder builder) throws IOException { + builder.startObject(); + builder.field("subobjects", false); + + if (fullyDynamicMapping == false) { + builder.startObject("properties") + + .startObject("@timestamp") + .field("type", "date") + .endObject() + + .startObject("host.name") + .field("type", "keyword") + .field("ignore_above", randomIntBetween(1000, 1200)) + .endObject() + + .startObject("message") + .field("type", "keyword") + .field("ignore_above", randomIntBetween(1000, 1200)) + .endObject() + + .startObject("method") + .field("type", "keyword") + .field("ignore_above", randomIntBetween(1000, 1200)) + .endObject() + + .startObject("memory_usage_bytes") + .field("type", "long") + .field("ignore_malformed", randomBoolean()) + .endObject() + + .endObject(); + } + + builder.endObject(); + } + + @Override + protected XContentBuilder generateDocument(final Instant timestamp) throws IOException { + return XContentFactory.jsonBuilder() + .startObject() + .field("@timestamp", DateFormatter.forPattern(FormatNames.STRICT_DATE_OPTIONAL_TIME.getName()).format(timestamp)) + .field("host.name", randomFrom("foo", "bar", "baz")) + .field("message", randomFrom("a message", "another message", "still another message", "one more message")) + .field("method", randomFrom("put", "post", "get")) + .field("memory_usage_bytes", randomLongBetween(1000, 2000)) + .endObject(); + } +} diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsStoredSourceChallengeRestIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkStoredSourceChallengeRestIT.java similarity index 85% rename from x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsStoredSourceChallengeRestIT.java rename to x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkStoredSourceChallengeRestIT.java index 2f018b7dc0b38..ab5be0fe5760c 100644 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsStoredSourceChallengeRestIT.java +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/BulkStoredSourceChallengeRestIT.java @@ -13,7 +13,7 @@ * This test compares behavior of a standard mode data stream and a logsdb data stream using stored source. * There should be no differences between such two data streams. */ -public class StandardVersusLogsStoredSourceChallengeRestIT extends StandardVersusLogsIndexModeRandomDataChallengeRestIT { +public class BulkStoredSourceChallengeRestIT extends BulkChallengeRestIT { @Override public void contenderSettings(Settings.Builder builder) { super.contenderSettings(builder); diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/ReindexChallengeRestIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/ReindexChallengeRestIT.java index 83344b688ff8c..4833fbee42ddb 100644 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/ReindexChallengeRestIT.java +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/ReindexChallengeRestIT.java @@ -8,8 +8,8 @@ package org.elasticsearch.xpack.logsdb.qa; import org.elasticsearch.client.Request; -import org.elasticsearch.client.Response; import org.elasticsearch.common.CheckedSupplier; +import org.elasticsearch.common.Strings; import org.elasticsearch.xcontent.XContentBuilder; import java.io.IOException; @@ -18,9 +18,29 @@ import static org.hamcrest.Matchers.equalTo; -public abstract class ReindexChallengeRestIT extends StandardVersusLogsIndexModeRandomDataChallengeRestIT { +public abstract class ReindexChallengeRestIT extends StandardVersusLogsIndexModeChallengeRestIT { + @Override - public Response indexContenderDocuments(CheckedSupplier, IOException> documentsSupplier) throws IOException { + public void indexDocuments( + final CheckedSupplier, IOException> baselineSupplier, + final CheckedSupplier, IOException> contencontenderSupplierderSupplier + ) throws IOException { + indexBaselineDocuments(baselineSupplier); + indexContenderDocuments(); + } + + private void indexBaselineDocuments(final CheckedSupplier, IOException> documentsSupplier) throws IOException { + final StringBuilder sb = new StringBuilder(); + int id = 0; + for (var document : documentsSupplier.get()) { + sb.append(Strings.format("{ \"create\": { \"_id\" : \"%d\" } }\n", id)); + sb.append(Strings.toString(document)).append("\n"); + id++; + } + performBulkRequest(sb.toString(), true); + } + + private void indexContenderDocuments() throws IOException { var reindexRequest = new Request("POST", "/_reindex?refresh=true"); reindexRequest.setJsonEntity(String.format(Locale.ROOT, """ { @@ -38,7 +58,5 @@ public Response indexContenderDocuments(CheckedSupplier, I var body = entityAsMap(response); assertThat("encountered failures when performing reindex:\n " + body, body.get("failures"), equalTo(List.of())); - - return response; } } diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeChallengeRestIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeChallengeRestIT.java index f18e57c229345..2a8c85efc863b 100644 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeChallengeRestIT.java +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeChallengeRestIT.java @@ -11,7 +11,6 @@ import org.elasticsearch.client.Response; import org.elasticsearch.client.ResponseException; import org.elasticsearch.client.RestClient; -import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.time.DateFormatter; import org.elasticsearch.common.time.FormatNames; @@ -19,7 +18,6 @@ import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.logsdb.datageneration.matchers.MatchResult; import org.elasticsearch.logsdb.datageneration.matchers.Matcher; -import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval; import org.elasticsearch.search.aggregations.bucket.histogram.HistogramAggregationBuilder; @@ -29,7 +27,6 @@ import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.XContentFactory; import org.elasticsearch.xcontent.XContentType; -import org.hamcrest.Matchers; import java.io.IOException; import java.time.Instant; @@ -46,103 +43,34 @@ import static org.hamcrest.Matchers.greaterThan; /** - * Basic challenge test - we index same documents into an index with standard index mode and an index with logsdb index mode. - * Then we verify that results of common operations are the same modulo knows differences like synthetic source modifications. - * This test uses simple mapping and document structure in order to allow easier debugging of the test itself. + * Challenge test (see {@link BulkStaticMappingChallengeRestIT}) that uses randomly generated + * mapping and documents in order to cover more code paths and permutations. */ -public class StandardVersusLogsIndexModeChallengeRestIT extends AbstractChallengeRestTest { +public abstract class StandardVersusLogsIndexModeChallengeRestIT extends AbstractChallengeRestTest { + protected final boolean fullyDynamicMapping = randomBoolean(); + private final boolean useCustomSortConfig = fullyDynamicMapping == false && randomBoolean(); + private final boolean routeOnSortFields = useCustomSortConfig && randomBoolean(); private final int numShards = randomBoolean() ? randomIntBetween(2, 4) : 0; private final int numReplicas = randomBoolean() ? randomIntBetween(1, 3) : 0; - private final boolean fullyDynamicMapping = randomBoolean(); + protected final DataGenerationHelper dataGenerationHelper; public StandardVersusLogsIndexModeChallengeRestIT() { + this(new DataGenerationHelper()); + } + + protected StandardVersusLogsIndexModeChallengeRestIT(DataGenerationHelper dataGenerationHelper) { super("standard-apache-baseline", "logs-apache-contender", "baseline-template", "contender-template", 101, 101); + this.dataGenerationHelper = dataGenerationHelper; } @Override public void baselineMappings(XContentBuilder builder) throws IOException { - if (fullyDynamicMapping == false) { - builder.startObject() - .startObject("properties") - - .startObject("@timestamp") - .field("type", "date") - .endObject() - - .startObject("host.name") - .field("type", "keyword") - .field("ignore_above", randomIntBetween(1000, 1200)) - .endObject() - - .startObject("message") - .field("type", "keyword") - .field("ignore_above", randomIntBetween(1000, 1200)) - .endObject() - - .startObject("method") - .field("type", "keyword") - .field("ignore_above", randomIntBetween(1000, 1200)) - .endObject() - - .startObject("memory_usage_bytes") - .field("type", "long") - .field("ignore_malformed", randomBoolean()) - .endObject() - - .endObject() - - .endObject(); - } else { - // We want dynamic mapping, but we need host.name to be a keyword instead of text to support aggregations. - builder.startObject() - .startObject("properties") - - .startObject("host.name") - .field("type", "keyword") - .field("ignore_above", randomIntBetween(1000, 1200)) - .endObject() - - .endObject() - .endObject(); - } + dataGenerationHelper.standardMapping(builder); } @Override public void contenderMappings(XContentBuilder builder) throws IOException { - builder.startObject(); - builder.field("subobjects", false); - - if (fullyDynamicMapping == false) { - builder.startObject("properties") - - .startObject("@timestamp") - .field("type", "date") - .endObject() - - .startObject("host.name") - .field("type", "keyword") - .field("ignore_above", randomIntBetween(1000, 1200)) - .endObject() - - .startObject("message") - .field("type", "keyword") - .field("ignore_above", randomIntBetween(1000, 1200)) - .endObject() - - .startObject("method") - .field("type", "keyword") - .field("ignore_above", randomIntBetween(1000, 1200)) - .endObject() - - .startObject("memory_usage_bytes") - .field("type", "long") - .field("ignore_malformed", randomBoolean()) - .endObject() - - .endObject(); - } - - builder.endObject(); + dataGenerationHelper.logsDbMapping(builder); } @Override @@ -159,6 +87,14 @@ public void commonSettings(Settings.Builder builder) { @Override public void contenderSettings(Settings.Builder builder) { builder.put("index.mode", "logsdb"); + if (useCustomSortConfig) { + builder.putList("index.sort.field", "host.name", "method", "@timestamp"); + builder.putList("index.sort.order", "asc", "asc", "desc"); + if (routeOnSortFields) { + builder.put("index.logsdb.route_on_sort_fields", true); + } + } + dataGenerationHelper.logsDbSettings(builder); } @Override @@ -169,6 +105,10 @@ public void beforeStart() throws Exception { waitForLogs(client()); } + protected boolean autoGenerateId() { + return routeOnSortFields; + } + protected static void waitForLogs(RestClient client) throws Exception { assertBusy(() -> { try { @@ -330,28 +270,6 @@ public void testFieldCaps() throws IOException { assertTrue(matchResult.getMessage(), matchResult.isMatch()); } - @Override - public Response indexBaselineDocuments(CheckedSupplier, IOException> documentsSupplier) throws IOException { - var response = super.indexBaselineDocuments(documentsSupplier); - - assertThat(response.getStatusLine().getStatusCode(), Matchers.equalTo(RestStatus.OK.getStatus())); - var baselineResponseBody = entityAsMap(response); - assertThat("errors in baseline bulk response:\n " + baselineResponseBody, baselineResponseBody.get("errors"), equalTo(false)); - - return response; - } - - @Override - public Response indexContenderDocuments(CheckedSupplier, IOException> documentsSupplier) throws IOException { - var response = super.indexContenderDocuments(documentsSupplier); - - assertThat(response.getStatusLine().getStatusCode(), Matchers.equalTo(RestStatus.OK.getStatus())); - var contenderResponseBody = entityAsMap(response); - assertThat("errors in contender bulk response:\n " + contenderResponseBody, contenderResponseBody.get("errors"), equalTo(false)); - - return response; - } - private List generateDocuments(int numberOfDocuments) throws IOException { final List documents = new ArrayList<>(); // This is static in order to be able to identify documents between test runs. @@ -364,14 +282,12 @@ private List generateDocuments(int numberOfDocuments) throws IO } protected XContentBuilder generateDocument(final Instant timestamp) throws IOException { - return XContentFactory.jsonBuilder() - .startObject() - .field("@timestamp", DateFormatter.forPattern(FormatNames.STRICT_DATE_OPTIONAL_TIME.getName()).format(timestamp)) - .field("host.name", randomFrom("foo", "bar", "baz")) - .field("message", randomFrom("a message", "another message", "still another message", "one more message")) - .field("method", randomFrom("put", "post", "get")) - .field("memory_usage_bytes", randomLongBetween(1000, 2000)) - .endObject(); + var document = XContentFactory.jsonBuilder(); + dataGenerationHelper.generateDocument( + document, + Map.of("@timestamp", DateFormatter.forPattern(FormatNames.STRICT_DATE_OPTIONAL_TIME.getName()).format(timestamp)) + ); + return document; } @SuppressWarnings("unchecked") @@ -383,7 +299,7 @@ private static List> getQueryHits(final Response response) t assertThat(hitsList.size(), greaterThan(0)); return hitsList.stream() - .sorted(Comparator.comparingInt((Map hit) -> Integer.parseInt((String) hit.get("_id")))) + .sorted(Comparator.comparing((Map hit) -> ((String) hit.get("_id")))) .map(hit -> (Map) hit.get("_source")) .toList(); } @@ -404,7 +320,7 @@ private static List> getEsqlSourceResults(final Response res // Results contain a list of [source, id] lists. return values.stream() - .sorted(Comparator.comparingInt((List value) -> Integer.parseInt((String) value.get(1)))) + .sorted(Comparator.comparing((List value) -> ((String) value.get(1)))) .map(value -> (Map) value.get(0)) .toList(); } @@ -437,4 +353,19 @@ private static List> getAggregationBuckets(final Response re private void indexDocuments(List documents) throws IOException { indexDocuments(() -> documents, () -> documents); } + + protected final Map performBulkRequest(String json, boolean isBaseline) throws IOException { + var request = new Request("POST", "/" + (isBaseline ? getBaselineDataStreamName() : getContenderDataStreamName()) + "/_bulk"); + request.setJsonEntity(json); + request.addParameter("refresh", "true"); + var response = client.performRequest(request); + assertOK(response); + var responseBody = entityAsMap(response); + assertThat( + "errors in " + (isBaseline ? "baseline" : "contender") + " bulk response:\n " + responseBody, + responseBody.get("errors"), + equalTo(false) + ); + return responseBody; + } } diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeRandomDataChallengeRestIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeRandomDataChallengeRestIT.java deleted file mode 100644 index 3b141908f45b1..0000000000000 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeRandomDataChallengeRestIT.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.logsdb.qa; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.time.DateFormatter; -import org.elasticsearch.common.time.FormatNames; -import org.elasticsearch.xcontent.XContentBuilder; -import org.elasticsearch.xcontent.XContentFactory; - -import java.io.IOException; -import java.time.Instant; -import java.util.Map; - -/** - * Challenge test (see {@link StandardVersusLogsIndexModeChallengeRestIT}) that uses randomly generated - * mapping and documents in order to cover more code paths and permutations. - */ -public class StandardVersusLogsIndexModeRandomDataChallengeRestIT extends StandardVersusLogsIndexModeChallengeRestIT { - protected final DataGenerationHelper dataGenerationHelper; - - public StandardVersusLogsIndexModeRandomDataChallengeRestIT() { - this(new DataGenerationHelper()); - } - - protected StandardVersusLogsIndexModeRandomDataChallengeRestIT(DataGenerationHelper dataGenerationHelper) { - super(); - this.dataGenerationHelper = dataGenerationHelper; - } - - @Override - public void baselineMappings(XContentBuilder builder) throws IOException { - dataGenerationHelper.standardMapping(builder); - } - - @Override - public void contenderMappings(XContentBuilder builder) throws IOException { - dataGenerationHelper.logsDbMapping(builder); - } - - @Override - public void contenderSettings(Settings.Builder builder) { - super.contenderSettings(builder); - dataGenerationHelper.logsDbSettings(builder); - } - - @Override - protected XContentBuilder generateDocument(final Instant timestamp) throws IOException { - var document = XContentFactory.jsonBuilder(); - dataGenerationHelper.generateDocument( - document, - Map.of("@timestamp", DateFormatter.forPattern(FormatNames.STRICT_DATE_OPTIONAL_TIME.getName()).format(timestamp)) - ); - return document; - } -}