Repository: hadoop
Updated Branches:
  refs/heads/branch-2 6dee42f6d -> fb49967e9


HADOOP-8934. Shell command ls should include sort options (Jonathan Allen via 
aw)

(cherry picked from commit 30b797ee9df30260314eeadffc7d51492871b352)

Conflicts:
        hadoop-common-project/hadoop-common/src/site/apt/FileSystemShell.apt.vm


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

Branch: refs/heads/branch-2
Commit: 3d0e2e54a19937996aecdb2773d6fcc919e591e3
Parents: 6dee42f
Author: Allen Wittenauer <a...@apache.org>
Authored: Mon Feb 9 12:50:44 2015 -0800
Committer: Akira Ajisaka <aajis...@apache.org>
Committed: Tue May 19 17:38:22 2015 +0900

----------------------------------------------------------------------
 hadoop-common-project/hadoop-common/CHANGES.txt |   3 +
 .../java/org/apache/hadoop/fs/shell/Ls.java     | 187 ++++++++++++++++---
 .../src/test/resources/testConf.xml             |  34 +++-
 .../src/test/resources/testHDFSConf.xml         | 148 +++++++++++++++
 4 files changed, 343 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/3d0e2e54/hadoop-common-project/hadoop-common/CHANGES.txt
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt 
b/hadoop-common-project/hadoop-common/CHANGES.txt
index 3205a4a..93304dc 100644
--- a/hadoop-common-project/hadoop-common/CHANGES.txt
+++ b/hadoop-common-project/hadoop-common/CHANGES.txt
@@ -19,6 +19,9 @@ Release 2.8.0 - UNRELEASED
 
     HADOOP-11949. Add user-provided plugins to test-patch (Sean Busbey via aw)
 
+    HADOOP-8934. Shell command ls should include sort options (Jonathan Allen
+    via aw)
+
   IMPROVEMENTS
 
     HADOOP-6842. "hadoop fs -text" does not give a useful text representation

http://git-wip-us.apache.org/repos/asf/hadoop/blob/3d0e2e54/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java
 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java
index c7e80b6..0e46700 100644
--- 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java
+++ 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/Ls.java
@@ -20,6 +20,8 @@ package org.apache.hadoop.fs.shell;
 
 import java.io.IOException;
 import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.LinkedList;
 import org.apache.hadoop.util.StringUtils;
@@ -40,29 +42,59 @@ class Ls extends FsCommand {
     factory.addClass(Ls.class, "-ls");
     factory.addClass(Lsr.class, "-lsr");
   }
-  
+
+  private static final String OPTION_DIRECTORY = "d";
+  private static final String OPTION_HUMAN = "h";
+  private static final String OPTION_RECURSIVE = "R";
+  private static final String OPTION_REVERSE = "r";
+  private static final String OPTION_MTIME = "t";
+  private static final String OPTION_ATIME = "u";
+  private static final String OPTION_SIZE = "S";
+
   public static final String NAME = "ls";
-  public static final String USAGE = "[-d] [-h] [-R] [<path> ...]";
+  public static final String USAGE = "[-" + OPTION_DIRECTORY + "] [-"
+      + OPTION_HUMAN + "] " + "[-" + OPTION_RECURSIVE + "] [-" + OPTION_MTIME
+      + "] [-" + OPTION_SIZE + "] [-" + OPTION_REVERSE + "] " + "[-"
+      + OPTION_ATIME + "] [<path> ...]";
+
   public static final String DESCRIPTION =
