diff options
author | Ilya Biryukov <ibiryukov@google.com> | 2018-09-04 14:15:53 +0000 |
---|---|---|
committer | Ilya Biryukov <ibiryukov@google.com> | 2018-09-04 14:15:53 +0000 |
commit | d5554c512de686a1c158370fe264648f079b89a2 (patch) | |
tree | 87464b83dd50f29ec59775d67cc4b37775397138 /clang/unittests/Basic/VirtualFileSystemTest.cpp | |
parent | 6cb12444ccc40a052431f99b1b2834b2f96cad61 (diff) | |
download | llvm-d5554c512de686a1c158370fe264648f079b89a2.zip llvm-d5554c512de686a1c158370fe264648f079b89a2.tar.gz llvm-d5554c512de686a1c158370fe264648f079b89a2.tar.bz2 |
Adding HardLink Support to VirtualFileSystem.
Summary:
Added support of creating a hardlink from one file to another file.
After a hardlink is added between two files, both file will have the same:
1. UniqueID (inode)
2. Size
3. Buffer
This will bring replay of compilation closer to the actual compilation. There are instances where clang checks for the UniqueID of the file/header to be loaded which leads to a different behavior during replay as all files have different UniqueIDs.
Patch by Utkarsh Saxena!
Reviewers: ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D51359
llvm-svn: 341366
Diffstat (limited to 'clang/unittests/Basic/VirtualFileSystemTest.cpp')
-rw-r--r-- | clang/unittests/Basic/VirtualFileSystemTest.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/clang/unittests/Basic/VirtualFileSystemTest.cpp b/clang/unittests/Basic/VirtualFileSystemTest.cpp index 23dbc57..3d41db7 100644 --- a/clang/unittests/Basic/VirtualFileSystemTest.cpp +++ b/clang/unittests/Basic/VirtualFileSystemTest.cpp @@ -15,8 +15,10 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/SourceMgr.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" #include <map> +#include <string> using namespace clang; using namespace llvm; @@ -697,6 +699,16 @@ protected: NormalizedFS(/*UseNormalizedPaths=*/true) {} }; +MATCHER_P2(IsHardLinkTo, FS, Target, "") { + StringRef From = arg; + StringRef To = Target; + auto OpenedFrom = FS->openFileForRead(From); + auto OpenedTo = FS->openFileForRead(To); + return !OpenedFrom.getError() && !OpenedTo.getError() && + (*OpenedFrom)->status()->getUniqueID() == + (*OpenedTo)->status()->getUniqueID(); +} + TEST_F(InMemoryFileSystemTest, IsEmpty) { auto Stat = FS.status("/a"); ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString(); @@ -958,6 +970,108 @@ TEST_F(InMemoryFileSystemTest, StatusName) { ASSERT_EQ("../b/c", getPosixPath(It->getName())); } +TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) { + StringRef FromLink = "/path/to/FROM/link"; + StringRef Target = "/path/to/TO/file"; + FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target")); + EXPECT_TRUE(FS.addHardLink(FromLink, Target)); + EXPECT_THAT(FromLink, IsHardLinkTo(&FS, Target)); + EXPECT_TRUE(FS.status(FromLink)->getSize() == FS.status(Target)->getSize()); + EXPECT_TRUE(FS.getBufferForFile(FromLink)->get()->getBuffer() == + FS.getBufferForFile(Target)->get()->getBuffer()); +} + +TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) { + StringRef Link0 = "/path/to/0/link"; + StringRef Link1 = "/path/to/1/link"; + StringRef Link2 = "/path/to/2/link"; + StringRef Target = "/path/to/target"; + FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target file")); + EXPECT_TRUE(FS.addHardLink(Link2, Target)); + EXPECT_TRUE(FS.addHardLink(Link1, Link2)); + EXPECT_TRUE(FS.addHardLink(Link0, Link1)); + EXPECT_THAT(Link0, IsHardLinkTo(&FS, Target)); + EXPECT_THAT(Link1, IsHardLinkTo(&FS, Target)); + EXPECT_THAT(Link2, IsHardLinkTo(&FS, Target)); +} + +TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) { + EXPECT_FALSE(FS.addHardLink("/path/to/link", "/path/to/target")); +} + +TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) { + StringRef Link = "/path/to/link"; + StringRef Target = "/path/to/target"; + FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target")); + FS.addFile(Link, 0, MemoryBuffer::getMemBuffer("content of link")); + EXPECT_FALSE(FS.addHardLink(Link, Target)); +} + +TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) { + StringRef Link = "/path/to/link"; + StringRef Target = "/path/to/target"; + FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target")); + EXPECT_TRUE(FS.addHardLink(Link, Target)); + EXPECT_FALSE(FS.addHardLink(Link, Target)); +} + +TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) { + StringRef Link = "/path/to/link"; + StringRef Target = "/path/to/target"; + StringRef Content = "content of target"; + EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content))); + EXPECT_TRUE(FS.addHardLink(Link, Target)); + EXPECT_TRUE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(Content))); +} + +TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) { + StringRef Link = "/path/to/link"; + StringRef Target = "/path/to/target"; + StringRef Content = "content of target"; + StringRef LinkContent = "different content of link"; + EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content))); + EXPECT_TRUE(FS.addHardLink(Link, Target)); + EXPECT_FALSE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(LinkContent))); +} + +TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) { + StringRef Dir = "path/to/dummy/dir"; + StringRef Link = "/path/to/link"; + StringRef File = "path/to/dummy/dir/target"; + StringRef Content = "content of target"; + EXPECT_TRUE(FS.addFile(File, 0, MemoryBuffer::getMemBuffer(Content))); + EXPECT_FALSE(FS.addHardLink(Link, Dir)); +} + +TEST_F(InMemoryFileSystemTest, AddHardLinkFromADirectory) { + StringRef Dir = "path/to/dummy/dir"; + StringRef Target = "path/to/dummy/dir/target"; + StringRef Content = "content of target"; + EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content))); + EXPECT_FALSE(FS.addHardLink(Dir, Target)); +} + +TEST_F(InMemoryFileSystemTest, AddHardLinkUnderAFile) { + StringRef CommonContent = "content string"; + FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer(CommonContent)); + FS.addFile("/c/d", 0, MemoryBuffer::getMemBuffer(CommonContent)); + EXPECT_FALSE(FS.addHardLink("/c/d/e", "/a/b")); +} + +TEST_F(InMemoryFileSystemTest, RecursiveIterationWithHardLink) { + std::error_code EC; + FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("content string")); + EXPECT_TRUE(FS.addHardLink("/c/d", "/a/b")); + auto I = vfs::recursive_directory_iterator(FS, "/", EC); + ASSERT_FALSE(EC); + std::vector<std::string> Nodes; + for (auto E = vfs::recursive_directory_iterator(); !EC && I != E; + I.increment(EC)) { + Nodes.push_back(getPosixPath(I->getName())); + } + EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/a", "/a/b", "/c", "/c/d")); +} + // 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 { |