diff options
Diffstat (limited to 'unittests/Basic/VirtualFileSystemTest.cpp')
-rw-r--r-- | unittests/Basic/VirtualFileSystemTest.cpp | 172 |
1 files changed, 163 insertions, 9 deletions
diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp index 71d2d2b..ac07035 100644 --- a/unittests/Basic/VirtualFileSystemTest.cpp +++ b/unittests/Basic/VirtualFileSystemTest.cpp @@ -14,11 +14,24 @@ #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" #include <map> + using namespace clang; using namespace llvm; using llvm::sys::fs::UniqueID; namespace { +struct DummyFile : public vfs::File { + vfs::Status S; + explicit DummyFile(vfs::Status S) : S(S) {} + llvm::ErrorOr<vfs::Status> status() override { return S; } + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, + bool IsVolatile) override { + llvm_unreachable("unimplemented"); + } + virtual std::error_code close() override { return std::error_code(); } +}; + class DummyFileSystem : public vfs::FileSystem { int FSID; // used to produce UniqueIDs int FileID; // used to produce UniqueIDs @@ -41,7 +54,16 @@ public: } ErrorOr<std::unique_ptr<vfs::File>> openFileForRead(const Twine &Path) override { - llvm_unreachable("unimplemented"); + auto S = status(Path); + if (S) + return std::unique_ptr<vfs::File>(new DummyFile{*S}); + return S.getError(); + } + llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override { + return std::string(); + } + std::error_code setCurrentWorkingDirectory(const Twine &Path) override { + return std::error_code(); } struct DirIterImpl : public clang::vfs::detail::DirIterImpl { @@ -92,20 +114,20 @@ public: } void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) { - vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), - 0, 0, 1024, sys::fs::file_type::regular_file, Perms); + vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0, + 1024, sys::fs::file_type::regular_file, Perms); addEntry(Path, S); } void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) { - vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), - 0, 0, 0, sys::fs::file_type::directory_file, Perms); + vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0, + 0, sys::fs::file_type::directory_file, Perms); addEntry(Path, S); } void addSymlink(StringRef Path) { - vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), - 0, 0, 0, sys::fs::file_type::symlink_file, sys::fs::all_all); + vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0, + 0, sys::fs::file_type::symlink_file, sys::fs::all_all); addEntry(Path, S); } }; @@ -279,7 +301,7 @@ struct ScopedDir { } operator StringRef() { return Path.str(); } }; -} +} // end anonymous namespace TEST(VirtualFileSystemTest, BasicRealFSIteration) { ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true); @@ -515,6 +537,128 @@ TEST(VirtualFileSystemTest, HiddenInIteration) { } } +class InMemoryFileSystemTest : public ::testing::Test { +protected: + clang::vfs::InMemoryFileSystem FS; + clang::vfs::InMemoryFileSystem NormalizedFS; + + InMemoryFileSystemTest() + : FS(/*UseNormalizedPaths=*/false), + NormalizedFS(/*UseNormalizedPaths=*/true) {} +}; + +TEST_F(InMemoryFileSystemTest, IsEmpty) { + auto Stat = FS.status("/a"); + ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString(); + Stat = FS.status("/"); + ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString(); +} + +TEST_F(InMemoryFileSystemTest, WindowsPath) { + FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer("")); + auto Stat = FS.status("c:"); +#if !defined(_WIN32) + ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); +#endif + Stat = FS.status("c:/windows/system128/foo.cpp"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); + FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer("")); + Stat = FS.status("d:/windows/foo.cpp"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); +} + +TEST_F(InMemoryFileSystemTest, OverlayFile) { + FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")); + NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")); + auto Stat = FS.status("/"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); + Stat = FS.status("/."); + ASSERT_FALSE(Stat); + Stat = NormalizedFS.status("/."); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); + Stat = FS.status("/a"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); + ASSERT_EQ("/a", Stat->getName()); +} + +TEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) { + auto Buf = MemoryBuffer::getMemBuffer("a"); + FS.addFileNoOwn("/a", 0, Buf.get()); + auto Stat = FS.status("/a"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); + ASSERT_EQ("/a", Stat->getName()); +} + +TEST_F(InMemoryFileSystemTest, OpenFileForRead) { + FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")); + FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c")); + FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d")); + NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")); + NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c")); + NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d")); + auto File = FS.openFileForRead("/a"); + ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer()); + File = FS.openFileForRead("/a"); // Open again. + ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer()); + File = NormalizedFS.openFileForRead("/././a"); // Open again. + ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer()); + File = FS.openFileForRead("/"); + ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString(); + File = FS.openFileForRead("/b"); + ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString(); + File = FS.openFileForRead("./c"); + ASSERT_FALSE(File); + File = FS.openFileForRead("e/../d"); + ASSERT_FALSE(File); + File = NormalizedFS.openFileForRead("./c"); + ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer()); + File = NormalizedFS.openFileForRead("e/../d"); + ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer()); +} + +TEST_F(InMemoryFileSystemTest, DuplicatedFile) { + ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"))); + ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a"))); + ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"))); + ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b"))); +} + +TEST_F(InMemoryFileSystemTest, DirectoryIteration) { + FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("")); + FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer("")); + + std::error_code EC; + vfs::directory_iterator I = FS.dir_begin("/", EC); + ASSERT_FALSE(EC); + ASSERT_EQ("/a", I->getName()); + I.increment(EC); + ASSERT_FALSE(EC); + ASSERT_EQ("/b", I->getName()); + I.increment(EC); + ASSERT_FALSE(EC); + ASSERT_EQ(vfs::directory_iterator(), I); + + I = FS.dir_begin("/b", EC); + ASSERT_FALSE(EC); + ASSERT_EQ("/b/c", I->getName()); + I.increment(EC); + ASSERT_FALSE(EC); + ASSERT_EQ(vfs::directory_iterator(), I); +} + +TEST_F(InMemoryFileSystemTest, WorkingDirectory) { + FS.setCurrentWorkingDirectory("/b"); + FS.addFile("c", 0, MemoryBuffer::getMemBuffer("")); + + auto Stat = FS.status("/b/c"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); + ASSERT_EQ("c", Stat->getName()); + ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory()); + + Stat = FS.status("c"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); +} + // NOTE: in the tests below, we use '//root/' as our root directory, since it is // a legal *absolute* path on Windows as well as *nix. class VFSFromYAMLTest : public ::testing::Test { @@ -589,10 +733,20 @@ TEST_F(VFSFromYAMLTest, MappedFiles) { ErrorOr<vfs::Status> S = O->status("//root/file1"); ASSERT_FALSE(S.getError()); EXPECT_EQ("//root/foo/bar/a", S->getName()); + EXPECT_TRUE(S->IsVFSMapped); ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a"); EXPECT_EQ("//root/foo/bar/a", SLower->getName()); EXPECT_TRUE(S->equivalent(*SLower)); + EXPECT_FALSE(SLower->IsVFSMapped); + + // file after opening + auto OpenedF = O->openFileForRead("//root/file1"); + ASSERT_FALSE(OpenedF.getError()); + auto OpenedS = (*OpenedF)->status(); + ASSERT_FALSE(OpenedS.getError()); + EXPECT_EQ("//root/foo/bar/a", OpenedS->getName()); + EXPECT_TRUE(OpenedS->IsVFSMapped); // directory S = O->status("//root/"); @@ -906,7 +1060,7 @@ TEST_F(VFSFromYAMLTest, DirectoryIteration) { "]\n" "}", Lower); - ASSERT_TRUE(FS.get() != NULL); + ASSERT_TRUE(FS.get() != nullptr); IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( new vfs::OverlayFileSystem(Lower)); |