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:
Nik Everett 2017-07-28 12:51:43 -04:00 committed by GitHub
parent 38e31cb4f6
commit 2379c40f58
3 changed files with 138 additions and 1 deletions

View File

@ -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 *
**********************************************/

View File

@ -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;

View File

@ -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());
}
}
}