summaryrefslogtreecommitdiff
path: root/unittests/Basic/VirtualFileSystemTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/Basic/VirtualFileSystemTest.cpp')
-rw-r--r--unittests/Basic/VirtualFileSystemTest.cpp99
1 files changed, 88 insertions, 11 deletions
diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp
index f9efbeaee565b..c795be07acf1b 100644
--- a/unittests/Basic/VirtualFileSystemTest.cpp
+++ b/unittests/Basic/VirtualFileSystemTest.cpp
@@ -9,6 +9,7 @@
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -66,6 +67,21 @@ public:
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
return std::error_code();
}
+ // Map any symlink to "/symlink".
+ std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const override {
+ auto I = FilesAndDirs.find(Path.str());
+ if (I == FilesAndDirs.end())
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+ if (I->second.isSymlink()) {
+ Output.clear();
+ Twine("/symlink").toVector(Output);
+ return std::error_code();
+ }
+ Output.clear();
+ Path.toVector(Output);
+ return std::error_code();
+ }
struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
std::map<std::string, vfs::Status> &FilesAndDirs;
@@ -195,6 +211,35 @@ TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
EXPECT_TRUE(Status->equivalent(*Status2));
}
+TEST(VirtualFileSystemTest, GetRealPathInOverlay) {
+ IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+ Lower->addRegularFile("/foo");
+ Lower->addSymlink("/lower_link");
+ IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
+
+ IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+ new vfs::OverlayFileSystem(Lower));
+ O->pushOverlay(Upper);
+
+ // Regular file.
+ SmallString<16> RealPath;
+ EXPECT_FALSE(O->getRealPath("/foo", RealPath));
+ EXPECT_EQ(RealPath.str(), "/foo");
+
+ // Expect no error getting real path for symlink in lower overlay.
+ EXPECT_FALSE(O->getRealPath("/lower_link", RealPath));
+ EXPECT_EQ(RealPath.str(), "/symlink");
+
+ // Try a non-existing link.
+ EXPECT_EQ(O->getRealPath("/upper_link", RealPath),
+ errc::no_such_file_or_directory);
+
+ // Add a new symlink in upper.
+ Upper->addSymlink("/upper_link");
+ EXPECT_FALSE(O->getRealPath("/upper_link", RealPath));
+ EXPECT_EQ(RealPath.str(), "/symlink");
+}
+
TEST(VirtualFileSystemTest, OverlayFiles) {
IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
@@ -442,16 +487,17 @@ TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) {
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::vector<StringRef> ExpectedBrokenSymlinks = {_a, _ba, _bc, _c, _e};
+ std::vector<StringRef> ExpectedNonBrokenSymlinks = {_b, _bb, _d, _dd, _ddd};
+ std::vector<std::string> VisitedBrokenSymlinks;
+ std::vector<std::string> VisitedNonBrokenSymlinks;
std::error_code EC;
for (vfs::recursive_directory_iterator I(*FS, Twine(TestDirectory), EC), E;
I != E; I.increment(EC)) {
- // Skip broken symlinks.
auto EC2 = std::make_error_code(std::errc::no_such_file_or_directory);
if (EC == EC2) {
- EC.clear();
+ VisitedBrokenSymlinks.push_back(I->getName());
continue;
}
// For bot debugging.
@@ -467,13 +513,20 @@ TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) {
<< "EC message: " << EC2.message() << "\n";
}
ASSERT_FALSE(EC);
- Contents.push_back(I->getName());
+ VisitedNonBrokenSymlinks.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()));
+ // Check visited file names.
+ std::sort(VisitedBrokenSymlinks.begin(), VisitedBrokenSymlinks.end());
+ std::sort(VisitedNonBrokenSymlinks.begin(), VisitedNonBrokenSymlinks.end());
+ EXPECT_EQ(ExpectedBrokenSymlinks.size(), VisitedBrokenSymlinks.size());
+ EXPECT_TRUE(std::equal(VisitedBrokenSymlinks.begin(),
+ VisitedBrokenSymlinks.end(),
+ ExpectedBrokenSymlinks.begin()));
+ EXPECT_EQ(ExpectedNonBrokenSymlinks.size(), VisitedNonBrokenSymlinks.size());
+ EXPECT_TRUE(std::equal(VisitedNonBrokenSymlinks.begin(),
+ VisitedNonBrokenSymlinks.end(),
+ ExpectedNonBrokenSymlinks.begin()));
}
#endif
@@ -488,8 +541,8 @@ static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) {
for (DirIter E; !EC && I != E; I.increment(EC))
InputToCheck.push_back(I->getName());
- std::sort(InputToCheck.begin(), InputToCheck.end());
- std::sort(Expected.begin(), Expected.end());
+ llvm::sort(InputToCheck.begin(), InputToCheck.end());
+ llvm::sort(Expected.begin(), Expected.end());
EXPECT_EQ(InputToCheck.size(), Expected.size());
unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
@@ -760,6 +813,30 @@ TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
NormalizedFS.getCurrentWorkingDirectory().get()));
}
+#if !defined(_WIN32)
+TEST_F(InMemoryFileSystemTest, GetRealPath) {
+ SmallString<16> Path;
+ EXPECT_EQ(FS.getRealPath("b", Path), errc::operation_not_permitted);
+
+ auto GetRealPath = [this](StringRef P) {
+ SmallString<16> Output;
+ auto EC = FS.getRealPath(P, Output);
+ EXPECT_FALSE(EC);
+ return Output.str().str();
+ };
+
+ FS.setCurrentWorkingDirectory("a");
+ EXPECT_EQ(GetRealPath("b"), "a/b");
+ EXPECT_EQ(GetRealPath("../b"), "b");
+ EXPECT_EQ(GetRealPath("b/./c"), "a/b/c");
+
+ FS.setCurrentWorkingDirectory("/a");
+ EXPECT_EQ(GetRealPath("b"), "/a/b");
+ EXPECT_EQ(GetRealPath("../b"), "/b");
+ EXPECT_EQ(GetRealPath("b/./c"), "/a/b/c");
+}
+#endif // _WIN32
+
TEST_F(InMemoryFileSystemTest, AddFileWithUser) {
FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), 0xFEEDFACE);
auto Stat = FS.status("/a");