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 6b29df831eb..eb0faf91d0a 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 abstract class CliTool { 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 0c0070f9720..244fe5ca42e 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 @@ import java.util.Locale; */ 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 abstract class Terminal { } private Verbosity verbosity = Verbosity.NORMAL; - + private final boolean isDebugEnabled; public Terminal() { this(Verbosity.NORMAL); @@ -64,6 +66,7 @@ public abstract class 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 abstract class Terminal { 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 abstract class Terminal { 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 abstract class Terminal { return console.writer(); } + @Override + public void printStackTrace(Throwable t) { + t.printStackTrace(console.writer()); + } } private static class SystemTerminal extends Terminal { @@ -168,6 +184,11 @@ public abstract class Terminal { 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 208d757e28a..96d45bee051 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 class CliToolTestCase extends ElasticsearchTestCase { 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 class CliToolTestCase extends ElasticsearchTestCase { 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 0f09182dc60..cd505193e44 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 @@ package org.elasticsearch.common.cli; 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 class CliToolTests extends CliToolTestCase { 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())); }