Skip to content

Commit bf8e14f

Browse files
authored
ESQL: Assert no partial results in integration tests (#129293) (#129568)
This injects assertions in spec-based and YAML integration tests that the received results aren't partial. This only happens in case the tests themselves don't set "allow_partial_results": true. Closes #129256 (cherry picked from commit d51d643)
1 parent bad1e04 commit bf8e14f

File tree

6 files changed

+58
-12
lines changed

6 files changed

+58
-12
lines changed

x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/AbstractEsqlClientYamlIT.java

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import org.elasticsearch.test.rest.yaml.section.ClientYamlTestSection;
1515
import org.elasticsearch.test.rest.yaml.section.DoSection;
1616
import org.elasticsearch.test.rest.yaml.section.ExecutableSection;
17+
import org.elasticsearch.test.rest.yaml.section.IsFalseAssertion;
18+
import org.elasticsearch.xcontent.XContentLocation;
1719
import org.elasticsearch.xpack.esql.qa.rest.EsqlSpecTestCase;
1820
import org.junit.After;
1921
import org.junit.Before;
@@ -51,18 +53,25 @@ private void assertRequestBreakerEmpty() throws Exception {
5153
EsqlSpecTestCase.assertRequestBreakerEmpty();
5254
}
5355

54-
public static Iterable<Object[]> updateEsqlQueryDoSections(Iterable<Object[]> parameters, Function<DoSection, ExecutableSection> modify)
55-
throws Exception {
56+
public static Iterable<Object[]> partialResultsCheckingParameters() throws Exception {
57+
return updateExecutableSections(createParameters(), AbstractEsqlClientYamlIT::insertPartialResultsAssertion);
58+
}
59+
60+
public static Iterable<Object[]> updateExecutableSections(
61+
Iterable<Object[]> parameters,
62+
Function<List<ExecutableSection>, List<ExecutableSection>> updateFunction
63+
) {
5664
List<Object[]> result = new ArrayList<>();
5765
for (Object[] orig : parameters) {
5866
assert orig.length == 1;
5967
ClientYamlTestCandidate candidate = (ClientYamlTestCandidate) orig[0];
6068
try {
69+
var testSection = candidate.getTestSection();
6170
ClientYamlTestSection modified = new ClientYamlTestSection(
62-
candidate.getTestSection().getLocation(),
63-
candidate.getTestSection().getName(),
64-
candidate.getTestSection().getPrerequisiteSection(),
65-
candidate.getTestSection().getExecutableSections().stream().map(e -> modifyExecutableSection(e, modify)).toList()
71+
testSection.getLocation(),
72+
testSection.getName(),
73+
testSection.getPrerequisiteSection(),
74+
updateFunction.apply(testSection.getExecutableSections())
6675
);
6776
result.add(new Object[] { new ClientYamlTestCandidate(candidate.getRestTestSuite(), modified) });
6877
} catch (IllegalArgumentException e) {
@@ -72,6 +81,33 @@ public static Iterable<Object[]> updateEsqlQueryDoSections(Iterable<Object[]> pa
7281
return result;
7382
}
7483

84+
public static Iterable<Object[]> updateEsqlQueryDoSections(
85+
Iterable<Object[]> parameters,
86+
Function<DoSection, ExecutableSection> modify
87+
) {
88+
return updateExecutableSections(parameters, sections -> sections.stream().map(e -> modifyExecutableSection(e, modify)).toList());
89+
}
90+
91+
private static List<ExecutableSection> insertPartialResultsAssertion(List<ExecutableSection> sections) {
92+
var newSections = new ArrayList<ExecutableSection>(sections.size());
93+
for (var section : sections) {
94+
var insertIsPartial = false;
95+
if (section instanceof DoSection doSection) {
96+
var apiCallSection = doSection.getApiCallSection();
97+
if (apiCallSection.getApi().equals("esql.query")) {
98+
// If `allow_partial_results` is explicitly set to true, partial results are allowed.
99+
// If it's missing, no partial results are expected, even if the parameter's default is true.
100+
insertIsPartial = "true".equals(apiCallSection.getParams().get("allow_partial_results")) == false;
101+
}
102+
}
103+
newSections.add(section);
104+
if (insertIsPartial) {
105+
newSections.add(new IsFalseAssertion(XContentLocation.UNKNOWN, "is_partial"));
106+
}
107+
}
108+
return newSections.size() == sections.size() ? sections : newSections;
109+
}
110+
75111
private static ExecutableSection modifyExecutableSection(ExecutableSection e, Function<DoSection, ExecutableSection> modify) {
76112
if (false == (e instanceof DoSection)) {
77113
return e;

x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public EsqlClientYamlAsyncIT(final ClientYamlTestCandidate testCandidate) {
2626

2727
@ParametersFactory
2828
public static Iterable<Object[]> parameters() throws Exception {
29-
return updateEsqlQueryDoSections(createParameters(), doSection -> {
29+
return updateEsqlQueryDoSections(partialResultsCheckingParameters(), doSection -> {
3030
ApiCallSection copy = doSection.getApiCallSection().copyWithNewApi("esql.async_query");
3131
for (Map<String, Object> body : copy.getBodies()) {
3232
body.put("wait_for_completion_timeout", "30m");

x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncSubmitAndFetchIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public EsqlClientYamlAsyncSubmitAndFetchIT(final ClientYamlTestCandidate testCan
3232

3333
@ParametersFactory
3434
public static Iterable<Object[]> parameters() throws Exception {
35-
return updateEsqlQueryDoSections(createParameters(), DoEsqlAsync::new);
35+
return updateEsqlQueryDoSections(partialResultsCheckingParameters(), DoEsqlAsync::new);
3636
}
3737

3838
private static class DoEsqlAsync implements ExecutableSection {

x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ public EsqlClientYamlIT(final ClientYamlTestCandidate testCandidate) {
2222

2323
@ParametersFactory
2424
public static Iterable<Object[]> parameters() throws Exception {
25-
return createParameters();
25+
return partialResultsCheckingParameters();
2626
}
2727
}

x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@
7474
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.RERANK;
7575
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.SEMANTIC_TEXT_FIELD_CAPS;
7676
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.cap;
77+
import static org.hamcrest.Matchers.anyOf;
78+
import static org.hamcrest.Matchers.is;
79+
import static org.hamcrest.Matchers.nullValue;
7780

7881
// This test can run very long in serverless configurations
7982
@TimeoutSuite(millis = 30 * TimeUnits.MINUTE)
@@ -266,6 +269,10 @@ protected final void doTest() throws Throwable {
266269

267270
Map<String, Object> answer = runEsql(builder.query(testCase.query), testCase.assertWarnings(deduplicateExactWarnings()));
268271

272+
var clusters = answer.get("_clusters");
273+
var reason = "unexpected partial results" + (clusters != null ? ": _clusters=" + clusters : "");
274+
assertThat(reason, answer.get("is_partial"), anyOf(nullValue(), is(false)));
275+
269276
var expectedColumnsWithValues = loadCsvSpecValues(testCase.expectedResults);
270277

271278
var metadata = answer.get("columns");

x-pack/plugin/esql/qa/testFixtures/src/main/resources/knn-function.csv-spec

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ aqua marine | [127.0, 255.0, 212.0]
4848
teal | [0.0, 128.0, 128.0]
4949
;
5050

51-
knnSearchWithSimilarityOption
51+
# https://github.com/elastic/elasticsearch/issues/129550
52+
knnSearchWithSimilarityOption-Ignore
5253
required_capability: knn_function
5354

5455
from colors metadata _score
@@ -227,7 +228,8 @@ green | false
227228
maroon | false
228229
;
229230

230-
testKnnWithNonPushableDisjunctions
231+
# https://github.com/elastic/elasticsearch/issues/129550
232+
testKnnWithNonPushableDisjunctions-Ignore
231233
required_capability: knn_function
232234

233235
from colors metadata _score
@@ -243,7 +245,8 @@ lemon chiffon
243245
papaya whip
244246
;
245247

246-
testKnnWithNonPushableDisjunctionsOnComplexExpressions
248+
# https://github.com/elastic/elasticsearch/issues/129550
249+
testKnnWithNonPushableDisjunctionsOnComplexExpressions-Ignore
247250
required_capability: knn_function
248251

249252
from colors metadata _score

0 commit comments

Comments
 (0)