Add basic integration test for /_sql endpoint (elastic/x-pack-elasticsearch#2109)
Similar to my work in elastic/x-pack-elasticsearch#2106, this adds a basic integration test for the rest sql action. We can add more as we go. Specifically, I'd like to add testing around handling of invalid SQL and a test for timezones, but neither work particularly well yet. Original commit: elastic/x-pack-elasticsearch@923d941d0d
This commit is contained in:
parent
38e31cb4f6
commit
2379c40f58
|
@ -1,3 +1,5 @@
|
|||
import org.elasticsearch.gradle.test.RunTask
|
||||
|
||||
apply plugin: 'elasticsearch.build'
|
||||
|
||||
description = 'The server components of SQL for Elasticsearch'
|
||||
|
@ -26,6 +28,34 @@ dependencyLicenses {
|
|||
compileJava.options.compilerArgs << "-parameters"
|
||||
compileTestJava.options.compilerArgs << "-parameters"
|
||||
|
||||
// Configure integration tests
|
||||
apply plugin: 'elasticsearch.rest-test'
|
||||
integTest.mustRunAfter test
|
||||
|
||||
integTestCluster {
|
||||
distribution = 'zip' // NOCOMMIT make double sure we want all the modules
|
||||
plugin project(':x-pack-elasticsearch:plugin').path
|
||||
/* Get a "clean" test without the other x-pack features here and check them
|
||||
* all together later on. */
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setting 'xpack.ml.enabled', 'false'
|
||||
setting 'xpack.watcher.enabled', 'false'
|
||||
setting 'script.max_compilations_per_minute', '1000'
|
||||
}
|
||||
|
||||
task run(type: RunTask) {
|
||||
distribution = 'zip' // NOCOMMIT make double sure we want all the modules
|
||||
plugin project(':x-pack-elasticsearch:plugin').path
|
||||
/* Get a "clean" test without the other x-pack features here and check them
|
||||
* all together later on. */
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setting 'xpack.ml.enabled', 'false'
|
||||
setting 'xpack.watcher.enabled', 'false'
|
||||
setting 'script.max_compilations_per_minute', '1000'
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* SQL Parser regeneration *
|
||||
**********************************************/
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
|||
import org.elasticsearch.xpack.sql.analysis.catalog.EsCatalog;
|
||||
import org.elasticsearch.xpack.sql.execution.PlanExecutor;
|
||||
import org.elasticsearch.xpack.sql.session.RowSetCursor;
|
||||
import org.elasticsearch.xpack.sql.session.SqlSettings;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.sql.server;
|
||||
|
||||
import org.elasticsearch.client.Response;
|
||||
import org.elasticsearch.client.ResponseException;
|
||||
import org.elasticsearch.client.http.HttpEntity;
|
||||
import org.elasticsearch.client.http.entity.ContentType;
|
||||
import org.elasticsearch.client.http.entity.StringEntity;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.test.NotEqualMessageBuilder;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class RestSqlIT extends ESRestTestCase {
|
||||
public void testBasicQuery() throws IOException {
|
||||
StringBuilder bulk = new StringBuilder();
|
||||
bulk.append("{\"index\":{\"_id\":\"1\"}}\n");
|
||||
bulk.append("{\"test\":\"test\"}\n");
|
||||
bulk.append("{\"index\":{\"_id\":\"2\"}}\n");
|
||||
bulk.append("{\"test\":\"test\"}\n");
|
||||
client().performRequest("POST", "/test/test/_bulk", singletonMap("refresh", "true"),
|
||||
new StringEntity(bulk.toString(), ContentType.APPLICATION_JSON));
|
||||
|
||||
Map<String, Object> expected = new HashMap<>();
|
||||
expected.put("columns", singletonMap("test", singletonMap("type", "text")));
|
||||
expected.put("rows", Arrays.asList(singletonMap("test", "test"), singletonMap("test", "test")));
|
||||
expected.put("size", 2);
|
||||
assertResponse(expected, runSql("SELECT * FROM test.test"));
|
||||
}
|
||||
|
||||
@AwaitsFix(bugUrl="https://github.com/elastic/x-pack-elasticsearch/issues/2074")
|
||||
public void testTimeZone() throws IOException {
|
||||
StringBuilder bulk = new StringBuilder();
|
||||
bulk.append("{\"index\":{\"_id\":\"1\"}}\n");
|
||||
bulk.append("{\"test\":\"2017-07-27 00:00:00\"}\n");
|
||||
bulk.append("{\"index\":{\"_id\":\"2\"}}\n");
|
||||
bulk.append("{\"test\":\"2017-07-27 01:00:00\"}\n");
|
||||
client().performRequest("POST", "/test/test/_bulk", singletonMap("refresh", "true"),
|
||||
new StringEntity(bulk.toString(), ContentType.APPLICATION_JSON));
|
||||
|
||||
Map<String, Object> expected = new HashMap<>();
|
||||
expected.put("columns", singletonMap("test", singletonMap("type", "text")));
|
||||
expected.put("rows", Arrays.asList(singletonMap("test", "test"), singletonMap("test", "test")));
|
||||
expected.put("size", 2);
|
||||
|
||||
// Default TimeZone is UTC
|
||||
assertResponse(expected, runSql(
|
||||
new StringEntity("{\"query\":\"SELECT DAY_OF_YEAR(test), COUNT(*) FROM test.test\"}", ContentType.APPLICATION_JSON)));
|
||||
}
|
||||
|
||||
public void testMissingField() throws IOException {
|
||||
StringBuilder bulk = new StringBuilder();
|
||||
bulk.append("{\"index\":{\"_id\":\"1\"}}\n");
|
||||
bulk.append("{\"test\":\"test\"}\n");
|
||||
client().performRequest("POST", "/test/test/_bulk", singletonMap("refresh", "true"),
|
||||
new StringEntity(bulk.toString(), ContentType.APPLICATION_JSON));
|
||||
|
||||
// NOCOMMIT test the error messages
|
||||
expectSqlThrows(() -> runSql("SELECT foo FROM test.test"), containsString("500"));
|
||||
expectSqlThrows(() -> runSql("SELECT DAY_OF_YEAR(foo) FROM test.test"), containsString("500"));
|
||||
expectSqlThrows(() -> runSql("SELECT foo, * FROM test.test GROUP BY DAY_OF_YEAR(foo)"), containsString("500"));
|
||||
expectSqlThrows(() -> runSql("SELECT * FROM test.test WHERE foo = 1"), containsString("500"));
|
||||
expectSqlThrows(() -> runSql("SELECT * FROM test.test WHERE DAY_OF_YEAR(foo) = 1"), containsString("500"));
|
||||
expectSqlThrows(() -> runSql("SELECT * FROM test.test ORDER BY foo"), containsString("500"));
|
||||
expectSqlThrows(() -> runSql("SELECT * FROM test.test ORDER BY DAY_OF_YEAR(foo)"), containsString("500"));
|
||||
}
|
||||
|
||||
private void expectSqlThrows(ThrowingRunnable code, Matcher<String> errorMessageMatcher) {
|
||||
ResponseException e = expectThrows(ResponseException.class, code);
|
||||
assertThat(e.getMessage(), containsString("500"));
|
||||
// NOCOMMIT This should return a 400 or 422
|
||||
assertThat(e.getMessage(), errorMessageMatcher);
|
||||
}
|
||||
|
||||
private Map<String, Object> runSql(String sql) throws IOException {
|
||||
return runSql(new StringEntity("{\"query\":\"" + sql + "\"}", ContentType.APPLICATION_JSON));
|
||||
}
|
||||
|
||||
private Map<String, Object> runSql(HttpEntity sql) throws IOException {
|
||||
Response response = client().performRequest("POST", "/_sql", emptyMap(), sql);
|
||||
try (InputStream content = response.getEntity().getContent()) {
|
||||
return XContentHelper.convertToMap(JsonXContent.jsonXContent, content, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertResponse(Map<String, Object> expected, Map<String, Object> actual) {
|
||||
if (false == expected.equals(actual)) {
|
||||
NotEqualMessageBuilder message = new NotEqualMessageBuilder();
|
||||
message.compareMaps(actual, expected);
|
||||
fail("Response does not match:\n" + message.toString());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue