diff options
Diffstat (limited to 'lldb/unittests/Utility/FileCollectorTest.cpp')
| -rw-r--r-- | lldb/unittests/Utility/FileCollectorTest.cpp | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/lldb/unittests/Utility/FileCollectorTest.cpp b/lldb/unittests/Utility/FileCollectorTest.cpp new file mode 100644 index 00000000000..bf49f5984b0 --- /dev/null +++ b/lldb/unittests/Utility/FileCollectorTest.cpp @@ -0,0 +1,214 @@ +//===-- FileCollectorTest.cpp -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "lldb/Utility/FileCollector.h" +#include "lldb/Utility/FileSpec.h" + +#include "llvm/Support/FileSystem.h" + +using namespace llvm; +using namespace lldb_private; + +namespace llvm { +namespace vfs { +inline bool operator==(const llvm::vfs::YAMLVFSEntry &LHS, + const llvm::vfs::YAMLVFSEntry &RHS) { + return LHS.VPath == RHS.VPath && LHS.RPath == RHS.RPath; +} +} // namespace vfs +} // namespace llvm + +namespace { +class TestingFileCollector : public FileCollector { +public: + using FileCollector::FileCollector; + using FileCollector::m_root; + using FileCollector::m_seen; + using FileCollector::m_symlink_map; + using FileCollector::m_vfs_writer; + + bool HasSeen(FileSpec fs) { + return m_seen.find(fs.GetPath()) != m_seen.end(); + } +}; + +struct ScopedDir { + SmallString<128> Path; + ScopedDir(const Twine &Name, bool Unique = false) { + std::error_code EC; + if (Unique) { + EC = llvm::sys::fs::createUniqueDirectory(Name, Path); + } else { + Path = Name.str(); + EC = llvm::sys::fs::create_directory(Twine(Path)); + } + if (EC) + Path = ""; + EXPECT_FALSE(EC); + // Ensure the path is the real path so tests can use it to compare against + // realpath output. + SmallString<128> RealPath; + if (!llvm::sys::fs::real_path(Path, RealPath)) + Path.swap(RealPath); + } + ~ScopedDir() { + if (Path != "") { + EXPECT_FALSE(llvm::sys::fs::remove_directories(Path.str())); + } + } + operator StringRef() { return Path.str(); } +}; + +struct ScopedLink { + SmallString<128> Path; + ScopedLink(const Twine &To, const Twine &From) { + Path = From.str(); + std::error_code EC = sys::fs::create_link(To, From); + if (EC) + Path = ""; + EXPECT_FALSE(EC); + } + ~ScopedLink() { + if (Path != "") { + EXPECT_FALSE(llvm::sys::fs::remove(Path.str())); + } + } + operator StringRef() { return Path.str(); } +}; + +struct ScopedFile { + SmallString<128> Path; + ScopedFile(const Twine &Name) { + std::error_code EC; + EC = llvm::sys::fs::createUniqueFile(Name, Path); + if (EC) + Path = ""; + EXPECT_FALSE(EC); + } + ~ScopedFile() { + if (Path != "") { + EXPECT_FALSE(llvm::sys::fs::remove(Path.str())); + } + } + operator StringRef() { return Path.str(); } +}; +} // end anonymous namespace + +TEST(FileCollectorTest, AddFile) { + ScopedDir root("add_file_root", true); + FileSpec root_fs(root.Path); + TestingFileCollector file_collector(root_fs); + + file_collector.AddFile(FileSpec("/path/to/a")); + file_collector.AddFile(FileSpec("/path/to/b")); + file_collector.AddFile(FileSpec("/path/to/c")); + + // Make sure the root is correct. + EXPECT_EQ(file_collector.m_root, root_fs); + + // Make sure we've seen all the added files. + EXPECT_TRUE(file_collector.HasSeen(FileSpec("/path/to/a"))); + EXPECT_TRUE(file_collector.HasSeen(FileSpec("/path/to/b"))); + EXPECT_TRUE(file_collector.HasSeen(FileSpec("/path/to/c"))); + + // Make sure we've only seen the added files. + EXPECT_FALSE(file_collector.HasSeen(FileSpec("/path/to/d"))); +} + +TEST(FileCollectorTest, CopyFiles) { + ScopedDir file_root("file_root", true); + ScopedFile a(file_root + "/aaa"); + ScopedFile b(file_root + "/bbb"); + ScopedFile c(file_root + "/ccc"); + + // Create file collector and add files. + ScopedDir root("copy_files_root", true); + FileSpec root_fs(root.Path); + TestingFileCollector file_collector(root_fs); + file_collector.AddFile(a.Path); + file_collector.AddFile(b.Path); + file_collector.AddFile(c.Path); + + // Make sure we can copy the files. + std::error_code ec = file_collector.CopyFiles(true); + EXPECT_FALSE(ec); + + // Now add a bogus file and make sure we error out. + file_collector.AddFile("/some/bogus/file"); + ec = file_collector.CopyFiles(true); + EXPECT_TRUE(ec); + + // However, if stop_on_error is true the copy should still succeed. + ec = file_collector.CopyFiles(false); + EXPECT_FALSE(ec); +} + +#ifndef WINDOWS +TEST(FileCollectorTest, Symlinks) { + // Root where the original files live. + ScopedDir file_root("file_root", true); + + // Create some files in the file root. + ScopedFile a(file_root + "/aaa"); + ScopedFile b(file_root + "/bbb"); + ScopedFile c(file_root + "/ccc"); + + // Create a directory foo with file ddd. + ScopedDir foo(file_root + "/foo"); + ScopedFile d(foo + "/ddd"); + + // Create a file eee in the foo's parent directory. + ScopedFile e(foo + "/../eee"); + + // Create a symlink bar pointing to foo. + ScopedLink symlink(file_root + "/foo", file_root + "/bar"); + + // Root where files are copied to. + ScopedDir reproducer_root("reproducer_root", true); + FileSpec root_fs(reproducer_root.Path); + TestingFileCollector file_collector(root_fs); + + // Add all the files to the collector. + file_collector.AddFile(a.Path); + file_collector.AddFile(b.Path); + file_collector.AddFile(c.Path); + file_collector.AddFile(d.Path); + file_collector.AddFile(e.Path); + file_collector.AddFile(file_root + "/bar/ddd"); + + auto mapping = file_collector.m_vfs_writer.getMappings(); + + { + // Make sure the common case works. + std::string vpath = (file_root + "/aaa").str(); + std::string rpath = (reproducer_root.Path + file_root.Path + "/aaa").str(); + printf("%s -> %s\n", vpath.c_str(), rpath.c_str()); + EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath))); + } + + { + // Make sure the virtual path points to the real source path. + std::string vpath = (file_root + "/bar/ddd").str(); + std::string rpath = + (reproducer_root.Path + file_root.Path + "/foo/ddd").str(); + printf("%s -> %s\n", vpath.c_str(), rpath.c_str()); + EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath))); + } + + { + // Make sure that .. is removed from the source path. + std::string vpath = (file_root + "/eee").str(); + std::string rpath = (reproducer_root.Path + file_root.Path + "/eee").str(); + printf("%s -> %s\n", vpath.c_str(), rpath.c_str()); + EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath))); + } +} +#endif |

