diff --git a/core/src/main/java/org/elasticsearch/bootstrap/BootstrapCLIParser.java b/core/src/main/java/org/elasticsearch/bootstrap/BootstrapCLIParser.java index ca67fc91132..25ae53873fe 100644 --- a/core/src/main/java/org/elasticsearch/bootstrap/BootstrapCLIParser.java +++ b/core/src/main/java/org/elasticsearch/bootstrap/BootstrapCLIParser.java @@ -26,8 +26,8 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.cli.CliTool; import org.elasticsearch.common.cli.CliToolConfig; -import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.cli.UserError; +import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.monitor.jvm.JvmInfo; @@ -37,7 +37,6 @@ import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Properties; -import java.util.Set; import static org.elasticsearch.common.cli.CliToolConfig.Builder.cmd; import static org.elasticsearch.common.cli.CliToolConfig.Builder.optionBuilder; diff --git a/core/src/main/java/org/elasticsearch/common/cli/Terminal.java b/core/src/main/java/org/elasticsearch/common/cli/Terminal.java index 8d4a8036bdf..fbef1f78cc3 100644 --- a/core/src/main/java/org/elasticsearch/common/cli/Terminal.java +++ b/core/src/main/java/org/elasticsearch/common/cli/Terminal.java @@ -23,6 +23,7 @@ import java.io.BufferedReader; import java.io.Console; import java.io.IOException; import java.io.InputStreamReader; +import java.io.PrintWriter; import java.nio.charset.Charset; import org.elasticsearch.common.SuppressForbidden; @@ -52,6 +53,13 @@ public abstract class Terminal { /** The current verbosity for the terminal, defaulting to {@link Verbosity#NORMAL}. */ private Verbosity verbosity = Verbosity.NORMAL; + /** The newline used when calling println. */ + private final String lineSeparator; + + protected Terminal(String lineSeparator) { + this.lineSeparator = lineSeparator; + } + /** Sets the verbosity of the terminal. */ void setVerbosity(Verbosity verbosity) { this.verbosity = verbosity; @@ -63,8 +71,8 @@ public abstract class Terminal { /** Reads password text from the terminal input. See {@link Console#readPassword()}}. */ public abstract char[] readSecret(String prompt); - /** Print a message directly to the terminal. */ - protected abstract void doPrint(String msg); + /** Returns a Writer which can be used to write to the terminal directly. */ + public abstract PrintWriter getWriter(); /** Prints a line to the terminal at {@link Verbosity#NORMAL} verbosity level. */ public final void println(String msg) { @@ -74,7 +82,8 @@ public abstract class Terminal { /** Prints a line to the terminal at {@code verbosity} level. */ public final void println(Verbosity verbosity, String msg) { if (this.verbosity.ordinal() >= verbosity.ordinal()) { - doPrint(msg + System.lineSeparator()); + getWriter().print(msg + lineSeparator); + getWriter().flush(); } } @@ -82,14 +91,17 @@ public abstract class Terminal { private static final Console console = System.console(); + ConsoleTerminal() { + super(System.lineSeparator()); + } + static boolean isSupported() { return console != null; } @Override - public void doPrint(String msg) { - console.printf("%s", msg); - console.flush(); + public PrintWriter getWriter() { + return console.writer(); } @Override @@ -105,16 +117,25 @@ public abstract class Terminal { private static class SystemTerminal extends Terminal { + private final PrintWriter writer = newWriter(); + + SystemTerminal() { + super(System.lineSeparator()); + } + + @SuppressForbidden(reason = "Writer for System.out") + private static PrintWriter newWriter() { + return new PrintWriter(System.out); + } + @Override - @SuppressForbidden(reason = "System#out") - public void doPrint(String msg) { - System.out.print(msg); - System.out.flush(); + public PrintWriter getWriter() { + return writer; } @Override public String readText(String text) { - doPrint(text); + getWriter().print(text); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset())); try { return reader.readLine(); 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 0e71ac7cd6a..deb64e906b4 100644 --- a/core/src/test/java/org/elasticsearch/common/cli/TerminalTests.java +++ b/core/src/test/java/org/elasticsearch/common/cli/TerminalTests.java @@ -19,41 +19,41 @@ package org.elasticsearch.common.cli; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.hasSize; - public class TerminalTests extends CliToolTestCase { public void testVerbosity() throws Exception { - CaptureOutputTerminal terminal = new CaptureOutputTerminal(Terminal.Verbosity.SILENT); + MockTerminal terminal = new MockTerminal(); + terminal.setVerbosity(Terminal.Verbosity.SILENT); assertPrinted(terminal, Terminal.Verbosity.SILENT, "text"); assertNotPrinted(terminal, Terminal.Verbosity.NORMAL, "text"); assertNotPrinted(terminal, Terminal.Verbosity.VERBOSE, "text"); - terminal = new CaptureOutputTerminal(Terminal.Verbosity.NORMAL); + terminal = new MockTerminal(); assertPrinted(terminal, Terminal.Verbosity.SILENT, "text"); assertPrinted(terminal, Terminal.Verbosity.NORMAL, "text"); assertNotPrinted(terminal, Terminal.Verbosity.VERBOSE, "text"); - terminal = new CaptureOutputTerminal(Terminal.Verbosity.VERBOSE); + terminal = new MockTerminal(); + terminal.setVerbosity(Terminal.Verbosity.VERBOSE); assertPrinted(terminal, Terminal.Verbosity.SILENT, "text"); assertPrinted(terminal, Terminal.Verbosity.NORMAL, "text"); assertPrinted(terminal, Terminal.Verbosity.VERBOSE, "text"); } public void testEscaping() throws Exception { - CaptureOutputTerminal terminal = new CaptureOutputTerminal(Terminal.Verbosity.NORMAL); + MockTerminal terminal = new MockTerminal(); assertPrinted(terminal, Terminal.Verbosity.NORMAL, "This message contains percent like %20n"); } - private void assertPrinted(CaptureOutputTerminal logTerminal, Terminal.Verbosity verbosity, String text) { + private void assertPrinted(MockTerminal logTerminal, Terminal.Verbosity verbosity, String text) throws Exception { logTerminal.println(verbosity, text); - assertEquals(1, logTerminal.getTerminalOutput().size()); - assertTrue(logTerminal.getTerminalOutput().get(0).contains(text)); - logTerminal.terminalOutput.clear(); + String output = logTerminal.getOutput(); + assertTrue(output, output.contains(text)); + logTerminal.resetOutput(); } - private void assertNotPrinted(CaptureOutputTerminal logTerminal, Terminal.Verbosity verbosity, String text) { + private void assertNotPrinted(MockTerminal logTerminal, Terminal.Verbosity verbosity, String text) throws Exception { logTerminal.println(verbosity, text); - assertThat(logTerminal.getTerminalOutput(), hasSize(0)); + String output = logTerminal.getOutput(); + assertTrue(output, output.isEmpty()); } } 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 a6dda573304..0cca19d33bf 100644 --- a/core/src/test/java/org/elasticsearch/common/logging/LoggingConfigurationTests.java +++ b/core/src/test/java/org/elasticsearch/common/logging/LoggingConfigurationTests.java @@ -19,21 +19,21 @@ package org.elasticsearch.common.logging; -import org.apache.log4j.Appender; -import org.apache.log4j.Logger; -import org.elasticsearch.common.cli.CliToolTestCase; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.Environment; -import org.elasticsearch.node.internal.InternalSettingsPreparer; -import org.elasticsearch.test.ESTestCase; -import org.junit.Before; - import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.Arrays; +import org.apache.log4j.Appender; +import org.apache.log4j.Logger; +import org.elasticsearch.common.cli.MockTerminal; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; +import org.elasticsearch.node.internal.InternalSettingsPreparer; +import org.elasticsearch.test.ESTestCase; +import org.junit.Before; + import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -162,7 +162,7 @@ public class LoggingConfigurationTests extends ESTestCase { .put("appender.console.type", "console") .put("appender.console.layout.type", "consolePattern") .put("appender.console.layout.conversionPattern", "[%d{ISO8601}][%-5p][%-25c] %m%n") - .build(), new CliToolTestCase.MockTerminal()); + .build(), new MockTerminal()); LogConfigurator.configure(environment.settings(), true); // args should overwrite whatever is in the config ESLogger esLogger = ESLoggerFactory.getLogger("test_resolve_order"); @@ -187,7 +187,7 @@ public class LoggingConfigurationTests extends ESTestCase { Settings.builder() .put(Environment.PATH_CONF_SETTING.getKey(), tmpDir.toAbsolutePath()) .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) - .build(), new CliToolTestCase.MockTerminal()); + .build(), new MockTerminal()); LogConfigurator.configure(environment.settings(), false); ESLogger esLogger = ESLoggerFactory.getLogger("test_config_not_read"); 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 95439ebdc26..33876ef61ad 100644 --- a/core/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java +++ b/core/src/test/java/org/elasticsearch/node/internal/InternalSettingsPreparerTests.java @@ -19,9 +19,13 @@ package org.elasticsearch.node.internal; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.elasticsearch.common.cli.MockTerminal; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.common.cli.CliToolTestCase; -import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.env.Environment; @@ -29,17 +33,9 @@ import org.elasticsearch.test.ESTestCase; import org.junit.After; import org.junit.Before; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; - import static org.elasticsearch.common.settings.Settings.settingsBuilder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; public class InternalSettingsPreparerTests extends ESTestCase { @@ -81,17 +77,9 @@ public class InternalSettingsPreparerTests extends ESTestCase { } public void testReplacePromptPlaceholders() { - final Terminal terminal = new CliToolTestCase.MockTerminal() { - @Override - public char[] readSecret(String message) { - return "replaced".toCharArray(); - } - - @Override - public String readText(String message) { - return "text"; - } - }; + MockTerminal terminal = new MockTerminal(); + terminal.addTextInput("text"); + terminal.addSecretInput("replaced"); Settings.Builder builder = settingsBuilder() .put(baseEnvSettings) diff --git a/core/src/test/java/org/elasticsearch/plugins/PluginCliTests.java b/core/src/test/java/org/elasticsearch/plugins/PluginCliTests.java index 3a121590083..bd280e4e1d7 100644 --- a/core/src/test/java/org/elasticsearch/plugins/PluginCliTests.java +++ b/core/src/test/java/org/elasticsearch/plugins/PluginCliTests.java @@ -20,6 +20,7 @@ package org.elasticsearch.plugins; import org.elasticsearch.common.cli.CliToolTestCase; +import org.elasticsearch.common.cli.MockTerminal; import static org.elasticsearch.common.cli.CliTool.ExitStatus.OK_AND_EXIT; import static org.hamcrest.Matchers.containsString; @@ -28,22 +29,22 @@ import static org.hamcrest.Matchers.is; public class PluginCliTests extends CliToolTestCase { public void testHelpWorks() throws Exception { - CliToolTestCase.CaptureOutputTerminal terminal = new CliToolTestCase.CaptureOutputTerminal(); + MockTerminal terminal = new MockTerminal(); assertThat(new PluginCli(terminal).execute(args("--help")), is(OK_AND_EXIT)); assertTerminalOutputContainsHelpFile(terminal, "/org/elasticsearch/plugins/plugin.help"); - terminal.getTerminalOutput().clear(); + terminal.resetOutput(); assertThat(new PluginCli(terminal).execute(args("install -h")), is(OK_AND_EXIT)); assertTerminalOutputContainsHelpFile(terminal, "/org/elasticsearch/plugins/plugin-install.help"); for (String plugin : InstallPluginCommand.OFFICIAL_PLUGINS) { - assertThat(terminal.getTerminalOutput(), hasItem(containsString(plugin))); + assertThat(terminal.getOutput(), containsString(plugin)); } - terminal.getTerminalOutput().clear(); + terminal.resetOutput(); assertThat(new PluginCli(terminal).execute(args("remove --help")), is(OK_AND_EXIT)); assertTerminalOutputContainsHelpFile(terminal, "/org/elasticsearch/plugins/plugin-remove.help"); - terminal.getTerminalOutput().clear(); + terminal.resetOutput(); assertThat(new PluginCli(terminal).execute(args("list -h")), is(OK_AND_EXIT)); assertTerminalOutputContainsHelpFile(terminal, "/org/elasticsearch/plugins/plugin-list.help"); } 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 012af99cef0..c172999e7cb 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 @@ -24,10 +24,10 @@ import org.elasticsearch.Version; import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.cli.CliTool.ExitStatus; import org.elasticsearch.common.cli.CliToolTestCase; +import org.elasticsearch.common.cli.MockTerminal; import org.elasticsearch.common.cli.UserError; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.monitor.jvm.JvmInfo; -import org.hamcrest.Matcher; import org.junit.After; import org.junit.Before; @@ -37,7 +37,6 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Properties; import static org.elasticsearch.common.cli.CliTool.ExitStatus.OK; import static org.elasticsearch.common.cli.CliTool.ExitStatus.OK_AND_EXIT; @@ -50,7 +49,7 @@ import static org.hamcrest.Matchers.nullValue; @SuppressForbidden(reason = "modifies system properties intentionally") public class BootstrapCliParserTests extends CliToolTestCase { - private CaptureOutputTerminal terminal = new CaptureOutputTerminal(); + private MockTerminal terminal = new MockTerminal(); private List propertiesToClear = new ArrayList<>(); private Map properties; @@ -73,10 +72,11 @@ public class BootstrapCliParserTests extends CliToolTestCase { ExitStatus status = parser.execute(args("version")); assertStatus(status, OK_AND_EXIT); - assertThatTerminalOutput(containsString(Version.CURRENT.toString())); - assertThatTerminalOutput(containsString(Build.CURRENT.shortHash())); - assertThatTerminalOutput(containsString(Build.CURRENT.date())); - assertThatTerminalOutput(containsString(JvmInfo.jvmInfo().version())); + String output = terminal.getOutput(); + assertTrue(output, output.contains(Version.CURRENT.toString())); + assertTrue(output, output.contains(Build.CURRENT.shortHash())); + assertTrue(output, output.contains(Build.CURRENT.date())); + assertTrue(output, output.contains(JvmInfo.jvmInfo().version())); } public void testThatVersionIsReturnedAsStartParameter() throws Exception { @@ -84,20 +84,22 @@ public class BootstrapCliParserTests extends CliToolTestCase { ExitStatus status = parser.execute(args("start -V")); assertStatus(status, OK_AND_EXIT); - assertThatTerminalOutput(containsString(Version.CURRENT.toString())); - assertThatTerminalOutput(containsString(Build.CURRENT.shortHash())); - assertThatTerminalOutput(containsString(Build.CURRENT.date())); - assertThatTerminalOutput(containsString(JvmInfo.jvmInfo().version())); + String output = terminal.getOutput(); + assertTrue(output, output.contains(Version.CURRENT.toString())); + assertTrue(output, output.contains(Build.CURRENT.shortHash())); + assertTrue(output, output.contains(Build.CURRENT.date())); + assertTrue(output, output.contains(JvmInfo.jvmInfo().version())); - CaptureOutputTerminal terminal = new CaptureOutputTerminal(); + terminal.resetOutput(); parser = new BootstrapCLIParser(terminal); status = parser.execute(args("start --version")); assertStatus(status, OK_AND_EXIT); - assertThatTerminalOutput(containsString(Version.CURRENT.toString())); - assertThatTerminalOutput(containsString(Build.CURRENT.shortHash())); - assertThatTerminalOutput(containsString(Build.CURRENT.date())); - assertThatTerminalOutput(containsString(JvmInfo.jvmInfo().version())); + output = terminal.getOutput(); + assertTrue(output, output.contains(Version.CURRENT.toString())); + assertTrue(output, output.contains(Build.CURRENT.shortHash())); + assertTrue(output, output.contains(Build.CURRENT.date())); + assertTrue(output, output.contains(JvmInfo.jvmInfo().version())); } public void testThatPidFileCanBeConfigured() throws Exception { @@ -173,11 +175,14 @@ public class BootstrapCliParserTests extends CliToolTestCase { ExitStatus status = parser.execute(args("start --network.host")); assertStatus(status, USAGE); - assertThatTerminalOutput(containsString("Parameter [network.host] needs value")); + String output = terminal.getOutput(); + assertTrue(output, output.contains("Parameter [network.host] needs value")); + terminal.resetOutput(); status = parser.execute(args("start --network.host --foo")); assertStatus(status, USAGE); - assertThatTerminalOutput(containsString("Parameter [network.host] needs value")); + output = terminal.getOutput(); + assertTrue(output, output.contains("Parameter [network.host] needs value")); } public void testParsingErrors() throws Exception { @@ -186,28 +191,32 @@ public class BootstrapCliParserTests extends CliToolTestCase { // unknown params ExitStatus status = parser.execute(args("version --unknown-param /tmp/pid")); assertStatus(status, USAGE); - assertThatTerminalOutput(containsString("Unrecognized option: --unknown-param")); + String output = terminal.getOutput(); + assertTrue(output, output.contains("Unrecognized option: --unknown-param")); // single dash in extra params - terminal = new CaptureOutputTerminal(); + terminal.resetOutput(); parser = new BootstrapCLIParser(terminal); status = parser.execute(args("start -network.host 127.0.0.1")); assertStatus(status, USAGE); - assertThatTerminalOutput(containsString("Parameter [-network.host]does not start with --")); + output = terminal.getOutput(); + assertTrue(output, output.contains("Parameter [-network.host]does not start with --")); // never ended parameter - terminal = new CaptureOutputTerminal(); + terminal = new MockTerminal(); parser = new BootstrapCLIParser(terminal); status = parser.execute(args("start --network.host")); assertStatus(status, USAGE); - assertThatTerminalOutput(containsString("Parameter [network.host] needs value")); + output = terminal.getOutput(); + assertTrue(output, output.contains("Parameter [network.host] needs value")); // free floating value - terminal = new CaptureOutputTerminal(); + terminal = new MockTerminal(); parser = new BootstrapCLIParser(terminal); status = parser.execute(args("start 127.0.0.1")); assertStatus(status, USAGE); - assertThatTerminalOutput(containsString("Parameter [127.0.0.1]does not start with --")); + output = terminal.getOutput(); + assertTrue(output, output.contains("Parameter [127.0.0.1]does not start with --")); } public void testHelpWorks() throws Exception { @@ -220,7 +229,7 @@ public class BootstrapCliParserTests extends CliToolTestCase { tuples.add(new Tuple<>("-h", "elasticsearch.help")); for (Tuple tuple : tuples) { - terminal = new CaptureOutputTerminal(); + terminal.resetOutput(); BootstrapCLIParser parser = new BootstrapCLIParser(terminal); ExitStatus status = parser.execute(args(tuple.v1())); assertStatus(status, OK_AND_EXIT); @@ -253,16 +262,12 @@ public class BootstrapCliParserTests extends CliToolTestCase { propertiesToClear.addAll(Arrays.asList(systemProperties)); } - private void assertSystemProperty(String name, String expectedValue) { - String msg = String.format(Locale.ROOT, "Expected property %s to be %s, terminal output was %s", name, expectedValue, terminal.getTerminalOutput()); + private void assertSystemProperty(String name, String expectedValue) throws Exception { + String msg = String.format(Locale.ROOT, "Expected property %s to be %s, terminal output was %s", name, expectedValue, terminal.getOutput()); assertThat(msg, System.getProperty(name), is(expectedValue)); } - private void assertStatus(ExitStatus status, ExitStatus expectedStatus) { - assertThat(String.format(Locale.ROOT, "Expected status to be [%s], but was [%s], terminal output was %s", expectedStatus, status, terminal.getTerminalOutput()), status, is(expectedStatus)); - } - - private void assertThatTerminalOutput(Matcher matcher) { - assertThat(terminal.getTerminalOutput(), hasItem(matcher)); + private void assertStatus(ExitStatus status, ExitStatus expectedStatus) throws Exception { + assertThat(String.format(Locale.ROOT, "Expected status to be [%s], but was [%s], terminal output was %s", expectedStatus, status, terminal.getOutput()), status, is(expectedStatus)); } } diff --git a/qa/evil-tests/src/test/java/org/elasticsearch/common/cli/CheckFileCommandTests.java b/qa/evil-tests/src/test/java/org/elasticsearch/common/cli/CheckFileCommandTests.java index 45f3df22cd7..485886b5cf4 100644 --- a/qa/evil-tests/src/test/java/org/elasticsearch/common/cli/CheckFileCommandTests.java +++ b/qa/evil-tests/src/test/java/org/elasticsearch/common/cli/CheckFileCommandTests.java @@ -49,7 +49,7 @@ import static org.hamcrest.Matchers.is; */ public class CheckFileCommandTests extends ESTestCase { - private CliToolTestCase.CaptureOutputTerminal captureOutputTerminal = new CliToolTestCase.CaptureOutputTerminal(); + private MockTerminal captureOutputTerminal = new MockTerminal(); private Configuration jimFsConfiguration = Configuration.unix().toBuilder().setAttributeViews("basic", "owner", "posix", "unix").build(); private Configuration jimFsConfigurationWithoutPermissions = randomBoolean() ? Configuration.unix().toBuilder().setAttributeViews("basic").build() : Configuration.windows(); @@ -60,62 +60,62 @@ public class CheckFileCommandTests extends ESTestCase { public void testThatCommandLogsErrorMessageOnFail() throws Exception { executeCommand(jimFsConfiguration, new PermissionCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.CHANGE)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasItem(containsString("Please ensure that the user account running Elasticsearch has read access to this file"))); + assertThat(captureOutputTerminal.getOutput(), containsString("Please ensure that the user account running Elasticsearch has read access to this file")); } public void testThatCommandLogsNothingWhenPermissionRemains() throws Exception { executeCommand(jimFsConfiguration, new PermissionCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.KEEP)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandLogsNothingWhenDisabled() throws Exception { executeCommand(jimFsConfiguration, new PermissionCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.DISABLED)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandLogsNothingIfFilesystemDoesNotSupportPermissions() throws Exception { executeCommand(jimFsConfigurationWithoutPermissions, new PermissionCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.DISABLED)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandLogsOwnerChange() throws Exception { executeCommand(jimFsConfiguration, new OwnerCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.CHANGE)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasItem(allOf(containsString("Owner of file ["), containsString("] used to be ["), containsString("], but now is [")))); + assertThat(captureOutputTerminal.getOutput(), allOf(containsString("Owner of file ["), containsString("] used to be ["), containsString("], but now is ["))); } public void testThatCommandLogsNothingIfOwnerRemainsSame() throws Exception { executeCommand(jimFsConfiguration, new OwnerCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.KEEP)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandLogsNothingIfOwnerIsDisabled() throws Exception { executeCommand(jimFsConfiguration, new OwnerCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.DISABLED)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandLogsNothingIfFileSystemDoesNotSupportOwners() throws Exception { executeCommand(jimFsConfigurationWithoutPermissions, new OwnerCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.DISABLED)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandLogsIfGroupChanges() throws Exception { executeCommand(jimFsConfiguration, new GroupCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.CHANGE)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasItem(allOf(containsString("Group of file ["), containsString("] used to be ["), containsString("], but now is [")))); + assertThat(captureOutputTerminal.getOutput(), allOf(containsString("Group of file ["), containsString("] used to be ["), containsString("], but now is ["))); } public void testThatCommandLogsNothingIfGroupRemainsSame() throws Exception { executeCommand(jimFsConfiguration, new GroupCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.KEEP)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandLogsNothingIfGroupIsDisabled() throws Exception { executeCommand(jimFsConfiguration, new GroupCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.DISABLED)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandLogsNothingIfFileSystemDoesNotSupportGroups() throws Exception { executeCommand(jimFsConfigurationWithoutPermissions, new GroupCheckFileCommand(createTempDir(), captureOutputTerminal, Mode.DISABLED)); - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandDoesNotLogAnythingOnFileCreation() throws Exception { @@ -130,7 +130,7 @@ public class CheckFileCommandTests extends ESTestCase { assertThat(Files.exists(path), is(true)); } - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } public void testThatCommandWorksIfFileIsDeletedByCommand() throws Exception { @@ -147,7 +147,7 @@ public class CheckFileCommandTests extends ESTestCase { assertThat(Files.exists(path), is(false)); } - assertThat(captureOutputTerminal.getTerminalOutput(), hasSize(0)); + assertTrue(captureOutputTerminal.getOutput().isEmpty()); } private void executeCommand(Configuration configuration, AbstractTestCheckFileCommand command) throws Exception { diff --git a/qa/evil-tests/src/test/java/org/elasticsearch/common/cli/CliToolTests.java b/qa/evil-tests/src/test/java/org/elasticsearch/common/cli/CliToolTests.java index 5033914632a..144a12f141b 100644 --- a/qa/evil-tests/src/test/java/org/elasticsearch/common/cli/CliToolTests.java +++ b/qa/evil-tests/src/test/java/org/elasticsearch/common/cli/CliToolTests.java @@ -20,7 +20,6 @@ package org.elasticsearch.common.cli; import org.apache.commons.cli.CommandLine; -import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.Strings; import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.settings.Settings; @@ -133,7 +132,7 @@ public class CliToolTests extends CliToolTestCase { } public void testSingleCommandToolHelp() throws Exception { - CaptureOutputTerminal terminal = new CaptureOutputTerminal(); + MockTerminal terminal = new MockTerminal(); final AtomicReference executed = new AtomicReference<>(false); final NamedCommand cmd = new NamedCommand("cmd1", terminal) { @Override @@ -145,12 +144,11 @@ public class CliToolTests extends CliToolTestCase { SingleCmdTool tool = new SingleCmdTool("tool", terminal, cmd); CliTool.ExitStatus status = tool.execute(args("-h")); assertStatus(status, CliTool.ExitStatus.OK_AND_EXIT); - assertThat(terminal.getTerminalOutput(), hasSize(3)); - assertThat(terminal.getTerminalOutput(), hasItem(containsString("cmd1 help"))); + assertThat(terminal.getOutput(), containsString("cmd1 help")); } public void testMultiCommandToolHelp() throws Exception { - CaptureOutputTerminal terminal = new CaptureOutputTerminal(); + MockTerminal terminal = new MockTerminal(); NamedCommand[] cmds = new NamedCommand[2]; cmds[0] = new NamedCommand("cmd0", terminal) { @Override @@ -167,12 +165,11 @@ public class CliToolTests extends CliToolTestCase { MultiCmdTool tool = new MultiCmdTool("tool", terminal, cmds); CliTool.ExitStatus status = tool.execute(args("-h")); assertStatus(status, CliTool.ExitStatus.OK_AND_EXIT); - assertThat(terminal.getTerminalOutput(), hasSize(3)); - assertThat(terminal.getTerminalOutput(), hasItem(containsString("tool help"))); + assertThat(terminal.getOutput(), containsString("tool help")); } public void testMultiCommandCmdHelp() throws Exception { - CaptureOutputTerminal terminal = new CaptureOutputTerminal(); + MockTerminal terminal = new MockTerminal(); NamedCommand[] cmds = new NamedCommand[2]; cmds[0] = new NamedCommand("cmd0", terminal) { @Override @@ -189,12 +186,11 @@ public class CliToolTests extends CliToolTestCase { MultiCmdTool tool = new MultiCmdTool("tool", terminal, cmds); CliTool.ExitStatus status = tool.execute(args("cmd1 -h")); assertStatus(status, CliTool.ExitStatus.OK_AND_EXIT); - assertThat(terminal.getTerminalOutput(), hasSize(3)); - assertThat(terminal.getTerminalOutput(), hasItem(containsString("cmd1 help"))); + assertThat(terminal.getOutput(), containsString("cmd1 help")); } public void testNonUserErrorPropagates() throws Exception { - CaptureOutputTerminal terminal = new CaptureOutputTerminal(); + MockTerminal terminal = new MockTerminal(); NamedCommand cmd = new NamedCommand("cmd", terminal) { @Override public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception { @@ -225,22 +221,11 @@ public class CliToolTests extends CliToolTestCase { } public void testPromptForSetting() throws Exception { - final AtomicInteger counter = new AtomicInteger(); final AtomicReference promptedSecretValue = new AtomicReference<>(null); final AtomicReference promptedTextValue = new AtomicReference<>(null); - final Terminal terminal = new MockTerminal() { - @Override - public char[] readSecret(String text) { - counter.incrementAndGet(); - return "changeit".toCharArray(); - } - - @Override - public String readText(String text) { - counter.incrementAndGet(); - return "replaced"; - } - }; + final MockTerminal terminal = new MockTerminal(); + terminal.addTextInput("replaced"); + terminal.addSecretInput("changeit"); final NamedCommand cmd = new NamedCommand("noop", terminal) { @Override public CliTool.ExitStatus execute(Settings settings, Environment env) { @@ -259,7 +244,6 @@ public class CliToolTests extends CliToolTestCase { System.clearProperty("es.replace"); } - assertThat(counter.intValue(), is(2)); assertThat(promptedSecretValue.get(), is("changeit")); assertThat(promptedTextValue.get(), is("replaced")); } @@ -269,7 +253,7 @@ public class CliToolTests extends CliToolTestCase { final CliToolConfig.Cmd strictCommand = cmd("strict", CliTool.Command.Exit.class).stopAtNonOption(false).build(); final CliToolConfig config = CliToolConfig.config("elasticsearch", CliTool.class).cmds(lenientCommand, strictCommand).build(); - final CaptureOutputTerminal terminal = new CaptureOutputTerminal(); + MockTerminal terminal = new MockTerminal(); final CliTool cliTool = new CliTool(config, terminal) { @Override protected Command parse(String cmdName, CommandLine cli) throws Exception { @@ -292,11 +276,11 @@ public class CliToolTests extends CliToolTestCase { // unknown parameters, error assertStatus(cliTool.execute(args("strict --unknown")), USAGE); - assertThat(terminal.getTerminalOutput(), hasItem(containsString("Unrecognized option: --unknown"))); + assertThat(terminal.getOutput(), containsString("Unrecognized option: --unknown")); - terminal.getTerminalOutput().clear(); + terminal.resetOutput(); assertStatus(cliTool.execute(args("strict -u")), USAGE); - assertThat(terminal.getTerminalOutput(), hasItem(containsString("Unrecognized option: -u"))); + assertThat(terminal.getOutput(), containsString("Unrecognized option: -u")); } private void assertStatus(CliTool.ExitStatus status, CliTool.ExitStatus expectedStatus) { 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 66dfa67ccbd..86f02fe6f30 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 @@ -46,6 +46,7 @@ import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.Version; 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.common.cli.UserError; import org.elasticsearch.common.settings.Settings; @@ -116,8 +117,8 @@ public class InstallPluginCommandTests extends ESTestCase { return writeZip(structure, "elasticsearch"); } - static CliToolTestCase.CaptureOutputTerminal installPlugin(String pluginUrl, Environment env) throws Exception { - CliToolTestCase.CaptureOutputTerminal terminal = new CliToolTestCase.CaptureOutputTerminal(Terminal.Verbosity.NORMAL); + static MockTerminal installPlugin(String pluginUrl, Environment env) throws Exception { + MockTerminal terminal = new MockTerminal(); CliTool.ExitStatus status = new InstallPluginCommand(terminal, pluginUrl, true).execute(env.settings(), env); assertEquals(CliTool.ExitStatus.OK, status); return terminal; 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 c68e207c0c3..c86a6464eb0 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 @@ -28,6 +28,7 @@ import java.util.List; import org.apache.lucene.util.LuceneTestCase; 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.common.settings.Settings; import org.elasticsearch.env.Environment; @@ -45,8 +46,8 @@ public class ListPluginsCommandTests extends ESTestCase { return new Environment(settings); } - static CliToolTestCase.CaptureOutputTerminal listPlugins(Environment env) throws Exception { - CliToolTestCase.CaptureOutputTerminal terminal = new CliToolTestCase.CaptureOutputTerminal(Terminal.Verbosity.NORMAL); + static MockTerminal listPlugins(Environment env) throws Exception { + MockTerminal terminal = new MockTerminal(); CliTool.ExitStatus status = new ListPluginsCommand(terminal).execute(env.settings(), env); assertEquals(CliTool.ExitStatus.OK, status); return terminal; @@ -62,29 +63,24 @@ public class ListPluginsCommandTests extends ESTestCase { } public void testNoPlugins() throws Exception { - CliToolTestCase.CaptureOutputTerminal terminal = listPlugins(createEnv()); - List lines = terminal.getTerminalOutput(); - assertEquals(0, lines.size()); + MockTerminal terminal = listPlugins(createEnv()); + assertTrue(terminal.getOutput(), terminal.getOutput().isEmpty()); } public void testOnePlugin() throws Exception { Environment env = createEnv(); Files.createDirectory(env.pluginsFile().resolve("fake")); - CliToolTestCase.CaptureOutputTerminal terminal = listPlugins(env); - List lines = terminal.getTerminalOutput(); - assertEquals(1, lines.size()); - assertTrue(lines.get(0).contains("fake")); + MockTerminal terminal = listPlugins(env); + assertTrue(terminal.getOutput(), terminal.getOutput().contains("fake")); } public void testTwoPlugins() throws Exception { Environment env = createEnv(); Files.createDirectory(env.pluginsFile().resolve("fake1")); Files.createDirectory(env.pluginsFile().resolve("fake2")); - CliToolTestCase.CaptureOutputTerminal terminal = listPlugins(env); - List lines = terminal.getTerminalOutput(); - assertEquals(2, lines.size()); - Collections.sort(lines); - assertTrue(lines.get(0).contains("fake1")); - assertTrue(lines.get(1).contains("fake2")); + MockTerminal terminal = listPlugins(env); + String output = terminal.getOutput(); + assertTrue(output, output.contains("fake1")); + assertTrue(output, output.contains("fake2")); } } diff --git a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/PluginSecurityTests.java b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/PluginSecurityTests.java index de1486a3bc2..acc300c6cf5 100644 --- a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/PluginSecurityTests.java +++ b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/PluginSecurityTests.java @@ -31,7 +31,7 @@ import java.util.List; /** Tests plugin manager security check */ public class PluginSecurityTests extends ESTestCase { - + /** Test that we can parse the set of permissions correctly for a simple policy */ public void testParsePermissions() throws Exception { assumeTrue("test cannot run with security manager enabled", System.getSecurityManager() == null); @@ -42,7 +42,7 @@ public class PluginSecurityTests extends ESTestCase { PermissionCollection actual = PluginSecurity.parsePermissions(Terminal.DEFAULT, testFile, scratch); assertEquals(expected, actual); } - + /** Test that we can parse the set of permissions correctly for a complex policy */ public void testParseTwoPermissions() throws Exception { assumeTrue("test cannot run with security manager enabled", System.getSecurityManager() == null); @@ -54,12 +54,12 @@ public class PluginSecurityTests extends ESTestCase { PermissionCollection actual = PluginSecurity.parsePermissions(Terminal.DEFAULT, testFile, scratch); assertEquals(expected, actual); } - + /** Test that we can format some simple permissions properly */ public void testFormatSimplePermission() throws Exception { assertEquals("java.lang.RuntimePermission queuePrintJob", PluginSecurity.formatPermission(new RuntimePermission("queuePrintJob"))); } - + /** Test that we can format an unresolved permission properly */ public void testFormatUnresolvedPermission() throws Exception { assumeTrue("test cannot run with security manager enabled", System.getSecurityManager() == null); @@ -70,7 +70,7 @@ public class PluginSecurityTests extends ESTestCase { assertEquals(1, permissions.size()); assertEquals("org.fake.FakePermission fakeName", PluginSecurity.formatPermission(permissions.get(0))); } - + /** no guaranteed equals on these classes, we assert they contain the same set */ private void assertEquals(PermissionCollection expected, PermissionCollection actual) { assertEquals(asSet(Collections.list(expected.elements())), asSet(Collections.list(actual.elements()))); 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 10fbc3c2696..0bfdf5c34a8 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 @@ -27,6 +27,7 @@ import java.nio.file.Path; import org.apache.lucene.util.LuceneTestCase; 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.common.cli.UserError; import org.elasticsearch.common.settings.Settings; @@ -48,8 +49,8 @@ public class RemovePluginCommandTests extends ESTestCase { return new Environment(settings); } - static CliToolTestCase.CaptureOutputTerminal removePlugin(String name, Environment env) throws Exception { - CliToolTestCase.CaptureOutputTerminal terminal = new CliToolTestCase.CaptureOutputTerminal(Terminal.Verbosity.VERBOSE); + static MockTerminal removePlugin(String name, Environment env) throws Exception { + MockTerminal terminal = new MockTerminal(); CliTool.ExitStatus status = new RemovePluginCommand(terminal, name).execute(env.settings(), env); assertEquals(CliTool.ExitStatus.OK, status); return terminal; 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 6d6c176b27d..9debf4b8f33 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 @@ -19,7 +19,8 @@ package org.elasticsearch.common.cli; -import org.elasticsearch.ExceptionsHelper; +import java.io.IOException; + import org.elasticsearch.common.Strings; import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.test.ESTestCase; @@ -27,14 +28,6 @@ import org.elasticsearch.test.StreamsUtils; import org.junit.After; import org.junit.Before; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.hasSize; - public abstract class CliToolTestCase extends ESTestCase { @Before @@ -56,63 +49,10 @@ public abstract class CliToolTestCase extends ESTestCase { return command.split("\\s+"); } - /** - * A terminal implementation that discards everything - */ - public static class MockTerminal extends Terminal { - - @Override - protected void doPrint(String msg) {} - - @Override - public String readText(String prompt) { - return null; - } - - @Override - public char[] readSecret(String prompt) { - return new char[0]; - } - } - - /** - * A terminal implementation that captures everything written to it - */ - public static class CaptureOutputTerminal extends MockTerminal { - - List terminalOutput = new ArrayList<>(); - - public CaptureOutputTerminal() { - this(Verbosity.NORMAL); - } - - public CaptureOutputTerminal(Verbosity verbosity) { - setVerbosity(verbosity); - } - - @Override - protected void doPrint(String msg) { - terminalOutput.add(msg); - } - - public List getTerminalOutput() { - return terminalOutput; - } - } - - public static void assertTerminalOutputContainsHelpFile(CliToolTestCase.CaptureOutputTerminal terminal, String classPath) throws IOException { - List nonEmptyLines = new ArrayList<>(); - for (String line : terminal.getTerminalOutput()) { - String originalPrintedLine = line.replaceAll(System.lineSeparator(), ""); - if (Strings.isNullOrEmpty(originalPrintedLine)) { - nonEmptyLines.add(originalPrintedLine); - } - } - assertThat(nonEmptyLines, hasSize(greaterThan(0))); - + public static void assertTerminalOutputContainsHelpFile(MockTerminal terminal, String classPath) throws IOException { + String output = terminal.getOutput(); + assertFalse(output, output.isEmpty()); String expectedDocs = StreamsUtils.copyToStringFromClasspath(classPath); - for (String nonEmptyLine : nonEmptyLines) { - assertThat(expectedDocs, containsString(nonEmptyLine.replaceAll(System.lineSeparator(), ""))); - } + assertTrue(output, output.contains(expectedDocs)); } } diff --git a/test/framework/src/main/java/org/elasticsearch/common/cli/MockTerminal.java b/test/framework/src/main/java/org/elasticsearch/common/cli/MockTerminal.java new file mode 100644 index 00000000000..3b2903b3fab --- /dev/null +++ b/test/framework/src/main/java/org/elasticsearch/common/cli/MockTerminal.java @@ -0,0 +1,85 @@ +/* + * 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 java.io.ByteArrayOutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * A terminal for tests which captures all output, and + * can be plugged with fake input. + */ +public class MockTerminal extends Terminal { + + private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + private final PrintWriter writer = new PrintWriter(new OutputStreamWriter(buffer, StandardCharsets.UTF_8)); + private final Deque textInput = new ArrayDeque<>(); + private final Deque secretInput = new ArrayDeque<>(); + + public MockTerminal() { + super("\n"); // always *nix newlines for tests + } + + @Override + public String readText(String prompt) { + if (textInput.isEmpty()) { + return null; + } + return textInput.removeFirst(); + } + + @Override + public char[] readSecret(String prompt) { + if (secretInput.isEmpty()) { + return null; + } + return secretInput.removeFirst().toCharArray(); + } + + @Override + public PrintWriter getWriter() { + return writer; + } + + /** Adds an an input that will be return from {@link #readText(String)}. Values are read in FIFO order. */ + public void addTextInput(String input) { + textInput.addLast(input); + } + + /** Adds an an input that will be return from {@link #readText(String)}. Values are read in FIFO order. */ + public void addSecretInput(String input) { + secretInput.addLast(input); + } + + /** Returns all output written to this terminal. */ + public String getOutput() throws UnsupportedEncodingException { + return buffer.toString("UTF-8"); + } + + /** Wipes the output. */ + public void resetOutput() { + buffer.reset(); + } +}