diff --git a/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/AbstractEsqlClientYamlIT.java b/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/AbstractEsqlClientYamlIT.java index b2a3b12c2a027..b9b7ba5f82394 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/AbstractEsqlClientYamlIT.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/AbstractEsqlClientYamlIT.java @@ -14,6 +14,8 @@ import org.elasticsearch.test.rest.yaml.section.ClientYamlTestSection; import org.elasticsearch.test.rest.yaml.section.DoSection; import org.elasticsearch.test.rest.yaml.section.ExecutableSection; +import org.elasticsearch.test.rest.yaml.section.IsFalseAssertion; +import org.elasticsearch.xcontent.XContentLocation; import org.elasticsearch.xpack.esql.qa.rest.EsqlSpecTestCase; import org.junit.After; import org.junit.Before; @@ -51,18 +53,25 @@ private void assertRequestBreakerEmpty() throws Exception { EsqlSpecTestCase.assertRequestBreakerEmpty(); } - public static Iterable updateEsqlQueryDoSections(Iterable parameters, Function modify) - throws Exception { + public static Iterable partialResultsCheckingParameters() throws Exception { + return updateExecutableSections(createParameters(), AbstractEsqlClientYamlIT::insertPartialResultsAssertion); + } + + public static Iterable updateExecutableSections( + Iterable parameters, + Function, List> updateFunction + ) { List result = new ArrayList<>(); for (Object[] orig : parameters) { assert orig.length == 1; ClientYamlTestCandidate candidate = (ClientYamlTestCandidate) orig[0]; try { + var testSection = candidate.getTestSection(); ClientYamlTestSection modified = new ClientYamlTestSection( - candidate.getTestSection().getLocation(), - candidate.getTestSection().getName(), - candidate.getTestSection().getPrerequisiteSection(), - candidate.getTestSection().getExecutableSections().stream().map(e -> modifyExecutableSection(e, modify)).toList() + testSection.getLocation(), + testSection.getName(), + testSection.getPrerequisiteSection(), + updateFunction.apply(testSection.getExecutableSections()) ); result.add(new Object[] { new ClientYamlTestCandidate(candidate.getRestTestSuite(), modified) }); } catch (IllegalArgumentException e) { @@ -72,6 +81,33 @@ public static Iterable updateEsqlQueryDoSections(Iterable pa return result; } + public static Iterable updateEsqlQueryDoSections( + Iterable parameters, + Function modify + ) { + return updateExecutableSections(parameters, sections -> sections.stream().map(e -> modifyExecutableSection(e, modify)).toList()); + } + + private static List insertPartialResultsAssertion(List sections) { + var newSections = new ArrayList(sections.size()); + for (var section : sections) { + var insertIsPartial = false; + if (section instanceof DoSection doSection) { + var apiCallSection = doSection.getApiCallSection(); + if (apiCallSection.getApi().equals("esql.query")) { + // If `allow_partial_results` is explicitly set to true, partial results are allowed. + // If it's missing, no partial results are expected, even if the parameter's default is true. + insertIsPartial = "true".equals(apiCallSection.getParams().get("allow_partial_results")) == false; + } + } + newSections.add(section); + if (insertIsPartial) { + newSections.add(new IsFalseAssertion(XContentLocation.UNKNOWN, "is_partial")); + } + } + return newSections.size() == sections.size() ? sections : newSections; + } + private static ExecutableSection modifyExecutableSection(ExecutableSection e, Function modify) { if (false == (e instanceof DoSection)) { return e; diff --git a/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncIT.java b/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncIT.java index f5bd1efb106a3..b840bbc193b6e 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncIT.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncIT.java @@ -26,7 +26,7 @@ public EsqlClientYamlAsyncIT(final ClientYamlTestCandidate testCandidate) { @ParametersFactory public static Iterable parameters() throws Exception { - return updateEsqlQueryDoSections(createParameters(), doSection -> { + return updateEsqlQueryDoSections(partialResultsCheckingParameters(), doSection -> { ApiCallSection copy = doSection.getApiCallSection().copyWithNewApi("esql.async_query"); for (Map body : copy.getBodies()) { body.put("wait_for_completion_timeout", "30m"); diff --git a/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncSubmitAndFetchIT.java b/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncSubmitAndFetchIT.java index 38051007568e9..dc86293829979 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncSubmitAndFetchIT.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlAsyncSubmitAndFetchIT.java @@ -32,7 +32,7 @@ public EsqlClientYamlAsyncSubmitAndFetchIT(final ClientYamlTestCandidate testCan @ParametersFactory public static Iterable parameters() throws Exception { - return updateEsqlQueryDoSections(createParameters(), DoEsqlAsync::new); + return updateEsqlQueryDoSections(partialResultsCheckingParameters(), DoEsqlAsync::new); } private static class DoEsqlAsync implements ExecutableSection { diff --git a/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlIT.java b/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlIT.java index 7556b0916e1f6..aa33fe3ec94be 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlIT.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/yamlRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/EsqlClientYamlIT.java @@ -22,6 +22,6 @@ public EsqlClientYamlIT(final ClientYamlTestCandidate testCandidate) { @ParametersFactory public static Iterable parameters() throws Exception { - return createParameters(); + return partialResultsCheckingParameters(); } } diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java index e4c8b67d4eb72..5ba4ccd2443fe 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java @@ -76,6 +76,9 @@ import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.RERANK; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.SEMANTIC_TEXT_FIELD_CAPS; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.SOURCE_FIELD_MAPPING; +import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; // This test can run very long in serverless configurations @TimeoutSuite(millis = 30 * TimeUnits.MINUTE) @@ -273,6 +276,10 @@ protected final void doTest(String query) throws Throwable { Map prevTooks = supportsTook() ? tooks() : null; Map answer = runEsql(builder.query(query), testCase.assertWarnings(deduplicateExactWarnings())); + var clusters = answer.get("_clusters"); + var reason = "unexpected partial results" + (clusters != null ? ": _clusters=" + clusters : ""); + assertThat(reason, answer.get("is_partial"), anyOf(nullValue(), is(false))); + var expectedColumnsWithValues = loadCsvSpecValues(testCase.expectedResults); var metadata = answer.get("columns"); diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/knn-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/knn-function.csv-spec index 5e65e6269e652..ac6c16f35de01 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/knn-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/knn-function.csv-spec @@ -48,7 +48,8 @@ aqua marine | [127.0, 255.0, 212.0] teal | [0.0, 128.0, 128.0] ; -knnSearchWithSimilarityOption +# https://github.com/elastic/elasticsearch/issues/129550 +knnSearchWithSimilarityOption-Ignore required_capability: knn_function from colors metadata _score @@ -227,7 +228,8 @@ green | false maroon | false ; -testKnnWithNonPushableDisjunctions +# https://github.com/elastic/elasticsearch/issues/129550 +testKnnWithNonPushableDisjunctions-Ignore required_capability: knn_function from colors metadata _score @@ -243,7 +245,8 @@ lemon chiffon papaya whip ; -testKnnWithNonPushableDisjunctionsOnComplexExpressions +# https://github.com/elastic/elasticsearch/issues/129550 +testKnnWithNonPushableDisjunctionsOnComplexExpressions-Ignore required_capability: knn_function from colors metadata _score