HDFS-13661. Ls command with e option fails when the filesystem is not HDFS.

(cherry picked from commit d963575918)
This commit is contained in:
Takanobu Asanuma 2018-12-20 10:03:33 +09:00
parent 956e6cfee6
commit 9f30916a1b
2 changed files with 93 additions and 14 deletions

View File

@ -25,6 +25,7 @@ import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.LinkedList; import java.util.LinkedList;
import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.util.StringUtils;
@ -155,7 +156,7 @@ class Ls extends FsCommand {
* Should display only paths of files and directories. * Should display only paths of files and directories.
* @return true display paths only, false display all fields * @return true display paths only, false display all fields
*/ */
@InterfaceAudience.Private @VisibleForTesting
boolean isPathOnly() { boolean isPathOnly() {
return this.pathOnly; return this.pathOnly;
} }
@ -164,7 +165,7 @@ class Ls extends FsCommand {
* Should the contents of the directory be shown or just the directory? * Should the contents of the directory be shown or just the directory?
* @return true if directory contents, false if just directory * @return true if directory contents, false if just directory
*/ */
@InterfaceAudience.Private @VisibleForTesting
boolean isDirRecurse() { boolean isDirRecurse() {
return this.dirRecurse; return this.dirRecurse;
} }
@ -173,12 +174,12 @@ class Ls extends FsCommand {
* Should file sizes be returned in human readable format rather than bytes? * Should file sizes be returned in human readable format rather than bytes?
* @return true is human readable, false if bytes * @return true is human readable, false if bytes
*/ */
@InterfaceAudience.Private @VisibleForTesting
boolean isHumanReadable() { boolean isHumanReadable() {
return this.humanReadable; return this.humanReadable;
} }
@InterfaceAudience.Private @VisibleForTesting
private boolean isHideNonPrintable() { private boolean isHideNonPrintable() {
return hideNonPrintable; return hideNonPrintable;
} }
@ -187,7 +188,7 @@ class Ls extends FsCommand {
* Should directory contents be displayed in reverse order * Should directory contents be displayed in reverse order
* @return true reverse order, false default order * @return true reverse order, false default order
*/ */
@InterfaceAudience.Private @VisibleForTesting
boolean isOrderReverse() { boolean isOrderReverse() {
return this.orderReverse; return this.orderReverse;
} }
@ -196,7 +197,7 @@ class Ls extends FsCommand {
* Should directory contents be displayed in mtime order. * Should directory contents be displayed in mtime order.
* @return true mtime order, false default order * @return true mtime order, false default order
*/ */
@InterfaceAudience.Private @VisibleForTesting
boolean isOrderTime() { boolean isOrderTime() {
return this.orderTime; return this.orderTime;
} }
@ -205,7 +206,7 @@ class Ls extends FsCommand {
* Should directory contents be displayed in size order. * Should directory contents be displayed in size order.
* @return true size order, false default order * @return true size order, false default order
*/ */
@InterfaceAudience.Private @VisibleForTesting
boolean isOrderSize() { boolean isOrderSize() {
return this.orderSize; return this.orderSize;
} }
@ -214,13 +215,28 @@ class Ls extends FsCommand {
* Should access time be used rather than modification time. * Should access time be used rather than modification time.
* @return true use access time, false use modification time * @return true use access time, false use modification time
*/ */
@InterfaceAudience.Private @VisibleForTesting
boolean isUseAtime() { boolean isUseAtime() {
return this.useAtime; return this.useAtime;
} }
/**
* Should EC policies be displayed.
* @return true display EC policies, false doesn't display EC policies
*/
@VisibleForTesting
boolean isDisplayECPolicy() {
return this.displayECPolicy;
}
@Override @Override
protected void processPathArgument(PathData item) throws IOException { protected void processPathArgument(PathData item) throws IOException {
if (isDisplayECPolicy() && item.fs.getContentSummary(item.path)
.getErasureCodingPolicy() == null) {
throw new UnsupportedOperationException("FileSystem "
+ item.fs.getUri() + " does not support Erasure Coding");
}
// implicitly recurse once for cmdline directories // implicitly recurse once for cmdline directories
if (dirRecurse && item.stat.isDirectory()) { if (dirRecurse && item.stat.isDirectory()) {
recursePath(item); recursePath(item);
@ -298,6 +314,8 @@ class Ls extends FsCommand {
StringBuilder fmt = new StringBuilder(); StringBuilder fmt = new StringBuilder();
fmt.append("%s%s"); // permission string fmt.append("%s%s"); // permission string
fmt.append("%" + maxRepl + "s "); fmt.append("%" + maxRepl + "s ");
fmt.append((maxOwner > 0) ? "%-" + maxOwner + "s " : "%s");
fmt.append((maxGroup > 0) ? "%-" + maxGroup + "s " : "%s");
// Do not use '%-0s' as a formatting conversion, since it will throw a // Do not use '%-0s' as a formatting conversion, since it will throw a
// a MissingFormatWidthException if it is used in String.format(). // a MissingFormatWidthException if it is used in String.format().
// http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html#intFlags // http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html#intFlags
@ -307,10 +325,8 @@ class Ls extends FsCommand {
ContentSummary contentSummary = item.fs.getContentSummary(item.path); ContentSummary contentSummary = item.fs.getContentSummary(item.path);
maxEC=maxLength(maxEC,contentSummary.getErasureCodingPolicy().length()); maxEC=maxLength(maxEC,contentSummary.getErasureCodingPolicy().length());
} }
fmt.append(" %"+maxEC+"s "); fmt.append((maxEC > 0) ? "%-" + maxEC + "s " : "%s");
} }
fmt.append((maxOwner > 0) ? "%-" + maxOwner + "s " : "%s");
fmt.append((maxGroup > 0) ? "%-" + maxGroup + "s " : "%s");
fmt.append("%" + maxLen + "s "); fmt.append("%" + maxLen + "s ");
fmt.append("%s %s"); // mod time & path fmt.append("%s %s"); // mod time & path
lineFormat = fmt.toString(); lineFormat = fmt.toString();

View File

@ -17,6 +17,7 @@
*/ */
package org.apache.hadoop.fs.shell; package org.apache.hadoop.fs.shell;
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_DEFAULT_NAME_KEY;
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SHELL_MISSING_DEFAULT_FS_WARNING_KEY; import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SHELL_MISSING_DEFAULT_FS_WARNING_KEY;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
@ -26,6 +27,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -57,17 +59,18 @@ public class TestLs {
@BeforeClass @BeforeClass
public static void setup() throws IOException { public static void setup() throws IOException {
conf = new Configuration(); conf = new Configuration();
conf.set("fs.defaultFS", "mockfs:///"); conf.set(FS_DEFAULT_NAME_KEY, "mockfs:///");
conf.setClass("fs.mockfs.impl", MockFileSystem.class, FileSystem.class); conf.setClass("fs.mockfs.impl", MockFileSystem.class, FileSystem.class);
mockFs = mock(FileSystem.class); mockFs = mock(FileSystem.class);
} }
@Before @Before
public void resetMock() throws IOException { public void resetMock() throws IOException, URISyntaxException {
reset(mockFs); reset(mockFs);
AclStatus mockAclStatus = mock(AclStatus.class); AclStatus mockAclStatus = mock(AclStatus.class);
when(mockAclStatus.getEntries()).thenReturn(new ArrayList<AclEntry>()); when(mockAclStatus.getEntries()).thenReturn(new ArrayList<AclEntry>());
when(mockFs.getAclStatus(any(Path.class))).thenReturn(mockAclStatus); when(mockFs.getAclStatus(any(Path.class))).thenReturn(mockAclStatus);
when(mockFs.getUri()).thenReturn(new URI(conf.get(FS_DEFAULT_NAME_KEY)));
} }
// check that default options are correct // check that default options are correct
@ -84,6 +87,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertFalse(ls.isOrderTime()); assertFalse(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// check the -C option is recognised // check the -C option is recognised
@ -101,6 +105,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertFalse(ls.isOrderTime()); assertFalse(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// check the -d option is recognised // check the -d option is recognised
@ -118,6 +123,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertFalse(ls.isOrderTime()); assertFalse(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// check the -h option is recognised // check the -h option is recognised
@ -135,6 +141,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertFalse(ls.isOrderTime()); assertFalse(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// check the -R option is recognised // check the -R option is recognised
@ -152,6 +159,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertFalse(ls.isOrderTime()); assertFalse(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// check the -r option is recognised // check the -r option is recognised
@ -169,6 +177,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertFalse(ls.isOrderTime()); assertFalse(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// check the -S option is recognised // check the -S option is recognised
@ -186,6 +195,7 @@ public class TestLs {
assertTrue(ls.isOrderSize()); assertTrue(ls.isOrderSize());
assertFalse(ls.isOrderTime()); assertFalse(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// check the -t option is recognised // check the -t option is recognised
@ -203,6 +213,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertTrue(ls.isOrderTime()); assertTrue(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// check the precedence of the -t and -S options // check the precedence of the -t and -S options
@ -221,6 +232,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertTrue(ls.isOrderTime()); assertTrue(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// check the precedence of the -t, -S and -r options // check the precedence of the -t, -S and -r options
@ -240,6 +252,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertTrue(ls.isOrderTime()); assertTrue(ls.isOrderTime());
assertFalse(ls.isUseAtime()); assertFalse(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
} }
// chheck the -u option is recognised // chheck the -u option is recognised
@ -257,6 +270,25 @@ public class TestLs {
assertFalse(ls.isOrderSize()); assertFalse(ls.isOrderSize());
assertFalse(ls.isOrderTime()); assertFalse(ls.isOrderTime());
assertTrue(ls.isUseAtime()); assertTrue(ls.isUseAtime());
assertFalse(ls.isDisplayECPolicy());
}
// chheck the -e option is recognised
@Test
public void processOptionsDisplayECPolicy() throws IOException {
LinkedList<String> options = new LinkedList<String>();
options.add("-e");
Ls ls = new Ls();
ls.processOptions(options);
assertFalse(ls.isPathOnly());
assertTrue(ls.isDirRecurse());
assertFalse(ls.isHumanReadable());
assertFalse(ls.isRecursive());
assertFalse(ls.isOrderReverse());
assertFalse(ls.isOrderSize());
assertFalse(ls.isOrderTime());
assertFalse(ls.isUseAtime());
assertTrue(ls.isDisplayECPolicy());
} }
// check all options is handled correctly // check all options is handled correctly
@ -271,6 +303,7 @@ public class TestLs {
options.add("-t"); // time order options.add("-t"); // time order
options.add("-S"); // size order options.add("-S"); // size order
options.add("-u"); // show atime options.add("-u"); // show atime
options.add("-e"); // show EC policies
Ls ls = new Ls(); Ls ls = new Ls();
ls.processOptions(options); ls.processOptions(options);
assertTrue(ls.isPathOnly()); assertTrue(ls.isPathOnly());
@ -281,6 +314,7 @@ public class TestLs {
assertFalse(ls.isOrderSize()); // -t overrules -S assertFalse(ls.isOrderSize()); // -t overrules -S
assertTrue(ls.isOrderTime()); assertTrue(ls.isOrderTime());
assertTrue(ls.isUseAtime()); assertTrue(ls.isUseAtime());
assertTrue(ls.isDisplayECPolicy());
} }
// check listing of a single file // check listing of a single file
@ -1100,6 +1134,35 @@ public class TestLs {
assertEquals("Ls.getName", expected, actual); assertEquals("Ls.getName", expected, actual);
} }
@Test(expected = UnsupportedOperationException.class)
public void processPathFileDisplayECPolicyWhenUnsupported()
throws IOException {
TestFile testFile = new TestFile("testDirectory", "testFile");
LinkedList<PathData> pathData = new LinkedList<PathData>();
pathData.add(testFile.getPathData());
Ls ls = new Ls();
LinkedList<String> options = new LinkedList<String>();
options.add("-e");
ls.processOptions(options);
ls.processArguments(pathData);
}
@Test(expected = UnsupportedOperationException.class)
public void processPathDirDisplayECPolicyWhenUnsupported()
throws IOException {
TestFile testFile = new TestFile("testDirectory", "testFile");
TestFile testDir = new TestFile("", "testDirectory");
testDir.setIsDir(true);
testDir.addContents(testFile);
LinkedList<PathData> pathData = new LinkedList<PathData>();
pathData.add(testDir.getPathData());
Ls ls = new Ls();
LinkedList<String> options = new LinkedList<String>();
options.add("-e");
ls.processOptions(options);
ls.processArguments(pathData);
}
// test class representing a file to be listed // test class representing a file to be listed
static class TestFile { static class TestFile {
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat( private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(