FileCollectorTest.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. //===-- FileCollectorTest.cpp -----------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "gmock/gmock.h"
  9. #include "gtest/gtest.h"
  10. #include "llvm/Support/FileCollector.h"
  11. #include "llvm/Support/FileSystem.h"
  12. using namespace llvm;
  13. namespace llvm {
  14. namespace vfs {
  15. inline bool operator==(const llvm::vfs::YAMLVFSEntry &LHS,
  16. const llvm::vfs::YAMLVFSEntry &RHS) {
  17. return LHS.VPath == RHS.VPath && LHS.RPath == RHS.RPath;
  18. }
  19. } // namespace vfs
  20. } // namespace llvm
  21. namespace {
  22. class TestingFileCollector : public FileCollector {
  23. public:
  24. using FileCollector::FileCollector;
  25. using FileCollector::Root;
  26. using FileCollector::Seen;
  27. using FileCollector::SymlinkMap;
  28. using FileCollector::VFSWriter;
  29. bool hasSeen(StringRef fs) {
  30. return Seen.find(fs) != Seen.end();
  31. }
  32. };
  33. struct ScopedDir {
  34. SmallString<128> Path;
  35. ScopedDir(const Twine &Name, bool Unique = false) {
  36. std::error_code EC;
  37. if (Unique) {
  38. EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
  39. } else {
  40. Path = Name.str();
  41. EC = llvm::sys::fs::create_directory(Twine(Path));
  42. }
  43. if (EC)
  44. Path = "";
  45. EXPECT_FALSE(EC);
  46. // Ensure the path is the real path so tests can use it to compare against
  47. // realpath output.
  48. SmallString<128> RealPath;
  49. if (!llvm::sys::fs::real_path(Path, RealPath))
  50. Path.swap(RealPath);
  51. }
  52. ~ScopedDir() {
  53. if (Path != "") {
  54. EXPECT_FALSE(llvm::sys::fs::remove_directories(Path.str()));
  55. }
  56. }
  57. operator StringRef() { return Path.str(); }
  58. };
  59. struct ScopedLink {
  60. SmallString<128> Path;
  61. ScopedLink(const Twine &To, const Twine &From) {
  62. Path = From.str();
  63. std::error_code EC = sys::fs::create_link(To, From);
  64. if (EC)
  65. Path = "";
  66. EXPECT_FALSE(EC);
  67. }
  68. ~ScopedLink() {
  69. if (Path != "") {
  70. EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
  71. }
  72. }
  73. operator StringRef() { return Path.str(); }
  74. };
  75. struct ScopedFile {
  76. SmallString<128> Path;
  77. ScopedFile(const Twine &Name) {
  78. std::error_code EC;
  79. EC = llvm::sys::fs::createUniqueFile(Name, Path);
  80. if (EC)
  81. Path = "";
  82. EXPECT_FALSE(EC);
  83. }
  84. ~ScopedFile() {
  85. if (Path != "") {
  86. EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
  87. }
  88. }
  89. operator StringRef() { return Path.str(); }
  90. };
  91. } // end anonymous namespace
  92. TEST(FileCollectorTest, addFile) {
  93. ScopedDir root("add_file_root", true);
  94. std::string root_fs = root.Path.str();
  95. TestingFileCollector FileCollector(root_fs, root_fs);
  96. FileCollector.addFile("/path/to/a");
  97. FileCollector.addFile("/path/to/b");
  98. FileCollector.addFile("/path/to/c");
  99. // Make sure the root is correct.
  100. EXPECT_EQ(FileCollector.Root, root_fs);
  101. // Make sure we've seen all the added files.
  102. EXPECT_TRUE(FileCollector.hasSeen("/path/to/a"));
  103. EXPECT_TRUE(FileCollector.hasSeen("/path/to/b"));
  104. EXPECT_TRUE(FileCollector.hasSeen("/path/to/c"));
  105. // Make sure we've only seen the added files.
  106. EXPECT_FALSE(FileCollector.hasSeen("/path/to/d"));
  107. }
  108. TEST(FileCollectorTest, copyFiles) {
  109. ScopedDir file_root("file_root", true);
  110. ScopedFile a(file_root + "/aaa");
  111. ScopedFile b(file_root + "/bbb");
  112. ScopedFile c(file_root + "/ccc");
  113. // Create file collector and add files.
  114. ScopedDir root("copy_files_root", true);
  115. std::string root_fs = root.Path.str();
  116. TestingFileCollector FileCollector(root_fs, root_fs);
  117. FileCollector.addFile(a.Path);
  118. FileCollector.addFile(b.Path);
  119. FileCollector.addFile(c.Path);
  120. // Make sure we can copy the files.
  121. std::error_code ec = FileCollector.copyFiles(true);
  122. EXPECT_FALSE(ec);
  123. // Now add a bogus file and make sure we error out.
  124. FileCollector.addFile("/some/bogus/file");
  125. ec = FileCollector.copyFiles(true);
  126. EXPECT_TRUE(ec);
  127. // However, if stop_on_error is true the copy should still succeed.
  128. ec = FileCollector.copyFiles(false);
  129. EXPECT_FALSE(ec);
  130. }
  131. TEST(FileCollectorTest, recordAndConstructDirectory) {
  132. ScopedDir file_root("dir_root", true);
  133. ScopedDir subdir(file_root + "/subdir");
  134. ScopedDir subdir2(file_root + "/subdir2");
  135. ScopedFile a(subdir2 + "/a");
  136. // Create file collector and add files.
  137. ScopedDir root("copy_files_root", true);
  138. std::string root_fs = root.Path.str();
  139. TestingFileCollector FileCollector(root_fs, root_fs);
  140. FileCollector.addFile(a.Path);
  141. // The empty directory isn't seen until we add it.
  142. EXPECT_TRUE(FileCollector.hasSeen(a.Path));
  143. EXPECT_FALSE(FileCollector.hasSeen(subdir.Path));
  144. FileCollector.addFile(subdir.Path);
  145. EXPECT_TRUE(FileCollector.hasSeen(subdir.Path));
  146. // Make sure we can construct the directory.
  147. std::error_code ec = FileCollector.copyFiles(true);
  148. EXPECT_FALSE(ec);
  149. bool IsDirectory = false;
  150. llvm::SmallString<128> SubdirInRoot = root.Path;
  151. llvm::sys::path::append(SubdirInRoot,
  152. llvm::sys::path::relative_path(subdir.Path));
  153. ec = sys::fs::is_directory(SubdirInRoot, IsDirectory);
  154. EXPECT_FALSE(ec);
  155. ASSERT_TRUE(IsDirectory);
  156. }
  157. TEST(FileCollectorTest, recordVFSAccesses) {
  158. ScopedDir file_root("dir_root", true);
  159. ScopedDir subdir(file_root + "/subdir");
  160. ScopedDir subdir2(file_root + "/subdir2");
  161. ScopedFile a(subdir2 + "/a");
  162. ScopedFile b(file_root + "/b");
  163. ScopedDir subdir3(file_root + "/subdir3");
  164. ScopedFile subdir3a(subdir3 + "/aa");
  165. ScopedDir subdir3b(subdir3 + "/subdirb");
  166. {
  167. ScopedFile subdir3fileremoved(subdir3 + "/removed");
  168. }
  169. // Create file collector and add files.
  170. ScopedDir root("copy_files_root", true);
  171. std::string root_fs = root.Path.str();
  172. auto Collector = std::make_shared<TestingFileCollector>(root_fs, root_fs);
  173. auto VFS =
  174. FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);
  175. VFS->status(a.Path);
  176. EXPECT_TRUE(Collector->hasSeen(a.Path));
  177. VFS->openFileForRead(b.Path);
  178. EXPECT_TRUE(Collector->hasSeen(b.Path));
  179. VFS->status(subdir.Path);
  180. EXPECT_TRUE(Collector->hasSeen(subdir.Path));
  181. #ifndef _WIN32
  182. std::error_code EC;
  183. auto It = VFS->dir_begin(subdir3.Path, EC);
  184. EXPECT_FALSE(EC);
  185. EXPECT_TRUE(Collector->hasSeen(subdir3.Path));
  186. EXPECT_TRUE(Collector->hasSeen(subdir3a.Path));
  187. EXPECT_TRUE(Collector->hasSeen(subdir3b.Path));
  188. std::string RemovedFileName = (Twine(subdir3.Path) + "/removed").str();
  189. EXPECT_FALSE(Collector->hasSeen(RemovedFileName));
  190. #endif
  191. }
  192. #ifndef _WIN32
  193. TEST(FileCollectorTest, Symlinks) {
  194. // Root where the original files live.
  195. ScopedDir file_root("file_root", true);
  196. // Create some files in the file root.
  197. ScopedFile a(file_root + "/aaa");
  198. ScopedFile b(file_root + "/bbb");
  199. ScopedFile c(file_root + "/ccc");
  200. // Create a directory foo with file ddd.
  201. ScopedDir foo(file_root + "/foo");
  202. ScopedFile d(foo + "/ddd");
  203. // Create a file eee in the foo's parent directory.
  204. ScopedFile e(foo + "/../eee");
  205. // Create a symlink bar pointing to foo.
  206. ScopedLink symlink(file_root + "/foo", file_root + "/bar");
  207. // Root where files are copied to.
  208. ScopedDir reproducer_root("reproducer_root", true);
  209. std::string root_fs = reproducer_root.Path.str();
  210. TestingFileCollector FileCollector(root_fs, root_fs);
  211. // Add all the files to the collector.
  212. FileCollector.addFile(a.Path);
  213. FileCollector.addFile(b.Path);
  214. FileCollector.addFile(c.Path);
  215. FileCollector.addFile(d.Path);
  216. FileCollector.addFile(e.Path);
  217. FileCollector.addFile(file_root + "/bar/ddd");
  218. auto mapping = FileCollector.VFSWriter.getMappings();
  219. {
  220. // Make sure the common case works.
  221. std::string vpath = (file_root + "/aaa").str();
  222. std::string rpath = (reproducer_root.Path + file_root.Path + "/aaa").str();
  223. printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
  224. EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
  225. }
  226. {
  227. // Make sure the virtual path points to the real source path.
  228. std::string vpath = (file_root + "/bar/ddd").str();
  229. std::string rpath =
  230. (reproducer_root.Path + file_root.Path + "/foo/ddd").str();
  231. printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
  232. EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
  233. }
  234. {
  235. // Make sure that .. is removed from the source path.
  236. std::string vpath = (file_root + "/eee").str();
  237. std::string rpath = (reproducer_root.Path + file_root.Path + "/eee").str();
  238. printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
  239. EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
  240. }
  241. }
  242. TEST(FileCollectorTest, recordVFSSymlinkAccesses) {
  243. ScopedDir file_root("dir_root", true);
  244. ScopedFile a(file_root + "/a");
  245. ScopedLink symlink(file_root + "/a", file_root + "/b");
  246. // Create file collector and add files.
  247. ScopedDir root("copy_files_root", true);
  248. std::string root_fs = root.Path.str();
  249. auto Collector = std::make_shared<TestingFileCollector>(root_fs, root_fs);
  250. auto VFS =
  251. FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);
  252. SmallString<256> Output;
  253. VFS->getRealPath(symlink.Path, Output);
  254. EXPECT_TRUE(Collector->hasSeen(a.Path));
  255. EXPECT_TRUE(Collector->hasSeen(symlink.Path));
  256. }
  257. #endif