283 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "gmock/gmock.h"10#include "gtest/gtest.h"11 12#include "llvm/Support/FileCollector.h"13#include "llvm/Support/FileSystem.h"14#include "llvm/Testing/Support/SupportHelpers.h"15 16using namespace llvm;17using llvm::unittest::TempDir;18using llvm::unittest::TempFile;19using llvm::unittest::TempLink;20 21namespace llvm {22namespace vfs {23inline bool operator==(const llvm::vfs::YAMLVFSEntry &LHS,24 const llvm::vfs::YAMLVFSEntry &RHS) {25 return LHS.VPath == RHS.VPath && LHS.RPath == RHS.RPath;26}27} // namespace vfs28} // namespace llvm29 30namespace {31class TestingFileCollector : public FileCollector {32public:33 using FileCollector::FileCollector;34 using FileCollector::Root;35 using FileCollector::Seen;36 using FileCollector::VFSWriter;37 38 bool hasSeen(StringRef fs) { return Seen.contains(fs); }39};40 41} // end anonymous namespace42 43TEST(FileCollectorTest, addFile) {44 TempDir root("add_file_root", /*Unique*/ true);45 std::string root_fs(root.path());46 TestingFileCollector FileCollector(root_fs, root_fs,47 vfs::getRealFileSystem());48 49 FileCollector.addFile("/path/to/a");50 FileCollector.addFile("/path/to/b");51 FileCollector.addFile("/path/to/c");52 53 // Make sure the root is correct.54 EXPECT_EQ(FileCollector.Root, root_fs);55 56 // Make sure we've seen all the added files.57 EXPECT_TRUE(FileCollector.hasSeen("/path/to/a"));58 EXPECT_TRUE(FileCollector.hasSeen("/path/to/b"));59 EXPECT_TRUE(FileCollector.hasSeen("/path/to/c"));60 61 // Make sure we've only seen the added files.62 EXPECT_FALSE(FileCollector.hasSeen("/path/to/d"));63}64 65TEST(FileCollectorTest, addDirectory) {66 TempDir file_root("file_root", /*Unique*/ true);67 68 llvm::SmallString<128> aaa(file_root.path());69 llvm::sys::path::append(aaa, "aaa");70 TempFile a(aaa.str());71 72 llvm::SmallString<128> bbb(file_root.path());73 llvm::sys::path::append(bbb, "bbb");74 TempFile b(bbb.str());75 76 llvm::SmallString<128> ccc(file_root.path());77 llvm::sys::path::append(ccc, "ccc");78 TempFile c(ccc.str());79 80 std::string root_fs(file_root.path());81 TestingFileCollector FileCollector(root_fs, root_fs,82 vfs::getRealFileSystem());83 84 FileCollector.addDirectory(file_root.path());85 86 // Make sure the root is correct.87 EXPECT_EQ(FileCollector.Root, root_fs);88 89 // Make sure we've seen all the added files.90 EXPECT_TRUE(FileCollector.hasSeen(a.path()));91 EXPECT_TRUE(FileCollector.hasSeen(b.path()));92 EXPECT_TRUE(FileCollector.hasSeen(c.path()));93 94 // Make sure we've only seen the added files.95 llvm::SmallString<128> ddd(file_root.path());96 llvm::sys::path::append(ddd, "ddd");97 TempFile d(ddd);98 EXPECT_FALSE(FileCollector.hasSeen(d.path()));99}100 101TEST(FileCollectorTest, copyFiles) {102 TempDir file_root("file_root", /*Unique*/ true);103 TempFile a(file_root.path("aaa"));104 TempFile b(file_root.path("bbb"));105 TempFile c(file_root.path("ccc"));106 107 // Create file collector and add files.108 TempDir root("copy_files_root", /*Unique*/ true);109 std::string root_fs(root.path());110 TestingFileCollector FileCollector(root_fs, root_fs,111 vfs::getRealFileSystem());112 FileCollector.addFile(a.path());113 FileCollector.addFile(b.path());114 FileCollector.addFile(c.path());115 116 // Make sure we can copy the files.117 std::error_code ec = FileCollector.copyFiles(true);118 EXPECT_FALSE(ec);119 120 // Now add a bogus file and make sure we error out.121 FileCollector.addFile("/some/bogus/file");122 ec = FileCollector.copyFiles(true);123 EXPECT_TRUE(ec);124 125 // However, if stop_on_error is true the copy should still succeed.126 ec = FileCollector.copyFiles(false);127 EXPECT_FALSE(ec);128}129 130TEST(FileCollectorTest, recordAndConstructDirectory) {131 TempDir file_root("dir_root", /*Unique*/ true);132 TempDir subdir(file_root.path("subdir"));133 TempDir subdir2(file_root.path("subdir2"));134 TempFile a(subdir2.path("a"));135 136 // Create file collector and add files.137 TempDir root("copy_files_root", /*Unique*/ true);138 std::string root_fs(root.path());139 TestingFileCollector FileCollector(root_fs, root_fs,140 vfs::getRealFileSystem());141 FileCollector.addFile(a.path());142 143 // The empty directory isn't seen until we add it.144 EXPECT_TRUE(FileCollector.hasSeen(a.path()));145 EXPECT_FALSE(FileCollector.hasSeen(subdir.path()));146 147 FileCollector.addFile(subdir.path());148 EXPECT_TRUE(FileCollector.hasSeen(subdir.path()));149 150 // Make sure we can construct the directory.151 std::error_code ec = FileCollector.copyFiles(true);152 EXPECT_FALSE(ec);153 bool IsDirectory = false;154 llvm::SmallString<128> SubdirInRoot = root.path();155 llvm::sys::path::append(SubdirInRoot,156 llvm::sys::path::relative_path(subdir.path()));157 ec = sys::fs::is_directory(SubdirInRoot, IsDirectory);158 EXPECT_FALSE(ec);159 ASSERT_TRUE(IsDirectory);160}161 162TEST(FileCollectorTest, recordVFSAccesses) {163 TempDir file_root("dir_root", /*Unique*/ true);164 TempDir subdir(file_root.path("subdir"));165 TempDir subdir2(file_root.path("subdir2"));166 TempFile a(subdir2.path("a"));167 TempFile b(file_root.path("b"));168 TempDir subdir3(file_root.path("subdir3"));169 TempFile subdir3a(subdir3.path("aa"));170 TempDir subdir3b(subdir3.path("subdirb"));171 { TempFile subdir3fileremoved(subdir3.path("removed")); }172 173 // Create file collector and add files.174 TempDir root("copy_files_root", /*Unique*/ true);175 std::string root_fs(root.path());176 auto Collector = std::make_shared<TestingFileCollector>(177 root_fs, root_fs, vfs::getRealFileSystem());178 auto VFS =179 FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);180 VFS->status(a.path());181 EXPECT_TRUE(Collector->hasSeen(a.path()));182 183 VFS->openFileForRead(b.path());184 EXPECT_TRUE(Collector->hasSeen(b.path()));185 186 VFS->status(subdir.path());187 EXPECT_TRUE(Collector->hasSeen(subdir.path()));188 189#ifndef _WIN32190 std::error_code EC;191 auto It = VFS->dir_begin(subdir3.path(), EC);192 EXPECT_FALSE(EC);193 EXPECT_TRUE(Collector->hasSeen(subdir3.path()));194 EXPECT_TRUE(Collector->hasSeen(subdir3a.path()));195 EXPECT_TRUE(Collector->hasSeen(subdir3b.path()));196 std::string RemovedFileName((Twine(subdir3.path("removed"))).str());197 EXPECT_FALSE(Collector->hasSeen(RemovedFileName));198#endif199}200 201#ifndef _WIN32202TEST(FileCollectorTest, Symlinks) {203 // Root where the original files live.204 TempDir file_root("file_root", /*Unique*/ true);205 206 // Create some files in the file root.207 TempFile a(file_root.path("aaa"));208 TempFile b(file_root.path("bbb"));209 TempFile c(file_root.path("ccc"));210 211 // Create a directory foo with file ddd.212 TempDir foo(file_root.path("foo"));213 TempFile d(foo.path("ddd"));214 215 // Create a file eee in the foo's parent directory.216 TempFile e(foo.path("../eee"));217 218 // Create a symlink bar pointing to foo.219 TempLink symlink(file_root.path("foo"), file_root.path("bar"));220 221 // Root where files are copied to.222 TempDir reproducer_root("reproducer_root", /*Unique*/ true);223 std::string root_fs(reproducer_root.path());224 TestingFileCollector FileCollector(root_fs, root_fs,225 vfs::getRealFileSystem());226 227 // Add all the files to the collector.228 FileCollector.addFile(a.path());229 FileCollector.addFile(b.path());230 FileCollector.addFile(c.path());231 FileCollector.addFile(d.path());232 FileCollector.addFile(e.path());233 FileCollector.addFile(file_root.path() + "/bar/ddd");234 235 auto mapping = FileCollector.VFSWriter.getMappings();236 237 {238 // Make sure the common case works.239 std::string vpath = (file_root.path() + "/aaa").str();240 std::string rpath =241 (reproducer_root.path() + file_root.path() + "/aaa").str();242 printf("%s -> %s\n", vpath.c_str(), rpath.c_str());243 EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));244 }245 246 {247 // Make sure the virtual path points to the real source path.248 std::string vpath = (file_root.path() + "/bar/ddd").str();249 std::string rpath =250 (reproducer_root.path() + file_root.path() + "/foo/ddd").str();251 printf("%s -> %s\n", vpath.c_str(), rpath.c_str());252 EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));253 }254 255 {256 // Make sure that .. is removed from the source path.257 std::string vpath = (file_root.path() + "/eee").str();258 std::string rpath =259 (reproducer_root.path() + file_root.path() + "/eee").str();260 printf("%s -> %s\n", vpath.c_str(), rpath.c_str());261 EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));262 }263}264 265TEST(FileCollectorTest, recordVFSSymlinkAccesses) {266 TempDir file_root("dir_root", /*Unique*/ true);267 TempFile a(file_root.path("a"));268 TempLink symlink(file_root.path("a"), file_root.path("b"));269 270 // Create file collector and add files.271 TempDir root("copy_files_root", true);272 std::string root_fs(root.path());273 auto Collector = std::make_shared<TestingFileCollector>(274 root_fs, root_fs, vfs::getRealFileSystem());275 auto VFS =276 FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);277 SmallString<256> Output;278 VFS->getRealPath(symlink.path(), Output);279 EXPECT_TRUE(Collector->hasSeen(a.path()));280 EXPECT_TRUE(Collector->hasSeen(symlink.path()));281}282#endif283