HADOOP-13824. FsShell can suppress the real error if no error message is present. Contributed by John Zhuge.
This commit is contained in:
parent
5bd7dece92
commit
b606e025f1
@ -328,7 +328,12 @@ public int run(String argv[]) throws Exception {
|
|||||||
scope.close();
|
scope.close();
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} 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);
|
printUsage(System.err);
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
printInstanceUsage(System.err, instance);
|
printInstanceUsage(System.err, instance);
|
||||||
|
@ -17,18 +17,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.hadoop.fs;
|
package org.apache.hadoop.fs;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
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.tracing.SetSpanReceiver;
|
||||||
import org.apache.hadoop.util.ToolRunner;
|
import org.apache.hadoop.util.ToolRunner;
|
||||||
import org.apache.htrace.core.AlwaysSampler;
|
import org.apache.htrace.core.AlwaysSampler;
|
||||||
import org.apache.htrace.core.Tracer;
|
import org.apache.htrace.core.Tracer;
|
||||||
|
import org.hamcrest.core.StringContains;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
public class TestFsShell {
|
public class TestFsShell {
|
||||||
|
|
||||||
@ -73,30 +74,42 @@ public void testTracing() throws Throwable {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDFSWithInvalidCommmand() throws Throwable {
|
public void testDFSWithInvalidCommmand() throws Throwable {
|
||||||
Configuration conf = new Configuration();
|
FsShell shell = new FsShell(new Configuration());
|
||||||
FsShell shell = new FsShell(conf);
|
try (GenericTestUtils.SystemErrCapturer capture =
|
||||||
String[] args = new String[1];
|
new GenericTestUtils.SystemErrCapturer()) {
|
||||||
args[0] = "dfs -mkdirs";
|
ToolRunner.run(shell, new String[]{"dfs -mkdirs"});
|
||||||
final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
Assert.assertThat("FSShell dfs command did not print the error " +
|
||||||
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 " +
|
|
||||||
"message when invalid command is passed",
|
"message when invalid command is passed",
|
||||||
errorValue.contains("Usage: hadoop fs [generic options]"));
|
capture.getOutput(), StringContains.containsString(
|
||||||
} finally {
|
"-mkdirs: Unknown command"));
|
||||||
IOUtils.closeStream(out);
|
Assert.assertThat("FSShell dfs command did not print help " +
|
||||||
System.setErr(oldErr);
|
"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"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,13 @@
|
|||||||
package org.apache.hadoop.test;
|
package org.apache.hadoop.test;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.management.ThreadInfo;
|
import java.lang.management.ThreadInfo;
|
||||||
@ -273,6 +276,73 @@ public static void waitFor(Supplier<Boolean> check,
|
|||||||
TimedOutTestsListener.buildThreadDiagnosticString());
|
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 {
|
public static class LogCapturer {
|
||||||
private StringWriter sw = new StringWriter();
|
private StringWriter sw = new StringWriter();
|
||||||
private WriterAppender appender;
|
private WriterAppender appender;
|
||||||
|
Loading…
Reference in New Issue
Block a user