aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Basic/VirtualFileSystemTest.cpp
diff options
context:
space:
mode:
authorIlya Biryukov <ibiryukov@google.com>2018-09-04 14:15:53 +0000
committerIlya Biryukov <ibiryukov@google.com>2018-09-04 14:15:53 +0000
commitd5554c512de686a1c158370fe264648f079b89a2 (patch)
tree87464b83dd50f29ec59775d67cc4b37775397138 /clang/unittests/Basic/VirtualFileSystemTest.cpp
parent6cb12444ccc40a052431f99b1b2834b2f96cad61 (diff)
downloadllvm-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.cpp114
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 {