From 45b5ab24fec2fae36e0eb205ccd00d8040ed9c7e Mon Sep 17 00:00:00 2001 From: Ryan Ernst <ryan@iernst.net> Date: Mon, 7 Mar 2016 12:42:15 -0800 Subject: [PATCH] Moved MockTerminal and created a base test case for cli commands. --- .../java/org/elasticsearch/cli/Command.java | 6 +- .../common/cli/CheckFileCommand.java | 138 ------------------ .../common/cli/TerminalTests.java | 7 +- .../logging/LoggingConfigurationTests.java | 2 +- .../InternalSettingsPreparerTests.java | 2 +- .../elasticsearch/plugins/PluginCliTests.java | 4 +- .../bootstrap/BootstrapCliParserTests.java | 10 +- .../plugins/InstallPluginCommandTests.java | 7 +- .../plugins/ListPluginsCommandTests.java | 7 +- .../plugins/RemovePluginCommandTests.java | 4 +- .../elasticsearch/cli/CommandTestCase.java | 48 ++++++ .../{common => }/cli/MockTerminal.java | 10 +- .../common/cli/CliToolTestCase.java | 1 + 13 files changed, 75 insertions(+), 171 deletions(-) delete mode 100644 core/src/main/java/org/elasticsearch/common/cli/CheckFileCommand.java create mode 100644 test/framework/src/main/java/org/elasticsearch/cli/CommandTestCase.java rename test/framework/src/main/java/org/elasticsearch/{common => }/cli/MockTerminal.java (92%) diff --git a/core/src/main/java/org/elasticsearch/cli/Command.java b/core/src/main/java/org/elasticsearch/cli/Command.java index d688347099d..6e57905b5b2 100644 --- a/core/src/main/java/org/elasticsearch/cli/Command.java +++ b/core/src/main/java/org/elasticsearch/cli/Command.java @@ -49,14 +49,14 @@ public abstract class Command { } /** Parses options for this command from args and executes it. */ - public final int main(String[] args, Terminal terminal) throws Exception { + protected final int main(String[] args, Terminal terminal) throws Exception { final OptionSet options; try { options = parser.parse(args); } catch (OptionException e) { printHelp(terminal); - terminal.println("ERROR: " + e.getMessage()); + terminal.println(Terminal.Verbosity.SILENT, "ERROR: " + e.getMessage()); return ExitCodes.USAGE; } @@ -69,7 +69,7 @@ public abstract class Command { if (options.has(verboseOption)) { // mutually exclusive, we can remove this with jopt-simple 5.0, which natively supports it printHelp(terminal); - terminal.println("ERROR: Cannot specify -s and -v together"); + terminal.println(Terminal.Verbosity.SILENT, "ERROR: Cannot specify -s and -v together"); return ExitCodes.USAGE; } terminal.setVerbosity(Terminal.Verbosity.SILENT); diff --git a/core/src/main/java/org/elasticsearch/common/cli/CheckFileCommand.java b/core/src/main/java/org/elasticsearch/common/cli/CheckFileCommand.java deleted file mode 100644 index e2fcbe89df8..00000000000 --- a/core/src/main/java/org/elasticsearch/common/cli/CheckFileCommand.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.common.cli; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.Environment; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.attribute.PosixFileAttributeView; -import java.nio.file.attribute.PosixFileAttributes; -import java.nio.file.attribute.PosixFilePermission; -import java.nio.file.attribute.PosixFilePermissions; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * A helper command that checks if configured paths have been changed when running a CLI command. - * It is only executed in case of specified paths by the command and if the paths underlying filesystem - * supports posix permissions. - * - * If this is the case, a warn message is issued whenever an owner, a group or the file permissions is changed by - * the command being executed and not configured back to its prior state, which should be the task of the command - * being executed. - * - */ -public abstract class CheckFileCommand extends CliTool.Command { - - public CheckFileCommand(Terminal terminal) { - super(terminal); - } - - /** - * abstract method, which should implement the same logic as CliTool.Command.execute(), but is wrapped - */ - public abstract CliTool.ExitStatus doExecute(Settings settings, Environment env) throws Exception; - - /** - * Returns the array of paths, that should be checked if the permissions, user or groups have changed - * before and after execution of the command - * - */ - protected abstract Path[] pathsForPermissionsCheck(Settings settings, Environment env) throws Exception; - - @Override - public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception { - Path[] paths = pathsForPermissionsCheck(settings, env); - - if (paths == null || paths.length == 0) { - return doExecute(settings, env); - } - - Map<Path, Set<PosixFilePermission>> permissions = new HashMap<>(paths.length); - Map<Path, String> owners = new HashMap<>(paths.length); - Map<Path, String> groups = new HashMap<>(paths.length); - - if (paths != null && paths.length > 0) { - for (Path path : paths) { - try { - boolean supportsPosixPermissions = Environment.getFileStore(path).supportsFileAttributeView(PosixFileAttributeView.class); - if (supportsPosixPermissions) { - PosixFileAttributes attributes = Files.readAttributes(path, PosixFileAttributes.class); - permissions.put(path, attributes.permissions()); - owners.put(path, attributes.owner().getName()); - groups.put(path, attributes.group().getName()); - } - } catch (IOException e) { - // silently swallow if not supported, no need to log things - } - } - } - - CliTool.ExitStatus status = doExecute(settings, env); - - // check if permissions differ - for (Map.Entry<Path, Set<PosixFilePermission>> entry : permissions.entrySet()) { - if (!Files.exists(entry.getKey())) { - continue; - } - - Set<PosixFilePermission> permissionsBeforeWrite = entry.getValue(); - Set<PosixFilePermission> permissionsAfterWrite = Files.getPosixFilePermissions(entry.getKey()); - if (!permissionsBeforeWrite.equals(permissionsAfterWrite)) { - terminal.println(Terminal.Verbosity.SILENT, "WARNING: The file permissions of [" + entry.getKey() + "] have changed " - + "from [" + PosixFilePermissions.toString(permissionsBeforeWrite) + "] " - + "to [" + PosixFilePermissions.toString(permissionsAfterWrite) + "]"); - terminal.println(Terminal.Verbosity.SILENT, "Please ensure that the user account running Elasticsearch has read access to this file!"); - } - } - - // check if owner differs - for (Map.Entry<Path, String> entry : owners.entrySet()) { - if (!Files.exists(entry.getKey())) { - continue; - } - - String ownerBeforeWrite = entry.getValue(); - String ownerAfterWrite = Files.getOwner(entry.getKey()).getName(); - if (!ownerAfterWrite.equals(ownerBeforeWrite)) { - terminal.println(Terminal.Verbosity.SILENT, "WARNING: Owner of file [" + entry.getKey() + "] used to be [" + ownerBeforeWrite + "], but now is [" + ownerAfterWrite + "]"); - } - } - - // check if group differs - for (Map.Entry<Path, String> entry : groups.entrySet()) { - if (!Files.exists(entry.getKey())) { - continue; - } - - String groupBeforeWrite = entry.getValue(); - String groupAfterWrite = Files.readAttributes(entry.getKey(), PosixFileAttributes.class).group().getName(); - if (!groupAfterWrite.equals(groupBeforeWrite)) { - terminal.println(Terminal.Verbosity.SILENT, "WARNING: Group of file [" + entry.getKey() + "] used to be [" + groupBeforeWrite + "], but now is [" + groupAfterWrite + "]"); - } - } - - return status; - } -} diff --git a/core/src/test/java/org/elasticsearch/common/cli/TerminalTests.java b/core/src/test/java/org/elasticsearch/common/cli/TerminalTests.java index deb64e906b4..12fc4cb77e4 100644 --- a/core/src/test/java/org/elasticsearch/common/cli/TerminalTests.java +++ b/core/src/test/java/org/elasticsearch/common/cli/TerminalTests.java @@ -19,7 +19,10 @@ package org.elasticsearch.common.cli; -public class TerminalTests extends CliToolTestCase { +import org.elasticsearch.cli.MockTerminal; +import org.elasticsearch.test.ESTestCase; + +public class TerminalTests extends ESTestCase { public void testVerbosity() throws Exception { MockTerminal terminal = new MockTerminal(); terminal.setVerbosity(Terminal.Verbosity.SILENT); @@ -48,7 +51,7 @@ public class TerminalTests extends CliToolTestCase { logTerminal.println(verbosity, text); String output = logTerminal.getOutput(); assertTrue(output, output.contains(text)); - logTerminal.resetOutput(); + logTerminal.reset(); } private void assertNotPrinted(MockTerminal logTerminal, Terminal.Verbosity verbosity, String text) throws Exception { diff --git a/core/src/test/java/org/elasticsearch/common/logging/LoggingConfigurationTests.java b/core/src/test/java/org/elasticsearch/common/logging/LoggingConfigurationTests.java index 0cca19d33bf..5c812cca0a7 100644 --- a/core/src/test/java/org/elasticsearch/common/logging/LoggingConfigurationTests.java +++ b/core/src/test/java/org/elasticsearch/common/logging/LoggingConfigurationTests.java @@ -27,7 +27,7 @@ import java.util.Arrays; import org.apache.log4j.Appender; import org.apache.log4j.Logger; -import org.elasticsearch.common.cli.MockTerminal; +import org.elasticsearch.cli.MockTerminal; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.node.internal.InternalSettingsPreparer; diff --git a/core/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java b/core/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java index 33876ef61ad..c979b2f4013 100644 --- a/core/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java +++ b/core/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java @@ -24,7 +24,7 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; -import org.elasticsearch.common.cli.MockTerminal; +import org.elasticsearch.cli.MockTerminal; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.SettingsException; diff --git a/core/src/test/java/org/elasticsearch/plugins/PluginCliTests.java b/core/src/test/java/org/elasticsearch/plugins/PluginCliTests.java index 7a4590f8e25..708cefd91b2 100644 --- a/core/src/test/java/org/elasticsearch/plugins/PluginCliTests.java +++ b/core/src/test/java/org/elasticsearch/plugins/PluginCliTests.java @@ -20,10 +20,8 @@ package org.elasticsearch.plugins; import org.elasticsearch.common.cli.CliToolTestCase; -import org.elasticsearch.common.cli.MockTerminal; +import org.elasticsearch.cli.MockTerminal; -import static org.elasticsearch.common.cli.CliTool.ExitStatus.OK_AND_EXIT; -import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; diff --git a/qa/evil-tests/src/test/java/org/elasticsearch/bootstrap/BootstrapCliParserTests.java b/qa/evil-tests/src/test/java/org/elasticsearch/bootstrap/BootstrapCliParserTests.java index 12b5ab9eb39..18d6e0ac3c9 100644 --- a/qa/evil-tests/src/test/java/org/elasticsearch/bootstrap/BootstrapCliParserTests.java +++ b/qa/evil-tests/src/test/java/org/elasticsearch/bootstrap/BootstrapCliParserTests.java @@ -25,7 +25,7 @@ import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.cli.CliTool.ExitStatus; import org.elasticsearch.common.cli.CliToolTestCase; import org.elasticsearch.cli.UserError; -import org.elasticsearch.common.cli.MockTerminal; +import org.elasticsearch.cli.MockTerminal; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.monitor.jvm.JvmInfo; import org.junit.After; @@ -89,7 +89,7 @@ public class BootstrapCliParserTests extends CliToolTestCase { assertTrue(output, output.contains(Build.CURRENT.date())); assertTrue(output, output.contains(JvmInfo.jvmInfo().version())); - terminal.resetOutput(); + terminal.reset(); parser = new BootstrapCLIParser(terminal); status = parser.execute(args("start --version")); assertStatus(status, OK_AND_EXIT); @@ -177,7 +177,7 @@ public class BootstrapCliParserTests extends CliToolTestCase { String output = terminal.getOutput(); assertTrue(output, output.contains("Parameter [network.host] needs value")); - terminal.resetOutput(); + terminal.reset(); status = parser.execute(args("start --network.host --foo")); assertStatus(status, USAGE); output = terminal.getOutput(); @@ -194,7 +194,7 @@ public class BootstrapCliParserTests extends CliToolTestCase { assertTrue(output, output.contains("Unrecognized option: --unknown-param")); // single dash in extra params - terminal.resetOutput(); + terminal.reset(); parser = new BootstrapCLIParser(terminal); status = parser.execute(args("start -network.host 127.0.0.1")); assertStatus(status, USAGE); @@ -228,7 +228,7 @@ public class BootstrapCliParserTests extends CliToolTestCase { tuples.add(new Tuple<>("-h", "elasticsearch.help")); for (Tuple<String, String> tuple : tuples) { - terminal.resetOutput(); + terminal.reset(); BootstrapCLIParser parser = new BootstrapCLIParser(terminal); ExitStatus status = parser.execute(args(tuple.v1())); assertStatus(status, OK_AND_EXIT); diff --git a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java index 342b579a175..514090d9869 100644 --- a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java +++ b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java @@ -36,7 +36,6 @@ import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFileAttributes; import java.nio.file.attribute.PosixFilePermission; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -45,11 +44,7 @@ import java.util.zip.ZipOutputStream; import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.Version; -import org.elasticsearch.cli.ExitCodes; -import org.elasticsearch.common.cli.CliTool; -import org.elasticsearch.common.cli.CliToolTestCase; -import org.elasticsearch.common.cli.MockTerminal; -import org.elasticsearch.common.cli.Terminal; +import org.elasticsearch.cli.MockTerminal; import org.elasticsearch.cli.UserError; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; diff --git a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/ListPluginsCommandTests.java b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/ListPluginsCommandTests.java index aed1696898a..cbdd031dea1 100644 --- a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/ListPluginsCommandTests.java +++ b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/ListPluginsCommandTests.java @@ -22,15 +22,10 @@ package org.elasticsearch.plugins; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collections; -import java.util.List; import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.cli.ExitCodes; -import org.elasticsearch.common.cli.CliTool; -import org.elasticsearch.common.cli.CliToolTestCase; -import org.elasticsearch.common.cli.MockTerminal; -import org.elasticsearch.common.cli.Terminal; +import org.elasticsearch.cli.MockTerminal; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.test.ESTestCase; diff --git a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/RemovePluginCommandTests.java b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/RemovePluginCommandTests.java index a678d4f25f6..d9d5661b834 100644 --- a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/RemovePluginCommandTests.java +++ b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/RemovePluginCommandTests.java @@ -26,9 +26,7 @@ import java.nio.file.Path; import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.cli.UserError; -import org.elasticsearch.common.cli.CliToolTestCase; -import org.elasticsearch.common.cli.MockTerminal; -import org.elasticsearch.common.cli.Terminal; +import org.elasticsearch.cli.MockTerminal; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.test.ESTestCase; diff --git a/test/framework/src/main/java/org/elasticsearch/cli/CommandTestCase.java b/test/framework/src/main/java/org/elasticsearch/cli/CommandTestCase.java new file mode 100644 index 00000000000..3af25509adb --- /dev/null +++ b/test/framework/src/main/java/org/elasticsearch/cli/CommandTestCase.java @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.cli; + +import joptsimple.OptionSet; +import org.elasticsearch.common.cli.Terminal; +import org.elasticsearch.test.ESTestCase; +import org.junit.Before; + +/** + * A base test case for cli tools. + */ +public abstract class CommandTestCase extends ESTestCase { + + protected final MockTerminal terminal = new MockTerminal(); + + @Before + public void resetTerminal() { + terminal.reset(); + terminal.setVerbosity(Terminal.Verbosity.NORMAL); + } + + protected abstract Command newCommand(); + + public String execute(String... args) throws Exception { + Command command = newCommand(); + OptionSet options = command.parser.parse(args); + command.execute(terminal, options); + return terminal.getOutput(); + } +} diff --git a/test/framework/src/main/java/org/elasticsearch/common/cli/MockTerminal.java b/test/framework/src/main/java/org/elasticsearch/cli/MockTerminal.java similarity index 92% rename from test/framework/src/main/java/org/elasticsearch/common/cli/MockTerminal.java rename to test/framework/src/main/java/org/elasticsearch/cli/MockTerminal.java index 3b2903b3fab..bb01369ac50 100644 --- a/test/framework/src/main/java/org/elasticsearch/common/cli/MockTerminal.java +++ b/test/framework/src/main/java/org/elasticsearch/cli/MockTerminal.java @@ -17,7 +17,7 @@ * under the License. */ -package org.elasticsearch.common.cli; +package org.elasticsearch.cli; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; @@ -27,6 +27,8 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayDeque; import java.util.Deque; +import org.elasticsearch.common.cli.Terminal; + /** * A terminal for tests which captures all output, and * can be plugged with fake input. @@ -78,8 +80,10 @@ public class MockTerminal extends Terminal { return buffer.toString("UTF-8"); } - /** Wipes the output. */ - public void resetOutput() { + /** Wipes the input and output. */ + public void reset() { buffer.reset(); + textInput.clear(); + secretInput.clear(); } } diff --git a/test/framework/src/main/java/org/elasticsearch/common/cli/CliToolTestCase.java b/test/framework/src/main/java/org/elasticsearch/common/cli/CliToolTestCase.java index 9debf4b8f33..330758223a5 100644 --- a/test/framework/src/main/java/org/elasticsearch/common/cli/CliToolTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/common/cli/CliToolTestCase.java @@ -21,6 +21,7 @@ package org.elasticsearch.common.cli; import java.io.IOException; +import org.elasticsearch.cli.MockTerminal; import org.elasticsearch.common.Strings; import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.test.ESTestCase;