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)38*b595eb83SKazu Hirata bool hasSeen(StringRef fs) { return Seen.contains(fs); }
3986814bf6SAlex Lorenz };
4086814bf6SAlex Lorenz
4186814bf6SAlex Lorenz } // end anonymous namespace
4286814bf6SAlex Lorenz
TEST(FileCollectorTest,addFile)433e4e0478SJonas Devlieghere TEST(FileCollectorTest, addFile) {
44fad75598SSergej Jaskiewicz TempDir root("add_file_root", /*Unique*/ true);
45fad75598SSergej Jaskiewicz std::string root_fs(root.path());
463e4e0478SJonas Devlieghere TestingFileCollector FileCollector(root_fs, root_fs);
4786814bf6SAlex Lorenz
483e4e0478SJonas Devlieghere FileCollector.addFile("/path/to/a");
493e4e0478SJonas Devlieghere FileCollector.addFile("/path/to/b");
503e4e0478SJonas Devlieghere FileCollector.addFile("/path/to/c");
5186814bf6SAlex Lorenz
5286814bf6SAlex Lorenz // Make sure the root is correct.
533e4e0478SJonas Devlieghere EXPECT_EQ(FileCollector.Root, root_fs);
5486814bf6SAlex Lorenz
5586814bf6SAlex Lorenz // Make sure we've seen all the added files.
563e4e0478SJonas Devlieghere EXPECT_TRUE(FileCollector.hasSeen("/path/to/a"));
573e4e0478SJonas Devlieghere EXPECT_TRUE(FileCollector.hasSeen("/path/to/b"));
583e4e0478SJonas Devlieghere EXPECT_TRUE(FileCollector.hasSeen("/path/to/c"));
5986814bf6SAlex Lorenz
6086814bf6SAlex Lorenz // Make sure we've only seen the added files.
613e4e0478SJonas Devlieghere EXPECT_FALSE(FileCollector.hasSeen("/path/to/d"));
6286814bf6SAlex Lorenz }
6386814bf6SAlex Lorenz
TEST(FileCollectorTest,addDirectory)644151f2d0SJonas Devlieghere TEST(FileCollectorTest, addDirectory) {
65fad75598SSergej Jaskiewicz TempDir file_root("file_root", /*Unique*/ true);
664151f2d0SJonas Devlieghere
67fad75598SSergej Jaskiewicz llvm::SmallString<128> aaa(file_root.path());
684151f2d0SJonas Devlieghere llvm::sys::path::append(aaa, "aaa");
69fad75598SSergej Jaskiewicz TempFile a(aaa.str());
704151f2d0SJonas Devlieghere
71fad75598SSergej Jaskiewicz llvm::SmallString<128> bbb(file_root.path());
724151f2d0SJonas Devlieghere llvm::sys::path::append(bbb, "bbb");
73fad75598SSergej Jaskiewicz TempFile b(bbb.str());
744151f2d0SJonas Devlieghere
75fad75598SSergej Jaskiewicz llvm::SmallString<128> ccc(file_root.path());
764151f2d0SJonas Devlieghere llvm::sys::path::append(ccc, "ccc");
77fad75598SSergej Jaskiewicz TempFile c(ccc.str());
784151f2d0SJonas Devlieghere
79fad75598SSergej Jaskiewicz std::string root_fs(file_root.path());
804151f2d0SJonas Devlieghere TestingFileCollector FileCollector(root_fs, root_fs);
814151f2d0SJonas Devlieghere
82fad75598SSergej Jaskiewicz FileCollector.addDirectory(file_root.path());
834151f2d0SJonas Devlieghere
844151f2d0SJonas Devlieghere // Make sure the root is correct.
854151f2d0SJonas Devlieghere EXPECT_EQ(FileCollector.Root, root_fs);
864151f2d0SJonas Devlieghere
874151f2d0SJonas Devlieghere // Make sure we've seen all the added files.
88fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(a.path()));
89fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(b.path()));
90fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(c.path()));
914151f2d0SJonas Devlieghere
924151f2d0SJonas Devlieghere // Make sure we've only seen the added files.
93fad75598SSergej Jaskiewicz llvm::SmallString<128> ddd(file_root.path());
944151f2d0SJonas Devlieghere llvm::sys::path::append(ddd, "ddd");
95224d8153SSergej Jaskiewicz TempFile d(ddd);
96fad75598SSergej Jaskiewicz EXPECT_FALSE(FileCollector.hasSeen(d.path()));
974151f2d0SJonas Devlieghere }
984151f2d0SJonas Devlieghere
TEST(FileCollectorTest,copyFiles)993e4e0478SJonas Devlieghere TEST(FileCollectorTest, copyFiles) {
100fad75598SSergej Jaskiewicz TempDir file_root("file_root", /*Unique*/ true);
101fad75598SSergej Jaskiewicz TempFile a(file_root.path("aaa"));
102fad75598SSergej Jaskiewicz TempFile b(file_root.path("bbb"));
103fad75598SSergej Jaskiewicz TempFile c(file_root.path("ccc"));
10486814bf6SAlex Lorenz
10586814bf6SAlex Lorenz // Create file collector and add files.
106fad75598SSergej Jaskiewicz TempDir root("copy_files_root", /*Unique*/ true);
107fad75598SSergej Jaskiewicz std::string root_fs(root.path());
1083e4e0478SJonas Devlieghere TestingFileCollector FileCollector(root_fs, root_fs);
109fad75598SSergej Jaskiewicz FileCollector.addFile(a.path());
110fad75598SSergej Jaskiewicz FileCollector.addFile(b.path());
111fad75598SSergej Jaskiewicz FileCollector.addFile(c.path());
11286814bf6SAlex Lorenz
11386814bf6SAlex Lorenz // Make sure we can copy the files.
1143e4e0478SJonas Devlieghere std::error_code ec = FileCollector.copyFiles(true);
11586814bf6SAlex Lorenz EXPECT_FALSE(ec);
11686814bf6SAlex Lorenz
11786814bf6SAlex Lorenz // Now add a bogus file and make sure we error out.
1183e4e0478SJonas Devlieghere FileCollector.addFile("/some/bogus/file");
1193e4e0478SJonas Devlieghere ec = FileCollector.copyFiles(true);
12086814bf6SAlex Lorenz EXPECT_TRUE(ec);
12186814bf6SAlex Lorenz
12286814bf6SAlex Lorenz // However, if stop_on_error is true the copy should still succeed.
1233e4e0478SJonas Devlieghere ec = FileCollector.copyFiles(false);
12486814bf6SAlex Lorenz EXPECT_FALSE(ec);
12586814bf6SAlex Lorenz }
12686814bf6SAlex Lorenz
TEST(FileCollectorTest,recordAndConstructDirectory)127b680422eSAlex Lorenz TEST(FileCollectorTest, recordAndConstructDirectory) {
128fad75598SSergej Jaskiewicz TempDir file_root("dir_root", /*Unique*/ true);
129fad75598SSergej Jaskiewicz TempDir subdir(file_root.path("subdir"));
130fad75598SSergej Jaskiewicz TempDir subdir2(file_root.path("subdir2"));
131fad75598SSergej Jaskiewicz TempFile a(subdir2.path("a"));
132b680422eSAlex Lorenz
133b680422eSAlex Lorenz // Create file collector and add files.
134fad75598SSergej Jaskiewicz TempDir root("copy_files_root", /*Unique*/ true);
135fad75598SSergej Jaskiewicz std::string root_fs(root.path());
136b680422eSAlex Lorenz TestingFileCollector FileCollector(root_fs, root_fs);
137fad75598SSergej Jaskiewicz FileCollector.addFile(a.path());
138b680422eSAlex Lorenz
139b680422eSAlex Lorenz // The empty directory isn't seen until we add it.
140fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(a.path()));
141fad75598SSergej Jaskiewicz EXPECT_FALSE(FileCollector.hasSeen(subdir.path()));
142b680422eSAlex Lorenz
143fad75598SSergej Jaskiewicz FileCollector.addFile(subdir.path());
144fad75598SSergej Jaskiewicz EXPECT_TRUE(FileCollector.hasSeen(subdir.path()));
145b680422eSAlex Lorenz
146b680422eSAlex Lorenz // Make sure we can construct the directory.
147b680422eSAlex Lorenz std::error_code ec = FileCollector.copyFiles(true);
148b680422eSAlex Lorenz EXPECT_FALSE(ec);
149b680422eSAlex Lorenz bool IsDirectory = false;
150fad75598SSergej Jaskiewicz llvm::SmallString<128> SubdirInRoot = root.path();
151b680422eSAlex Lorenz llvm::sys::path::append(SubdirInRoot,
152fad75598SSergej Jaskiewicz llvm::sys::path::relative_path(subdir.path()));
153b680422eSAlex Lorenz ec = sys::fs::is_directory(SubdirInRoot, IsDirectory);
154b680422eSAlex Lorenz EXPECT_FALSE(ec);
155b680422eSAlex Lorenz ASSERT_TRUE(IsDirectory);
156b680422eSAlex Lorenz }
157b680422eSAlex Lorenz
TEST(FileCollectorTest,recordVFSAccesses)1589e38f4d9SAlex Lorenz TEST(FileCollectorTest, recordVFSAccesses) {
159fad75598SSergej Jaskiewicz TempDir file_root("dir_root", /*Unique*/ true);
160fad75598SSergej Jaskiewicz TempDir subdir(file_root.path("subdir"));
161fad75598SSergej Jaskiewicz TempDir subdir2(file_root.path("subdir2"));
162fad75598SSergej Jaskiewicz TempFile a(subdir2.path("a"));
163fad75598SSergej Jaskiewicz TempFile b(file_root.path("b"));
164fad75598SSergej Jaskiewicz TempDir subdir3(file_root.path("subdir3"));
165fad75598SSergej Jaskiewicz TempFile subdir3a(subdir3.path("aa"));
166fad75598SSergej Jaskiewicz TempDir subdir3b(subdir3.path("subdirb"));
167fad75598SSergej Jaskiewicz { TempFile subdir3fileremoved(subdir3.path("removed")); }
1689e38f4d9SAlex Lorenz
1699e38f4d9SAlex Lorenz // Create file collector and add files.
170fad75598SSergej Jaskiewicz TempDir root("copy_files_root", /*Unique*/ true);
171fad75598SSergej Jaskiewicz std::string root_fs(root.path());
1729e38f4d9SAlex Lorenz auto Collector = std::make_shared<TestingFileCollector>(root_fs, root_fs);
1739e38f4d9SAlex Lorenz auto VFS =
1749e38f4d9SAlex Lorenz FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);
175fad75598SSergej Jaskiewicz VFS->status(a.path());
176fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(a.path()));
1779e38f4d9SAlex Lorenz
178fad75598SSergej Jaskiewicz VFS->openFileForRead(b.path());
179fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(b.path()));
1809e38f4d9SAlex Lorenz
181fad75598SSergej Jaskiewicz VFS->status(subdir.path());
182fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(subdir.path()));
1839e38f4d9SAlex Lorenz
184a171f6c9SAlex Lorenz #ifndef _WIN32
1859e38f4d9SAlex Lorenz std::error_code EC;
186fad75598SSergej Jaskiewicz auto It = VFS->dir_begin(subdir3.path(), EC);
1879e38f4d9SAlex Lorenz EXPECT_FALSE(EC);
188fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(subdir3.path()));
189fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(subdir3a.path()));
190fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(subdir3b.path()));
191fad75598SSergej Jaskiewicz std::string RemovedFileName((Twine(subdir3.path("removed"))).str());
1929e38f4d9SAlex Lorenz EXPECT_FALSE(Collector->hasSeen(RemovedFileName));
193a171f6c9SAlex Lorenz #endif
1949e38f4d9SAlex Lorenz }
1959e38f4d9SAlex Lorenz
19686814bf6SAlex Lorenz #ifndef _WIN32
TEST(FileCollectorTest,Symlinks)19786814bf6SAlex Lorenz TEST(FileCollectorTest, Symlinks) {
19886814bf6SAlex Lorenz // Root where the original files live.
199fad75598SSergej Jaskiewicz TempDir file_root("file_root", /*Unique*/ true);
20086814bf6SAlex Lorenz
20186814bf6SAlex Lorenz // Create some files in the file root.
202fad75598SSergej Jaskiewicz TempFile a(file_root.path("aaa"));
203fad75598SSergej Jaskiewicz TempFile b(file_root.path("bbb"));
204fad75598SSergej Jaskiewicz TempFile c(file_root.path("ccc"));
20586814bf6SAlex Lorenz
20686814bf6SAlex Lorenz // Create a directory foo with file ddd.
207fad75598SSergej Jaskiewicz TempDir foo(file_root.path("foo"));
208fad75598SSergej Jaskiewicz TempFile d(foo.path("ddd"));
20986814bf6SAlex Lorenz
21086814bf6SAlex Lorenz // Create a file eee in the foo's parent directory.
211fad75598SSergej Jaskiewicz TempFile e(foo.path("../eee"));
21286814bf6SAlex Lorenz
21386814bf6SAlex Lorenz // Create a symlink bar pointing to foo.
214fad75598SSergej Jaskiewicz TempLink symlink(file_root.path("foo"), file_root.path("bar"));
21586814bf6SAlex Lorenz
21686814bf6SAlex Lorenz // Root where files are copied to.
217fad75598SSergej Jaskiewicz TempDir reproducer_root("reproducer_root", /*Unique*/ true);
218fad75598SSergej Jaskiewicz std::string root_fs(reproducer_root.path());
2193e4e0478SJonas Devlieghere TestingFileCollector FileCollector(root_fs, root_fs);
22086814bf6SAlex Lorenz
22186814bf6SAlex Lorenz // Add all the files to the collector.
222fad75598SSergej Jaskiewicz FileCollector.addFile(a.path());
223fad75598SSergej Jaskiewicz FileCollector.addFile(b.path());
224fad75598SSergej Jaskiewicz FileCollector.addFile(c.path());
225fad75598SSergej Jaskiewicz FileCollector.addFile(d.path());
226fad75598SSergej Jaskiewicz FileCollector.addFile(e.path());
227fad75598SSergej Jaskiewicz FileCollector.addFile(file_root.path() + "/bar/ddd");
22886814bf6SAlex Lorenz
2293e4e0478SJonas Devlieghere auto mapping = FileCollector.VFSWriter.getMappings();
23086814bf6SAlex Lorenz
23186814bf6SAlex Lorenz {
23286814bf6SAlex Lorenz // Make sure the common case works.
233fad75598SSergej Jaskiewicz std::string vpath = (file_root.path() + "/aaa").str();
234fad75598SSergej Jaskiewicz std::string rpath =
235fad75598SSergej Jaskiewicz (reproducer_root.path() + file_root.path() + "/aaa").str();
23686814bf6SAlex Lorenz printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
23786814bf6SAlex Lorenz EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
23886814bf6SAlex Lorenz }
23986814bf6SAlex Lorenz
24086814bf6SAlex Lorenz {
24186814bf6SAlex Lorenz // Make sure the virtual path points to the real source path.
242fad75598SSergej Jaskiewicz std::string vpath = (file_root.path() + "/bar/ddd").str();
24386814bf6SAlex Lorenz std::string rpath =
244fad75598SSergej Jaskiewicz (reproducer_root.path() + file_root.path() + "/foo/ddd").str();
24586814bf6SAlex Lorenz printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
24686814bf6SAlex Lorenz EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
24786814bf6SAlex Lorenz }
24886814bf6SAlex Lorenz
24986814bf6SAlex Lorenz {
25086814bf6SAlex Lorenz // Make sure that .. is removed from the source path.
251fad75598SSergej Jaskiewicz std::string vpath = (file_root.path() + "/eee").str();
252fad75598SSergej Jaskiewicz std::string rpath =
253fad75598SSergej Jaskiewicz (reproducer_root.path() + file_root.path() + "/eee").str();
25486814bf6SAlex Lorenz printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
25586814bf6SAlex Lorenz EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
25686814bf6SAlex Lorenz }
25786814bf6SAlex Lorenz }
2589e38f4d9SAlex Lorenz
TEST(FileCollectorTest,recordVFSSymlinkAccesses)2599e38f4d9SAlex Lorenz TEST(FileCollectorTest, recordVFSSymlinkAccesses) {
260fad75598SSergej Jaskiewicz TempDir file_root("dir_root", /*Unique*/ true);
261fad75598SSergej Jaskiewicz TempFile a(file_root.path("a"));
262fad75598SSergej Jaskiewicz TempLink symlink(file_root.path("a"), file_root.path("b"));
2639e38f4d9SAlex Lorenz
2649e38f4d9SAlex Lorenz // Create file collector and add files.
265fad75598SSergej Jaskiewicz TempDir root("copy_files_root", true);
266fad75598SSergej Jaskiewicz std::string root_fs(root.path());
2679e38f4d9SAlex Lorenz auto Collector = std::make_shared<TestingFileCollector>(root_fs, root_fs);
2689e38f4d9SAlex Lorenz auto VFS =
2699e38f4d9SAlex Lorenz FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);
2709e38f4d9SAlex Lorenz SmallString<256> Output;
271fad75598SSergej Jaskiewicz VFS->getRealPath(symlink.path(), Output);
272fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(a.path()));
273fad75598SSergej Jaskiewicz EXPECT_TRUE(Collector->hasSeen(symlink.path()));
2749e38f4d9SAlex Lorenz }
27586814bf6SAlex Lorenz #endif
276