-                   "List the contents that match the specified file pattern. 
If " +
-                   "path is not specified, the contents of /user/<currentUser> 
" +
-                   "will be listed. Directory entries are of the form:\n" +
-                   "\tpermissions - userId groupId sizeOfDirectory(in bytes) 
modificationDate(yyyy-MM-dd HH:mm) directoryName\n\n" +
-                   "and file entries are of the form:\n" +
-                   "\tpermissions numberOfReplicas userId groupId 
sizeOfFile(in bytes) modificationDate(yyyy-MM-dd HH:mm) fileName\n" +
-                   "-d:  Directories are listed as plain files.\n" +
-                   "-h:  Formats the sizes of files in a human-readable 
fashion " +
-                   "rather than a number of bytes.\n" +
-                   "-R:  Recursively list the contents of directories.";
-                 
-  
-
-  protected final SimpleDateFormat dateFormat =
+      "List the contents that match the specified file pattern. If " +
+          "path is not specified, the contents of /user/<currentUser> " +
+          "will be listed. For a directory a list of its direct children " +
+          "is returned (unless -" + OPTION_DIRECTORY +
+          " option is specified).\n\n" +
+          "Directory entries are of the form:\n" +
+          "\tpermissions - userId groupId sizeOfDirectory(in bytes) 
modificationDate(yyyy-MM-dd HH:mm) directoryName\n\n" +
+          "and file entries are of the form:\n" +
+          "\tpermissions numberOfReplicas userId groupId sizeOfFile(in bytes) 
modificationDate(yyyy-MM-dd HH:mm) fileName\n\n" +
+          "  -" + OPTION_DIRECTORY +
+          "  Directories are listed as plain files.\n" +
+          "  -" + OPTION_HUMAN +
+          "  Formats the sizes of files in a human-readable fashion\n" +
+          "      rather than a number of bytes.\n" +
+          "  -" + OPTION_RECURSIVE +
+          "  Recursively list the contents of directories.\n" +
+          "  -" + OPTION_MTIME +
+          "  Sort files by modification time (most recent first).\n" +
+          "  -" + OPTION_SIZE +
+          "  Sort files by size.\n" +
+          "  -" + OPTION_REVERSE +
+          "  Reverse the order of the sort.\n" +
+          "  -" + OPTION_ATIME +
+          "  Use time of last access instead of modification for\n" +
+          "      display and sorting.";
+
+  protected static final SimpleDateFormat dateFormat =
     new SimpleDateFormat("yyyy-MM-dd HH:mm");
 
   protected int maxRepl = 3, maxLen = 10, maxOwner = 0, maxGroup = 0;
   protected String lineFormat;
   protected boolean dirRecurse;
+  private boolean orderReverse;
+  private boolean orderTime;
+  private boolean orderSize;
+  private boolean useAtime;
+  private Comparator<PathData> orderComparator;
 
   protected boolean humanReadable = false;
 
