From e689a0ad7135450bd2ae073f682802f710105ddf Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Mon, 11 Aug 2014 18:20:53 +0200 Subject: [PATCH] Test: Allow CliTool to write out stacktraces In order to have the possibility of debugging on the command line, the user now can either set the es.cli.debug system property which results in stack traces being written to to the terminal. Closes #7222 --- .../org/elasticsearch/common/cli/CliTool.java | 6 ++-- .../elasticsearch/common/cli/Terminal.java | 23 ++++++++++++++- .../common/cli/CliToolTestCase.java | 11 +++++++ .../common/cli/CliToolTests.java | 29 +++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/cli/CliTool.java b/src/main/java/org/elasticsearch/common/cli/CliTool.java index 6b29df831eb6b..eb0faf91d0ac9 100644 --- a/src/main/java/org/elasticsearch/common/cli/CliTool.java +++ b/src/main/java/org/elasticsearch/common/cli/CliTool.java @@ -144,13 +144,13 @@ public final int execute(String... args) { return command.execute(settings, env).status; } catch (IOException ioe) { - terminal.printError(ioe.getMessage()); + terminal.printError(ioe); return ExitStatus.IO_ERROR.status; } catch (IllegalArgumentException | ElasticsearchIllegalArgumentException ilae) { - terminal.printError(ilae.getMessage()); + terminal.printError(ilae); return ExitStatus.USAGE.status; } catch (Throwable t) { - terminal.printError(t.getMessage()); + terminal.printError(t); if (command == null) { return ExitStatus.USAGE.status; } diff --git a/src/main/java/org/elasticsearch/common/cli/Terminal.java b/src/main/java/org/elasticsearch/common/cli/Terminal.java index 0c0070f97203e..244fe5ca42e5e 100644 --- a/src/main/java/org/elasticsearch/common/cli/Terminal.java +++ b/src/main/java/org/elasticsearch/common/cli/Terminal.java @@ -29,6 +29,8 @@ */ public abstract class Terminal { + public static final String DEBUG_SYSTEM_PROPERTY = "es.cli.debug"; + public static final Terminal DEFAULT = ConsoleTerminal.supported() ? new ConsoleTerminal() : new SystemTerminal(); public static enum Verbosity { @@ -56,7 +58,7 @@ public static Verbosity resolve(CommandLine cli) { } private Verbosity verbosity = Verbosity.NORMAL; - + private final boolean isDebugEnabled; public Terminal() { this(Verbosity.NORMAL); @@ -64,6 +66,7 @@ public Terminal() { public Terminal(Verbosity verbosity) { this.verbosity = verbosity; + this.isDebugEnabled = "true".equals(System.getProperty(DEBUG_SYSTEM_PROPERTY, "false")); } public void verbosity(Verbosity verbosity) { @@ -78,6 +81,8 @@ public Verbosity verbosity() { public abstract char[] readSecret(String text, Object... args); + protected abstract void printStackTrace(Throwable t); + public void println() { println(Verbosity.NORMAL); } @@ -108,6 +113,13 @@ public void printError(String msg, Object... args) { println(Verbosity.SILENT, "ERROR: " + msg, args); } + public void printError(Throwable t) { + printError("%s", t.getMessage()); + if (isDebugEnabled) { + printStackTrace(t); + } + } + protected abstract void doPrint(String msg, Object... args); public abstract PrintWriter writer(); @@ -141,6 +153,10 @@ public PrintWriter writer() { return console.writer(); } + @Override + public void printStackTrace(Throwable t) { + t.printStackTrace(console.writer()); + } } private static class SystemTerminal extends Terminal { @@ -168,6 +184,11 @@ public char[] readSecret(String text, Object... args) { return readText(text, args).toCharArray(); } + @Override + public void printStackTrace(Throwable t) { + t.printStackTrace(printWriter); + } + @Override public PrintWriter writer() { return printWriter; diff --git a/src/test/java/org/elasticsearch/common/cli/CliToolTestCase.java b/src/test/java/org/elasticsearch/common/cli/CliToolTestCase.java index 208d757e28aa5..96d45bee051c5 100644 --- a/src/test/java/org/elasticsearch/common/cli/CliToolTestCase.java +++ b/src/test/java/org/elasticsearch/common/cli/CliToolTestCase.java @@ -19,6 +19,7 @@ package org.elasticsearch.common.cli; +import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.common.Strings; import org.elasticsearch.test.ElasticsearchTestCase; @@ -74,6 +75,11 @@ public char[] readSecret(String text, Object... args) { public void print(String msg, Object... args) { } + @Override + public void printStackTrace(Throwable t) { + return; + } + @Override public PrintWriter writer() { return DEV_NULL; @@ -120,6 +126,11 @@ public void print(String msg, Object... args) { doPrint(msg, args); } + @Override + public void printStackTrace(Throwable t) { + terminalOutput.add(ExceptionsHelper.stackTrace(t)); + } + public List getTerminalOutput() { return terminalOutput; } diff --git a/src/test/java/org/elasticsearch/common/cli/CliToolTests.java b/src/test/java/org/elasticsearch/common/cli/CliToolTests.java index 0f09182dc60cd..cd505193e446c 100644 --- a/src/test/java/org/elasticsearch/common/cli/CliToolTests.java +++ b/src/test/java/org/elasticsearch/common/cli/CliToolTests.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap; import org.apache.commons.cli.CommandLine; +import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.junit.Test; @@ -224,6 +225,34 @@ public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exc assertThat(terminal.getTerminalOutput(), hasItem(containsString("cmd1 help"))); } + @Test + public void testThatThrowExceptionCanBeLogged() throws Exception { + CaptureOutputTerminal terminal = new CaptureOutputTerminal(); + NamedCommand cmd = new NamedCommand("cmd", terminal) { + @Override + public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception { + throw new ElasticsearchException("error message"); + } + }; + SingleCmdTool tool = new SingleCmdTool("tool", terminal, cmd); + assertStatus(tool.execute(), CliTool.ExitStatus.CODE_ERROR); + assertThat(terminal.getTerminalOutput(), hasSize(1)); + assertThat(terminal.getTerminalOutput(), hasItem(containsString("error message"))); + + // set env... and log stack trace + try { + System.setProperty(Terminal.DEBUG_SYSTEM_PROPERTY, "true"); + terminal = new CaptureOutputTerminal(); + assertStatus(new SingleCmdTool("tool", terminal, cmd).execute(), CliTool.ExitStatus.CODE_ERROR); + assertThat(terminal.getTerminalOutput(), hasSize(2)); + assertThat(terminal.getTerminalOutput(), hasItem(containsString("error message"))); + // This class must be part of the stack strace + assertThat(terminal.getTerminalOutput(), hasItem(containsString(getClass().getName()))); + } finally { + System.clearProperty(Terminal.DEBUG_SYSTEM_PROPERTY); + } + } + private void assertStatus(int status, CliTool.ExitStatus expectedStatus) { assertThat(status, is(expectedStatus.status())); }