|
22 | 22 | import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_FILE_CLOSE_NUM_COMMITTED_ALLOWED_KEY; |
23 | 23 | import static org.apache.hadoop.hdfs.client.HdfsAdmin.TRASH_PERMISSION; |
24 | 24 | import static org.apache.hadoop.hdfs.client.HdfsClientConfigKeys.DFS_CLIENT_CONTEXT; |
| 25 | +import static org.assertj.core.api.Assertions.assertThat; |
25 | 26 | import static org.junit.Assert.assertEquals; |
26 | 27 | import static org.junit.Assert.assertFalse; |
27 | 28 | import static org.junit.Assert.assertNotNull; |
|
31 | 32 | import static org.mockito.ArgumentMatchers.eq; |
32 | 33 | import static org.mockito.Mockito.inOrder; |
33 | 34 | import static org.mockito.Mockito.mock; |
| 35 | +import static org.mockito.Mockito.spy; |
34 | 36 |
|
35 | 37 | import java.io.File; |
36 | 38 | import java.io.FileNotFoundException; |
|
123 | 125 | import org.apache.hadoop.util.DataChecksum; |
124 | 126 | import org.apache.hadoop.util.Time; |
125 | 127 | import org.apache.hadoop.util.concurrent.HadoopExecutors; |
| 128 | +import org.apache.hadoop.util.functional.RemoteIterators; |
126 | 129 | import org.junit.Assert; |
127 | 130 | import org.junit.Test; |
128 | 131 | import org.mockito.InOrder; |
| 132 | +import org.mockito.Mockito; |
129 | 133 | import org.slf4j.Logger; |
130 | 134 | import org.slf4j.LoggerFactory; |
131 | 135 | import org.slf4j.event.Level; |
@@ -1557,6 +1561,56 @@ public void testListFiles() throws IOException { |
1557 | 1561 | } |
1558 | 1562 | } |
1559 | 1563 |
|
| 1564 | + @Test |
| 1565 | + public void testListFilesRecursive() throws IOException { |
| 1566 | + Configuration conf = getTestConfiguration(); |
| 1567 | + |
| 1568 | + try (MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf).build();) { |
| 1569 | + DistributedFileSystem fs = cluster.getFileSystem(); |
| 1570 | + |
| 1571 | + // Create some directories and files. |
| 1572 | + Path dir = new Path("/dir"); |
| 1573 | + Path subDir1 = fs.makeQualified(new Path(dir, "subDir1")); |
| 1574 | + Path subDir2 = fs.makeQualified(new Path(dir, "subDir2")); |
| 1575 | + |
| 1576 | + fs.create(new Path(dir, "foo1")).close(); |
| 1577 | + fs.create(new Path(dir, "foo2")).close(); |
| 1578 | + fs.create(new Path(subDir1, "foo3")).close(); |
| 1579 | + fs.create(new Path(subDir2, "foo4")).close(); |
| 1580 | + |
| 1581 | + // Mock the filesystem, and throw FNF when listing is triggered for the subdirectory. |
| 1582 | + FileSystem mockFs = spy(fs); |
| 1583 | + Mockito.doThrow(new FileNotFoundException("")).when(mockFs).listLocatedStatus(eq(subDir1)); |
| 1584 | + List<LocatedFileStatus> str = RemoteIterators.toList(mockFs.listFiles(dir, true)); |
| 1585 | + assertThat(str).hasSize(3); |
| 1586 | + |
| 1587 | + // Mock the filesystem to depict a scenario where the directory got deleted and a file |
| 1588 | + // got created with the same name. |
| 1589 | + Mockito.doReturn(getMockedIterator(subDir1)).when(mockFs).listLocatedStatus(eq(subDir1)); |
| 1590 | + |
| 1591 | + str = RemoteIterators.toList(mockFs.listFiles(dir, true)); |
| 1592 | + assertThat(str).hasSize(4); |
| 1593 | + } |
| 1594 | + } |
| 1595 | + |
| 1596 | + private static RemoteIterator<LocatedFileStatus> getMockedIterator(Path subDir1) { |
| 1597 | + return new RemoteIterator<LocatedFileStatus>() { |
| 1598 | + private int remainingEntries = 1; |
| 1599 | + |
| 1600 | + @Override |
| 1601 | + public boolean hasNext() throws IOException { |
| 1602 | + return remainingEntries > 0; |
| 1603 | + } |
| 1604 | + |
| 1605 | + @Override |
| 1606 | + public LocatedFileStatus next() throws IOException { |
| 1607 | + remainingEntries--; |
| 1608 | + return new LocatedFileStatus(0, false, 1, 1024, 0L, 0, null, null, null, null, subDir1, |
| 1609 | + false, false, false, null); |
| 1610 | + } |
| 1611 | + }; |
| 1612 | + } |
| 1613 | + |
1560 | 1614 | @Test |
1561 | 1615 | public void testListStatusOfSnapshotDirs() throws IOException { |
1562 | 1616 | MiniDFSCluster cluster = new MiniDFSCluster.Builder(getTestConfiguration()) |
|
0 commit comments