diff --git a/x-pack/plugin/eql/qa/common/src/main/java/org/elasticsearch/test/eql/CommonEqlRestTestCase.java b/x-pack/plugin/eql/qa/common/src/main/java/org/elasticsearch/test/eql/CommonEqlRestTestCase.java index 4d5b8367be7..a00f361b0a5 100644 --- a/x-pack/plugin/eql/qa/common/src/main/java/org/elasticsearch/test/eql/CommonEqlRestTestCase.java +++ b/x-pack/plugin/eql/qa/common/src/main/java/org/elasticsearch/test/eql/CommonEqlRestTestCase.java @@ -5,8 +5,91 @@ */ package org.elasticsearch.test.eql; +import org.apache.http.util.EntityUtils; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.test.rest.ESRestTestCase; +import org.junit.After; +import org.junit.Before; + +import java.util.ArrayList; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; public abstract class CommonEqlRestTestCase extends ESRestTestCase { - // TODO: add common tests here + + static class SearchTestConfiguration { + final String input; + final int expectedStatus; + final String expectedMessage; + + SearchTestConfiguration(String input, int status, String msg) { + this.input = input; + this.expectedStatus = status; + this.expectedMessage = msg; + } + } + + public static final String defaultValidationIndexName = "eql_search_validation_test"; + private static final String validRule = "process where user = 'SYSTEM'"; + + public static final ArrayList searchValidationTests; + static { + searchValidationTests = new ArrayList<>(); + searchValidationTests.add(new SearchTestConfiguration(null, 400, "request body or source parameter is required")); + searchValidationTests.add(new SearchTestConfiguration("{}", 400, "rule is null or empty")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"\"}", 400, "rule is null or empty")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"" + validRule + "\", \"timestamp_field\": \"\"}", + 400, "timestamp field is null or empty")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"" + validRule + "\", \"event_type_field\": \"\"}", + 400, "event type field is null or empty")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"" + validRule + "\", \"implicit_join_key_field\": \"\"}", + 400, "implicit join key field is null or empty")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"" + validRule + "\", \"size\": 0}", + 400, "size must be more than 0")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"" + validRule + "\", \"size\": -1}", + 400, "size must be more than 0")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"" + validRule + "\", \"search_after\": null}", + 400, "search_after doesn't support values of type: VALUE_NULL")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"" + validRule + "\", \"search_after\": []}", + 400, "must contains at least one value")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"" + validRule + "\", \"query\": null}", + 400, "query doesn't support values of type: VALUE_NULL")); + searchValidationTests.add(new SearchTestConfiguration("{\"rule\": \"" + validRule + "\", \"query\": {}}", + 400, "query malformed, empty clause found")); + } + + @Before + public void setup() throws Exception { + createIndex(defaultValidationIndexName, Settings.EMPTY); + } + + @After + public void cleanup() throws Exception { + deleteIndex(defaultValidationIndexName); + } + + public void testSearchValidationFailures() throws Exception { + final String contentType = "application/json"; + for (SearchTestConfiguration config : searchValidationTests) { + final String endpoint = "/" + defaultValidationIndexName + "/_eql/search"; + Request request = new Request("GET", endpoint); + request.setJsonEntity(config.input); + + Response response = null; + if (config.expectedStatus == 400) { + ResponseException e = expectThrows(ResponseException.class, () -> client().performRequest(request)); + response = e.getResponse(); + } else { + response = client().performRequest(request); + } + + assertThat(response.getHeader("Content-Type"), containsString(contentType)); + assertThat(EntityUtils.toString(response.getEntity()), containsString(config.expectedMessage)); + assertThat(response.getStatusLine().getStatusCode(), is(config.expectedStatus)); + } + } } diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/action/EqlSearchRequest.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/action/EqlSearchRequest.java index 3d2f9d077ff..00814783527 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/action/EqlSearchRequest.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/action/EqlSearchRequest.java @@ -10,7 +10,6 @@ import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.ObjectParser; @@ -92,6 +91,10 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re } } + if (rule == null || rule.isEmpty()) { + validationException = addValidationError("rule is null or empty", validationException); + } + if (timestampField == null || timestampField.isEmpty()) { validationException = addValidationError("timestamp field is null or empty", validationException); } @@ -101,11 +104,11 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re } if (implicitJoinKeyField == null || implicitJoinKeyField.isEmpty()) { - validationException = addValidationError("implicit join key field field is null or empty", validationException); + validationException = addValidationError("implicit join key field is null or empty", validationException); } if (fetchSize <= 0) { - validationException = addValidationError("size must be more than 0.", validationException); + validationException = addValidationError("size must be more than 0", validationException); } return validationException; @@ -166,36 +169,27 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re public String timestampField() { return this.timestampField; } public EqlSearchRequest timestampField(String timestampField) { - if (!Strings.isNullOrEmpty(timestampField)) { - this.timestampField = timestampField; - } + this.timestampField = timestampField; return this; } public String eventTypeField() { return this.eventTypeField; } public EqlSearchRequest eventTypeField(String eventTypeField) { - if (!Strings.isNullOrEmpty(eventTypeField)) { - this.eventTypeField = eventTypeField; - } + this.eventTypeField = eventTypeField; return this; } public String implicitJoinKeyField() { return this.implicitJoinKeyField; } public EqlSearchRequest implicitJoinKeyField(String implicitJoinKeyField) { - if (!Strings.isNullOrEmpty(eventTypeField)) { - this.implicitJoinKeyField = implicitJoinKeyField; - } + this.implicitJoinKeyField = implicitJoinKeyField; return this; } public int fetchSize() { return this.fetchSize; } public EqlSearchRequest fetchSize(int size) { - if (size <= 0) { - throw new IllegalArgumentException("size must be more than 0."); - } this.fetchSize = size; return this; } diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/EqlSearchRequestTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/EqlSearchRequestTests.java index 8c37a5afea6..91c70f29f23 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/EqlSearchRequestTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/EqlSearchRequestTests.java @@ -132,13 +132,4 @@ public class EqlSearchRequestTests extends AbstractSerializingTestCase eqlSearchRequest.fetchSize(-1)); - assertEquals("size must be more than 0.", e.getMessage()); - - e = expectThrows(IllegalArgumentException.class, () -> eqlSearchRequest.fetchSize(0)); - assertEquals("size must be more than 0.", e.getMessage()); - } }