Repository: hadoop
Updated Branches:
  refs/heads/trunk 5bd7dece9 -> b606e025f


HADOOP-13824. FsShell can suppress the real error if no error message is 
present. Contributed by  John Zhuge.


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/b606e025
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/b606e025
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/b606e025

Branch: refs/heads/trunk
Commit: b606e025f10daed18b90b45ac00cd0c82e818581
Parents: 5bd7dec
Author: Wei-Chiu Chuang <weic...@apache.org>
Authored: Fri Dec 9 15:22:21 2016 -0800
Committer: Wei-Chiu Chuang <weic...@apache.org>
Committed: Fri Dec 9 15:22:21 2016 -0800

----------------------------------------------------------------------
 .../main/java/org/apache/hadoop/fs/FsShell.java |  7 +-
 .../java/org/apache/hadoop/fs/TestFsShell.java  | 67 ++++++++++--------
 .../apache/hadoop/test/GenericTestUtils.java    | 72 +++++++++++++++++++-
 3 files changed, 117 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/b606e025/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FsShell.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FsShell.java
 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FsShell.java
index 1de9374..59d15c2 100644
--- 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FsShell.java
+++ 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FsShell.java
@@ -328,7 +328,12 @@ public class FsShell extends Configured implements Tool {
           scope.close();
         }
       } catch (IllegalArgumentException e) {
-        displayError(cmd, e.getLocalizedMessage());
+        if (e.getMessage() == null) {
+          displayError(cmd, "Null exception message");
+          e.printStackTrace(System.err);
+        } else {
+          displayError(cmd, e.getLocalizedMessage());
+        }
         printUsage(System.err);
         if (instance != null) {
           printInstanceUsage(System.err, instance);

http://git-wip-us.apache.org/repos/asf/hadoop/blob/b606e025/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFsShell.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFsShell.java
 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFsShell.java
index 376f8a6..162a942 100644
--- 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFsShell.java
+++ 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFsShell.java
@@ -17,18 +17,19 @@
  */
 package org.apache.hadoop.fs;
 
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-
 import junit.framework.AssertionFailedError;
 import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.io.IOUtils;
+import org.apache.hadoop.fs.shell.Command;
+import org.apache.hadoop.fs.shell.CommandFactory;
+import org.apache.hadoop.test.GenericTestUtils;
 import org.apache.hadoop.tracing.SetSpanReceiver;
 import org.apache.hadoop.util.ToolRunner;
 import org.apache.htrace.core.AlwaysSampler;
 import org.apache.htrace.core.Tracer;
+import org.hamcrest.core.StringContains;
 import org.junit.Assert;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 public class TestFsShell {
 
@@ -73,30 +74,42 @@ public class TestFsShell {
 
   @Test
   public void testDFSWithInvalidCommmand() throws Throwable {
-    Configuration conf = new Configuration();
-    FsShell shell = new FsShell(conf);
-    String[] args = new String[1];
-    args[0] = "dfs -mkdirs";
-    final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-    final PrintStream out = new PrintStream(bytes);
-    final PrintStream oldErr = System.err;
-    try {
-      System.setErr(out);
-      ToolRunner.run(shell, args);
-      String errorValue=new String(bytes.toString());
-      Assert
-      .assertTrue(
-          "FSShell dfs command did not print the error " +
-          "message when invalid command is passed",
-          errorValue.contains("-mkdirs: Unknown command"));
-      Assert
-          .assertTrue(
-              "FSShell dfs command did not print help " +
+    FsShell shell = new FsShell(new Configuration());
+    try (GenericTestUtils.SystemErrCapturer capture =
+             new GenericTestUtils.SystemErrCapturer()) {
+      ToolRunner.run(shell, new String[]{"dfs -mkdirs"});
+      Assert.assertThat("FSShell dfs command did not print the error " +
               "message when invalid command is passed",
-          errorValue.contains("Usage: hadoop fs [generic options]"));
-    } finally {
-      IOUtils.closeStream(out);
-      System.setErr(oldErr);
+          capture.getOutput(), StringContains.containsString(
+              "-mkdirs: Unknown command"));
+      Assert.assertThat("FSShell dfs command did not print help " +
+              "message when invalid command is passed",
+          capture.getOutput(), StringContains.containsString(
+              "Usage: hadoop fs [generic options]"));
+    }
+  }
+
+  @Test
+  public void testExceptionNullMessage() throws Exception {
+    final String cmdName = "-cmdExNullMsg";
+    final Command cmd = Mockito.mock(Command.class);
+    Mockito.when(cmd.run(Mockito.anyVararg())).thenThrow(
+        new IllegalArgumentException());
+    Mockito.when(cmd.getUsage()).thenReturn(cmdName);
+
+    final CommandFactory cmdFactory = Mockito.mock(CommandFactory.class);
+    final String[] names = {cmdName};
+    Mockito.when(cmdFactory.getNames()).thenReturn(names);
+    Mockito.when(cmdFactory.getInstance(cmdName)).thenReturn(cmd);
+
+    FsShell shell = new FsShell(new Configuration());
+    shell.commandFactory = cmdFactory;
+    try (GenericTestUtils.SystemErrCapturer capture =
+             new GenericTestUtils.SystemErrCapturer()) {
+      ToolRunner.run(shell, new String[]{cmdName});
+      Assert.assertThat(capture.getOutput(),
+          StringContains.containsString(cmdName
+              + ": Null exception message"));
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/b606e025/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/test/GenericTestUtils.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/test/GenericTestUtils.java
 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/test/GenericTestUtils.java
index 0b73cf5..96ba123 100644
--- 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/test/GenericTestUtils.java
+++ 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/test/GenericTestUtils.java
@@ -18,10 +18,13 @@
 package org.apache.hadoop.test;
 
 import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
 import java.io.StringWriter;
 import java.lang.management.ManagementFactory;
 import java.lang.management.ThreadInfo;
@@ -272,7 +275,74 @@ public abstract class GenericTestUtils {
         "Thread diagnostics:\n" +
         TimedOutTestsListener.buildThreadDiagnosticString());
   }
-  
+
+  /**
+   * Prints output to one {@link PrintStream} while copying to the other.
+   * <p>
+   * Closing the main {@link PrintStream} will NOT close the other.
+   */
+  public static class TeePrintStream extends PrintStream {
+    private final PrintStream other;
+
+    public TeePrintStream(OutputStream main, PrintStream other) {
+      super(main);
+      this.other = other;
+    }
+
+    @Override
+    public void flush() {
+      super.flush();
+      other.flush();
+    }
+
+    @Override
+    public void write(byte[] buf, int off, int len) {
+      super.write(buf, off, len);
+      other.write(buf, off, len);
+    }
+  }
+
+  /**
+   * Capture output printed to {@link System#err}.
+   * <p>
+   * Usage:
+   * <pre>
+   *   try (SystemErrCapturer capture = new SystemErrCapturer()) {
+   *     ...
+   *     // Call capture.getOutput() to get the output string
+   *   }
+   * </pre>
+   *
+   * TODO: Add lambda support once Java 8 is common.
+   * <pre>
+   *   SystemErrCapturer.withCapture(capture -> {
+   *     ...
+   *   })
+   * </pre>
+   */
+  public static class SystemErrCapturer implements AutoCloseable {
+    final private ByteArrayOutputStream bytes;
+    final private PrintStream bytesPrintStream;
+    final private PrintStream oldErr;
+
+    public SystemErrCapturer() {
+      bytes = new ByteArrayOutputStream();
+      bytesPrintStream = new PrintStream(bytes);
+      oldErr = System.err;
+      System.setErr(new TeePrintStream(oldErr, bytesPrintStream));
+    }
+
+    public String getOutput() {
+      return bytes.toString();
+    }
+
+    @Override
+    public void close() throws Exception {
+      IOUtils.closeQuietly(bytesPrintStream);
+      System.setErr(oldErr);
+    }
+  }
+
   public static class LogCapturer {
     private StringWriter sw = new StringWriter();
     private WriterAppender appender;


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-commits-h...@hadoop.apache.org

Reply via email to