186814bf6SAlex Lorenz //===-- FileCollectorTest.cpp -----------------------------------*- C++ -*-===//
286814bf6SAlex Lorenz //
386814bf6SAlex Lorenz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
486814bf6SAlex Lorenz // See https://llvm.org/LICENSE.txt for license information.
586814bf6SAlex Lorenz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
686814bf6SAlex Lorenz //
786814bf6SAlex Lorenz //===----------------------------------------------------------------------===//
886814bf6SAlex Lorenz
986814bf6SAlex Lorenz #include "gmock/gmock.h"
1086814bf6SAlex Lorenz #include "gtest/gtest.h"
1186814bf6SAlex Lorenz
1286814bf6SAlex Lorenz #include "llvm/Support/FileCollector.h"
1386814bf6SAlex Lorenz #include "llvm/Support/FileSystem.h"
14fad75598SSergej Jaskiewicz #include "llvm/Testing/Support/SupportHelpers.h"
1586814bf6SAlex Lorenz
1686814bf6SAlex Lorenz using namespace llvm;
17fad75598SSergej Jaskiewicz using llvm::unittest::TempDir;
18fad75598SSergej Jaskiewicz using llvm::unittest::TempFile;
19fad75598SSergej Jaskiewicz using llvm::unittest::TempLink;
2086814bf6SAlex Lorenz
2186814bf6SAlex Lorenz namespace llvm {
2286814bf6SAlex Lorenz namespace vfs {
operator ==(const llvm::vfs::YAMLVFSEntry & LHS,const llvm::vfs::YAMLVFSEntry & RHS)2386814bf6SAlex Lorenz inline bool operator==(const llvm::vfs::YAMLVFSEntry &LHS,
2486814bf6SAlex Lorenz const llvm::vfs::YAMLVFSEntry &RHS) {
2586814bf6SAlex Lorenz return LHS.VPath == RHS.VPath && LHS.RPath == RHS.RPath;
2686814bf6SAlex Lorenz }
2786814bf6SAlex Lorenz } // namespace vfs
2886814bf6SAlex Lorenz } // namespace llvm
2986814bf6SAlex Lorenz
3086814bf6SAlex Lorenz namespace {
3186814bf6SAlex Lorenz class TestingFileCollector : public FileCollector {
3286814bf6SAlex Lorenz public:
3386814bf6SAlex Lorenz using FileCollector::FileCollector;
343e4e0478SJonas Devlieghere using FileCollector::Root;
353e4e0478SJonas Devlieghere using FileCollector::Seen;
363e4e0478SJonas Devlieghere using FileCollector::VFSWriter;
3786814bf6SAlex Lorenz
hasSeen(StringRef fs)383e4e0478SJonas Devlieghere bool hasSeen(StringRef fs) {
393e4e0478SJonas Devlieghere return Seen.find(fs) != Seen.end();
4086814bf6SAlex Lorenz }
4186814bf6SAlex Lorenz };
4286814bf6SAlex Lorenz
4386814bf6SAlex Lorenz } // end anonymous namespace
4486814bf6SAlex Lorenz
TEST(FileCollectorTest,addFile)453e4e0478SJonas Devlieghere TEST(FileCollectorTest, addFile) {
46fad75598SSergej Jaskiewicz TempDir root("add_file_root", /*Unique*/ true);
47fad75598SSergej Jaskiewicz std::string root_fs(root.path());
483e4e0478SJonas Devlieghere TestingFileCollector FileCollector(root_fs, root_fs);
4986814bf6SAlex Lorenz
503e4e0478SJonas Devlieghere FileCollector.addFile("/path/to/a");
513e4e0478SJonas Devlieghere FileCollector.addFile("/path/to/b");
523e4e0478SJonas Devlieghere FileCollector.addFile("/path/to/c");
5386814bf6SAlex Lorenz
5486814bf6SAlex Lorenz // Make sure the root is correct.
553e4e0478SJonas Devlieghere EXPECT_EQ(FileCollector.Root, root_fs);
5686814bf6SAlex Lorenz
5786814bf6SAlex Lorenz // Make sure we've seen all the added files.
583e4e0478SJonas Devlieghere EXPECT_TRUE(FileCollector.hasSeen("/path/to/a"));
593e4e0478SJonas Devlieghere EXPECT_TRUE(FileCollector.hasSeen("/path/to/b"));
603e4e0478SJonas Devlieghere EXPECT_TRUE(FileCollector.hasSeen("/path/to/c"));
6186814bf6SAlex Lorenz
6286814bf6SAlex Lorenz // Make sure we've only seen the added files.
633e4e0478SJonas Devlieghere EXPECT_FALSE(FileCollector.hasSeen("/path/to/d"));
6486814bf6SAlex Lorenz }
6586814bf6SAlex Lorenz
TEST(FileCollectorTest,addDirectory)664151f2d0SJonas Devlieghere TEST(FileCollectorTest, addDirectory) {
67fad75598SSergej Jaskiewicz TempDir file_root("file_root", /*Unique*/ true);
684151f2d0SJonas Devlieghere
69fad75598SSergej Jaskiewicz llvm::SmallString<128> aaa(file_root.path());
704151f2d0SJonas Devlieghere llvm::sys::path::append(aaa, "aaa");
71fad75598SSergej Jaskiewicz TempFile a(aaa.str());
724151f2d0SJonas Devlieghere
73fad75598SSergej Jaskiewicz llvm::SmallString<128> bbb(file_root.path());
744151f2d0SJonas Devlieghere llvm::sys::path::append(bbb, "bbb");
75fad75598SSergej Jaskiewicz TempFile b(bbb.str());
764151f2d0SJonas Devlieghere
77fad75598SSergej Jaskiewicz llvm::SmallString<128> ccc(file_root.path());
784151f2d0SJonas Devlieghere llvm::sys::path::append(ccc, "ccc");
79fad75598SSergej Jaskiewicz TempFile c(ccc.str());
804151f2d0SJonas Devlieghere
81fad75598SSergej Jaskiewicz std::string root_fs(file_root.path());
824151f2d0SJonas Devlieghere TestingFileCollector FileCollector(root_fs, root_fs);
834151f2d0SJonas Devlieghere
84fad75598SSergej Jaskiewicz FileCollector.addDirectory(file_root.path());
854151f2d0SJonas Devlieghere
864151f2d0SJonas Devlieghere // Make sure the root is correct.
874151f2d0SJonas Devlieghere EXPECT_EQ(FileCollector.Root, root_fs);
884151f2d0SJonas Devlieghere
894151f2d0SJonas Devlieghere // Make sure we've seen all the added files.
90fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(a.path()));
91fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(b.path()));
92fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(c.path()));
934151f2d0SJonas Devlieghere
944151f2d0SJonas Devlieghere // Make sure we've only seen the added files.
95fad75598SSergej Jaskiewicz llvm::SmallString<128> ddd(file_root.path());
964151f2d0SJonas Devlieghere llvm::sys::path::append(ddd, "ddd");
97*224d8153SSergej Jaskiewicz TempFile d(ddd);
98fad75598SSergej Jaskiewicz EXPECT_FALSE(FileCollector.hasSeen(d.path()));
994151f2d0SJonas Devlieghere }
1004151f2d0SJonas Devlieghere
TEST(FileCollectorTest,copyFiles)1013e4e0478SJonas Devlieghere TEST(FileCollectorTest, copyFiles) {
102fad75598SSergej Jaskiewicz TempDir file_root("file_root", /*Unique*/ true);
103fad75598SSergej Jaskiewicz TempFile a(file_root.path("aaa"));
104fad75598SSergej Jaskiewicz TempFile b(file_root.path("bbb"));
105fad75598SSergej Jaskiewicz TempFile c(file_root.path("ccc"));
10686814bf6SAlex Lorenz
10786814bf6SAlex Lorenz // Create file collector and add files.
108fad75598SSergej Jaskiewicz TempDir root("copy_files_root", /*Unique*/ true);
109fad75598SSergej Jaskiewicz std::string root_fs(root.path());
1103e4e0478SJonas Devlieghere TestingFileCollector FileCollector(root_fs, root_fs);
111fad75598SSergej Jaskiewicz FileCollector.addFile(a.path());
112fad75598SSergej Jaskiewicz FileCollector.addFile(b.path());
113fad75598SSergej Jaskiewicz FileCollector.addFile(c.path());
11486814bf6SAlex Lorenz
11586814bf6SAlex Lorenz // Make sure we can copy the files.
1163e4e0478SJonas Devlieghere std::error_code ec = FileCollector.copyFiles(true);
11786814bf6SAlex Lorenz EXPECT_FALSE(ec);
11886814bf6SAlex Lorenz
11986814bf6SAlex Lorenz // Now add a bogus file and make sure we error out.
1203e4e0478SJonas Devlieghere FileCollector.addFile("/some/bogus/file");
1213e4e0478SJonas Devlieghere ec = FileCollector.copyFiles(true);
12286814bf6SAlex Lorenz EXPECT_TRUE(ec);
12386814bf6SAlex Lorenz
12486814bf6SAlex Lorenz // However, if stop_on_error is true the copy should still succeed.
1253e4e0478SJonas Devlieghere ec = FileCollector.copyFiles(false);
12686814bf6SAlex Lorenz EXPECT_FALSE(ec);
12786814bf6SAlex Lorenz }
12886814bf6SAlex Lorenz
TEST(FileCollectorTest,recordAndConstructDirectory)129b680422eSAlex Lorenz TEST(FileCollectorTest, recordAndConstructDirectory) {
130fad75598SSergej Jaskiewicz TempDir file_root("dir_root", /*Unique*/ true);
131fad75598SSergej Jaskiewicz TempDir subdir(file_root.path("subdir"));
132fad75598SSergej Jaskiewicz TempDir subdir2(file_root.path("subdir2"));
133fad75598SSergej Jaskiewicz TempFile a(subdir2.path("a"));
134b680422eSAlex Lorenz
135b680422eSAlex Lorenz // Create file collector and add files.
136fad75598SSergej Jaskiewicz TempDir root("copy_files_root", /*Unique*/ true);
137fad75598SSergej Jaskiewicz std::string root_fs(root.path());
138b680422eSAlex Lorenz TestingFileCollector FileCollector(root_fs, root_fs);
139fad75598SSergej Jaskiewicz FileCollector.addFile(a.path());
140b680422eSAlex Lorenz
141b680422eSAlex Lorenz // The empty directory isn't seen until we add it.
142fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(a.path()));
143fad75598SSergej Jaskiewicz EXPECT_FALSE(FileCollector.hasSeen(subdir.path()));
144b680422eSAlex Lorenz
145fad75598SSergej Jaskiewicz FileCollector.addFile(subdir.path());
146fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(subdir.path()));
147b680422eSAlex Lorenz
148b680422eSAlex Lorenz // Make sure we can construct the directory.
149b680422eSAlex Lorenz std::error_code ec = FileCollector.copyFiles(true);
150b680422eSAlex Lorenz EXPECT_FALSE(ec);
151b680422eSAlex Lorenz bool IsDirectory = false;
152fad75598SSergej Jaskiewicz llvm::SmallString<128> SubdirInRoot = root.path();
153b680422eSAlex Lorenz llvm::sys::path::append(SubdirInRoot,
154fad75598SSergej Jaskiewicz llvm::sys::path::relative_path(subdir.path()));
155b680422eSAlex Lorenz ec = sys::fs::is_directory(SubdirInRoot, IsDirectory);
156b680422eSAlex Lorenz EXPECT_FALSE(ec);
157b680422eSAlex Lorenz ASSERT_TRUE(IsDirectory);
158b680422eSAlex Lorenz }
159b680422eSAlex Lorenz
TEST(FileCollectorTest,recordVFSAccesses)1609e38f4d9SAlex Lorenz TEST(FileCollectorTest, recordVFSAccesses) {
161fad75598SSergej Jaskiewicz TempDir file_root("dir_root", /*Unique*/ true);
162fad75598SSergej Jaskiewicz TempDir subdir(file_root.path("subdir"));
163fad75598SSergej Jaskiewicz TempDir subdir2(file_root.path("subdir2"));
164fad75598SSergej Jaskiewicz TempFile a(subdir2.path("a"));
165fad75598SSergej Jaskiewicz TempFile b(file_root.path("b"));
166fad75598SSergej Jaskiewicz TempDir subdir3(file_root.path("subdir3"));
167fad75598SSergej Jaskiewicz TempFile subdir3a(subdir3.path("aa"));
168fad75598SSergej Jaskiewicz TempDir subdir3b(subdir3.path("subdirb"));
169fad75598SSergej Jaskiewicz { TempFile subdir3fileremoved(subdir3.path("removed")); }
1709e38f4d9SAlex Lorenz
1719e38f4d9SAlex Lorenz // Create file collector and add files.
172fad75598SSergej Jaskiewicz TempDir root("copy_files_root", /*Unique*/ true);
173fad75598SSergej Jaskiewicz std::string root_fs(root.path());
1749e38f4d9SAlex Lorenz auto Collector = std::make_shared<TestingFileCollector>(root_fs, root_fs);
1759e38f4d9SAlex Lorenz auto VFS =
1769e38f4d9SAlex Lorenz FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);
177fad75598SSergej Jaskiewicz VFS->status(a.path());
178fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(a.path()));
1799e38f4d9SAlex Lorenz
180fad75598SSergej Jaskiewicz VFS->openFileForRead(b.path());
181fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(b.path()));
1829e38f4d9SAlex Lorenz
183fad75598SSergej Jaskiewicz VFS->status(subdir.path());
184fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(subdir.path()));
1859e38f4d9SAlex Lorenz
186a171f6c9SAlex Lorenz #ifndef _WIN32
1879e38f4d9SAlex Lorenz std::error_code EC;
188fad75598SSergej Jaskiewicz auto It = VFS->dir_begin(subdir3.path(), EC);
1899e38f4d9SAlex Lorenz EXPECT_FALSE(EC);
190fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(subdir3.path()));
191fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(subdir3a.path()));
192fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(subdir3b.path()));
193fad75598SSergej Jaskiewicz std::string RemovedFileName((Twine(subdir3.path("removed"))).str());
1949e38f4d9SAlex Lorenz EXPECT_FALSE(Collector->hasSeen(RemovedFileName));
195a171f6c9SAlex Lorenz #endif
1969e38f4d9SAlex Lorenz }
1979e38f4d9SAlex Lorenz
19886814bf6SAlex Lorenz #ifndef _WIN32
TEST(FileCollectorTest,Symlinks)19986814bf6SAlex Lorenz TEST(FileCollectorTest, Symlinks) {
20086814bf6SAlex Lorenz // Root where the original files live.
201fad75598SSergej Jaskiewicz TempDir file_root("file_root", /*Unique*/ true);
20286814bf6SAlex Lorenz
20386814bf6SAlex Lorenz // Create some files in the file root.
204fad75598SSergej Jaskiewicz TempFile a(file_root.path("aaa"));
205fad75598SSergej Jaskiewicz TempFile b(file_root.path("bbb"));
206fad75598SSergej Jaskiewicz TempFile c(file_root.path("ccc"));
20786814bf6SAlex Lorenz
20886814bf6SAlex Lorenz // Create a directory foo with file ddd.
209fad75598SSergej Jaskiewicz TempDir foo(file_root.path("foo"));
210fad75598SSergej Jaskiewicz TempFile d(foo.path("ddd"));
21186814bf6SAlex Lorenz
21286814bf6SAlex Lorenz // Create a file eee in the foo's parent directory.
213fad75598SSergej Jaskiewicz TempFile e(foo.path("../eee"));
21486814bf6SAlex Lorenz
21586814bf6SAlex Lorenz // Create a symlink bar pointing to foo.
216fad75598SSergej Jaskiewicz TempLink symlink(file_root.path("foo"), file_root.path("bar"));
21786814bf6SAlex Lorenz
21886814bf6SAlex Lorenz // Root where files are copied to.
219fad75598SSergej Jaskiewicz TempDir reproducer_root("reproducer_root", /*Unique*/ true);
220fad75598SSergej Jaskiewicz std::string root_fs(reproducer_root.path());
2213e4e0478SJonas Devlieghere TestingFileCollector FileCollector(root_fs, root_fs);
22286814bf6SAlex Lorenz
22386814bf6SAlex Lorenz // Add all the files to the collector.
224fad75598SSergej Jaskiewicz FileCollector.addFile(a.path());
225fad75598SSergej Jaskiewicz FileCollector.addFile(b.path());
226fad75598SSergej Jaskiewicz FileCollector.addFile(c.path());
227fad75598SSergej Jaskiewicz FileCollector.addFile(d.path());
228fad75598SSergej Jaskiewicz FileCollector.addFile(e.path());
229fad75598SSergej Jaskiewicz FileCollector.addFile(file_root.path() + "/bar/ddd");
23086814bf6SAlex Lorenz
2313e4e0478SJonas Devlieghere auto mapping = FileCollector.VFSWriter.getMappings();
23286814bf6SAlex Lorenz
23386814bf6SAlex Lorenz {
23486814bf6SAlex Lorenz // Make sure the common case works.
235fad75598SSergej Jaskiewicz std::string vpath = (file_root.path() + "/aaa").str();
236fad75598SSergej Jaskiewicz std::string rpath =
237fad75598SSergej Jaskiewicz (reproducer_root.path() + file_root.path() + "/aaa").str();
23886814bf6SAlex Lorenz printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
23986814bf6SAlex Lorenz EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
24086814bf6SAlex Lorenz }
24186814bf6SAlex Lorenz
24286814bf6SAlex Lorenz {
24386814bf6SAlex Lorenz // Make sure the virtual path points to the real source path.
244fad75598SSergej Jaskiewicz std::string vpath = (file_root.path() + "/bar/ddd").str();
24586814bf6SAlex Lorenz std::string rpath =
246fad75598SSergej Jaskiewicz (reproducer_root.path() + file_root.path() + "/foo/ddd").str();
24786814bf6SAlex Lorenz printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
24886814bf6SAlex Lorenz EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
24986814bf6SAlex Lorenz }
25086814bf6SAlex Lorenz
25186814bf6SAlex Lorenz {
25286814bf6SAlex Lorenz // Make sure that .. is removed from the source path.
253fad75598SSergej Jaskiewicz std::string vpath = (file_root.path() + "/eee").str();
254fad75598SSergej Jaskiewicz std::string rpath =
255fad75598SSergej Jaskiewicz (reproducer_root.path() + file_root.path() + "/eee").str();
25686814bf6SAlex Lorenz printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
25786814bf6SAlex Lorenz EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
25886814bf6SAlex Lorenz }
25986814bf6SAlex Lorenz }
2609e38f4d9SAlex Lorenz
TEST(FileCollectorTest,recordVFSSymlinkAccesses)2619e38f4d9SAlex Lorenz TEST(FileCollectorTest, recordVFSSymlinkAccesses) {
262fad75598SSergej Jaskiewicz TempDir file_root("dir_root", /*Unique*/ true);
263fad75598SSergej Jaskiewicz TempFile a(file_root.path("a"));
264fad75598SSergej Jaskiewicz TempLink symlink(file_root.path("a"), file_root.path("b"));
2659e38f4d9SAlex Lorenz
2669e38f4d9SAlex Lorenz // Create file collector and add files.
267fad75598SSergej Jaskiewicz TempDir root("copy_files_root", true);
268fad75598SSergej Jaskiewicz std::string root_fs(root.path());
2699e38f4d9SAlex Lorenz auto Collector = std::make_shared<TestingFileCollector>(root_fs, root_fs);
2709e38f4d9SAlex Lorenz auto VFS =
2719e38f4d9SAlex Lorenz FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);
2729e38f4d9SAlex Lorenz SmallString<256> Output;
273fad75598SSergej Jaskiewicz VFS->getRealPath(symlink.path(), Output);
274fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(a.path()));
275fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(symlink.path()));
2769e38f4d9SAlex Lorenz }
27786814bf6SAlex Lorenz #endif
278