VirtualFileSystemTest.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. //===- unittests/Basic/VirtualFileSystem.cpp ---------------- VFS tests ---===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "clang/Basic/VirtualFileSystem.h"
  10. #include "llvm/Support/Path.h"
  11. #include "gtest/gtest.h"
  12. #include <map>
  13. using namespace clang;
  14. using namespace llvm;
  15. using llvm::sys::fs::UniqueID;
  16. namespace {
  17. class DummyFileSystem : public vfs::FileSystem {
  18. int FSID; // used to produce UniqueIDs
  19. int FileID; // used to produce UniqueIDs
  20. std::map<std::string, vfs::Status> FilesAndDirs;
  21. static int getNextFSID() {
  22. static int Count = 0;
  23. return Count++;
  24. }
  25. public:
  26. DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
  27. ErrorOr<vfs::Status> status(const Twine &Path) {
  28. std::map<std::string, vfs::Status>::iterator I =
  29. FilesAndDirs.find(Path.str());
  30. if (I == FilesAndDirs.end())
  31. return error_code(errc::no_such_file_or_directory, posix_category());
  32. return I->second;
  33. }
  34. error_code openFileForRead(const Twine &Path, OwningPtr<vfs::File> &Result) {
  35. llvm_unreachable("unimplemented");
  36. }
  37. error_code getBufferForFile(const Twine &Name,
  38. OwningPtr<MemoryBuffer> &Result,
  39. int64_t FileSize = -1,
  40. bool RequiresNullTerminator = true) {
  41. llvm_unreachable("unimplemented");
  42. }
  43. void addEntry(StringRef Path, const vfs::Status &Status) {
  44. FilesAndDirs[Path] = Status;
  45. }
  46. void addRegularFile(StringRef Path, sys::fs::perms Perms=sys::fs::all_all) {
  47. vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
  48. 0, 0, 1024, sys::fs::file_type::regular_file, Perms);
  49. addEntry(Path, S);
  50. }
  51. void addDirectory(StringRef Path, sys::fs::perms Perms=sys::fs::all_all) {
  52. vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
  53. 0, 0, 0, sys::fs::file_type::directory_file, Perms);
  54. addEntry(Path, S);
  55. }
  56. void addSymlink(StringRef Path) {
  57. vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
  58. 0, 0, 0, sys::fs::file_type::symlink_file, sys::fs::all_all);
  59. addEntry(Path, S);
  60. }
  61. };
  62. } // end anonymous namespace
  63. TEST(VirtualFileSystemTest, statusQueries) {
  64. IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
  65. ErrorOr<vfs::Status> Status((error_code()));
  66. D->addRegularFile("/foo");
  67. Status = D->status("/foo");
  68. ASSERT_EQ(errc::success, Status.getError());
  69. EXPECT_TRUE(Status->isStatusKnown());
  70. EXPECT_FALSE(Status->isDirectory());
  71. EXPECT_TRUE(Status->isRegularFile());
  72. EXPECT_FALSE(Status->isSymlink());
  73. EXPECT_FALSE(Status->isOther());
  74. EXPECT_TRUE(Status->exists());
  75. D->addDirectory("/bar");
  76. Status = D->status("/bar");
  77. ASSERT_EQ(errc::success, Status.getError());
  78. EXPECT_TRUE(Status->isStatusKnown());
  79. EXPECT_TRUE(Status->isDirectory());
  80. EXPECT_FALSE(Status->isRegularFile());
  81. EXPECT_FALSE(Status->isSymlink());
  82. EXPECT_FALSE(Status->isOther());
  83. EXPECT_TRUE(Status->exists());
  84. D->addSymlink("/baz");
  85. Status = D->status("/baz");
  86. ASSERT_EQ(errc::success, Status.getError());
  87. EXPECT_TRUE(Status->isStatusKnown());
  88. EXPECT_FALSE(Status->isDirectory());
  89. EXPECT_FALSE(Status->isRegularFile());
  90. EXPECT_TRUE(Status->isSymlink());
  91. EXPECT_FALSE(Status->isOther());
  92. EXPECT_TRUE(Status->exists());
  93. EXPECT_TRUE(Status->equivalent(*Status));
  94. ErrorOr<vfs::Status> Status2 = D->status("/foo");
  95. ASSERT_EQ(errc::success, Status2.getError());
  96. EXPECT_FALSE(Status->equivalent(*Status2));
  97. }
  98. TEST(VirtualFileSystemTest, baseOnlyOverlay) {
  99. IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
  100. ErrorOr<vfs::Status> Status((error_code()));
  101. EXPECT_FALSE(Status = D->status("/foo"));
  102. IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
  103. EXPECT_FALSE(Status = O->status("/foo"));
  104. D->addRegularFile("/foo");
  105. Status = D->status("/foo");
  106. EXPECT_EQ(errc::success, Status.getError());
  107. ErrorOr<vfs::Status> Status2((error_code()));
  108. Status2 = O->status("/foo");
  109. EXPECT_EQ(errc::success, Status2.getError());
  110. EXPECT_TRUE(Status->equivalent(*Status2));
  111. }
  112. TEST(VirtualFileSystemTest, overlayFiles) {
  113. IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
  114. IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
  115. IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
  116. IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(Base));
  117. O->pushOverlay(Middle);
  118. O->pushOverlay(Top);
  119. ErrorOr<vfs::Status> Status1((error_code())), Status2((error_code())),
  120. Status3((error_code())), StatusB((error_code())),
  121. StatusM((error_code())), StatusT((error_code()));
  122. Base->addRegularFile("/foo");
  123. StatusB = Base->status("/foo");
  124. ASSERT_EQ(errc::success, StatusB.getError());
  125. Status1 = O->status("/foo");
  126. ASSERT_EQ(errc::success, Status1.getError());
  127. Middle->addRegularFile("/foo");
  128. StatusM = Middle->status("/foo");
  129. ASSERT_EQ(errc::success, StatusM.getError());
  130. Status2 = O->status("/foo");
  131. ASSERT_EQ(errc::success, Status2.getError());
  132. Top->addRegularFile("/foo");
  133. StatusT = Top->status("/foo");
  134. ASSERT_EQ(errc::success, StatusT.getError());
  135. Status3 = O->status("/foo");
  136. ASSERT_EQ(errc::success, Status3.getError());
  137. EXPECT_TRUE(Status1->equivalent(*StatusB));
  138. EXPECT_TRUE(Status2->equivalent(*StatusM));
  139. EXPECT_TRUE(Status3->equivalent(*StatusT));
  140. EXPECT_FALSE(Status1->equivalent(*Status2));
  141. EXPECT_FALSE(Status2->equivalent(*Status3));
  142. EXPECT_FALSE(Status1->equivalent(*Status3));
  143. }
  144. TEST(VirtualFileSystemTest, overlayDirsNonMerged) {
  145. IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
  146. IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
  147. IntrusiveRefCntPtr<vfs::OverlayFileSystem>
  148. O(new vfs::OverlayFileSystem(Lower));
  149. O->pushOverlay(Upper);
  150. Lower->addDirectory("/lower-only");
  151. Upper->addDirectory("/upper-only");
  152. // non-merged paths should be the same
  153. ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
  154. ASSERT_EQ(errc::success, Status1.getError());
  155. ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
  156. ASSERT_EQ(errc::success, Status2.getError());
  157. EXPECT_TRUE(Status1->equivalent(*Status2));
  158. Status1 = Upper->status("/upper-only");
  159. ASSERT_EQ(errc::success, Status1.getError());
  160. Status2 = O->status("/upper-only");
  161. ASSERT_EQ(errc::success, Status2.getError());
  162. EXPECT_TRUE(Status1->equivalent(*Status2));
  163. }
  164. TEST(VirtualFileSystemTest, mergedDirPermissions) {
  165. // merged directories get the permissions of the upper dir
  166. IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
  167. IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
  168. IntrusiveRefCntPtr<vfs::OverlayFileSystem>
  169. O(new vfs::OverlayFileSystem(Lower));
  170. O->pushOverlay(Upper);
  171. ErrorOr<vfs::Status> Status((error_code()));
  172. Lower->addDirectory("/both", sys::fs::owner_read);
  173. Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
  174. Status = O->status("/both");
  175. ASSERT_EQ(errc::success, Status.getError());
  176. EXPECT_EQ(0740, Status->getPermissions());
  177. // permissions (as usual) are not recursively applied
  178. Lower->addRegularFile("/both/foo", sys::fs::owner_read);
  179. Upper->addRegularFile("/both/bar", sys::fs::owner_write);
  180. Status = O->status("/both/foo");
  181. ASSERT_EQ(errc::success, Status.getError());
  182. EXPECT_EQ(0400, Status->getPermissions());
  183. Status = O->status("/both/bar");
  184. ASSERT_EQ(errc::success, Status.getError());
  185. EXPECT_EQ(0200, Status->getPermissions());
  186. }