mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-03 17:39:15 +00:00
Port some of CLI's demos to tests
Original commit: elastic/x-pack-elasticsearch@5827c08268
This commit is contained in:
parent
3eb1258b0d
commit
56803bdd1b
@ -1,3 +1,5 @@
|
||||
import org.elasticsearch.gradle.test.RunTask
|
||||
|
||||
apply plugin: 'elasticsearch.build'
|
||||
apply plugin: 'application'
|
||||
|
||||
@ -8,10 +10,12 @@ dependencies {
|
||||
compile project(':x-pack-elasticsearch:sql:net-client')
|
||||
compile project(':x-pack-elasticsearch:sql:cli-proto')
|
||||
|
||||
testCompile project(":x-pack-elasticsearch:transport-client")
|
||||
testCompile project(":x-pack-elasticsearch:transport-client") // NOCOMMIT probably can remove this
|
||||
testCompile project(path: ':x-pack-elasticsearch:plugin', configuration: 'testArtifacts')
|
||||
testCompile project(':x-pack-elasticsearch:sql:test-utils')
|
||||
testCompile project(':x-pack-elasticsearch:sql:server')
|
||||
|
||||
// Used by the hack to run InternalTestCluster if not running against a gradle-started cluster.
|
||||
testCompile project(path: ':modules:lang-painless', configuration: 'runtime')
|
||||
|
||||
runtime "org.fusesource.jansi:jansi:1.16"
|
||||
runtime "org.elasticsearch:jna:4.4.0-1"
|
||||
@ -37,10 +41,6 @@ jar {
|
||||
|
||||
mainClassName = "org.elasticsearch.sql.console.SqlConsole"
|
||||
|
||||
run {
|
||||
classpath = sourceSets.test.runtimeClasspath
|
||||
}
|
||||
|
||||
// Needed so we can launch graphviz if it is installed
|
||||
project.compactProfile = 'full'
|
||||
|
||||
@ -102,3 +102,29 @@ thirdPartyAudit.excludes = [
|
||||
'org.fusesource.jansi.internal.WindowsSupport',
|
||||
'org.mozilla.universalchardet.UniversalDetector'
|
||||
]
|
||||
|
||||
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'
|
||||
}
|
||||
|
||||
task runServer(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'
|
||||
run.dependsOn this
|
||||
}
|
||||
|
@ -5,12 +5,6 @@
|
||||
*/
|
||||
package org.elasticsearch.xpack.sql.cli;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.elasticsearch.xpack.sql.cli.net.client.CliHttpClient;
|
||||
import org.elasticsearch.xpack.sql.net.client.util.IOUtils;
|
||||
import org.jline.keymap.BindingReader;
|
||||
@ -24,6 +18,12 @@ import org.jline.utils.AttributedString;
|
||||
import org.jline.utils.AttributedStringBuilder;
|
||||
import org.jline.utils.InfoCmp.Capability;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.jline.utils.AttributedStyle.BOLD;
|
||||
import static org.jline.utils.AttributedStyle.BRIGHT;
|
||||
import static org.jline.utils.AttributedStyle.DEFAULT;
|
||||
@ -31,6 +31,17 @@ import static org.jline.utils.AttributedStyle.RED;
|
||||
import static org.jline.utils.AttributedStyle.YELLOW;
|
||||
|
||||
public class Cli {
|
||||
public static void main(String... args) throws Exception {
|
||||
try (Terminal term = TerminalBuilder.builder().build()) {
|
||||
try {
|
||||
Cli console = new Cli(new CliConfiguration("localhost:9200/_cli", new Properties()), term);
|
||||
console.run();
|
||||
} catch (FatalException e) {
|
||||
new PrintWriter(term.output()).println(e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final Terminal term;
|
||||
private final BindingReader bindingReader;
|
||||
@ -38,24 +49,16 @@ public class Cli {
|
||||
private final CliConfiguration cfg;
|
||||
private final CliHttpClient cliClient;
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
try (Terminal term = TerminalBuilder.builder().build()) {
|
||||
Cli console = new Cli(term);
|
||||
console.run();
|
||||
}
|
||||
}
|
||||
|
||||
private Cli(Terminal terminal) {
|
||||
Cli(CliConfiguration cfg, Terminal terminal) {
|
||||
term = terminal;
|
||||
bindingReader = new BindingReader(term.reader());
|
||||
keys = new Keys(term);
|
||||
|
||||
cfg = new CliConfiguration("localhost:9200/_cli", new Properties());
|
||||
this.cfg = cfg;
|
||||
cliClient = new CliHttpClient(cfg);
|
||||
}
|
||||
|
||||
|
||||
private void run() throws Exception {
|
||||
void run() throws IOException {
|
||||
PrintWriter out = term.writer();
|
||||
|
||||
LineReader reader = LineReaderBuilder.builder()
|
||||
@ -131,6 +134,7 @@ public class Cli {
|
||||
executeCommand(line, out);
|
||||
}
|
||||
} catch (RuntimeException ex) {
|
||||
ex.printStackTrace();
|
||||
AttributedStringBuilder asb = new AttributedStringBuilder();
|
||||
asb.append("Communication error [", BOLD.foreground(RED));
|
||||
asb.append(ex.getMessage(), DEFAULT.boldOff().italic().foreground(YELLOW));
|
||||
@ -145,13 +149,14 @@ public class Cli {
|
||||
}
|
||||
|
||||
private static String logo() {
|
||||
try (InputStream io = Cli.class.getResourceAsStream("logo.txt")) {
|
||||
if (io != null) {
|
||||
return IOUtils.asBytes(io).toString();
|
||||
try (InputStream io = Cli.class.getResourceAsStream("/logo.txt")) {
|
||||
if (io == null) {
|
||||
throw new FatalException("Could not find logo!");
|
||||
}
|
||||
} catch (IOException io) {
|
||||
return IOUtils.asBytes(io).toString();
|
||||
} catch (IOException e) {
|
||||
throw new FatalException("Could not load logo!", e);
|
||||
}
|
||||
return "Could not load logo...";
|
||||
}
|
||||
|
||||
private void printLogo(PrintWriter out) {
|
||||
@ -187,4 +192,14 @@ public class Cli {
|
||||
protected void executeCommand(String line, PrintWriter out) throws IOException {
|
||||
out.print(ResponseToString.toAnsi(cliClient.command(line, null)).toAnsi(term));
|
||||
}
|
||||
|
||||
static class FatalException extends RuntimeException {
|
||||
public FatalException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public FatalException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
@ -37,9 +37,7 @@ public class CliConfiguration extends ConnectionConfiguration {
|
||||
|
||||
// remove space
|
||||
u = u.trim();
|
||||
|
||||
String hostAndPort = u;
|
||||
|
||||
int index = u.indexOf("://");
|
||||
if (index > 0) {
|
||||
u = u.substring(index + 3);
|
||||
@ -58,7 +56,7 @@ public class CliConfiguration extends ConnectionConfiguration {
|
||||
}
|
||||
|
||||
// look for port
|
||||
index = hostAndPort.indexOf(":");
|
||||
index = hostAndPort.lastIndexOf(":");
|
||||
if (index > 0) {
|
||||
if (index + 1 >= hostAndPort.length()) {
|
||||
throw new IllegalArgumentException("Invalid port specified");
|
||||
|
@ -13,6 +13,8 @@ import org.elasticsearch.xpack.sql.net.client.util.Bytes;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
class HttpClient {
|
||||
|
||||
@ -31,7 +33,13 @@ class HttpClient {
|
||||
}
|
||||
|
||||
boolean head(String path) {
|
||||
return JreHttpUrlConnection.http(url(path), cfg, JreHttpUrlConnection::head);
|
||||
try {
|
||||
return AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> {
|
||||
return JreHttpUrlConnection.http(url(path), cfg, JreHttpUrlConnection::head);
|
||||
});
|
||||
} catch (ClientException ex) {
|
||||
throw new RuntimeException("Transport failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
Bytes put(DataOutputConsumer os) {
|
||||
@ -39,9 +47,15 @@ class HttpClient {
|
||||
}
|
||||
|
||||
Bytes put(String path, DataOutputConsumer os) {
|
||||
return JreHttpUrlConnection.http(url(path), cfg, con -> {
|
||||
return con.put(os);
|
||||
});
|
||||
try {
|
||||
return AccessController.doPrivileged((PrivilegedAction<Bytes>) () -> {
|
||||
return JreHttpUrlConnection.http(url(path), cfg, con -> {
|
||||
return con.put(os);
|
||||
});
|
||||
});
|
||||
} catch (ClientException ex) {
|
||||
throw new RuntimeException("Transport failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
void close() {}
|
||||
|
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.ThreadFilter;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings;
|
||||
import org.elasticsearch.common.CheckedConsumer;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.painless.PainlessPlugin;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.InternalTestCluster;
|
||||
import org.elasticsearch.test.NodeConfigurationSource;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.transport.Netty4Plugin;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.sql.cli.CliIntegrationTestCase.CliThreadLeakFilter;
|
||||
import org.elasticsearch.xpack.sql.net.client.SuppressForbidden;
|
||||
import org.jline.terminal.Attributes;
|
||||
import org.jline.terminal.Attributes.LocalFlag;
|
||||
import org.jline.terminal.Terminal;
|
||||
import org.jline.terminal.TerminalBuilder;
|
||||
import org.jline.utils.NonBlockingReader;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
||||
@ThreadLeakFilters(filters = CliThreadLeakFilter.class)
|
||||
public class CliIntegrationTestCase extends ESRestTestCase {
|
||||
private static InternalTestCluster internalTestCluster;
|
||||
|
||||
/**
|
||||
* Hack to run an {@link InternalTestCluster} if this is being run
|
||||
* in an environment without {@code tests.rest.cluster} set for easier
|
||||
* debugging. Note that this doesn't work in the security manager is
|
||||
* enabled.
|
||||
*/
|
||||
@BeforeClass
|
||||
@SuppressForbidden(reason="it is a hack anyway")
|
||||
public static void startInternalTestClusterIfNeeded() throws IOException, InterruptedException {
|
||||
if (System.getProperty("tests.rest.cluster") != null) {
|
||||
// Nothing to do, using an external Elasticsearch node.
|
||||
return;
|
||||
}
|
||||
long seed = randomLong();
|
||||
String name = InternalTestCluster.clusterName("", seed);
|
||||
NodeConfigurationSource config = new NodeConfigurationSource() {
|
||||
@Override
|
||||
public Settings nodeSettings(int nodeOrdinal) {
|
||||
Settings.Builder builder = Settings.builder()
|
||||
// Enable http because the tests use it
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
||||
.put(NetworkModule.HTTP_TYPE_KEY, Netty4Plugin.NETTY_HTTP_TRANSPORT_NAME)
|
||||
// Default the watermarks to absurdly low to prevent the tests
|
||||
// from failing on nodes without enough disk space
|
||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b")
|
||||
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b")
|
||||
// Mimic settings in build.gradle so we're closer to real
|
||||
.put("xpack.security.enabled", false)
|
||||
.put("xpack.monitoring.enabled", false)
|
||||
.put("xpack.ml.enabled", false)
|
||||
.put("xpack.watcher.enabled", false);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path nodeConfigPath(int nodeOrdinal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
// Use netty4 plugin to enable rest
|
||||
return Arrays.asList(Netty4Plugin.class, XPackPlugin.class, PainlessPlugin.class);
|
||||
}
|
||||
};
|
||||
internalTestCluster = new InternalTestCluster(seed, createTempDir(), false, true, 1, 1, name, config, 0, randomBoolean(), "",
|
||||
emptySet(), Function.identity());
|
||||
internalTestCluster.beforeTest(random(), 0);
|
||||
internalTestCluster.ensureAtLeastNumDataNodes(1);
|
||||
InetSocketAddress httpBound = internalTestCluster.httpAddresses()[0];
|
||||
String http = httpBound.getHostString() + ":" + httpBound.getPort();
|
||||
try {
|
||||
System.setProperty("tests.rest.cluster", http);
|
||||
} catch (SecurityException e) {
|
||||
throw new RuntimeException(
|
||||
"Failed to set system property required for tests. Security manager must be disabled to use this hack.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutDownInternalTestClusterIfNeeded() {
|
||||
if (internalTestCluster == null) {
|
||||
return;
|
||||
}
|
||||
internalTestCluster.close();
|
||||
}
|
||||
|
||||
protected PrintWriter out;
|
||||
protected BufferedReader in;
|
||||
|
||||
@Before
|
||||
public void startCli() throws IOException {
|
||||
PipedInputStream terminalIn = new PipedInputStream();
|
||||
out = new PrintWriter(new PipedOutputStream(terminalIn), true);
|
||||
PipedOutputStream terminalOut = new PipedOutputStream();
|
||||
in = new BufferedReader(new InputStreamReader(new PipedInputStream(terminalOut)));
|
||||
Terminal terminal = TerminalBuilder.builder()
|
||||
.system(false)
|
||||
.jansi(false)
|
||||
.jna(false)
|
||||
.type("dumb")
|
||||
.encoding("UTF-8")
|
||||
.streams(terminalIn, terminalOut)
|
||||
.build();
|
||||
// Work around https://github.com/jline/jline3/issues/145
|
||||
Attributes attrs = terminal.getAttributes();
|
||||
attrs.setLocalFlag(LocalFlag.ISIG, false);
|
||||
terminal.setAttributes(attrs);
|
||||
terminal.echo(false);
|
||||
Cli cli = new Cli(new CliConfiguration(System.getProperty("tests.rest.cluster") + "/_cli", new Properties()), terminal);
|
||||
Thread cliThread = new Thread(() -> {
|
||||
try {
|
||||
cli.run();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
cliThread.start();
|
||||
|
||||
// Throw out the logo so tests don't have to!
|
||||
while (false == in.readLine().contains("SQL"));
|
||||
// Throw out the empty line before all the good stuff
|
||||
assertEquals("", in.readLine());
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdownCli() throws IOException, InterruptedException {
|
||||
try {
|
||||
// Try and quit
|
||||
out.println("quit;");
|
||||
List<String> nonQuit = new ArrayList<>();
|
||||
String line;
|
||||
while (false == (line = in.readLine()).equals("sql> quit;")) {
|
||||
nonQuit.add(line);
|
||||
}
|
||||
assertThat("unconsumed lines", nonQuit, empty());
|
||||
assertEquals("", in.readLine());
|
||||
assertEquals("Bye!", in.readLine());
|
||||
assertFalse(in.ready());
|
||||
} finally {
|
||||
// but close the streams anyway so the tests shut down cleanly
|
||||
out.close();
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected void index(String index, CheckedConsumer<XContentBuilder, IOException> body) throws IOException {
|
||||
XContentBuilder builder = JsonXContent.contentBuilder().startObject();
|
||||
body.accept(builder);
|
||||
builder.endObject();
|
||||
HttpEntity doc = new StringEntity(builder.string(), ContentType.APPLICATION_JSON);
|
||||
client().performRequest("PUT", "/" + index + "/doc/1", singletonMap("refresh", "true"), doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command and assert the echo.
|
||||
*/
|
||||
protected void command(String command) throws IOException {
|
||||
assertThat("; automatically added", command, not(endsWith(";")));
|
||||
out.println(command + ";");
|
||||
assertEquals("sql> " + command + ";", in.readLine());
|
||||
assertEquals("", in.readLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link NonBlockingReader} just will not die. It looks harmless enough.
|
||||
* Hopefully it is ok to let it be.
|
||||
*/
|
||||
public static class CliThreadLeakFilter implements ThreadFilter {
|
||||
@Override
|
||||
public boolean reject(Thread t) {
|
||||
for (StackTraceElement ste : t.getStackTrace()) {
|
||||
if (ste.getClassName().equals(NonBlockingReader.class.getName()) && ste.getMethodName().equals("run")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
public class ExplainIT extends CliIntegrationTestCase {
|
||||
public void testExplainBasic() throws IOException {
|
||||
index("test", body -> body.field("test_field", "test_value"));
|
||||
|
||||
command("EXPLAIN (PLAN PARSED) SELECT * FROM test.doc");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("With[{}]"));
|
||||
assertThat(in.readLine(), startsWith("\\_Project[[?*]]"));
|
||||
assertThat(in.readLine(), startsWith(" \\_UnresolvedRelation[[index=test, type=doc],null]"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT * FROM test.doc");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("Project[[test_field{r}#"));
|
||||
assertThat(in.readLine(), startsWith("\\_SubQueryAlias[doc]"));
|
||||
assertThat(in.readLine(), startsWith(" \\_CatalogTable[index=test,type=doc][test_field{r}#"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
command("EXPLAIN (PLAN OPTIMIZED) SELECT * FROM test.doc");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("Project[[test_field{r}#"));
|
||||
assertThat(in.readLine(), startsWith("\\_CatalogTable[index=test,type=doc][test_field{r}#"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
// TODO in this case we should probably remove the source filtering entirely. Right? It costs but we don't need it.
|
||||
command("EXPLAIN (PLAN EXECUTABLE) SELECT * FROM test.doc");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("EsQueryExec[test/doc,{"));
|
||||
assertThat(in.readLine(), startsWith(" \"_source\" : {"));
|
||||
assertThat(in.readLine(), startsWith(" \"includes\" : ["));
|
||||
assertThat(in.readLine(), startsWith(" \"test_field\""));
|
||||
assertThat(in.readLine(), startsWith(" ],"));
|
||||
assertThat(in.readLine(), startsWith(" \"excludes\" : [ ]"));
|
||||
assertThat(in.readLine(), startsWith(" }"));
|
||||
assertThat(in.readLine(), startsWith("}]"));
|
||||
assertEquals("", in.readLine());
|
||||
}
|
||||
|
||||
public void testExplainWithWhere() throws IOException {
|
||||
index("test", body -> body.field("test_field", "test_value1").field("i", 1));
|
||||
index("test", body -> body.field("test_field", "test_value2").field("i", 2));
|
||||
|
||||
command("EXPLAIN (PLAN PARSED) SELECT * FROM test.doc WHERE i = 2");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("With[{}]"));
|
||||
assertThat(in.readLine(), startsWith("\\_Project[[?*]]"));
|
||||
assertThat(in.readLine(), startsWith(" \\_Filter[?i = 2]"));
|
||||
assertThat(in.readLine(), startsWith(" \\_UnresolvedRelation[[index=test, type=doc],null]"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT * FROM test.doc WHERE i = 2");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("Project[[i{r}#"));
|
||||
assertThat(in.readLine(), startsWith("\\_Filter[i{r}#"));
|
||||
assertThat(in.readLine(), startsWith(" \\_SubQueryAlias[doc]"));
|
||||
assertThat(in.readLine(), startsWith(" \\_CatalogTable[index=test,type=doc][i{r}#"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
command("EXPLAIN (PLAN OPTIMIZED) SELECT * FROM test.doc WHERE i = 2");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("Project[[i{r}#"));
|
||||
assertThat(in.readLine(), startsWith("\\_Filter[i{r}#"));
|
||||
assertThat(in.readLine(), startsWith(" \\_CatalogTable[index=test,type=doc][i{r}#"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
command("EXPLAIN (PLAN EXECUTABLE) SELECT * FROM test.doc WHERE i = 2");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("EsQueryExec[test/doc,{"));
|
||||
assertThat(in.readLine(), startsWith(" \"query\" : {"));
|
||||
assertThat(in.readLine(), startsWith(" \"term\" : {"));
|
||||
assertThat(in.readLine(), startsWith(" \"i\" : {"));
|
||||
assertThat(in.readLine(), startsWith(" \"value\" : 2,"));
|
||||
assertThat(in.readLine(), startsWith(" \"boost\" : 1.0"));
|
||||
assertThat(in.readLine(), startsWith(" }"));
|
||||
assertThat(in.readLine(), startsWith(" }"));
|
||||
assertThat(in.readLine(), startsWith(" },"));
|
||||
assertThat(in.readLine(), startsWith(" \"_source\" : {"));
|
||||
assertThat(in.readLine(), startsWith(" \"includes\" : ["));
|
||||
assertThat(in.readLine(), startsWith(" \"test_field\""));
|
||||
assertThat(in.readLine(), startsWith(" ],"));
|
||||
assertThat(in.readLine(), startsWith(" \"excludes\" : [ ]"));
|
||||
assertThat(in.readLine(), startsWith(" },"));
|
||||
assertThat(in.readLine(), startsWith(" \"docvalue_fields\" : ["));
|
||||
assertThat(in.readLine(), startsWith(" \"i\""));
|
||||
assertThat(in.readLine(), startsWith(" ]"));
|
||||
assertThat(in.readLine(), startsWith("}]"));
|
||||
assertEquals("", in.readLine());
|
||||
}
|
||||
|
||||
public void testExplainWithCount() throws IOException {
|
||||
index("test", body -> body.field("test_field", "test_value1").field("i", 1));
|
||||
index("test", body -> body.field("test_field", "test_value2").field("i", 2));
|
||||
|
||||
command("EXPLAIN (PLAN PARSED) SELECT COUNT(*) FROM test.doc");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("With[{}]"));
|
||||
assertThat(in.readLine(), startsWith("\\_Project[[?COUNT(?*)]]"));
|
||||
assertThat(in.readLine(), startsWith(" \\_UnresolvedRelation[[index=test, type=doc],null]"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
command("EXPLAIN " + (randomBoolean() ? "" : "(PLAN ANALYZED) ") + "SELECT COUNT(*) FROM test.doc");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("Aggregate[[],[COUNT(1)#"));
|
||||
assertThat(in.readLine(), startsWith("\\_SubQueryAlias[doc]"));
|
||||
assertThat(in.readLine(), startsWith(" \\_CatalogTable[index=test,type=doc][i{r}#"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
command("EXPLAIN (PLAN OPTIMIZED) SELECT COUNT(*) FROM test.doc");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("Aggregate[[],[COUNT(1)#"));
|
||||
assertThat(in.readLine(), startsWith("\\_CatalogTable[index=test,type=doc][i{r}#"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
command("EXPLAIN (PLAN EXECUTABLE) SELECT COUNT(*) FROM test.doc");
|
||||
assertThat(in.readLine(), containsString("plan"));
|
||||
assertThat(in.readLine(), startsWith("----------"));
|
||||
assertThat(in.readLine(), startsWith("EsQueryExec[test/doc,{"));
|
||||
assertThat(in.readLine(), startsWith(" \"size\" : 0,"));
|
||||
assertThat(in.readLine(), startsWith(" \"_source\" : false,"));
|
||||
assertThat(in.readLine(), startsWith(" \"stored_fields\" : \"_none_\""));
|
||||
assertThat(in.readLine(), startsWith("}]"));
|
||||
assertEquals("", in.readLine());
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import org.elasticsearch.test.hamcrest.RegexMatcher;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class SelectIT extends CliIntegrationTestCase {
|
||||
public void testSelect() throws IOException {
|
||||
index("test", body -> body.field("test_field", "test_value"));
|
||||
command("SELECT * FROM test.doc");
|
||||
assertThat(in.readLine(), containsString("test_field"));
|
||||
assertThat(in.readLine(), containsString("----------"));
|
||||
assertThat(in.readLine(), containsString("test_value"));
|
||||
assertEquals("", in.readLine());
|
||||
}
|
||||
|
||||
public void testSelectWithWhere() throws IOException {
|
||||
index("test", body -> body.field("test_field", "test_value1").field("i", 1));
|
||||
index("test", body -> body.field("test_field", "test_value2").field("i", 2));
|
||||
command("SELECT * FROM test.doc WHERE i = 2");
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*i\\s*\\|\\s*test_field\\s*"));
|
||||
assertThat(in.readLine(), containsString("----------"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*2\\s*\\|\\s*test_value2\\s*"));
|
||||
assertEquals("", in.readLine());
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import org.elasticsearch.test.hamcrest.RegexMatcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class ShowIT extends CliIntegrationTestCase {
|
||||
public void testShowTables() throws IOException {
|
||||
index("test1", body -> body.field("test_field", "test_value"));
|
||||
index("test2", body -> body.field("test_field", "test_value"));
|
||||
command("SHOW TABLES");
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*index\\s*\\|\\s*type\\s*"));
|
||||
assertThat(in.readLine(), containsString("----------"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*test[12]\\s*\\|\\s*doc\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*test[12]\\s*\\|\\s*doc\\s*"));
|
||||
assertEquals("", in.readLine());
|
||||
}
|
||||
|
||||
public void testShowFunctions() throws IOException {
|
||||
command("SHOW FUNCTIONS");
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*name\\s*\\|\\s*type\\s*"));
|
||||
assertThat(in.readLine(), containsString("----------"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*AVG\\s*\\|\\s*AGGREGATE\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*COUNT\\s*\\|\\s*AGGREGATE\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*MAX\\s*\\|\\s*AGGREGATE\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*MIN\\s*\\|\\s*AGGREGATE\\s*"));
|
||||
String line = in.readLine();
|
||||
Pattern aggregateFunction = Pattern.compile("\\s*[A-Z0-9_~]+\\s*\\|\\s*AGGREGATE\\s*");
|
||||
while (aggregateFunction.matcher(line).matches()) {
|
||||
line = in.readLine();
|
||||
}
|
||||
Pattern scalarFunction = Pattern.compile("\\s*[A-Z0-9_~]+\\s*\\|\\s*SCALAR\\s*");
|
||||
while (scalarFunction.matcher(line).matches()) {
|
||||
line = in.readLine();
|
||||
}
|
||||
assertEquals("", line);
|
||||
|
||||
command("SHOW FUNCTIONS LIKE 'L%'");
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*name\\s*\\|\\s*type\\s*"));
|
||||
assertThat(in.readLine(), containsString("----------"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*LOG\\s*\\|\\s*SCALAR\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*LOG10\\s*\\|\\s*SCALAR\\s*"));
|
||||
assertEquals("", in.readLine());
|
||||
|
||||
command("SHOW FUNCTIONS LIKE '%DAY%'");
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*name\\s*\\|\\s*type\\s*"));
|
||||
assertThat(in.readLine(), containsString("----------"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*DAY_OF_MONTH\\s*\\|\\s*SCALAR\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*DAY\\s*\\|\\s*SCALAR\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*DAY_OF_WEEK\\s*\\|\\s*SCALAR\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*DAY_OF_YEAR\\s*\\|\\s*SCALAR\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*HOUR_OF_DAY\\s*\\|\\s*SCALAR\\s*"));
|
||||
assertThat(in.readLine(), RegexMatcher.matches("\\s*MINUTE_OF_DAY\\s*\\|\\s*SCALAR\\s*"));
|
||||
assertEquals("", in.readLine());
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
public class ProtoTests extends ESTestCase {
|
||||
// NOCOMMIT probably should be an integration test that runs against a running copy of ES with SQL installed
|
||||
// NOCOMMIT port remaining demos
|
||||
|
||||
private static Client esClient;
|
||||
private static CliHttpServer server;
|
||||
@ -71,6 +71,7 @@ public class ProtoTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testInfoAction() throws Exception {
|
||||
// NOCOMMIT port to CliIntegrationTestCase
|
||||
InfoResponse esInfo = (InfoResponse) client.serverInfo();
|
||||
assertThat(esInfo, notNullValue());
|
||||
assertThat(esInfo.cluster, is("elasticsearch"));
|
||||
@ -81,23 +82,12 @@ public class ProtoTests extends ESTestCase {
|
||||
//assertThat(esInfo.minorVersion(), is(0));
|
||||
}
|
||||
|
||||
public void testBasicQuery() throws Exception {
|
||||
CommandResponse command = (CommandResponse) client.command("SHOW TABLES", null);
|
||||
System.out.println(command.data);
|
||||
}
|
||||
|
||||
public void testDemoQuery() throws Exception {
|
||||
CommandResponse command = (CommandResponse) client.command("SELECT first_name f, last_name l, YEAR(dep.from_date) start FROM emp.emp WHERE dep.dept_name = 'Production' AND tenure > 30 ORDER BY start", null);
|
||||
System.out.println(command.data);
|
||||
}
|
||||
|
||||
public void testDemo() throws Exception {
|
||||
// add math functions
|
||||
|
||||
// add statistical function + explanation on optimization
|
||||
|
||||
List<String> commands = Arrays.asList(
|
||||
"SHOW TABLES",
|
||||
"DESCRIBE emp.emp",
|
||||
"SELECT * FROM emp.emp",
|
||||
"SELECT * FROM emp.emp LIMIT 5",
|
||||
@ -106,18 +96,14 @@ public class ProtoTests extends ESTestCase {
|
||||
"SELECT * FROM emp.emp WHERE MATCH(first_name, 'Mary')",
|
||||
"SELECT * FROM emp.emp WHERE MATCH('first_name,last_name', 'Morton', 'type=best_fields;default_operator=OR')",
|
||||
"SELECT * FROM emp.emp WHERE QUERY('Elvis Alain')",
|
||||
"SHOW FUNCTIONS",
|
||||
"SHOW FUNCTIONS LIKE 'L%'",
|
||||
"SELECT LOG(salary) FROM emp.emp",
|
||||
"SELECT salary s, LOG(salary) m FROM emp.emp LIMIT 5",
|
||||
"SELECT salary s, EXP(LOG(salary)) m FROM emp.emp LIMIT 5",
|
||||
"SELECT salary s, ROUND(EXP(LOG(salary))) m FROM emp.emp LIMIT 5",
|
||||
"SELECT salary s, ROUND(EXP(LOG(salary))) m FROM emp.emp ORDER BY ROUND(LOG(emp_no)) LIMIT 5",
|
||||
"SHOW FUNCTIONS LIKE '%DAY%'",
|
||||
"SELECT year(birth_date) year, last_name l, first_name f FROM emp.emp WHERE year(birth_date) <=1960 AND tenure < 25 ORDER BY year LIMIT 5",
|
||||
"SELECT COUNT(*) FROM emp.emp",
|
||||
"SELECT COUNT(*) FROM emp.emp WHERE emp_no >= 10010",
|
||||
"EXPLAIN (PLAN EXECUTABLE) SELECT COUNT(*) FROM emp.emp",
|
||||
"SELECT tenure, COUNT(*) count, MIN(salary) min, AVG(salary) avg, MAX(salary) max FROM emp.emp GROUP BY tenure",
|
||||
"SELECT YEAR(birth_date) born, COUNT(*) count, MIN(salary) min, AVG(salary) avg, MAX(salary) max FROM emp.emp GROUP BY born",
|
||||
"SELECT tenure, gender, COUNT(tenure) count, AVG(salary) avg FROM emp.emp GROUP BY tenure, gender HAVING avg > 50000",
|
||||
|
4
sql/cli/src/test/resources/plugin-security.policy
Normal file
4
sql/cli/src/test/resources/plugin-security.policy
Normal file
@ -0,0 +1,4 @@
|
||||
grant {
|
||||
// Policy is required for tests to connect to testing Elasticsearch instance.
|
||||
permission java.net.SocketPermission "*", "connect,resolve";
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user