diff options
author | Juergen Ributzka <juergen@apple.com> | 2017-03-10 22:49:04 +0000 |
---|---|---|
committer | Juergen Ributzka <juergen@apple.com> | 2017-03-10 22:49:04 +0000 |
commit | 46541f1b0bc2126d2bb5b8c673ddec212c18c64e (patch) | |
tree | e91b3bece50c9c30f024ea7fa20db002f4242238 /clang/unittests/Basic/VirtualFileSystemTest.cpp | |
parent | 83c37c4dac6cc0d8af01902e81cf6f6f4995c8f6 (diff) | |
download | llvm-46541f1b0bc2126d2bb5b8c673ddec212c18c64e.zip llvm-46541f1b0bc2126d2bb5b8c673ddec212c18c64e.tar.gz llvm-46541f1b0bc2126d2bb5b8c673ddec212c18c64e.tar.bz2 |
Reapply [VFS] Ignore broken symlinks in the directory iterator.
Modified the tests to accept any iteration order.
The VFS directory iterator and recursive directory iterator behave differently
from the LLVM counterparts. Once the VFS iterators hit a broken symlink they
immediately abort. The LLVM counterparts allow to recover from this issue by
clearing the error code and skipping to the next entry.
This change adds the same functionality to the VFS iterators. There should be
no change in current behavior in the current CLANG source base, because all
clients have loop exit conditions that also check the error code.
This fixes rdar://problem/30934619.
Differential Revision: https://reviews.llvm.org/D30768
llvm-svn: 297528
Diffstat (limited to 'clang/unittests/Basic/VirtualFileSystemTest.cpp')
-rw-r--r-- | clang/unittests/Basic/VirtualFileSystemTest.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/clang/unittests/Basic/VirtualFileSystemTest.cpp b/clang/unittests/Basic/VirtualFileSystemTest.cpp index 580343d93..79b4d87 100644 --- a/clang/unittests/Basic/VirtualFileSystemTest.cpp +++ b/clang/unittests/Basic/VirtualFileSystemTest.cpp @@ -305,6 +305,22 @@ struct ScopedDir { } operator StringRef() { return Path.str(); } }; + +struct ScopedLink { + SmallString<128> Path; + ScopedLink(const Twine &To, const Twine &From) { + Path = From.str(); + std::error_code EC = sys::fs::create_link(To, From); + if (EC) + Path = ""; + EXPECT_FALSE(EC); + } + ~ScopedLink() { + if (Path != "") + EXPECT_FALSE(llvm::sys::fs::remove(Path.str())); + } + operator StringRef() { return Path.str(); } +}; } // end anonymous namespace TEST(VirtualFileSystemTest, BasicRealFSIteration) { @@ -334,6 +350,28 @@ TEST(VirtualFileSystemTest, BasicRealFSIteration) { EXPECT_EQ(vfs::directory_iterator(), I); } +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + + std::error_code EC; + for (vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC), E; + I != E; I.increment(EC)) { + // Skip broken symlinks. + if (EC == std::errc::no_such_file_or_directory) { + EC = std::error_code(); + continue; + } else if (EC) { + break; + } + EXPECT_TRUE(I->getName() == _b); + } +} + TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) { ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true); IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); @@ -373,6 +411,42 @@ TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) { EXPECT_EQ(1, Counts[3]); // d } +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _ba("no_such_file", TestDirectory + "/b/a"); + ScopedDir _bb(TestDirectory + "/b/b"); + ScopedLink _bc("no_such_file", TestDirectory + "/b/c"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + ScopedDir _d(TestDirectory + "/d"); + ScopedDir _dd(TestDirectory + "/d/d"); + ScopedDir _ddd(TestDirectory + "/d/d/d"); + ScopedLink _e("no_such_file", TestDirectory + "/e"); + std::vector<StringRef> Expected = {_b, _bb, _d, _dd, _ddd}; + + std::vector<std::string> Contents; + std::error_code EC; + for (vfs::recursive_directory_iterator I(*FS, Twine(TestDirectory), EC), E; + I != E; I.increment(EC)) { + // Skip broken symlinks. + if (EC == std::errc::no_such_file_or_directory) { + EC = std::error_code(); + continue; + } else if (EC) { + break; + } + Contents.push_back(I->getName()); + } + + // Check sorted contents. + std::sort(Contents.begin(), Contents.end()); + EXPECT_EQ(Expected.size(), Contents.size()); + EXPECT_TRUE(std::equal(Contents.begin(), Contents.end(), Expected.begin())); +} + template <typename DirIter> static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) { std::error_code EC; |