@@ -75,12 +107,74 @@ class Ls extends FsCommand {
   @Override
   protected void processOptions(LinkedList<String> args)
   throws IOException {
-    CommandFormat cf = new CommandFormat(0, Integer.MAX_VALUE, "d", "h", "R");
+    CommandFormat cf = new CommandFormat(0, Integer.MAX_VALUE,
+        OPTION_DIRECTORY, OPTION_HUMAN, OPTION_RECURSIVE, OPTION_REVERSE,
+        OPTION_MTIME, OPTION_SIZE, OPTION_ATIME);
     cf.parse(args);
-    dirRecurse = !cf.getOpt("d");
-    setRecursive(cf.getOpt("R") && dirRecurse);
-    humanReadable = cf.getOpt("h");
+    dirRecurse = !cf.getOpt(OPTION_DIRECTORY);
+    setRecursive(cf.getOpt(OPTION_RECURSIVE) && dirRecurse);
+    humanReadable = cf.getOpt(OPTION_HUMAN);
+    orderReverse = cf.getOpt(OPTION_REVERSE);
+    orderTime = cf.getOpt(OPTION_MTIME);
+    orderSize = !orderTime && cf.getOpt(OPTION_SIZE);
+    useAtime = cf.getOpt(OPTION_ATIME);
     if (args.isEmpty()) args.add(Path.CUR_DIR);
+
+    initialiseOrderComparator();
+  }
+
+  /**
+   * Should the contents of the directory be shown or just the directory?
+   * @return true if directory contents, false if just directory
+   */
+  @InterfaceAudience.Private
+  boolean isDirRecurse() {
+    return this.dirRecurse;
+  }
+
+  /**
+   * Should file sizes be returned in human readable format rather than bytes?
+   * @return true is human readable, false if bytes
+   */
+  @InterfaceAudience.Private
+  boolean isHumanReadable() {
+    return this.humanReadable;
+  }
+
+  /**
+   * Should directory contents be displayed in reverse order
+   * @return true reverse order, false default order
+   */
+  @InterfaceAudience.Private
+  boolean isOrderReverse() {
+    return this.orderReverse;
+  }
+
+  /**
+   * Should directory contents be displayed in mtime order.
+   * @return true mtime order, false default order
+   */
+  @InterfaceAudience.Private
+  boolean isOrderTime() {
+    return this.orderTime;
+  }
+
+  /**
+   * Should directory contents be displayed in size order.
+   * @return true size order, false default order
+   */
+  @InterfaceAudience.Private
+  boolean isOrderSize() {
+    return this.orderSize;
+  }
+
+  /**
+   * Should access time be used rather than modification time.
+   * @return true use access time, false use modification time
+   */
+  @InterfaceAudience.Private
+  boolean isUseAtime() {
+    return this.useAtime;
   }
 
   @Override
@@ -98,6 +192,7 @@ class Ls extends FsCommand {
   throws IOException {
     if (parent != null && !isRecursive() && items.length != 0) {
       out.println("Found " + items.length + " items");
+      Arrays.sort(items, getOrderComparator());
     }
     adjustColumnWidths(items);
     super.processPaths(parent, items);
@@ -113,9 +208,10 @@ class Ls extends FsCommand {
         stat.getOwner(),
         stat.getGroup(),
         formatSize(stat.getLen()),
-        dateFormat.format(new Date(stat.getModificationTime())),
-        item
-    );
+        dateFormat.format(new Date(isUseAtime()
+            ? stat.getAccessTime()
+            : stat.getModificationTime())),
+        item);
     out.println(line);
   }
 
@@ -150,6 +246,49 @@ class Ls extends FsCommand {
   }
 
   /**
+   * Get the comparator to be used for sorting files.
+   * @return comparator
+   */
+  private Comparator<PathData> getOrderComparator() {
+    return this.orderComparator;
+  }
+
+  /**
+   * Initialise the comparator to be used for sorting files. If multiple 
options
+   * are selected then the order is chosen in the following precedence: -
+   * Modification time (or access time if requested) - File size - File name
+   */
+  private void initialiseOrderComparator() {
+    if (isOrderTime()) {
+      // mtime is ordered latest date first in line with the unix ls -t command
+      this.orderComparator = new Comparator<PathData>() {
+        public int compare(PathData o1, PathData o2) {
+          Long o1Time = (isUseAtime() ? o1.stat.getAccessTime()
+              : o1.stat.getModificationTime());
+          Long o2Time = (isUseAtime() ? o2.stat.getAccessTime()
+              : o2.stat.getModificationTime());
+          return o2Time.compareTo(o1Time) * (isOrderReverse() ? -1 : 1);
+        }
+      };
+    } else if (isOrderSize()) {
+      // size is ordered largest first in line with the unix ls -S command
+      this.orderComparator = new Comparator<PathData>() {
+        public int compare(PathData o1, PathData o2) {
+          Long o1Length = o1.stat.getLen();
+          Long o2Length = o2.stat.getLen();
+          return o2Length.compareTo(o1Length) * (isOrderReverse() ? -1 : 1);
+        }
+      };
+    } else {
+      this.orderComparator = new Comparator<PathData>() {
+        public int compare(PathData o1, PathData o2) {
+          return o1.compareTo(o2) * (isOrderReverse() ? -1 : 1);
+        }
+      };
+    }
+  }
+
+  /**
    * Get a recursive listing of all files in that match the file patterns.
    * Same as "-ls -R"
    */
@@ -162,7 +301,7 @@ class Ls extends FsCommand {
       args.addFirst("-R");
       super.processOptions(args);
     }
-    
+
     @Override
     public String getReplacementCommand() {
       return "ls -R";

http://git-wip-us.apache.org/repos/asf/hadoop/blob/3d0e2e54/hadoop-common-project/hadoop-common/src/test/resources/testConf.xml
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/test/resources/testConf.xml 
b/hadoop-common-project/hadoop-common/src/test/resources/testConf.xml
index d36efd5..ae5f44c 100644
--- a/hadoop-common-project/hadoop-common/src/test/resources/testConf.xml
+++ b/hadoop-common-project/hadoop-common/src/test/resources/testConf.xml
@@ -54,7 +54,7 @@
       <comparators>
         <comparator>
           <type>RegexpComparator</type>
-          <expected-output>^-ls \[-d\] \[-h\] \[-R\] \[&lt;path&gt; \.\.\.\] 
:( |\t)*</expected-output>
+          <expected-output>^-ls \[-d\] \[-h\] \[-R\] \[-t\] \[-S\] \[-r\] 
\[-u\] \[&lt;path&gt; \.\.\.\] :( |\t)*</expected-output>
         </comparator>
         <comparator>
           <type>RegexpComparator</type>
@@ -62,11 +62,15 @@
         </comparator>
         <comparator>
           <type>RegexpComparator</type>
-          <expected-output>^\s*specified, the contents of 
/user/&lt;currentUser&gt; will be listed. Directory entries( 
)*</expected-output>
+          <expected-output>^\s*specified, the contents of 
/user/&lt;currentUser&gt; will be listed. For a directory a( 
)*</expected-output>
         </comparator>
         <comparator>
           <type>RegexpComparator</type>
-          <expected-output>^\s*are of the form:( )*</expected-output>
+          <expected-output>^( |\t)*list of its direct children is returned 
\(unless -d option is specified\).*</expected-output>
+        </comparator>
+        <comparator>
+          <type>RegexpComparator</type>
+          <expected-output>^( |\t)*Directory entries are of the form:( 
)*</expected-output>
         </comparator>
         <comparator>
           <type>RegexpComparator</type>
@@ -94,16 +98,36 @@
         </comparator>
         <comparator>
           <type>RegexpComparator</type>
-          <expected-output>^\s*-h\s+Formats the sizes of files in a 
human-readable fashion rather than a number( )*</expected-output>
+          <expected-output>^\s*-h\s+Formats the sizes of files in a 
human-readable fashion( )*</expected-output>
         </comparator>
         <comparator>
           <type>RegexpComparator</type>
-          <expected-output>^\s*of bytes\.( )*</expected-output>
+          <expected-output>^\s*rather than a number of bytes\.( 
)*</expected-output>
         </comparator>
         <comparator>
           <type>RegexpComparator</type>
           <expected-output>^\s*-R\s+Recursively list the contents of 
directories\.( )*</expected-output>
         </comparator>
+        <comparator>
+          <type>RegexpComparator</type>
+          <expected-output>^( |\t)*-t\s+Sort files by modification time \(most 
recent first\)\.</expected-output>
+        </comparator>
+        <comparator>
+          <type>RegexpComparator</type>
+          <expected-output>^( |\t)*-S\s+Sort files by size\.</expected-output>
+        </comparator>
+        <comparator>
+          <type>RegexpComparator</type>
+          <expected-output>^( |\t)*-r\s+Reverse the order of the 
sort\.</expected-output>
+        </comparator>
+        <comparator>
+          <type>RegexpComparator</type>
+          <expected-output>^( |\t)*-u\s+Use time of last access instead of 
modification for</expected-output>
+        </comparator>
+        <comparator>
+          <type>RegexpComparator</type>
+          <expected-output>^( |\t)*display and sorting\.</expected-output>
+        </comparator>
       </comparators>
     </test>
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/3d0e2e54/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testHDFSConf.xml
----------------------------------------------------------------------
diff --git 
a/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testHDFSConf.xml 
b/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testHDFSConf.xml
index 2ac79f8..8399235 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testHDFSConf.xml
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testHDFSConf.xml
@@ -1047,6 +1047,154 @@
     </test>
 
     <test> <!-- TESTED -->
+      <description>ls: files sorted in default order</description>
+      <test-commands>
+        <command>-fs NAMENODE -mkdir /dir</command>
+        <command>-fs NAMENODE -touchz /dir/file2 /dir/file1 
/dir/file3</command>
+        <command>-fs NAMENODE -ls /dir</command>
+      </test-commands>
+      <cleanup-commands>
+        <command>-fs NAMENODE -rm -r /dir</command>
+      </cleanup-commands>
+      <comparators>
+        <comparator>
+          <type>RegexpAcrossOutputComparator</type>
+          <expected-output>Found 3 items
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/file1
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/file2
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( 
)*/dir/file3</expected-output>
+        </comparator>
+      </comparators>
+    </test>
+
+    <test> <!-- TESTED -->
+      <description>ls: files sorted in reverse default order</description>
+      <test-commands>
+        <command>-fs NAMENODE -mkdir /dir</command>
+        <command>-fs NAMENODE -touchz /dir/file2 /dir/file1 
/dir/file3</command>
+        <command>-fs NAMENODE -ls -r /dir</command>
+      </test-commands>
+      <cleanup-commands>
+        <command>-fs NAMENODE -rm -r /dir</command>
+      </cleanup-commands>
+      <comparators>
+        <comparator>
+          <type>RegexpAcrossOutputComparator</type>
+          <expected-output>Found 3 items
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/file3
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/file2
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( 
)*/dir/file1</expected-output>
+        </comparator>
+      </comparators>
+    </test>
+
+    <test> <!-- TESTED -->
+      <description>ls: files sorted in size order</description>
+      <test-commands>
+        <command>-fs NAMENODE -mkdir /dir</command>
+        <command>-fs NAMENODE -put CLITEST_DATA/data30bytes 
/dir/data30bytes</command>
+        <command>-fs NAMENODE -put CLITEST_DATA/data15bytes 
/dir/data15bytes</command>
+        <command>-fs NAMENODE -put CLITEST_DATA/data120bytes 
/dir/data120bytes</command>
+        <command>-fs NAMENODE -put CLITEST_DATA/data60bytes 
/dir/data60bytes</command>
+        <command>-fs NAMENODE -ls -S /dir</command>
+      </test-commands>
+      <cleanup-commands>
+        <command>-fs NAMENODE -rm -r /dir</command>
+      </cleanup-commands>
+      <comparators>
+        <comparator>
+          <type>RegexpAcrossOutputComparator</type>
+          <expected-output>Found 4 items
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*120( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/data120bytes
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*60( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/data60bytes
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*30( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/data30bytes
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*15( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( 
)*/dir/data15bytes</expected-output>
+        </comparator>
+      </comparators>
+    </test>
+
+    <test> <!-- TESTED -->
+      <description>ls: files sorted in reverse size order</description>
+      <test-commands>
+        <command>-fs NAMENODE -mkdir /dir</command>
+        <command>-fs NAMENODE -put CLITEST_DATA/data30bytes 
/dir/data30bytes</command>
+        <command>-fs NAMENODE -put CLITEST_DATA/data15bytes 
/dir/data15bytes</command>
+        <command>-fs NAMENODE -put CLITEST_DATA/data120bytes 
/dir/data120bytes</command>
+        <command>-fs NAMENODE -put CLITEST_DATA/data60bytes 
/dir/data60bytes</command>
+        <command>-fs NAMENODE -ls -S -r /dir</command>
+      </test-commands>
+      <cleanup-commands>
+        <command>-fs NAMENODE -rm -r /dir</command>
+      </cleanup-commands>
+      <comparators>
+        <comparator>
+          <type>RegexpAcrossOutputComparator</type>
+          <expected-output>Found 4 items
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*15( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/data15bytes
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*30( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/data30bytes
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*60( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/data60bytes
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*120( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( 
)*/dir/data120bytes</expected-output>
+        </comparator>
+      </comparators>
+    </test>
+
+    <test> <!-- TESTED -->
+      <description>ls: files sorted in modification order</description>
+      <!-- this test assumes that the files take > 1ms each to create -->
+      <test-commands>
+        <command>-fs NAMENODE -mkdir /dir</command>
+        <command>-fs NAMENODE -touchz /dir/first</command>
+        <command>-fs NAMENODE -touchz /dir/second</command>
+        <command>-fs NAMENODE -touchz /dir/third</command>
+        <command>-fs NAMENODE -touchz /dir/fourth</command>
+        <command>-fs NAMENODE -touchz /dir/fifth</command>
+        <command>-fs NAMENODE -ls -t /dir</command>
+      </test-commands>
+      <cleanup-commands>
+        <command>-fs NAMENODE -rm -r /dir</command>
+      </cleanup-commands>
+      <comparators>
+        <comparator>
+          <type>RegexpAcrossOutputComparator</type>
+          <expected-output>Found 5 items
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/fifth
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/fourth
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/third
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/second
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( 
)*/dir/first</expected-output>
+        </comparator>
+      </comparators>
+    </test>
+
+    <test> <!-- TESTED -->
+      <description>ls: files sorted in reverse modification order</description>
+      <!-- this test assumes that the files take > 1ms each to create -->
+      <test-commands>
+        <command>-fs NAMENODE -mkdir /dir</command>
+        <command>-fs NAMENODE -touchz /dir/first</command>
+        <command>-fs NAMENODE -touchz /dir/second</command>
+        <command>-fs NAMENODE -touchz /dir/third</command>
+        <command>-fs NAMENODE -touchz /dir/fourth</command>
+        <command>-fs NAMENODE -touchz /dir/fifth</command>
+        <command>-fs NAMENODE -ls -t -r /dir</command>
+      </test-commands>
+      <cleanup-commands>
+        <command>-fs NAMENODE -rm -r /dir</command>
+      </cleanup-commands>
+      <comparators>
+        <comparator>
+          <type>RegexpAcrossOutputComparator</type>
+          <expected-output>Found 5 items
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/first
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/second
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/third
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( )*/dir/fourth
+-rw-r--r--( )*1( )*[a-zA-z0-9]*( )*supergroup( )*0( 
)*[0-9]{4,}-[0-9]{2,}-[0-9]{2,} [0-9]{2,}:[0-9]{2,}( 
)*/dir/fifth</expected-output>
+        </comparator>
+      </comparators>
+    </test>
+
+    <test> <!-- TESTED -->
       <description>rm: Test for quoted globbing </description>
       <windows>false</windows>
       <test-commands>

Reply via email to