From df6d242e2866311fe1e20dffc6d6077003978228 Mon Sep 17 00:00:00 2001 From: Allen Wittenauer Date: Mon, 9 Feb 2015 12:54:25 -0800 Subject: [PATCH] HADOOP-8934. Shell command ls should include sort options (Jonathan Allen via aw) (missed file) (cherry picked from commit 576459801c4e21effc4e3bca796527896b6e4f4b) --- .../org/apache/hadoop/fs/shell/TestLs.java | 1308 +++++++++++++++++ 1 file changed, 1308 insertions(+) create mode 100644 hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestLs.java diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestLs.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestLs.java new file mode 100644 index 00000000000..66403db3377 --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestLs.java @@ -0,0 +1,1308 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.fs.shell; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.*; + +import java.io.IOException; +import java.io.PrintStream; +import java.net.URI; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedList; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileStatus; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.FilterFileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.fs.permission.AclEntry; +import org.apache.hadoop.fs.permission.AclStatus; +import org.apache.hadoop.fs.permission.FsPermission; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.InOrder; + +/** + * JUnit test class for {@link org.apache.hadoop.fs.shell.Ls} + * + */ +public class TestLs { + private static Configuration conf; + private static FileSystem mockFs; + + private static final Date NOW = new Date(); + + @BeforeClass + public static void setup() throws IOException { + conf = new Configuration(); + conf.set("fs.defaultFS", "mockfs:///"); + conf.setClass("fs.mockfs.impl", MockFileSystem.class, FileSystem.class); + mockFs = mock(FileSystem.class); + } + + @Before + public void resetMock() throws IOException { + reset(mockFs); + AclStatus mockAclStatus = mock(AclStatus.class); + when(mockAclStatus.getEntries()).thenReturn(new ArrayList()); + when(mockFs.getAclStatus(any(Path.class))).thenReturn(mockAclStatus); + } + + // check that default options are correct + @Test + public void processOptionsNone() throws IOException { + LinkedList options = new LinkedList(); + Ls ls = new Ls(); + ls.processOptions(options); + assertTrue(ls.isDirRecurse()); + assertFalse(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); + assertFalse(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); + assertFalse(ls.isOrderTime()); + assertFalse(ls.isUseAtime()); + } + + // check the -d option is recognised + @Test + public void processOptionsDirectory() throws IOException { + LinkedList options = new LinkedList(); + options.add("-d"); + Ls ls = new Ls(); + ls.processOptions(options); + assertFalse(ls.isDirRecurse()); + assertFalse(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); + assertFalse(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); + assertFalse(ls.isOrderTime()); + assertFalse(ls.isUseAtime()); + } + + // check the -h option is recognised + @Test + public void processOptionsHuman() throws IOException { + LinkedList options = new LinkedList(); + options.add("-h"); + Ls ls = new Ls(); + ls.processOptions(options); + assertTrue(ls.isDirRecurse()); + assertTrue(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); + assertFalse(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); + assertFalse(ls.isOrderTime()); + assertFalse(ls.isUseAtime()); + } + + // check the -R option is recognised + @Test + public void processOptionsRecursive() throws IOException { + LinkedList options = new LinkedList(); + options.add("-R"); + Ls ls = new Ls(); + ls.processOptions(options); + assertTrue(ls.isDirRecurse()); + assertFalse(ls.isHumanReadable()); + assertTrue(ls.isRecursive()); + assertFalse(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); + assertFalse(ls.isOrderTime()); + assertFalse(ls.isUseAtime()); + } + + // check the -r option is recognised + @Test + public void processOptionsReverse() throws IOException { + LinkedList options = new LinkedList(); + options.add("-r"); + Ls ls = new Ls(); + ls.processOptions(options); + assertTrue(ls.isDirRecurse()); + assertFalse(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); + assertTrue(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); + assertFalse(ls.isOrderTime()); + assertFalse(ls.isUseAtime()); + } + + // check the -S option is recognised + @Test + public void processOptionsSize() throws IOException { + LinkedList options = new LinkedList(); + options.add("-S"); + Ls ls = new Ls(); + ls.processOptions(options); + assertTrue(ls.isDirRecurse()); + assertFalse(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); + assertFalse(ls.isOrderReverse()); + assertTrue(ls.isOrderSize()); + assertFalse(ls.isOrderTime()); + assertFalse(ls.isUseAtime()); + } + + // check the -t option is recognised + @Test + public void processOptionsMtime() throws IOException { + LinkedList options = new LinkedList(); + options.add("-t"); + Ls ls = new Ls(); + ls.processOptions(options); + assertTrue(ls.isDirRecurse()); + assertFalse(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); + assertFalse(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); + assertTrue(ls.isOrderTime()); + assertFalse(ls.isUseAtime()); + } + + // check the precedence of the -t and -S options + @Test + public void processOptionsMtimeSize() throws IOException { + LinkedList options = new LinkedList(); + options.add("-t"); + options.add("-S"); + Ls ls = new Ls(); + ls.processOptions(options); + assertTrue(ls.isDirRecurse()); + assertFalse(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); + assertFalse(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); + assertTrue(ls.isOrderTime()); + assertFalse(ls.isUseAtime()); + } + + // check the precedence of the -t, -S and -r options + @Test + public void processOptionsMtimeSizeReverse() throws IOException { + LinkedList options = new LinkedList(); + options.add("-t"); + options.add("-S"); + options.add("-r"); + Ls ls = new Ls(); + ls.processOptions(options); + assertTrue(ls.isDirRecurse()); + assertFalse(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); + assertTrue(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); + assertTrue(ls.isOrderTime()); + assertFalse(ls.isUseAtime()); + } + + // chheck the -u option is recognised + @Test + public void processOptionsAtime() throws IOException { + LinkedList options = new LinkedList(); + options.add("-u"); + Ls ls = new Ls(); + ls.processOptions(options); + assertTrue(ls.isDirRecurse()); + assertFalse(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); + assertFalse(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); + assertFalse(ls.isOrderTime()); + assertTrue(ls.isUseAtime()); + } + + // check all options is handled correctly + @Test + public void processOptionsAll() throws IOException { + LinkedList options = new LinkedList(); + options.add("-d"); // directory + options.add("-h"); // human readable + options.add("-R"); // recursive + options.add("-r"); // reverse order + options.add("-t"); // time order + options.add("-S"); // size order + options.add("-u"); // show atime + Ls ls = new Ls(); + ls.processOptions(options); + assertFalse(ls.isDirRecurse()); + assertTrue(ls.isHumanReadable()); + assertFalse(ls.isRecursive()); // -d overrules -R + assertTrue(ls.isOrderReverse()); + assertFalse(ls.isOrderSize()); // -t overrules -S + assertTrue(ls.isOrderTime()); + assertTrue(ls.isUseAtime()); + } + + // check listing of a single file + @Test + public void processPathFile() throws IOException { + TestFile testfile = new TestFile("testDir", "testFile"); + + LinkedList pathData = new LinkedList(); + pathData.add(testfile.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println(testfile.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check listing of multiple files + @Test + public void processPathFiles() throws IOException { + TestFile testfile01 = new TestFile("testDir01", "testFile01"); + TestFile testfile02 = new TestFile("testDir02", "testFile02"); + TestFile testfile03 = new TestFile("testDir03", "testFile03"); + TestFile testfile04 = new TestFile("testDir04", "testFile04"); + TestFile testfile05 = new TestFile("testDir05", "testFile05"); + TestFile testfile06 = new TestFile("testDir06", "testFile06"); + + LinkedList pathData = new LinkedList(); + pathData.add(testfile01.getPathData()); + pathData.add(testfile02.getPathData()); + pathData.add(testfile03.getPathData()); + pathData.add(testfile04.getPathData()); + pathData.add(testfile05.getPathData()); + pathData.add(testfile06.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check listing of a single directory + @Test + public void processPathDirectory() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check listing of multiple directories + @Test + public void processPathDirectories() throws IOException { + TestFile testfile01 = new TestFile("testDirectory01", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory01", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory01", "testFile03"); + + TestFile testDir01 = new TestFile("", "testDirectory01"); + testDir01.setIsDir(true); + testDir01.addContents(testfile01, testfile02, testfile03); + + TestFile testfile04 = new TestFile("testDirectory02", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory02", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory02", "testFile06"); + TestFile testDir02 = new TestFile("", "testDirectory02"); + testDir02.setIsDir(true); + testDir02.addContents(testfile04, testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir01.getPathData()); + pathData.add(testDir02.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 3 items"); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println("Found 3 items"); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check the default ordering + @Test + public void processPathDirOrderDefault() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + // add contents in non-lexigraphic order to show they get sorted + testDir.addContents(testfile01, testfile03, testfile05, testfile02, + testfile04, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check reverse default ordering + @Test + public void processPathDirOrderDefaultReverse() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + // add contents in non-lexigraphic order to show they get sorted + testDir.addContents(testfile01, testfile03, testfile05, testfile02, + testfile04, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-r"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check mtime ordering (-t option); most recent first in line with unix + // convention + @Test + public void processPathDirOrderMtime() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + // set file mtime in different order to file names + testfile01.setMtime(NOW.getTime() + 10); + testfile02.setMtime(NOW.getTime() + 30); + testfile03.setMtime(NOW.getTime() + 20); + testfile04.setMtime(NOW.getTime() + 60); + testfile05.setMtime(NOW.getTime() + 50); + testfile06.setMtime(NOW.getTime() + 40); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-t"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check reverse mtime ordering (-t -r options) + @Test + public void processPathDirOrderMtimeReverse() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + // set file mtime in different order to file names + testfile01.setMtime(NOW.getTime() + 10); + testfile02.setMtime(NOW.getTime() + 30); + testfile03.setMtime(NOW.getTime() + 20); + testfile04.setMtime(NOW.getTime() + 60); + testfile05.setMtime(NOW.getTime() + 50); + testfile06.setMtime(NOW.getTime() + 40); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-t"); + options.add("-r"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check multiple directories are order independently + @Test + public void processPathDirsOrderMtime() throws IOException { + TestFile testfile01 = new TestFile("testDirectory01", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory01", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory01", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory02", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory02", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory02", "testFile06"); + + // set file mtime in different order to file names + testfile01.setMtime(NOW.getTime() + 10); + testfile02.setMtime(NOW.getTime() + 30); + testfile03.setMtime(NOW.getTime() + 20); + testfile04.setMtime(NOW.getTime() + 60); + testfile05.setMtime(NOW.getTime() + 40); + testfile06.setMtime(NOW.getTime() + 50); + + TestFile testDir01 = new TestFile("", "testDirectory01"); + testDir01.setIsDir(true); + testDir01.addContents(testfile01, testfile02, testfile03); + + TestFile testDir02 = new TestFile("", "testDirectory02"); + testDir02.setIsDir(true); + testDir02.addContents(testfile04, testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir01.getPathData()); + pathData.add(testDir02.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-t"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 3 items"); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + inOrder.verify(out).println("Found 3 items"); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check mtime ordering with large time gaps between files (checks integer + // overflow issues) + @Test + public void processPathDirOrderMtimeYears() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + // set file mtime in different order to file names + testfile01.setMtime(NOW.getTime() + Integer.MAX_VALUE); + testfile02.setMtime(NOW.getTime() + Integer.MIN_VALUE); + testfile03.setMtime(NOW.getTime() + 0); + testfile04.setMtime(NOW.getTime() + Integer.MAX_VALUE + Integer.MAX_VALUE); + testfile05.setMtime(NOW.getTime() + 0); + testfile06.setMtime(NOW.getTime() + Integer.MIN_VALUE + Integer.MIN_VALUE); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-t"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check length order (-S option) + @Test + public void processPathDirOrderLength() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + // set file length in different order to file names + long length = 1234567890; + testfile01.setLength(length + 10); + testfile02.setLength(length + 30); + testfile03.setLength(length + 20); + testfile04.setLength(length + 60); + testfile05.setLength(length + 50); + testfile06.setLength(length + 40); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-S"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check reverse length order (-S -r options) + @Test + public void processPathDirOrderLengthReverse() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + // set file length in different order to file names + long length = 1234567890; + testfile01.setLength(length + 10); + testfile02.setLength(length + 30); + testfile03.setLength(length + 20); + testfile04.setLength(length + 60); + testfile05.setLength(length + 50); + testfile06.setLength(length + 40); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-S"); + options.add("-r"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check length ordering with large size gaps between files (checks integer + // overflow issues) + @Test + public void processPathDirOrderLengthLarge() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + // set file length in different order to file names + long length = 1234567890; + testfile01.setLength(length + 3l * Integer.MAX_VALUE); + testfile02.setLength(length + Integer.MAX_VALUE); + testfile03.setLength(length + 2l * Integer.MAX_VALUE); + testfile04.setLength(length + 4l * Integer.MAX_VALUE); + testfile05.setLength(length + 2l * Integer.MAX_VALUE); + testfile06.setLength(length + 0); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-S"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile04.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile01.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineMtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineMtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check access time display (-u option) + @Test + public void processPathDirectoryAtime() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-u"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile01.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile04.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineAtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check access time order (-u -t options) + @Test + public void processPathDirOrderAtime() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + // set file atime in different order to file names + testfile01.setAtime(NOW.getTime() + 10); + testfile02.setAtime(NOW.getTime() + 30); + testfile03.setAtime(NOW.getTime() + 20); + testfile04.setAtime(NOW.getTime() + 60); + testfile05.setAtime(NOW.getTime() + 50); + testfile06.setAtime(NOW.getTime() + 40); + + // set file mtime in different order to atime + testfile01.setMtime(NOW.getTime() + 60); + testfile02.setMtime(NOW.getTime() + 50); + testfile03.setMtime(NOW.getTime() + 20); + testfile04.setMtime(NOW.getTime() + 30); + testfile05.setMtime(NOW.getTime() + 10); + testfile06.setMtime(NOW.getTime() + 40); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-t"); + options.add("-u"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile04.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile01.formatLineAtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check reverse access time order (-u -t -r options) + @Test + public void processPathDirOrderAtimeReverse() throws IOException { + TestFile testfile01 = new TestFile("testDirectory", "testFile01"); + TestFile testfile02 = new TestFile("testDirectory", "testFile02"); + TestFile testfile03 = new TestFile("testDirectory", "testFile03"); + TestFile testfile04 = new TestFile("testDirectory", "testFile04"); + TestFile testfile05 = new TestFile("testDirectory", "testFile05"); + TestFile testfile06 = new TestFile("testDirectory", "testFile06"); + + // set file atime in different order to file names + testfile01.setAtime(NOW.getTime() + 10); + testfile02.setAtime(NOW.getTime() + 30); + testfile03.setAtime(NOW.getTime() + 20); + testfile04.setAtime(NOW.getTime() + 60); + testfile05.setAtime(NOW.getTime() + 50); + testfile06.setAtime(NOW.getTime() + 40); + + // set file mtime in different order to atime + testfile01.setMtime(NOW.getTime() + 60); + testfile02.setMtime(NOW.getTime() + 50); + testfile03.setMtime(NOW.getTime() + 20); + testfile04.setMtime(NOW.getTime() + 30); + testfile05.setMtime(NOW.getTime() + 10); + testfile06.setMtime(NOW.getTime() + 40); + + TestFile testDir = new TestFile("", "testDirectory"); + testDir.setIsDir(true); + testDir.addContents(testfile01, testfile02, testfile03, testfile04, + testfile05, testfile06); + + LinkedList pathData = new LinkedList(); + pathData.add(testDir.getPathData()); + + PrintStream out = mock(PrintStream.class); + + Ls ls = new Ls(); + ls.out = out; + + LinkedList options = new LinkedList(); + options.add("-t"); + options.add("-u"); + options.add("-r"); + ls.processOptions(options); + String lineFormat = TestFile.computeLineFormat(pathData); + + ls.processArguments(pathData); + InOrder inOrder = inOrder(out); + inOrder.verify(out).println("Found 6 items"); + inOrder.verify(out).println(testfile01.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile03.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile02.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile06.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile05.formatLineAtime(lineFormat)); + inOrder.verify(out).println(testfile04.formatLineAtime(lineFormat)); + verifyNoMoreInteractions(out); + } + + // check the deprecated flag isn't set + @Test + public void isDeprecated() { + Ls ls = new Ls(); + boolean actual = ls.isDeprecated(); + boolean expected = false; + assertEquals("Ls.isDeprecated", expected, actual); + } + + // check there's no replacement command + @Test + public void getReplacementCommand() { + Ls ls = new Ls(); + String actual = ls.getReplacementCommand(); + String expected = null; + assertEquals("Ls.getReplacementCommand", expected, actual); + } + + // check the correct name is returned + @Test + public void getName() { + Ls ls = new Ls(); + String actual = ls.getName(); + String expected = "ls"; + assertEquals("Ls.getName", expected, actual); + } + + // test class representing a file to be listed + static class TestFile { + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat( + "yyyy-MM-dd HH:mm"); + + private static final boolean DEFAULT_ISDIR = false; + private static final String DEFAULT_MODE = "750"; + private static final int DEFAULT_REPLICATION = 3; + private static final String DEFAULT_OWNER = "test_owner"; + private static final String DEFAULT_GROUP = "test_group"; + private static final long DEFAULT_LENGTH = 1234567890L; + private static final long DEFAULT_MTIME = NOW.getTime() - 86400000; + private static final long DEFAULT_ATIME = NOW.getTime() + 86400000; + private static final long DEFAULT_BLOCKSIZE = 64L * 1024 * 1024; + + private String dirname; + private String filename; + private boolean isDir; + private FsPermission permission; + private int replication; + private String owner; + private String group; + private long length; + private long mtime; + private long atime; + private long blocksize; + private ArrayList contents = new ArrayList(); + + private Path path = null; + private FileStatus fileStatus = null; + private PathData pathData = null; + + public TestFile(String dirname, String filename) { + setDirname(dirname); + setFilename(filename); + setIsDir(DEFAULT_ISDIR); + setPermission(DEFAULT_MODE); + setReplication(DEFAULT_REPLICATION); + setOwner(DEFAULT_OWNER); + setGroup(DEFAULT_GROUP); + setLength(DEFAULT_LENGTH); + setMtime(DEFAULT_MTIME); + setAtime(DEFAULT_ATIME); + setBlocksize(DEFAULT_BLOCKSIZE); + } + + public void setDirname(String dirname) { + this.dirname = dirname; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public void setIsDir(boolean isDir) { + this.isDir = isDir; + } + + public void setPermission(String mode) { + setPermission(new FsPermission(mode)); + } + + public void setPermission(FsPermission permission) { + this.permission = permission; + } + + public void setReplication(int replication) { + this.replication = replication; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public void setGroup(String group) { + this.group = group; + } + + public void setLength(long length) { + this.length = length; + } + + public void setMtime(long mtime) { + this.mtime = mtime; + } + + public void setAtime(long atime) { + this.atime = atime; + } + + public void setBlocksize(long blocksize) { + this.blocksize = blocksize; + } + + public void addContents(TestFile... contents) { + for (TestFile testFile : contents) { + this.contents.add(testFile.getFileStatus()); + } + } + + private String getDirname() { + return this.dirname; + } + + private String getFilename() { + return this.filename; + } + + private String getPathname() { + return getDirname() + "/" + getFilename(); + } + + private boolean isDir() { + return this.isDir; + } + + private boolean isFile() { + return !this.isDir(); + } + + private FsPermission getPermission() { + return this.permission; + } + + private int getReplication() { + return this.replication; + } + + private String getOwner() { + return this.owner; + } + + private String getGroup() { + return this.group; + } + + private long getLength() { + return this.length; + } + + private long getMtime() { + return this.mtime; + } + + private long getAtime() { + return this.atime; + } + + private long getBlocksize() { + return this.blocksize; + } + + private FileStatus[] getContents() { + return this.contents.toArray(new FileStatus[0]); + } + + /** + * Returns a formated output line based on the given format mask, file + * status and file name. + * + * @param lineFormat + * format mask + * @param fileStatus + * file status + * @param fileName + * file name + * @return formated line + */ + private String formatLineMtime(String lineFormat) { + return String.format(lineFormat, (isDir() ? "d" : "-"), getPermission(), + (isFile() ? getReplication() : "-"), getOwner(), getGroup(), + String.valueOf(getLength()), + DATE_FORMAT.format(new Date(getMtime())), getPathname()); + } + + /** + * Returns a formated output line based on the given format mask, file + * status and file name. + * + * @param lineFormat + * format mask + * @param fileStatus + * file status + * @param fileName + * file name + * @return formated line + */ + private String formatLineAtime(String lineFormat) { + return String.format(lineFormat, (isDir() ? "d" : "-"), getPermission(), + (isFile() ? getReplication() : "-"), getOwner(), getGroup(), + String.valueOf(getLength()), + DATE_FORMAT.format(new Date(getAtime())), getPathname()); + } + + public FileStatus getFileStatus() { + if (fileStatus == null) { + Path path = getPath(); + fileStatus = new FileStatus(getLength(), isDir(), getReplication(), + getBlocksize(), getMtime(), getAtime(), getPermission(), + getOwner(), getGroup(), path); + } + return fileStatus; + } + + public Path getPath() { + if (path == null) { + if ((getDirname() != null) && (!getDirname().equals(""))) { + path = new Path(getDirname(), getFilename()); + } else { + path = new Path(getFilename()); + } + } + return path; + } + + public PathData getPathData() throws IOException { + if (pathData == null) { + FileStatus fileStatus = getFileStatus(); + Path path = getPath(); + when(mockFs.getFileStatus(eq(path))).thenReturn(fileStatus); + pathData = new PathData(path.toString(), conf); + + if (getContents().length != 0) { + when(mockFs.listStatus(eq(path))).thenReturn(getContents()); + } + + } + return pathData; + } + + /** + * Compute format string based on maximum column widths. Copied from + * Ls.adjustColumnWidths as these tests are more interested in proving + * regression rather than absolute format. + * + * @param items + * to find the max field width for each column + */ + public static String computeLineFormat(LinkedList items) { + int maxRepl = 3, maxLen = 10, maxOwner = 0, maxGroup = 0; + for (PathData item : items) { + FileStatus stat = item.stat; + maxRepl = maxLength(maxRepl, stat.getReplication()); + maxLen = maxLength(maxLen, stat.getLen()); + maxOwner = maxLength(maxOwner, stat.getOwner()); + maxGroup = maxLength(maxGroup, stat.getGroup()); + } + + StringBuilder fmt = new StringBuilder(); + fmt.append("%s%s "); // permission string + fmt.append("%" + maxRepl + "s "); + // Do not use '%-0s' as a formatting conversion, since it will throw a + // a MissingFormatWidthException if it is used in String.format(). + // http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html#intFlags + fmt.append((maxOwner > 0) ? "%-" + maxOwner + "s " : "%s"); + fmt.append((maxGroup > 0) ? "%-" + maxGroup + "s " : "%s"); + fmt.append("%" + maxLen + "s "); + fmt.append("%s %s"); // mod time & path + return fmt.toString(); + } + + /** + * Return the maximum of two values, treating null as 0 + * + * @param n + * integer to be compared + * @param value + * value to be compared + * @return maximum of the two inputs + */ + private static int maxLength(int n, Object value) { + return Math.max(n, (value != null) ? String.valueOf(value).length() : 0); + } + } + + static class MockFileSystem extends FilterFileSystem { + Configuration conf; + + MockFileSystem() { + super(mockFs); + } + + @Override + public void initialize(URI uri, Configuration conf) { + this.conf = conf; + } + + @Override + public Path makeQualified(Path path) { + return path; + } + + @Override + public Configuration getConf() { + return conf; + } + } +}