1fc51490bSJonas Devlieghere //===- unittests/Support/VirtualFileSystem.cpp -------------- VFS tests ---===// 2fc51490bSJonas Devlieghere // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fc51490bSJonas Devlieghere // 7fc51490bSJonas Devlieghere //===----------------------------------------------------------------------===// 8fc51490bSJonas Devlieghere 9fc51490bSJonas Devlieghere #include "llvm/Support/VirtualFileSystem.h" 10fc51490bSJonas Devlieghere #include "llvm/ADT/Triple.h" 11fc51490bSJonas Devlieghere #include "llvm/Config/llvm-config.h" 12fc51490bSJonas Devlieghere #include "llvm/Support/Errc.h" 13fc51490bSJonas Devlieghere #include "llvm/Support/Host.h" 14fc51490bSJonas Devlieghere #include "llvm/Support/MemoryBuffer.h" 15fc51490bSJonas Devlieghere #include "llvm/Support/Path.h" 16fc51490bSJonas Devlieghere #include "llvm/Support/SourceMgr.h" 17fad75598SSergej Jaskiewicz #include "llvm/Testing/Support/SupportHelpers.h" 18fc51490bSJonas Devlieghere #include "gmock/gmock.h" 19fc51490bSJonas Devlieghere #include "gtest/gtest.h" 20fc51490bSJonas Devlieghere #include <map> 21fc51490bSJonas Devlieghere #include <string> 22fc51490bSJonas Devlieghere 23fc51490bSJonas Devlieghere using namespace llvm; 24fc51490bSJonas Devlieghere using llvm::sys::fs::UniqueID; 25fad75598SSergej Jaskiewicz using llvm::unittest::TempDir; 26fad75598SSergej Jaskiewicz using llvm::unittest::TempFile; 27fad75598SSergej Jaskiewicz using llvm::unittest::TempLink; 28fc51490bSJonas Devlieghere using testing::ElementsAre; 29fc51490bSJonas Devlieghere using testing::Pair; 30fc51490bSJonas Devlieghere using testing::UnorderedElementsAre; 31fc51490bSJonas Devlieghere 32fc51490bSJonas Devlieghere namespace { 33fc51490bSJonas Devlieghere struct DummyFile : public vfs::File { 34fc51490bSJonas Devlieghere vfs::Status S; 35fc51490bSJonas Devlieghere explicit DummyFile(vfs::Status S) : S(S) {} 36fc51490bSJonas Devlieghere llvm::ErrorOr<vfs::Status> status() override { return S; } 37fc51490bSJonas Devlieghere llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 38fc51490bSJonas Devlieghere getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, 39fc51490bSJonas Devlieghere bool IsVolatile) override { 40fc51490bSJonas Devlieghere llvm_unreachable("unimplemented"); 41fc51490bSJonas Devlieghere } 42fc51490bSJonas Devlieghere std::error_code close() override { return std::error_code(); } 43fc51490bSJonas Devlieghere }; 44fc51490bSJonas Devlieghere 45fc51490bSJonas Devlieghere class DummyFileSystem : public vfs::FileSystem { 46fc51490bSJonas Devlieghere int FSID; // used to produce UniqueIDs 47fc51490bSJonas Devlieghere int FileID; // used to produce UniqueIDs 4821703543SJonas Devlieghere std::string WorkingDirectory; 49fc51490bSJonas Devlieghere std::map<std::string, vfs::Status> FilesAndDirs; 5021703543SJonas Devlieghere typedef std::map<std::string, vfs::Status>::const_iterator const_iterator; 51fc51490bSJonas Devlieghere 52fc51490bSJonas Devlieghere static int getNextFSID() { 53fc51490bSJonas Devlieghere static int Count = 0; 54fc51490bSJonas Devlieghere return Count++; 55fc51490bSJonas Devlieghere } 56fc51490bSJonas Devlieghere 57fc51490bSJonas Devlieghere public: 58fc51490bSJonas Devlieghere DummyFileSystem() : FSID(getNextFSID()), FileID(0) {} 59fc51490bSJonas Devlieghere 60fc51490bSJonas Devlieghere ErrorOr<vfs::Status> status(const Twine &Path) override { 6121703543SJonas Devlieghere auto I = findEntry(Path); 62fc51490bSJonas Devlieghere if (I == FilesAndDirs.end()) 63fc51490bSJonas Devlieghere return make_error_code(llvm::errc::no_such_file_or_directory); 64fc51490bSJonas Devlieghere return I->second; 65fc51490bSJonas Devlieghere } 66fc51490bSJonas Devlieghere ErrorOr<std::unique_ptr<vfs::File>> 67fc51490bSJonas Devlieghere openFileForRead(const Twine &Path) override { 68fc51490bSJonas Devlieghere auto S = status(Path); 69fc51490bSJonas Devlieghere if (S) 70fc51490bSJonas Devlieghere return std::unique_ptr<vfs::File>(new DummyFile{*S}); 71fc51490bSJonas Devlieghere return S.getError(); 72fc51490bSJonas Devlieghere } 73fc51490bSJonas Devlieghere llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override { 7421703543SJonas Devlieghere return WorkingDirectory; 75fc51490bSJonas Devlieghere } 76fc51490bSJonas Devlieghere std::error_code setCurrentWorkingDirectory(const Twine &Path) override { 7721703543SJonas Devlieghere WorkingDirectory = Path.str(); 78fc51490bSJonas Devlieghere return std::error_code(); 79fc51490bSJonas Devlieghere } 80fc51490bSJonas Devlieghere // Map any symlink to "/symlink". 8199538e89SSam McCall std::error_code getRealPath(const Twine &Path, 8299538e89SSam McCall SmallVectorImpl<char> &Output) const override { 8321703543SJonas Devlieghere auto I = findEntry(Path); 84fc51490bSJonas Devlieghere if (I == FilesAndDirs.end()) 85fc51490bSJonas Devlieghere return make_error_code(llvm::errc::no_such_file_or_directory); 86fc51490bSJonas Devlieghere if (I->second.isSymlink()) { 87fc51490bSJonas Devlieghere Output.clear(); 88fc51490bSJonas Devlieghere Twine("/symlink").toVector(Output); 89fc51490bSJonas Devlieghere return std::error_code(); 90fc51490bSJonas Devlieghere } 91fc51490bSJonas Devlieghere Output.clear(); 92fc51490bSJonas Devlieghere Path.toVector(Output); 93fc51490bSJonas Devlieghere return std::error_code(); 94fc51490bSJonas Devlieghere } 95fc51490bSJonas Devlieghere 96fc51490bSJonas Devlieghere struct DirIterImpl : public llvm::vfs::detail::DirIterImpl { 97fc51490bSJonas Devlieghere std::map<std::string, vfs::Status> &FilesAndDirs; 98fc51490bSJonas Devlieghere std::map<std::string, vfs::Status>::iterator I; 99fc51490bSJonas Devlieghere std::string Path; 100fc51490bSJonas Devlieghere bool isInPath(StringRef S) { 101fc51490bSJonas Devlieghere if (Path.size() < S.size() && S.find(Path) == 0) { 102fc51490bSJonas Devlieghere auto LastSep = S.find_last_of('/'); 103fc51490bSJonas Devlieghere if (LastSep == Path.size() || LastSep == Path.size() - 1) 104fc51490bSJonas Devlieghere return true; 105fc51490bSJonas Devlieghere } 106fc51490bSJonas Devlieghere return false; 107fc51490bSJonas Devlieghere } 108fc51490bSJonas Devlieghere DirIterImpl(std::map<std::string, vfs::Status> &FilesAndDirs, 109fc51490bSJonas Devlieghere const Twine &_Path) 110fc51490bSJonas Devlieghere : FilesAndDirs(FilesAndDirs), I(FilesAndDirs.begin()), 111fc51490bSJonas Devlieghere Path(_Path.str()) { 112fc51490bSJonas Devlieghere for (; I != FilesAndDirs.end(); ++I) { 113fc51490bSJonas Devlieghere if (isInPath(I->first)) { 114adcd0268SBenjamin Kramer CurrentEntry = vfs::directory_entry(std::string(I->second.getName()), 115adcd0268SBenjamin Kramer I->second.getType()); 116fc51490bSJonas Devlieghere break; 117fc51490bSJonas Devlieghere } 118fc51490bSJonas Devlieghere } 119fc51490bSJonas Devlieghere } 120fc51490bSJonas Devlieghere std::error_code increment() override { 121fc51490bSJonas Devlieghere ++I; 122fc51490bSJonas Devlieghere for (; I != FilesAndDirs.end(); ++I) { 123fc51490bSJonas Devlieghere if (isInPath(I->first)) { 124adcd0268SBenjamin Kramer CurrentEntry = vfs::directory_entry(std::string(I->second.getName()), 125adcd0268SBenjamin Kramer I->second.getType()); 126fc51490bSJonas Devlieghere break; 127fc51490bSJonas Devlieghere } 128fc51490bSJonas Devlieghere } 129fc51490bSJonas Devlieghere if (I == FilesAndDirs.end()) 130fc51490bSJonas Devlieghere CurrentEntry = vfs::directory_entry(); 131fc51490bSJonas Devlieghere return std::error_code(); 132fc51490bSJonas Devlieghere } 133fc51490bSJonas Devlieghere }; 134fc51490bSJonas Devlieghere 135fc51490bSJonas Devlieghere vfs::directory_iterator dir_begin(const Twine &Dir, 136fc51490bSJonas Devlieghere std::error_code &EC) override { 137fc51490bSJonas Devlieghere return vfs::directory_iterator( 138fc51490bSJonas Devlieghere std::make_shared<DirIterImpl>(FilesAndDirs, Dir)); 139fc51490bSJonas Devlieghere } 140fc51490bSJonas Devlieghere 141fc51490bSJonas Devlieghere void addEntry(StringRef Path, const vfs::Status &Status) { 142adcd0268SBenjamin Kramer FilesAndDirs[std::string(Path)] = Status; 143fc51490bSJonas Devlieghere } 144fc51490bSJonas Devlieghere 14521703543SJonas Devlieghere const_iterator findEntry(const Twine &Path) const { 14621703543SJonas Devlieghere SmallString<128> P; 14721703543SJonas Devlieghere Path.toVector(P); 14821703543SJonas Devlieghere std::error_code EC = makeAbsolute(P); 14921703543SJonas Devlieghere assert(!EC); 150a3378063SDavid L. Jones (void)EC; 151adcd0268SBenjamin Kramer return FilesAndDirs.find(std::string(P.str())); 15221703543SJonas Devlieghere } 15321703543SJonas Devlieghere 154fc51490bSJonas Devlieghere void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) { 155fc51490bSJonas Devlieghere vfs::Status S(Path, UniqueID(FSID, FileID++), 156fc51490bSJonas Devlieghere std::chrono::system_clock::now(), 0, 0, 1024, 157fc51490bSJonas Devlieghere sys::fs::file_type::regular_file, Perms); 158fc51490bSJonas Devlieghere addEntry(Path, S); 159fc51490bSJonas Devlieghere } 160fc51490bSJonas Devlieghere 161fc51490bSJonas Devlieghere void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) { 162fc51490bSJonas Devlieghere vfs::Status S(Path, UniqueID(FSID, FileID++), 163fc51490bSJonas Devlieghere std::chrono::system_clock::now(), 0, 0, 0, 164fc51490bSJonas Devlieghere sys::fs::file_type::directory_file, Perms); 165fc51490bSJonas Devlieghere addEntry(Path, S); 166fc51490bSJonas Devlieghere } 167fc51490bSJonas Devlieghere 168fc51490bSJonas Devlieghere void addSymlink(StringRef Path) { 169fc51490bSJonas Devlieghere vfs::Status S(Path, UniqueID(FSID, FileID++), 170fc51490bSJonas Devlieghere std::chrono::system_clock::now(), 0, 0, 0, 171fc51490bSJonas Devlieghere sys::fs::file_type::symlink_file, sys::fs::all_all); 172fc51490bSJonas Devlieghere addEntry(Path, S); 173fc51490bSJonas Devlieghere } 174fc51490bSJonas Devlieghere }; 175fc51490bSJonas Devlieghere 17621703543SJonas Devlieghere class ErrorDummyFileSystem : public DummyFileSystem { 17721703543SJonas Devlieghere std::error_code setCurrentWorkingDirectory(const Twine &Path) override { 17821703543SJonas Devlieghere return llvm::errc::no_such_file_or_directory; 17921703543SJonas Devlieghere } 18021703543SJonas Devlieghere }; 18121703543SJonas Devlieghere 182fc51490bSJonas Devlieghere /// Replace back-slashes by front-slashes. 183fc51490bSJonas Devlieghere std::string getPosixPath(std::string S) { 184fc51490bSJonas Devlieghere SmallString<128> Result; 185fc51490bSJonas Devlieghere llvm::sys::path::native(S, Result, llvm::sys::path::Style::posix); 186adcd0268SBenjamin Kramer return std::string(Result.str()); 187fc51490bSJonas Devlieghere } 188fc51490bSJonas Devlieghere } // end anonymous namespace 189fc51490bSJonas Devlieghere 190fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, StatusQueries) { 191fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem()); 192fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status((std::error_code())); 193fc51490bSJonas Devlieghere 194fc51490bSJonas Devlieghere D->addRegularFile("/foo"); 195fc51490bSJonas Devlieghere Status = D->status("/foo"); 196fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError()); 197fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isStatusKnown()); 198fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isDirectory()); 199fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isRegularFile()); 200fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isSymlink()); 201fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isOther()); 202fc51490bSJonas Devlieghere EXPECT_TRUE(Status->exists()); 203fc51490bSJonas Devlieghere 204fc51490bSJonas Devlieghere D->addDirectory("/bar"); 205fc51490bSJonas Devlieghere Status = D->status("/bar"); 206fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError()); 207fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isStatusKnown()); 208fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isDirectory()); 209fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isRegularFile()); 210fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isSymlink()); 211fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isOther()); 212fc51490bSJonas Devlieghere EXPECT_TRUE(Status->exists()); 213fc51490bSJonas Devlieghere 214fc51490bSJonas Devlieghere D->addSymlink("/baz"); 215fc51490bSJonas Devlieghere Status = D->status("/baz"); 216fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError()); 217fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isStatusKnown()); 218fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isDirectory()); 219fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isRegularFile()); 220fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isSymlink()); 221fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isOther()); 222fc51490bSJonas Devlieghere EXPECT_TRUE(Status->exists()); 223fc51490bSJonas Devlieghere 224fc51490bSJonas Devlieghere EXPECT_TRUE(Status->equivalent(*Status)); 225fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status2 = D->status("/foo"); 226fc51490bSJonas Devlieghere ASSERT_FALSE(Status2.getError()); 227fc51490bSJonas Devlieghere EXPECT_FALSE(Status->equivalent(*Status2)); 228fc51490bSJonas Devlieghere } 229fc51490bSJonas Devlieghere 230fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BaseOnlyOverlay) { 231fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem()); 232fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status((std::error_code())); 233fc51490bSJonas Devlieghere EXPECT_FALSE(Status = D->status("/foo")); 234fc51490bSJonas Devlieghere 235fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D)); 236fc51490bSJonas Devlieghere EXPECT_FALSE(Status = O->status("/foo")); 237fc51490bSJonas Devlieghere 238fc51490bSJonas Devlieghere D->addRegularFile("/foo"); 239fc51490bSJonas Devlieghere Status = D->status("/foo"); 240fc51490bSJonas Devlieghere EXPECT_FALSE(Status.getError()); 241fc51490bSJonas Devlieghere 242fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status2((std::error_code())); 243fc51490bSJonas Devlieghere Status2 = O->status("/foo"); 244fc51490bSJonas Devlieghere EXPECT_FALSE(Status2.getError()); 245fc51490bSJonas Devlieghere EXPECT_TRUE(Status->equivalent(*Status2)); 246fc51490bSJonas Devlieghere } 247fc51490bSJonas Devlieghere 248fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, GetRealPathInOverlay) { 249fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 250fc51490bSJonas Devlieghere Lower->addRegularFile("/foo"); 251fc51490bSJonas Devlieghere Lower->addSymlink("/lower_link"); 252fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem()); 253fc51490bSJonas Devlieghere 254fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 255fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 256fc51490bSJonas Devlieghere O->pushOverlay(Upper); 257fc51490bSJonas Devlieghere 258fc51490bSJonas Devlieghere // Regular file. 259fc51490bSJonas Devlieghere SmallString<16> RealPath; 260fc51490bSJonas Devlieghere EXPECT_FALSE(O->getRealPath("/foo", RealPath)); 261fc51490bSJonas Devlieghere EXPECT_EQ(RealPath.str(), "/foo"); 262fc51490bSJonas Devlieghere 263fc51490bSJonas Devlieghere // Expect no error getting real path for symlink in lower overlay. 264fc51490bSJonas Devlieghere EXPECT_FALSE(O->getRealPath("/lower_link", RealPath)); 265fc51490bSJonas Devlieghere EXPECT_EQ(RealPath.str(), "/symlink"); 266fc51490bSJonas Devlieghere 267fc51490bSJonas Devlieghere // Try a non-existing link. 268fc51490bSJonas Devlieghere EXPECT_EQ(O->getRealPath("/upper_link", RealPath), 269fc51490bSJonas Devlieghere errc::no_such_file_or_directory); 270fc51490bSJonas Devlieghere 271fc51490bSJonas Devlieghere // Add a new symlink in upper. 272fc51490bSJonas Devlieghere Upper->addSymlink("/upper_link"); 273fc51490bSJonas Devlieghere EXPECT_FALSE(O->getRealPath("/upper_link", RealPath)); 274fc51490bSJonas Devlieghere EXPECT_EQ(RealPath.str(), "/symlink"); 275fc51490bSJonas Devlieghere } 276fc51490bSJonas Devlieghere 277fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, OverlayFiles) { 278fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem()); 279fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem()); 280fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem()); 281fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 282fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Base)); 283fc51490bSJonas Devlieghere O->pushOverlay(Middle); 284fc51490bSJonas Devlieghere O->pushOverlay(Top); 285fc51490bSJonas Devlieghere 286fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status1((std::error_code())), 287fc51490bSJonas Devlieghere Status2((std::error_code())), Status3((std::error_code())), 288fc51490bSJonas Devlieghere StatusB((std::error_code())), StatusM((std::error_code())), 289fc51490bSJonas Devlieghere StatusT((std::error_code())); 290fc51490bSJonas Devlieghere 291fc51490bSJonas Devlieghere Base->addRegularFile("/foo"); 292fc51490bSJonas Devlieghere StatusB = Base->status("/foo"); 293fc51490bSJonas Devlieghere ASSERT_FALSE(StatusB.getError()); 294fc51490bSJonas Devlieghere Status1 = O->status("/foo"); 295fc51490bSJonas Devlieghere ASSERT_FALSE(Status1.getError()); 296fc51490bSJonas Devlieghere Middle->addRegularFile("/foo"); 297fc51490bSJonas Devlieghere StatusM = Middle->status("/foo"); 298fc51490bSJonas Devlieghere ASSERT_FALSE(StatusM.getError()); 299fc51490bSJonas Devlieghere Status2 = O->status("/foo"); 300fc51490bSJonas Devlieghere ASSERT_FALSE(Status2.getError()); 301fc51490bSJonas Devlieghere Top->addRegularFile("/foo"); 302fc51490bSJonas Devlieghere StatusT = Top->status("/foo"); 303fc51490bSJonas Devlieghere ASSERT_FALSE(StatusT.getError()); 304fc51490bSJonas Devlieghere Status3 = O->status("/foo"); 305fc51490bSJonas Devlieghere ASSERT_FALSE(Status3.getError()); 306fc51490bSJonas Devlieghere 307fc51490bSJonas Devlieghere EXPECT_TRUE(Status1->equivalent(*StatusB)); 308fc51490bSJonas Devlieghere EXPECT_TRUE(Status2->equivalent(*StatusM)); 309fc51490bSJonas Devlieghere EXPECT_TRUE(Status3->equivalent(*StatusT)); 310fc51490bSJonas Devlieghere 311fc51490bSJonas Devlieghere EXPECT_FALSE(Status1->equivalent(*Status2)); 312fc51490bSJonas Devlieghere EXPECT_FALSE(Status2->equivalent(*Status3)); 313fc51490bSJonas Devlieghere EXPECT_FALSE(Status1->equivalent(*Status3)); 314fc51490bSJonas Devlieghere } 315fc51490bSJonas Devlieghere 316fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, OverlayDirsNonMerged) { 317fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 318fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem()); 319fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 320fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 321fc51490bSJonas Devlieghere O->pushOverlay(Upper); 322fc51490bSJonas Devlieghere 323fc51490bSJonas Devlieghere Lower->addDirectory("/lower-only"); 324fc51490bSJonas Devlieghere Upper->addDirectory("/upper-only"); 325fc51490bSJonas Devlieghere 326fc51490bSJonas Devlieghere // non-merged paths should be the same 327fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only"); 328fc51490bSJonas Devlieghere ASSERT_FALSE(Status1.getError()); 329fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status2 = O->status("/lower-only"); 330fc51490bSJonas Devlieghere ASSERT_FALSE(Status2.getError()); 331fc51490bSJonas Devlieghere EXPECT_TRUE(Status1->equivalent(*Status2)); 332fc51490bSJonas Devlieghere 333fc51490bSJonas Devlieghere Status1 = Upper->status("/upper-only"); 334fc51490bSJonas Devlieghere ASSERT_FALSE(Status1.getError()); 335fc51490bSJonas Devlieghere Status2 = O->status("/upper-only"); 336fc51490bSJonas Devlieghere ASSERT_FALSE(Status2.getError()); 337fc51490bSJonas Devlieghere EXPECT_TRUE(Status1->equivalent(*Status2)); 338fc51490bSJonas Devlieghere } 339fc51490bSJonas Devlieghere 340fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, MergedDirPermissions) { 341fc51490bSJonas Devlieghere // merged directories get the permissions of the upper dir 342fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 343fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem()); 344fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 345fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 346fc51490bSJonas Devlieghere O->pushOverlay(Upper); 347fc51490bSJonas Devlieghere 348fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status((std::error_code())); 349fc51490bSJonas Devlieghere Lower->addDirectory("/both", sys::fs::owner_read); 350fc51490bSJonas Devlieghere Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read); 351fc51490bSJonas Devlieghere Status = O->status("/both"); 352fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError()); 353fc51490bSJonas Devlieghere EXPECT_EQ(0740, Status->getPermissions()); 354fc51490bSJonas Devlieghere 355fc51490bSJonas Devlieghere // permissions (as usual) are not recursively applied 356fc51490bSJonas Devlieghere Lower->addRegularFile("/both/foo", sys::fs::owner_read); 357fc51490bSJonas Devlieghere Upper->addRegularFile("/both/bar", sys::fs::owner_write); 358fc51490bSJonas Devlieghere Status = O->status("/both/foo"); 359fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError()); 360fc51490bSJonas Devlieghere EXPECT_EQ(0400, Status->getPermissions()); 361fc51490bSJonas Devlieghere Status = O->status("/both/bar"); 362fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError()); 363fc51490bSJonas Devlieghere EXPECT_EQ(0200, Status->getPermissions()); 364fc51490bSJonas Devlieghere } 365fc51490bSJonas Devlieghere 366efe21088SJonas Devlieghere TEST(VirtualFileSystemTest, OverlayIterator) { 367efe21088SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 368efe21088SJonas Devlieghere Lower->addRegularFile("/foo"); 369efe21088SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem()); 370efe21088SJonas Devlieghere 371efe21088SJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 372efe21088SJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 373efe21088SJonas Devlieghere O->pushOverlay(Upper); 374efe21088SJonas Devlieghere 375efe21088SJonas Devlieghere ErrorOr<vfs::Status> Status((std::error_code())); 376efe21088SJonas Devlieghere { 377efe21088SJonas Devlieghere auto it = O->overlays_begin(); 378efe21088SJonas Devlieghere auto end = O->overlays_end(); 379efe21088SJonas Devlieghere 380efe21088SJonas Devlieghere EXPECT_NE(it, end); 381efe21088SJonas Devlieghere 382efe21088SJonas Devlieghere Status = (*it)->status("/foo"); 383efe21088SJonas Devlieghere ASSERT_TRUE(Status.getError()); 384efe21088SJonas Devlieghere 385efe21088SJonas Devlieghere it++; 386efe21088SJonas Devlieghere EXPECT_NE(it, end); 387efe21088SJonas Devlieghere 388efe21088SJonas Devlieghere Status = (*it)->status("/foo"); 389efe21088SJonas Devlieghere ASSERT_FALSE(Status.getError()); 390efe21088SJonas Devlieghere EXPECT_TRUE(Status->exists()); 391efe21088SJonas Devlieghere 392efe21088SJonas Devlieghere it++; 393efe21088SJonas Devlieghere EXPECT_EQ(it, end); 394efe21088SJonas Devlieghere } 395efe21088SJonas Devlieghere 396efe21088SJonas Devlieghere { 397efe21088SJonas Devlieghere auto it = O->overlays_rbegin(); 398efe21088SJonas Devlieghere auto end = O->overlays_rend(); 399efe21088SJonas Devlieghere 400efe21088SJonas Devlieghere EXPECT_NE(it, end); 401efe21088SJonas Devlieghere 402efe21088SJonas Devlieghere Status = (*it)->status("/foo"); 403efe21088SJonas Devlieghere ASSERT_FALSE(Status.getError()); 404efe21088SJonas Devlieghere EXPECT_TRUE(Status->exists()); 405efe21088SJonas Devlieghere 406efe21088SJonas Devlieghere it++; 407efe21088SJonas Devlieghere EXPECT_NE(it, end); 408efe21088SJonas Devlieghere 409efe21088SJonas Devlieghere Status = (*it)->status("/foo"); 410efe21088SJonas Devlieghere ASSERT_TRUE(Status.getError()); 411efe21088SJonas Devlieghere 412efe21088SJonas Devlieghere it++; 413efe21088SJonas Devlieghere EXPECT_EQ(it, end); 414efe21088SJonas Devlieghere } 415efe21088SJonas Devlieghere } 416efe21088SJonas Devlieghere 417fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BasicRealFSIteration) { 418fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 419fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); 420fc51490bSJonas Devlieghere 421fc51490bSJonas Devlieghere std::error_code EC; 422fad75598SSergej Jaskiewicz vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory.path()), EC); 423fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 424fc51490bSJonas Devlieghere EXPECT_EQ(vfs::directory_iterator(), I); // empty directory is empty 425fc51490bSJonas Devlieghere 426fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 427fad75598SSergej Jaskiewicz TempDir _ab(TestDirectory.path("a/b")); 428fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c")); 429fad75598SSergej Jaskiewicz TempDir _cd(TestDirectory.path("c/d")); 430fc51490bSJonas Devlieghere 431fad75598SSergej Jaskiewicz I = FS->dir_begin(Twine(TestDirectory.path()), EC); 432fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 433fc51490bSJonas Devlieghere ASSERT_NE(vfs::directory_iterator(), I); 434fc51490bSJonas Devlieghere // Check either a or c, since we can't rely on the iteration order. 435fc51490bSJonas Devlieghere EXPECT_TRUE(I->path().endswith("a") || I->path().endswith("c")); 436fc51490bSJonas Devlieghere I.increment(EC); 437fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 438fc51490bSJonas Devlieghere ASSERT_NE(vfs::directory_iterator(), I); 439fc51490bSJonas Devlieghere EXPECT_TRUE(I->path().endswith("a") || I->path().endswith("c")); 440fc51490bSJonas Devlieghere I.increment(EC); 441fc51490bSJonas Devlieghere EXPECT_EQ(vfs::directory_iterator(), I); 442fc51490bSJonas Devlieghere } 443fc51490bSJonas Devlieghere 44462ab1a1aSSam McCall #ifdef LLVM_ON_UNIX 44515e475e2SSam McCall TEST(VirtualFileSystemTest, MultipleWorkingDirs) { 44615e475e2SSam McCall // Our root contains a/aa, b/bb, c, where c is a link to a/. 44715e475e2SSam McCall // Run tests both in root/b/ and root/c/ (to test "normal" and symlink dirs). 44815e475e2SSam McCall // Interleave operations to show the working directories are independent. 449fad75598SSergej Jaskiewicz TempDir Root("r", /*Unique*/ true); 450fad75598SSergej Jaskiewicz TempDir ADir(Root.path("a")); 451fad75598SSergej Jaskiewicz TempDir BDir(Root.path("b")); 452fad75598SSergej Jaskiewicz TempLink C(ADir.path(), Root.path("c")); 453fad75598SSergej Jaskiewicz TempFile AA(ADir.path("aa"), "", "aaaa"); 454fad75598SSergej Jaskiewicz TempFile BB(BDir.path("bb"), "", "bbbb"); 45515e475e2SSam McCall std::unique_ptr<vfs::FileSystem> BFS = vfs::createPhysicalFileSystem(), 45615e475e2SSam McCall CFS = vfs::createPhysicalFileSystem(); 45715e475e2SSam McCall 458fad75598SSergej Jaskiewicz ASSERT_FALSE(BFS->setCurrentWorkingDirectory(BDir.path())); 459fad75598SSergej Jaskiewicz ASSERT_FALSE(CFS->setCurrentWorkingDirectory(C.path())); 460fad75598SSergej Jaskiewicz EXPECT_EQ(BDir.path(), *BFS->getCurrentWorkingDirectory()); 461fad75598SSergej Jaskiewicz EXPECT_EQ(C.path(), *CFS->getCurrentWorkingDirectory()); 46215e475e2SSam McCall 46315e475e2SSam McCall // openFileForRead(), indirectly. 46415e475e2SSam McCall auto BBuf = BFS->getBufferForFile("bb"); 46515e475e2SSam McCall ASSERT_TRUE(BBuf); 46615e475e2SSam McCall EXPECT_EQ("bbbb", (*BBuf)->getBuffer()); 46715e475e2SSam McCall 46815e475e2SSam McCall auto ABuf = CFS->getBufferForFile("aa"); 46915e475e2SSam McCall ASSERT_TRUE(ABuf); 47015e475e2SSam McCall EXPECT_EQ("aaaa", (*ABuf)->getBuffer()); 47115e475e2SSam McCall 47215e475e2SSam McCall // status() 47315e475e2SSam McCall auto BStat = BFS->status("bb"); 47415e475e2SSam McCall ASSERT_TRUE(BStat); 47515e475e2SSam McCall EXPECT_EQ("bb", BStat->getName()); 47615e475e2SSam McCall 47715e475e2SSam McCall auto AStat = CFS->status("aa"); 47815e475e2SSam McCall ASSERT_TRUE(AStat); 47915e475e2SSam McCall EXPECT_EQ("aa", AStat->getName()); // unresolved name 48015e475e2SSam McCall 48115e475e2SSam McCall // getRealPath() 48215e475e2SSam McCall SmallString<128> BPath; 48315e475e2SSam McCall ASSERT_FALSE(BFS->getRealPath("bb", BPath)); 484fad75598SSergej Jaskiewicz EXPECT_EQ(BB.path(), BPath); 48515e475e2SSam McCall 48615e475e2SSam McCall SmallString<128> APath; 48715e475e2SSam McCall ASSERT_FALSE(CFS->getRealPath("aa", APath)); 488fad75598SSergej Jaskiewicz EXPECT_EQ(AA.path(), APath); // Reports resolved name. 48915e475e2SSam McCall 49015e475e2SSam McCall // dir_begin 49115e475e2SSam McCall std::error_code EC; 49215e475e2SSam McCall auto BIt = BFS->dir_begin(".", EC); 49315e475e2SSam McCall ASSERT_FALSE(EC); 49415e475e2SSam McCall ASSERT_NE(BIt, vfs::directory_iterator()); 495fad75598SSergej Jaskiewicz EXPECT_EQ((BDir.path() + "/./bb").str(), BIt->path()); 49615e475e2SSam McCall BIt.increment(EC); 49715e475e2SSam McCall ASSERT_FALSE(EC); 49815e475e2SSam McCall ASSERT_EQ(BIt, vfs::directory_iterator()); 49915e475e2SSam McCall 50015e475e2SSam McCall auto CIt = CFS->dir_begin(".", EC); 50115e475e2SSam McCall ASSERT_FALSE(EC); 50215e475e2SSam McCall ASSERT_NE(CIt, vfs::directory_iterator()); 503fad75598SSergej Jaskiewicz EXPECT_EQ((ADir.path() + "/./aa").str(), 504fad75598SSergej Jaskiewicz CIt->path()); // Partly resolved name! 50515e475e2SSam McCall CIt.increment(EC); // Because likely to read through this path. 50615e475e2SSam McCall ASSERT_FALSE(EC); 50715e475e2SSam McCall ASSERT_EQ(CIt, vfs::directory_iterator()); 50815e475e2SSam McCall } 50915e475e2SSam McCall 510fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) { 511fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 512fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); 513fc51490bSJonas Devlieghere 514fad75598SSergej Jaskiewicz TempLink _a("no_such_file", TestDirectory.path("a")); 515fad75598SSergej Jaskiewicz TempDir _b(TestDirectory.path("b")); 516fad75598SSergej Jaskiewicz TempLink _c("no_such_file", TestDirectory.path("c")); 517fc51490bSJonas Devlieghere 518fc51490bSJonas Devlieghere // Should get no iteration error, but a stat error for the broken symlinks. 519fc51490bSJonas Devlieghere std::map<std::string, std::error_code> StatResults; 520fc51490bSJonas Devlieghere std::error_code EC; 521fad75598SSergej Jaskiewicz for (vfs::directory_iterator 522fad75598SSergej Jaskiewicz I = FS->dir_begin(Twine(TestDirectory.path()), EC), 523fad75598SSergej Jaskiewicz E; 524fc51490bSJonas Devlieghere I != E; I.increment(EC)) { 525fc51490bSJonas Devlieghere EXPECT_FALSE(EC); 526adcd0268SBenjamin Kramer StatResults[std::string(sys::path::filename(I->path()))] = 527fc51490bSJonas Devlieghere FS->status(I->path()).getError(); 528fc51490bSJonas Devlieghere } 529fc51490bSJonas Devlieghere EXPECT_THAT( 530fc51490bSJonas Devlieghere StatResults, 531fc51490bSJonas Devlieghere ElementsAre( 532fc51490bSJonas Devlieghere Pair("a", std::make_error_code(std::errc::no_such_file_or_directory)), 533fc51490bSJonas Devlieghere Pair("b", std::error_code()), 534fc51490bSJonas Devlieghere Pair("c", 535fc51490bSJonas Devlieghere std::make_error_code(std::errc::no_such_file_or_directory)))); 536fc51490bSJonas Devlieghere } 537fc51490bSJonas Devlieghere #endif 538fc51490bSJonas Devlieghere 539fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) { 540fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 541fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); 542fc51490bSJonas Devlieghere 543fc51490bSJonas Devlieghere std::error_code EC; 544fad75598SSergej Jaskiewicz auto I = 545fad75598SSergej Jaskiewicz vfs::recursive_directory_iterator(*FS, Twine(TestDirectory.path()), EC); 546fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 547fc51490bSJonas Devlieghere EXPECT_EQ(vfs::recursive_directory_iterator(), I); // empty directory is empty 548fc51490bSJonas Devlieghere 549fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 550fad75598SSergej Jaskiewicz TempDir _ab(TestDirectory.path("a/b")); 551fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c")); 552fad75598SSergej Jaskiewicz TempDir _cd(TestDirectory.path("c/d")); 553fc51490bSJonas Devlieghere 554fad75598SSergej Jaskiewicz I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory.path()), EC); 555fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 556fc51490bSJonas Devlieghere ASSERT_NE(vfs::recursive_directory_iterator(), I); 557fc51490bSJonas Devlieghere 558fc51490bSJonas Devlieghere std::vector<std::string> Contents; 559fc51490bSJonas Devlieghere for (auto E = vfs::recursive_directory_iterator(); !EC && I != E; 560fc51490bSJonas Devlieghere I.increment(EC)) { 561adcd0268SBenjamin Kramer Contents.push_back(std::string(I->path())); 562fc51490bSJonas Devlieghere } 563fc51490bSJonas Devlieghere 564fc51490bSJonas Devlieghere // Check contents, which may be in any order 565fc51490bSJonas Devlieghere EXPECT_EQ(4U, Contents.size()); 566fc51490bSJonas Devlieghere int Counts[4] = {0, 0, 0, 0}; 567fc51490bSJonas Devlieghere for (const std::string &Name : Contents) { 568fc51490bSJonas Devlieghere ASSERT_FALSE(Name.empty()); 569fc51490bSJonas Devlieghere int Index = Name[Name.size() - 1] - 'a'; 570fc51490bSJonas Devlieghere ASSERT_TRUE(Index >= 0 && Index < 4); 571fc51490bSJonas Devlieghere Counts[Index]++; 572fc51490bSJonas Devlieghere } 573fc51490bSJonas Devlieghere EXPECT_EQ(1, Counts[0]); // a 574fc51490bSJonas Devlieghere EXPECT_EQ(1, Counts[1]); // b 575fc51490bSJonas Devlieghere EXPECT_EQ(1, Counts[2]); // c 576fc51490bSJonas Devlieghere EXPECT_EQ(1, Counts[3]); // d 577fc51490bSJonas Devlieghere } 578fc51490bSJonas Devlieghere 57941fb951fSJonas Devlieghere TEST(VirtualFileSystemTest, BasicRealFSRecursiveIterationNoPush) { 580fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 58141fb951fSJonas Devlieghere 582fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 583fad75598SSergej Jaskiewicz TempDir _ab(TestDirectory.path("a/b")); 584fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c")); 585fad75598SSergej Jaskiewicz TempDir _cd(TestDirectory.path("c/d")); 586fad75598SSergej Jaskiewicz TempDir _e(TestDirectory.path("e")); 587fad75598SSergej Jaskiewicz TempDir _ef(TestDirectory.path("e/f")); 588fad75598SSergej Jaskiewicz TempDir _g(TestDirectory.path("g")); 58941fb951fSJonas Devlieghere 59041fb951fSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); 59141fb951fSJonas Devlieghere 59241fb951fSJonas Devlieghere // Test that calling no_push on entries without subdirectories has no effect. 59341fb951fSJonas Devlieghere { 59441fb951fSJonas Devlieghere std::error_code EC; 595fad75598SSergej Jaskiewicz auto I = 596fad75598SSergej Jaskiewicz vfs::recursive_directory_iterator(*FS, Twine(TestDirectory.path()), EC); 59741fb951fSJonas Devlieghere ASSERT_FALSE(EC); 59841fb951fSJonas Devlieghere 59941fb951fSJonas Devlieghere std::vector<std::string> Contents; 60041fb951fSJonas Devlieghere for (auto E = vfs::recursive_directory_iterator(); !EC && I != E; 60141fb951fSJonas Devlieghere I.increment(EC)) { 602adcd0268SBenjamin Kramer Contents.push_back(std::string(I->path())); 60341fb951fSJonas Devlieghere char last = I->path().back(); 60441fb951fSJonas Devlieghere switch (last) { 60541fb951fSJonas Devlieghere case 'b': 60641fb951fSJonas Devlieghere case 'd': 60741fb951fSJonas Devlieghere case 'f': 60841fb951fSJonas Devlieghere case 'g': 60941fb951fSJonas Devlieghere I.no_push(); 61041fb951fSJonas Devlieghere break; 61141fb951fSJonas Devlieghere default: 61241fb951fSJonas Devlieghere break; 61341fb951fSJonas Devlieghere } 61441fb951fSJonas Devlieghere } 61541fb951fSJonas Devlieghere EXPECT_EQ(7U, Contents.size()); 61641fb951fSJonas Devlieghere } 61741fb951fSJonas Devlieghere 61841fb951fSJonas Devlieghere // Test that calling no_push skips subdirectories. 61941fb951fSJonas Devlieghere { 62041fb951fSJonas Devlieghere std::error_code EC; 621fad75598SSergej Jaskiewicz auto I = 622fad75598SSergej Jaskiewicz vfs::recursive_directory_iterator(*FS, Twine(TestDirectory.path()), EC); 62341fb951fSJonas Devlieghere ASSERT_FALSE(EC); 62441fb951fSJonas Devlieghere 62541fb951fSJonas Devlieghere std::vector<std::string> Contents; 62641fb951fSJonas Devlieghere for (auto E = vfs::recursive_directory_iterator(); !EC && I != E; 62741fb951fSJonas Devlieghere I.increment(EC)) { 628adcd0268SBenjamin Kramer Contents.push_back(std::string(I->path())); 62941fb951fSJonas Devlieghere char last = I->path().back(); 63041fb951fSJonas Devlieghere switch (last) { 63141fb951fSJonas Devlieghere case 'a': 63241fb951fSJonas Devlieghere case 'c': 63341fb951fSJonas Devlieghere case 'e': 63441fb951fSJonas Devlieghere I.no_push(); 63541fb951fSJonas Devlieghere break; 63641fb951fSJonas Devlieghere default: 63741fb951fSJonas Devlieghere break; 63841fb951fSJonas Devlieghere } 63941fb951fSJonas Devlieghere } 64041fb951fSJonas Devlieghere 64141fb951fSJonas Devlieghere // Check contents, which may be in any order 64241fb951fSJonas Devlieghere EXPECT_EQ(4U, Contents.size()); 64341fb951fSJonas Devlieghere int Counts[7] = {0, 0, 0, 0, 0, 0, 0}; 64441fb951fSJonas Devlieghere for (const std::string &Name : Contents) { 64541fb951fSJonas Devlieghere ASSERT_FALSE(Name.empty()); 64641fb951fSJonas Devlieghere int Index = Name[Name.size() - 1] - 'a'; 64741fb951fSJonas Devlieghere ASSERT_TRUE(Index >= 0 && Index < 7); 64841fb951fSJonas Devlieghere Counts[Index]++; 64941fb951fSJonas Devlieghere } 65041fb951fSJonas Devlieghere EXPECT_EQ(1, Counts[0]); // a 65141fb951fSJonas Devlieghere EXPECT_EQ(0, Counts[1]); // b 65241fb951fSJonas Devlieghere EXPECT_EQ(1, Counts[2]); // c 65341fb951fSJonas Devlieghere EXPECT_EQ(0, Counts[3]); // d 65441fb951fSJonas Devlieghere EXPECT_EQ(1, Counts[4]); // e 65541fb951fSJonas Devlieghere EXPECT_EQ(0, Counts[5]); // f 65641fb951fSJonas Devlieghere EXPECT_EQ(1, Counts[6]); // g 65741fb951fSJonas Devlieghere } 65841fb951fSJonas Devlieghere } 65941fb951fSJonas Devlieghere 660fc51490bSJonas Devlieghere #ifdef LLVM_ON_UNIX 661fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) { 662fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 663fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); 664fc51490bSJonas Devlieghere 665fad75598SSergej Jaskiewicz TempLink _a("no_such_file", TestDirectory.path("a")); 666fad75598SSergej Jaskiewicz TempDir _b(TestDirectory.path("b")); 667fad75598SSergej Jaskiewicz TempLink _ba("no_such_file", TestDirectory.path("b/a")); 668fad75598SSergej Jaskiewicz TempDir _bb(TestDirectory.path("b/b")); 669fad75598SSergej Jaskiewicz TempLink _bc("no_such_file", TestDirectory.path("b/c")); 670fad75598SSergej Jaskiewicz TempLink _c("no_such_file", TestDirectory.path("c")); 671fad75598SSergej Jaskiewicz TempDir _d(TestDirectory.path("d")); 672fad75598SSergej Jaskiewicz TempDir _dd(TestDirectory.path("d/d")); 673fad75598SSergej Jaskiewicz TempDir _ddd(TestDirectory.path("d/d/d")); 674fad75598SSergej Jaskiewicz TempLink _e("no_such_file", TestDirectory.path("e")); 675fc51490bSJonas Devlieghere 676fc51490bSJonas Devlieghere std::vector<std::string> VisitedBrokenSymlinks; 677fc51490bSJonas Devlieghere std::vector<std::string> VisitedNonBrokenSymlinks; 678fc51490bSJonas Devlieghere std::error_code EC; 679fad75598SSergej Jaskiewicz for (vfs::recursive_directory_iterator 680fad75598SSergej Jaskiewicz I(*FS, Twine(TestDirectory.path()), EC), 681fad75598SSergej Jaskiewicz E; 682fc51490bSJonas Devlieghere I != E; I.increment(EC)) { 683fc51490bSJonas Devlieghere EXPECT_FALSE(EC); 684fc51490bSJonas Devlieghere (FS->status(I->path()) ? VisitedNonBrokenSymlinks : VisitedBrokenSymlinks) 685adcd0268SBenjamin Kramer .push_back(std::string(I->path())); 686fc51490bSJonas Devlieghere } 687fc51490bSJonas Devlieghere 688fc51490bSJonas Devlieghere // Check visited file names. 689fc51490bSJonas Devlieghere EXPECT_THAT(VisitedBrokenSymlinks, 690fad75598SSergej Jaskiewicz UnorderedElementsAre(_a.path().str(), _ba.path().str(), 691fad75598SSergej Jaskiewicz _bc.path().str(), _c.path().str(), 692fad75598SSergej Jaskiewicz _e.path().str())); 693fc51490bSJonas Devlieghere EXPECT_THAT(VisitedNonBrokenSymlinks, 694fad75598SSergej Jaskiewicz UnorderedElementsAre(_b.path().str(), _bb.path().str(), 695fad75598SSergej Jaskiewicz _d.path().str(), _dd.path().str(), 696fad75598SSergej Jaskiewicz _ddd.path().str())); 697fc51490bSJonas Devlieghere } 698fc51490bSJonas Devlieghere #endif 699fc51490bSJonas Devlieghere 700fc51490bSJonas Devlieghere template <typename DirIter> 701fc51490bSJonas Devlieghere static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) { 702fc51490bSJonas Devlieghere std::error_code EC; 703fc51490bSJonas Devlieghere SmallVector<StringRef, 4> Expected(ExpectedOut.begin(), ExpectedOut.end()); 704fc51490bSJonas Devlieghere SmallVector<std::string, 4> InputToCheck; 705fc51490bSJonas Devlieghere 706fc51490bSJonas Devlieghere // Do not rely on iteration order to check for contents, sort both 707fc51490bSJonas Devlieghere // content vectors before comparison. 708fc51490bSJonas Devlieghere for (DirIter E; !EC && I != E; I.increment(EC)) 709adcd0268SBenjamin Kramer InputToCheck.push_back(std::string(I->path())); 710fc51490bSJonas Devlieghere 711fc51490bSJonas Devlieghere llvm::sort(InputToCheck); 712fc51490bSJonas Devlieghere llvm::sort(Expected); 713fc51490bSJonas Devlieghere EXPECT_EQ(InputToCheck.size(), Expected.size()); 714fc51490bSJonas Devlieghere 715fc51490bSJonas Devlieghere unsigned LastElt = std::min(InputToCheck.size(), Expected.size()); 716fc51490bSJonas Devlieghere for (unsigned Idx = 0; Idx != LastElt; ++Idx) 717fc51490bSJonas Devlieghere EXPECT_EQ(StringRef(InputToCheck[Idx]), Expected[Idx]); 718fc51490bSJonas Devlieghere } 719fc51490bSJonas Devlieghere 720fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, OverlayIteration) { 721fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 722fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem()); 723fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 724fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 725fc51490bSJonas Devlieghere O->pushOverlay(Upper); 726fc51490bSJonas Devlieghere 727fc51490bSJonas Devlieghere std::error_code EC; 728fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>()); 729fc51490bSJonas Devlieghere 730fc51490bSJonas Devlieghere Lower->addRegularFile("/file1"); 731fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1")); 732fc51490bSJonas Devlieghere 733fc51490bSJonas Devlieghere Upper->addRegularFile("/file2"); 734fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), {"/file2", "/file1"}); 735fc51490bSJonas Devlieghere 736fc51490bSJonas Devlieghere Lower->addDirectory("/dir1"); 737fc51490bSJonas Devlieghere Lower->addRegularFile("/dir1/foo"); 738fc51490bSJonas Devlieghere Upper->addDirectory("/dir2"); 739fc51490bSJonas Devlieghere Upper->addRegularFile("/dir2/foo"); 740fc51490bSJonas Devlieghere checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo")); 741fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), {"/dir2", "/file2", "/dir1", "/file1"}); 742fc51490bSJonas Devlieghere } 743fc51490bSJonas Devlieghere 744fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, OverlayRecursiveIteration) { 745fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 746fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem()); 747fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem()); 748fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 749fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 750fc51490bSJonas Devlieghere O->pushOverlay(Middle); 751fc51490bSJonas Devlieghere O->pushOverlay(Upper); 752fc51490bSJonas Devlieghere 753fc51490bSJonas Devlieghere std::error_code EC; 754fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/", EC), 755fc51490bSJonas Devlieghere ArrayRef<StringRef>()); 756fc51490bSJonas Devlieghere 757fc51490bSJonas Devlieghere Lower->addRegularFile("/file1"); 758fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/", EC), 759fc51490bSJonas Devlieghere ArrayRef<StringRef>("/file1")); 760fc51490bSJonas Devlieghere 761fc51490bSJonas Devlieghere Upper->addDirectory("/dir"); 762fc51490bSJonas Devlieghere Upper->addRegularFile("/dir/file2"); 763fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/", EC), 764fc51490bSJonas Devlieghere {"/dir", "/dir/file2", "/file1"}); 765fc51490bSJonas Devlieghere 766fc51490bSJonas Devlieghere Lower->addDirectory("/dir1"); 767fc51490bSJonas Devlieghere Lower->addRegularFile("/dir1/foo"); 768fc51490bSJonas Devlieghere Lower->addDirectory("/dir1/a"); 769fc51490bSJonas Devlieghere Lower->addRegularFile("/dir1/a/b"); 770fc51490bSJonas Devlieghere Middle->addDirectory("/a"); 771fc51490bSJonas Devlieghere Middle->addDirectory("/a/b"); 772fc51490bSJonas Devlieghere Middle->addDirectory("/a/b/c"); 773fc51490bSJonas Devlieghere Middle->addRegularFile("/a/b/c/d"); 774fc51490bSJonas Devlieghere Middle->addRegularFile("/hiddenByUp"); 775fc51490bSJonas Devlieghere Upper->addDirectory("/dir2"); 776fc51490bSJonas Devlieghere Upper->addRegularFile("/dir2/foo"); 777fc51490bSJonas Devlieghere Upper->addRegularFile("/hiddenByUp"); 778fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/dir2", EC), 779fc51490bSJonas Devlieghere ArrayRef<StringRef>("/dir2/foo")); 780fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/", EC), 781fc51490bSJonas Devlieghere {"/dir", "/dir/file2", "/dir2", "/dir2/foo", "/hiddenByUp", 782fc51490bSJonas Devlieghere "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/dir1", "/dir1/a", 783fc51490bSJonas Devlieghere "/dir1/a/b", "/dir1/foo", "/file1"}); 784fc51490bSJonas Devlieghere } 785fc51490bSJonas Devlieghere 786fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, ThreeLevelIteration) { 787fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 788fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem()); 789fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem()); 790fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 791fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 792fc51490bSJonas Devlieghere O->pushOverlay(Middle); 793fc51490bSJonas Devlieghere O->pushOverlay(Upper); 794fc51490bSJonas Devlieghere 795fc51490bSJonas Devlieghere std::error_code EC; 796fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>()); 797fc51490bSJonas Devlieghere 798fc51490bSJonas Devlieghere Middle->addRegularFile("/file2"); 799fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2")); 800fc51490bSJonas Devlieghere 801fc51490bSJonas Devlieghere Lower->addRegularFile("/file1"); 802fc51490bSJonas Devlieghere Upper->addRegularFile("/file3"); 803fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), {"/file3", "/file2", "/file1"}); 804fc51490bSJonas Devlieghere } 805fc51490bSJonas Devlieghere 806fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, HiddenInIteration) { 807fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 808fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem()); 809fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem()); 810fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 811fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 812fc51490bSJonas Devlieghere O->pushOverlay(Middle); 813fc51490bSJonas Devlieghere O->pushOverlay(Upper); 814fc51490bSJonas Devlieghere 815fc51490bSJonas Devlieghere std::error_code EC; 816fc51490bSJonas Devlieghere Lower->addRegularFile("/onlyInLow"); 817fc51490bSJonas Devlieghere Lower->addDirectory("/hiddenByMid"); 818fc51490bSJonas Devlieghere Lower->addDirectory("/hiddenByUp"); 819fc51490bSJonas Devlieghere Middle->addRegularFile("/onlyInMid"); 820fc51490bSJonas Devlieghere Middle->addRegularFile("/hiddenByMid"); 821fc51490bSJonas Devlieghere Middle->addDirectory("/hiddenByUp"); 822fc51490bSJonas Devlieghere Upper->addRegularFile("/onlyInUp"); 823fc51490bSJonas Devlieghere Upper->addRegularFile("/hiddenByUp"); 824fc51490bSJonas Devlieghere checkContents( 825fc51490bSJonas Devlieghere O->dir_begin("/", EC), 826fc51490bSJonas Devlieghere {"/hiddenByUp", "/onlyInUp", "/hiddenByMid", "/onlyInMid", "/onlyInLow"}); 827fc51490bSJonas Devlieghere 828fc51490bSJonas Devlieghere // Make sure we get the top-most entry 829fc51490bSJonas Devlieghere { 830fc51490bSJonas Devlieghere std::error_code EC; 831fc51490bSJonas Devlieghere vfs::directory_iterator I = O->dir_begin("/", EC), E; 832fc51490bSJonas Devlieghere for (; !EC && I != E; I.increment(EC)) 833fc51490bSJonas Devlieghere if (I->path() == "/hiddenByUp") 834fc51490bSJonas Devlieghere break; 835fc51490bSJonas Devlieghere ASSERT_NE(E, I); 836fc51490bSJonas Devlieghere EXPECT_EQ(sys::fs::file_type::regular_file, I->type()); 837fc51490bSJonas Devlieghere } 838fc51490bSJonas Devlieghere { 839fc51490bSJonas Devlieghere std::error_code EC; 840fc51490bSJonas Devlieghere vfs::directory_iterator I = O->dir_begin("/", EC), E; 841fc51490bSJonas Devlieghere for (; !EC && I != E; I.increment(EC)) 842fc51490bSJonas Devlieghere if (I->path() == "/hiddenByMid") 843fc51490bSJonas Devlieghere break; 844fc51490bSJonas Devlieghere ASSERT_NE(E, I); 845fc51490bSJonas Devlieghere EXPECT_EQ(sys::fs::file_type::regular_file, I->type()); 846fc51490bSJonas Devlieghere } 847fc51490bSJonas Devlieghere } 848fc51490bSJonas Devlieghere 849937a1047SMichael J. Spencer TEST(ProxyFileSystemTest, Basic) { 850937a1047SMichael J. Spencer IntrusiveRefCntPtr<vfs::InMemoryFileSystem> Base( 851937a1047SMichael J. Spencer new vfs::InMemoryFileSystem()); 852937a1047SMichael J. Spencer vfs::ProxyFileSystem PFS(Base); 853937a1047SMichael J. Spencer 854937a1047SMichael J. Spencer Base->addFile("/a", 0, MemoryBuffer::getMemBuffer("test")); 855937a1047SMichael J. Spencer 856937a1047SMichael J. Spencer auto Stat = PFS.status("/a"); 857937a1047SMichael J. Spencer ASSERT_FALSE(Stat.getError()); 858937a1047SMichael J. Spencer 859937a1047SMichael J. Spencer auto File = PFS.openFileForRead("/a"); 860937a1047SMichael J. Spencer ASSERT_FALSE(File.getError()); 861937a1047SMichael J. Spencer EXPECT_EQ("test", (*(*File)->getBuffer("ignored"))->getBuffer()); 862937a1047SMichael J. Spencer 863937a1047SMichael J. Spencer std::error_code EC; 864937a1047SMichael J. Spencer vfs::directory_iterator I = PFS.dir_begin("/", EC); 865937a1047SMichael J. Spencer ASSERT_FALSE(EC); 866937a1047SMichael J. Spencer ASSERT_EQ("/a", I->path()); 867937a1047SMichael J. Spencer I.increment(EC); 868937a1047SMichael J. Spencer ASSERT_FALSE(EC); 869937a1047SMichael J. Spencer ASSERT_EQ(vfs::directory_iterator(), I); 870937a1047SMichael J. Spencer 871937a1047SMichael J. Spencer ASSERT_FALSE(PFS.setCurrentWorkingDirectory("/")); 872937a1047SMichael J. Spencer 873937a1047SMichael J. Spencer auto PWD = PFS.getCurrentWorkingDirectory(); 874937a1047SMichael J. Spencer ASSERT_FALSE(PWD.getError()); 875937a1047SMichael J. Spencer ASSERT_EQ("/", *PWD); 876937a1047SMichael J. Spencer 877937a1047SMichael J. Spencer SmallString<16> Path; 878937a1047SMichael J. Spencer ASSERT_FALSE(PFS.getRealPath("a", Path)); 879937a1047SMichael J. Spencer ASSERT_EQ("/a", Path); 880937a1047SMichael J. Spencer 881937a1047SMichael J. Spencer bool Local = true; 882937a1047SMichael J. Spencer ASSERT_FALSE(PFS.isLocal("/a", Local)); 8832a5a0ad1SMichael J. Spencer EXPECT_FALSE(Local); 884937a1047SMichael J. Spencer } 885937a1047SMichael J. Spencer 886fc51490bSJonas Devlieghere class InMemoryFileSystemTest : public ::testing::Test { 887fc51490bSJonas Devlieghere protected: 888fc51490bSJonas Devlieghere llvm::vfs::InMemoryFileSystem FS; 889fc51490bSJonas Devlieghere llvm::vfs::InMemoryFileSystem NormalizedFS; 890fc51490bSJonas Devlieghere 891fc51490bSJonas Devlieghere InMemoryFileSystemTest() 892fc51490bSJonas Devlieghere : FS(/*UseNormalizedPaths=*/false), 893fc51490bSJonas Devlieghere NormalizedFS(/*UseNormalizedPaths=*/true) {} 894fc51490bSJonas Devlieghere }; 895fc51490bSJonas Devlieghere 896fc51490bSJonas Devlieghere MATCHER_P2(IsHardLinkTo, FS, Target, "") { 897fc51490bSJonas Devlieghere StringRef From = arg; 898fc51490bSJonas Devlieghere StringRef To = Target; 899fc51490bSJonas Devlieghere auto OpenedFrom = FS->openFileForRead(From); 900fc51490bSJonas Devlieghere auto OpenedTo = FS->openFileForRead(To); 901fc51490bSJonas Devlieghere return !OpenedFrom.getError() && !OpenedTo.getError() && 902fc51490bSJonas Devlieghere (*OpenedFrom)->status()->getUniqueID() == 903fc51490bSJonas Devlieghere (*OpenedTo)->status()->getUniqueID(); 904fc51490bSJonas Devlieghere } 905fc51490bSJonas Devlieghere 906fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, IsEmpty) { 907fc51490bSJonas Devlieghere auto Stat = FS.status("/a"); 908fc51490bSJonas Devlieghere ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString(); 909fc51490bSJonas Devlieghere Stat = FS.status("/"); 910fc51490bSJonas Devlieghere ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString(); 911fc51490bSJonas Devlieghere } 912fc51490bSJonas Devlieghere 913fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, WindowsPath) { 914fc51490bSJonas Devlieghere FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer("")); 915fc51490bSJonas Devlieghere auto Stat = FS.status("c:"); 916fc51490bSJonas Devlieghere #if !defined(_WIN32) 917fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); 918fc51490bSJonas Devlieghere #endif 919fc51490bSJonas Devlieghere Stat = FS.status("c:/windows/system128/foo.cpp"); 920fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); 921fc51490bSJonas Devlieghere FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer("")); 922fc51490bSJonas Devlieghere Stat = FS.status("d:/windows/foo.cpp"); 923fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); 924fc51490bSJonas Devlieghere } 925fc51490bSJonas Devlieghere 926fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, OverlayFile) { 927fc51490bSJonas Devlieghere FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")); 928fc51490bSJonas Devlieghere NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")); 929fc51490bSJonas Devlieghere auto Stat = FS.status("/"); 930fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); 931fc51490bSJonas Devlieghere Stat = FS.status("/."); 932fc51490bSJonas Devlieghere ASSERT_FALSE(Stat); 933fc51490bSJonas Devlieghere Stat = NormalizedFS.status("/."); 934fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString(); 935fc51490bSJonas Devlieghere Stat = FS.status("/a"); 936fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 937fc51490bSJonas Devlieghere ASSERT_EQ("/a", Stat->getName()); 938fc51490bSJonas Devlieghere } 939fc51490bSJonas Devlieghere 940fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) { 941fc51490bSJonas Devlieghere auto Buf = MemoryBuffer::getMemBuffer("a"); 942e763e032SDuncan P. N. Exon Smith FS.addFileNoOwn("/a", 0, *Buf); 943fc51490bSJonas Devlieghere auto Stat = FS.status("/a"); 944fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 945fc51490bSJonas Devlieghere ASSERT_EQ("/a", Stat->getName()); 946fc51490bSJonas Devlieghere } 947fc51490bSJonas Devlieghere 948fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, OpenFileForRead) { 949fc51490bSJonas Devlieghere FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")); 950fc51490bSJonas Devlieghere FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c")); 951fc51490bSJonas Devlieghere FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d")); 952fc51490bSJonas Devlieghere NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")); 953fc51490bSJonas Devlieghere NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c")); 954fc51490bSJonas Devlieghere NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d")); 955fc51490bSJonas Devlieghere auto File = FS.openFileForRead("/a"); 956fc51490bSJonas Devlieghere ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer()); 957fc51490bSJonas Devlieghere File = FS.openFileForRead("/a"); // Open again. 958fc51490bSJonas Devlieghere ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer()); 959fc51490bSJonas Devlieghere File = NormalizedFS.openFileForRead("/././a"); // Open again. 960fc51490bSJonas Devlieghere ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer()); 961fc51490bSJonas Devlieghere File = FS.openFileForRead("/"); 962fc51490bSJonas Devlieghere ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString(); 963fc51490bSJonas Devlieghere File = FS.openFileForRead("/b"); 964fc51490bSJonas Devlieghere ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString(); 965fc51490bSJonas Devlieghere File = FS.openFileForRead("./c"); 966fc51490bSJonas Devlieghere ASSERT_FALSE(File); 967fc51490bSJonas Devlieghere File = FS.openFileForRead("e/../d"); 968fc51490bSJonas Devlieghere ASSERT_FALSE(File); 969fc51490bSJonas Devlieghere File = NormalizedFS.openFileForRead("./c"); 970fc51490bSJonas Devlieghere ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer()); 971fc51490bSJonas Devlieghere File = NormalizedFS.openFileForRead("e/../d"); 972fc51490bSJonas Devlieghere ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer()); 973fc51490bSJonas Devlieghere } 974fc51490bSJonas Devlieghere 975fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, DuplicatedFile) { 976fc51490bSJonas Devlieghere ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"))); 977fc51490bSJonas Devlieghere ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a"))); 978fc51490bSJonas Devlieghere ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"))); 979fc51490bSJonas Devlieghere ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b"))); 980fc51490bSJonas Devlieghere } 981fc51490bSJonas Devlieghere 982fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, DirectoryIteration) { 983fc51490bSJonas Devlieghere FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("")); 984fc51490bSJonas Devlieghere FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer("")); 985fc51490bSJonas Devlieghere 986fc51490bSJonas Devlieghere std::error_code EC; 987fc51490bSJonas Devlieghere vfs::directory_iterator I = FS.dir_begin("/", EC); 988fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 989fc51490bSJonas Devlieghere ASSERT_EQ("/a", I->path()); 990fc51490bSJonas Devlieghere I.increment(EC); 991fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 992fc51490bSJonas Devlieghere ASSERT_EQ("/b", I->path()); 993fc51490bSJonas Devlieghere I.increment(EC); 994fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 995fc51490bSJonas Devlieghere ASSERT_EQ(vfs::directory_iterator(), I); 996fc51490bSJonas Devlieghere 997fc51490bSJonas Devlieghere I = FS.dir_begin("/b", EC); 998fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 999fc51490bSJonas Devlieghere // When on Windows, we end up with "/b\\c" as the name. Convert to Posix 1000fc51490bSJonas Devlieghere // path for the sake of the comparison. 1001adcd0268SBenjamin Kramer ASSERT_EQ("/b/c", getPosixPath(std::string(I->path()))); 1002fc51490bSJonas Devlieghere I.increment(EC); 1003fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 1004fc51490bSJonas Devlieghere ASSERT_EQ(vfs::directory_iterator(), I); 1005fc51490bSJonas Devlieghere } 1006fc51490bSJonas Devlieghere 1007fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, WorkingDirectory) { 1008fc51490bSJonas Devlieghere FS.setCurrentWorkingDirectory("/b"); 1009fc51490bSJonas Devlieghere FS.addFile("c", 0, MemoryBuffer::getMemBuffer("")); 1010fc51490bSJonas Devlieghere 1011fc51490bSJonas Devlieghere auto Stat = FS.status("/b/c"); 1012fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1013fc51490bSJonas Devlieghere ASSERT_EQ("/b/c", Stat->getName()); 1014fc51490bSJonas Devlieghere ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory()); 1015fc51490bSJonas Devlieghere 1016fc51490bSJonas Devlieghere Stat = FS.status("c"); 1017fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1018fc51490bSJonas Devlieghere 1019fc51490bSJonas Devlieghere NormalizedFS.setCurrentWorkingDirectory("/b/c"); 1020fc51490bSJonas Devlieghere NormalizedFS.setCurrentWorkingDirectory("."); 1021fc51490bSJonas Devlieghere ASSERT_EQ("/b/c", 1022fc51490bSJonas Devlieghere getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get())); 1023fc51490bSJonas Devlieghere NormalizedFS.setCurrentWorkingDirectory(".."); 1024fc51490bSJonas Devlieghere ASSERT_EQ("/b", 1025fc51490bSJonas Devlieghere getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get())); 1026fc51490bSJonas Devlieghere } 1027fc51490bSJonas Devlieghere 1028cbb5c868SJonas Devlieghere TEST_F(InMemoryFileSystemTest, IsLocal) { 1029cbb5c868SJonas Devlieghere FS.setCurrentWorkingDirectory("/b"); 1030cbb5c868SJonas Devlieghere FS.addFile("c", 0, MemoryBuffer::getMemBuffer("")); 1031cbb5c868SJonas Devlieghere 1032cbb5c868SJonas Devlieghere std::error_code EC; 1033cbb5c868SJonas Devlieghere bool IsLocal = true; 1034cbb5c868SJonas Devlieghere EC = FS.isLocal("c", IsLocal); 1035cbb5c868SJonas Devlieghere ASSERT_FALSE(EC); 1036cbb5c868SJonas Devlieghere ASSERT_FALSE(IsLocal); 1037cbb5c868SJonas Devlieghere } 1038cbb5c868SJonas Devlieghere 1039fc51490bSJonas Devlieghere #if !defined(_WIN32) 1040fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, GetRealPath) { 1041fc51490bSJonas Devlieghere SmallString<16> Path; 1042fc51490bSJonas Devlieghere EXPECT_EQ(FS.getRealPath("b", Path), errc::operation_not_permitted); 1043fc51490bSJonas Devlieghere 1044fc51490bSJonas Devlieghere auto GetRealPath = [this](StringRef P) { 1045fc51490bSJonas Devlieghere SmallString<16> Output; 1046fc51490bSJonas Devlieghere auto EC = FS.getRealPath(P, Output); 1047fc51490bSJonas Devlieghere EXPECT_FALSE(EC); 1048b2924d99SJonas Devlieghere return std::string(Output); 1049fc51490bSJonas Devlieghere }; 1050fc51490bSJonas Devlieghere 1051fc51490bSJonas Devlieghere FS.setCurrentWorkingDirectory("a"); 1052fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("b"), "a/b"); 1053fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("../b"), "b"); 1054fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("b/./c"), "a/b/c"); 1055fc51490bSJonas Devlieghere 1056fc51490bSJonas Devlieghere FS.setCurrentWorkingDirectory("/a"); 1057fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("b"), "/a/b"); 1058fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("../b"), "/b"); 1059fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("b/./c"), "/a/b/c"); 1060fc51490bSJonas Devlieghere } 1061fc51490bSJonas Devlieghere #endif // _WIN32 1062fc51490bSJonas Devlieghere 1063fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileWithUser) { 1064fc51490bSJonas Devlieghere FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), 0xFEEDFACE); 1065fc51490bSJonas Devlieghere auto Stat = FS.status("/a"); 1066fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1067fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory()); 1068fc51490bSJonas Devlieghere ASSERT_EQ(0xFEEDFACE, Stat->getUser()); 1069fc51490bSJonas Devlieghere Stat = FS.status("/a/b"); 1070fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1071fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory()); 1072fc51490bSJonas Devlieghere ASSERT_EQ(0xFEEDFACE, Stat->getUser()); 1073fc51490bSJonas Devlieghere Stat = FS.status("/a/b/c"); 1074fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1075fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile()); 1076fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions()); 1077fc51490bSJonas Devlieghere ASSERT_EQ(0xFEEDFACE, Stat->getUser()); 1078fc51490bSJonas Devlieghere } 1079fc51490bSJonas Devlieghere 1080fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileWithGroup) { 1081fc51490bSJonas Devlieghere FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, 0xDABBAD00); 1082fc51490bSJonas Devlieghere auto Stat = FS.status("/a"); 1083fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1084fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory()); 1085fc51490bSJonas Devlieghere ASSERT_EQ(0xDABBAD00, Stat->getGroup()); 1086fc51490bSJonas Devlieghere Stat = FS.status("/a/b"); 1087fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory()); 1088fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1089fc51490bSJonas Devlieghere ASSERT_EQ(0xDABBAD00, Stat->getGroup()); 1090fc51490bSJonas Devlieghere Stat = FS.status("/a/b/c"); 1091fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1092fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile()); 1093fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions()); 1094fc51490bSJonas Devlieghere ASSERT_EQ(0xDABBAD00, Stat->getGroup()); 1095fc51490bSJonas Devlieghere } 1096fc51490bSJonas Devlieghere 1097fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileWithFileType) { 1098fc51490bSJonas Devlieghere FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, None, 1099fc51490bSJonas Devlieghere sys::fs::file_type::socket_file); 1100fc51490bSJonas Devlieghere auto Stat = FS.status("/a"); 1101fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1102fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory()); 1103fc51490bSJonas Devlieghere Stat = FS.status("/a/b"); 1104fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1105fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory()); 1106fc51490bSJonas Devlieghere Stat = FS.status("/a/b/c"); 1107fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1108fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::file_type::socket_file, Stat->getType()); 1109fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions()); 1110fc51490bSJonas Devlieghere } 1111fc51490bSJonas Devlieghere 1112fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileWithPerms) { 1113fc51490bSJonas Devlieghere FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, None, None, 1114fc51490bSJonas Devlieghere sys::fs::perms::owner_read | sys::fs::perms::owner_write); 1115fc51490bSJonas Devlieghere auto Stat = FS.status("/a"); 1116fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1117fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory()); 1118fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write | 1119fc51490bSJonas Devlieghere sys::fs::perms::owner_exe, 1120fc51490bSJonas Devlieghere Stat->getPermissions()); 1121fc51490bSJonas Devlieghere Stat = FS.status("/a/b"); 1122fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1123fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory()); 1124fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write | 1125fc51490bSJonas Devlieghere sys::fs::perms::owner_exe, 1126fc51490bSJonas Devlieghere Stat->getPermissions()); 1127fc51490bSJonas Devlieghere Stat = FS.status("/a/b/c"); 1128fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1129fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile()); 1130fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write, 1131fc51490bSJonas Devlieghere Stat->getPermissions()); 1132fc51490bSJonas Devlieghere } 1133fc51490bSJonas Devlieghere 1134fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddDirectoryThenAddChild) { 1135fc51490bSJonas Devlieghere FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""), /*User=*/None, 1136fc51490bSJonas Devlieghere /*Group=*/None, sys::fs::file_type::directory_file); 1137fc51490bSJonas Devlieghere FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("abc"), /*User=*/None, 1138fc51490bSJonas Devlieghere /*Group=*/None, sys::fs::file_type::regular_file); 1139fc51490bSJonas Devlieghere auto Stat = FS.status("/a"); 1140fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1141fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory()); 1142fc51490bSJonas Devlieghere Stat = FS.status("/a/b"); 1143fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); 1144fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile()); 1145fc51490bSJonas Devlieghere } 1146fc51490bSJonas Devlieghere 1147fc51490bSJonas Devlieghere // Test that the name returned by status() is in the same form as the path that 1148fc51490bSJonas Devlieghere // was requested (to match the behavior of RealFileSystem). 1149fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, StatusName) { 1150fc51490bSJonas Devlieghere NormalizedFS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), 1151fc51490bSJonas Devlieghere /*User=*/None, 1152fc51490bSJonas Devlieghere /*Group=*/None, sys::fs::file_type::regular_file); 1153fc51490bSJonas Devlieghere NormalizedFS.setCurrentWorkingDirectory("/a/b"); 1154fc51490bSJonas Devlieghere 1155fc51490bSJonas Devlieghere // Access using InMemoryFileSystem::status. 1156fc51490bSJonas Devlieghere auto Stat = NormalizedFS.status("../b/c"); 1157fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" 1158fc51490bSJonas Devlieghere << NormalizedFS.toString(); 1159fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile()); 1160fc51490bSJonas Devlieghere ASSERT_EQ("../b/c", Stat->getName()); 1161fc51490bSJonas Devlieghere 1162fc51490bSJonas Devlieghere // Access using InMemoryFileAdaptor::status. 1163fc51490bSJonas Devlieghere auto File = NormalizedFS.openFileForRead("../b/c"); 1164fc51490bSJonas Devlieghere ASSERT_FALSE(File.getError()) << File.getError() << "\n" 1165fc51490bSJonas Devlieghere << NormalizedFS.toString(); 1166fc51490bSJonas Devlieghere Stat = (*File)->status(); 1167fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" 1168fc51490bSJonas Devlieghere << NormalizedFS.toString(); 1169fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile()); 1170fc51490bSJonas Devlieghere ASSERT_EQ("../b/c", Stat->getName()); 1171fc51490bSJonas Devlieghere 1172fc51490bSJonas Devlieghere // Access using a directory iterator. 1173fc51490bSJonas Devlieghere std::error_code EC; 1174fc51490bSJonas Devlieghere llvm::vfs::directory_iterator It = NormalizedFS.dir_begin("../b", EC); 1175fc51490bSJonas Devlieghere // When on Windows, we end up with "../b\\c" as the name. Convert to Posix 1176fc51490bSJonas Devlieghere // path for the sake of the comparison. 1177adcd0268SBenjamin Kramer ASSERT_EQ("../b/c", getPosixPath(std::string(It->path()))); 1178fc51490bSJonas Devlieghere } 1179fc51490bSJonas Devlieghere 1180fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) { 1181fc51490bSJonas Devlieghere StringRef FromLink = "/path/to/FROM/link"; 1182fc51490bSJonas Devlieghere StringRef Target = "/path/to/TO/file"; 1183fc51490bSJonas Devlieghere FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target")); 1184fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(FromLink, Target)); 1185fc51490bSJonas Devlieghere EXPECT_THAT(FromLink, IsHardLinkTo(&FS, Target)); 1186fc51490bSJonas Devlieghere EXPECT_TRUE(FS.status(FromLink)->getSize() == FS.status(Target)->getSize()); 1187fc51490bSJonas Devlieghere EXPECT_TRUE(FS.getBufferForFile(FromLink)->get()->getBuffer() == 1188fc51490bSJonas Devlieghere FS.getBufferForFile(Target)->get()->getBuffer()); 1189fc51490bSJonas Devlieghere } 1190fc51490bSJonas Devlieghere 1191fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) { 1192fc51490bSJonas Devlieghere StringRef Link0 = "/path/to/0/link"; 1193fc51490bSJonas Devlieghere StringRef Link1 = "/path/to/1/link"; 1194fc51490bSJonas Devlieghere StringRef Link2 = "/path/to/2/link"; 1195fc51490bSJonas Devlieghere StringRef Target = "/path/to/target"; 1196fc51490bSJonas Devlieghere FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target file")); 1197fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link2, Target)); 1198fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link1, Link2)); 1199fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link0, Link1)); 1200fc51490bSJonas Devlieghere EXPECT_THAT(Link0, IsHardLinkTo(&FS, Target)); 1201fc51490bSJonas Devlieghere EXPECT_THAT(Link1, IsHardLinkTo(&FS, Target)); 1202fc51490bSJonas Devlieghere EXPECT_THAT(Link2, IsHardLinkTo(&FS, Target)); 1203fc51490bSJonas Devlieghere } 1204fc51490bSJonas Devlieghere 1205fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) { 1206fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink("/path/to/link", "/path/to/target")); 1207fc51490bSJonas Devlieghere } 1208fc51490bSJonas Devlieghere 1209fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) { 1210fc51490bSJonas Devlieghere StringRef Link = "/path/to/link"; 1211fc51490bSJonas Devlieghere StringRef Target = "/path/to/target"; 1212fc51490bSJonas Devlieghere FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target")); 1213fc51490bSJonas Devlieghere FS.addFile(Link, 0, MemoryBuffer::getMemBuffer("content of link")); 1214fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink(Link, Target)); 1215fc51490bSJonas Devlieghere } 1216fc51490bSJonas Devlieghere 1217fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) { 1218fc51490bSJonas Devlieghere StringRef Link = "/path/to/link"; 1219fc51490bSJonas Devlieghere StringRef Target = "/path/to/target"; 1220fc51490bSJonas Devlieghere FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target")); 1221fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link, Target)); 1222fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink(Link, Target)); 1223fc51490bSJonas Devlieghere } 1224fc51490bSJonas Devlieghere 1225fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) { 1226fc51490bSJonas Devlieghere StringRef Link = "/path/to/link"; 1227fc51490bSJonas Devlieghere StringRef Target = "/path/to/target"; 1228fc51490bSJonas Devlieghere StringRef Content = "content of target"; 1229fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content))); 1230fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link, Target)); 1231fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(Content))); 1232fc51490bSJonas Devlieghere } 1233fc51490bSJonas Devlieghere 1234fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) { 1235fc51490bSJonas Devlieghere StringRef Link = "/path/to/link"; 1236fc51490bSJonas Devlieghere StringRef Target = "/path/to/target"; 1237fc51490bSJonas Devlieghere StringRef Content = "content of target"; 1238fc51490bSJonas Devlieghere StringRef LinkContent = "different content of link"; 1239fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content))); 1240fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link, Target)); 1241fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(LinkContent))); 1242fc51490bSJonas Devlieghere } 1243fc51490bSJonas Devlieghere 1244fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) { 1245fc51490bSJonas Devlieghere StringRef Dir = "path/to/dummy/dir"; 1246fc51490bSJonas Devlieghere StringRef Link = "/path/to/link"; 1247fc51490bSJonas Devlieghere StringRef File = "path/to/dummy/dir/target"; 1248fc51490bSJonas Devlieghere StringRef Content = "content of target"; 1249fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(File, 0, MemoryBuffer::getMemBuffer(Content))); 1250fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink(Link, Dir)); 1251fc51490bSJonas Devlieghere } 1252fc51490bSJonas Devlieghere 1253fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkFromADirectory) { 1254fc51490bSJonas Devlieghere StringRef Dir = "path/to/dummy/dir"; 1255fc51490bSJonas Devlieghere StringRef Target = "path/to/dummy/dir/target"; 1256fc51490bSJonas Devlieghere StringRef Content = "content of target"; 1257fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content))); 1258fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink(Dir, Target)); 1259fc51490bSJonas Devlieghere } 1260fc51490bSJonas Devlieghere 1261fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkUnderAFile) { 1262fc51490bSJonas Devlieghere StringRef CommonContent = "content string"; 1263fc51490bSJonas Devlieghere FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer(CommonContent)); 1264fc51490bSJonas Devlieghere FS.addFile("/c/d", 0, MemoryBuffer::getMemBuffer(CommonContent)); 1265fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink("/c/d/e", "/a/b")); 1266fc51490bSJonas Devlieghere } 1267fc51490bSJonas Devlieghere 1268fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, RecursiveIterationWithHardLink) { 1269fc51490bSJonas Devlieghere std::error_code EC; 1270fc51490bSJonas Devlieghere FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("content string")); 1271fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink("/c/d", "/a/b")); 1272fc51490bSJonas Devlieghere auto I = vfs::recursive_directory_iterator(FS, "/", EC); 1273fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 1274fc51490bSJonas Devlieghere std::vector<std::string> Nodes; 1275fc51490bSJonas Devlieghere for (auto E = vfs::recursive_directory_iterator(); !EC && I != E; 1276fc51490bSJonas Devlieghere I.increment(EC)) { 1277adcd0268SBenjamin Kramer Nodes.push_back(getPosixPath(std::string(I->path()))); 1278fc51490bSJonas Devlieghere } 1279fc51490bSJonas Devlieghere EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/a", "/a/b", "/c", "/c/d")); 1280fc51490bSJonas Devlieghere } 1281fc51490bSJonas Devlieghere 1282fc51490bSJonas Devlieghere // NOTE: in the tests below, we use '//root/' as our root directory, since it is 1283fc51490bSJonas Devlieghere // a legal *absolute* path on Windows as well as *nix. 1284fc51490bSJonas Devlieghere class VFSFromYAMLTest : public ::testing::Test { 1285fc51490bSJonas Devlieghere public: 1286fc51490bSJonas Devlieghere int NumDiagnostics; 1287fc51490bSJonas Devlieghere 1288fc51490bSJonas Devlieghere void SetUp() override { NumDiagnostics = 0; } 1289fc51490bSJonas Devlieghere 1290fc51490bSJonas Devlieghere static void CountingDiagHandler(const SMDiagnostic &, void *Context) { 1291fc51490bSJonas Devlieghere VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context); 1292fc51490bSJonas Devlieghere ++Test->NumDiagnostics; 1293fc51490bSJonas Devlieghere } 1294fc51490bSJonas Devlieghere 1295a22eda54SDuncan P. N. Exon Smith std::unique_ptr<vfs::FileSystem> 1296fc51490bSJonas Devlieghere getFromYAMLRawString(StringRef Content, 1297fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) { 1298fc51490bSJonas Devlieghere std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content); 1299fc51490bSJonas Devlieghere return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, "", this, 1300fc51490bSJonas Devlieghere ExternalFS); 1301fc51490bSJonas Devlieghere } 1302fc51490bSJonas Devlieghere 1303a22eda54SDuncan P. N. Exon Smith std::unique_ptr<vfs::FileSystem> getFromYAMLString( 1304fc51490bSJonas Devlieghere StringRef Content, 1305fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) { 1306fc51490bSJonas Devlieghere std::string VersionPlusContent("{\n 'version':0,\n"); 1307fc51490bSJonas Devlieghere VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos); 1308fc51490bSJonas Devlieghere return getFromYAMLRawString(VersionPlusContent, ExternalFS); 1309fc51490bSJonas Devlieghere } 1310fc51490bSJonas Devlieghere 1311fc51490bSJonas Devlieghere // This is intended as a "XFAIL" for windows hosts. 1312fc51490bSJonas Devlieghere bool supportsSameDirMultipleYAMLEntries() { 1313fc51490bSJonas Devlieghere Triple Host(Triple::normalize(sys::getProcessTriple())); 1314fc51490bSJonas Devlieghere return !Host.isOSWindows(); 1315fc51490bSJonas Devlieghere } 1316fc51490bSJonas Devlieghere }; 1317fc51490bSJonas Devlieghere 1318fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) { 1319fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS; 1320fc51490bSJonas Devlieghere FS = getFromYAMLString(""); 1321fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1322fc51490bSJonas Devlieghere FS = getFromYAMLString("[]"); 1323fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1324fc51490bSJonas Devlieghere FS = getFromYAMLString("'string'"); 1325fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1326fc51490bSJonas Devlieghere EXPECT_EQ(3, NumDiagnostics); 1327fc51490bSJonas Devlieghere } 1328fc51490bSJonas Devlieghere 1329fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, MappedFiles) { 1330fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1331*ecb00a77SNathan Hawes Lower->addDirectory("//root/foo/bar"); 1332fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a"); 1333fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1334fc51490bSJonas Devlieghere "{ 'roots': [\n" 1335fc51490bSJonas Devlieghere "{\n" 1336fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1337fc51490bSJonas Devlieghere " 'name': '//root/',\n" 1338fc51490bSJonas Devlieghere " 'contents': [ {\n" 1339fc51490bSJonas Devlieghere " 'type': 'file',\n" 1340fc51490bSJonas Devlieghere " 'name': 'file1',\n" 1341fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n" 1342fc51490bSJonas Devlieghere " },\n" 1343fc51490bSJonas Devlieghere " {\n" 1344fc51490bSJonas Devlieghere " 'type': 'file',\n" 1345fc51490bSJonas Devlieghere " 'name': 'file2',\n" 1346fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/b'\n" 1347*ecb00a77SNathan Hawes " },\n" 1348*ecb00a77SNathan Hawes " {\n" 1349*ecb00a77SNathan Hawes " 'type': 'directory-remap',\n" 1350*ecb00a77SNathan Hawes " 'name': 'mappeddir',\n" 1351*ecb00a77SNathan Hawes " 'external-contents': '//root/foo/bar'\n" 1352*ecb00a77SNathan Hawes " },\n" 1353*ecb00a77SNathan Hawes " {\n" 1354*ecb00a77SNathan Hawes " 'type': 'directory-remap',\n" 1355*ecb00a77SNathan Hawes " 'name': 'mappeddir2',\n" 1356*ecb00a77SNathan Hawes " 'use-external-name': false,\n" 1357*ecb00a77SNathan Hawes " 'external-contents': '//root/foo/bar'\n" 1358fc51490bSJonas Devlieghere " }\n" 1359fc51490bSJonas Devlieghere " ]\n" 1360fc51490bSJonas Devlieghere "}\n" 1361fc51490bSJonas Devlieghere "]\n" 1362fc51490bSJonas Devlieghere "}", 1363fc51490bSJonas Devlieghere Lower); 1364fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1365fc51490bSJonas Devlieghere 1366fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1367fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1368fc51490bSJonas Devlieghere O->pushOverlay(FS); 1369fc51490bSJonas Devlieghere 1370fc51490bSJonas Devlieghere // file 1371fc51490bSJonas Devlieghere ErrorOr<vfs::Status> S = O->status("//root/file1"); 1372fc51490bSJonas Devlieghere ASSERT_FALSE(S.getError()); 1373fc51490bSJonas Devlieghere EXPECT_EQ("//root/foo/bar/a", S->getName()); 1374fc51490bSJonas Devlieghere EXPECT_TRUE(S->IsVFSMapped); 1375fc51490bSJonas Devlieghere 1376fc51490bSJonas Devlieghere ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a"); 1377fc51490bSJonas Devlieghere EXPECT_EQ("//root/foo/bar/a", SLower->getName()); 1378fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SLower)); 1379fc51490bSJonas Devlieghere EXPECT_FALSE(SLower->IsVFSMapped); 1380fc51490bSJonas Devlieghere 1381fc51490bSJonas Devlieghere // file after opening 1382fc51490bSJonas Devlieghere auto OpenedF = O->openFileForRead("//root/file1"); 1383fc51490bSJonas Devlieghere ASSERT_FALSE(OpenedF.getError()); 1384fc51490bSJonas Devlieghere auto OpenedS = (*OpenedF)->status(); 1385fc51490bSJonas Devlieghere ASSERT_FALSE(OpenedS.getError()); 1386fc51490bSJonas Devlieghere EXPECT_EQ("//root/foo/bar/a", OpenedS->getName()); 1387fc51490bSJonas Devlieghere EXPECT_TRUE(OpenedS->IsVFSMapped); 1388fc51490bSJonas Devlieghere 1389fc51490bSJonas Devlieghere // directory 1390fc51490bSJonas Devlieghere S = O->status("//root/"); 1391fc51490bSJonas Devlieghere ASSERT_FALSE(S.getError()); 1392fc51490bSJonas Devlieghere EXPECT_TRUE(S->isDirectory()); 1393fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID 1394fc51490bSJonas Devlieghere 1395*ecb00a77SNathan Hawes // remapped directory 1396*ecb00a77SNathan Hawes S = O->status("//root/mappeddir"); 1397*ecb00a77SNathan Hawes ASSERT_FALSE(S.getError()); 1398*ecb00a77SNathan Hawes EXPECT_TRUE(S->isDirectory()); 1399*ecb00a77SNathan Hawes EXPECT_TRUE(S->IsVFSMapped); 1400*ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*O->status("//root/foo/bar"))); 1401*ecb00a77SNathan Hawes 1402*ecb00a77SNathan Hawes SLower = O->status("//root/foo/bar"); 1403*ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar", SLower->getName()); 1404*ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SLower)); 1405*ecb00a77SNathan Hawes EXPECT_FALSE(SLower->IsVFSMapped); 1406*ecb00a77SNathan Hawes 1407*ecb00a77SNathan Hawes // file in remapped directory 1408*ecb00a77SNathan Hawes S = O->status("//root/mappeddir/a"); 1409*ecb00a77SNathan Hawes ASSERT_FALSE(S.getError()); 1410*ecb00a77SNathan Hawes ASSERT_FALSE(S->isDirectory()); 1411*ecb00a77SNathan Hawes ASSERT_TRUE(S->IsVFSMapped); 1412*ecb00a77SNathan Hawes ASSERT_EQ("//root/foo/bar/a", S->getName()); 1413*ecb00a77SNathan Hawes 1414*ecb00a77SNathan Hawes // file in remapped directory, with use-external-name=false 1415*ecb00a77SNathan Hawes S = O->status("//root/mappeddir2/a"); 1416*ecb00a77SNathan Hawes ASSERT_FALSE(S.getError()); 1417*ecb00a77SNathan Hawes ASSERT_FALSE(S->isDirectory()); 1418*ecb00a77SNathan Hawes ASSERT_TRUE(S->IsVFSMapped); 1419*ecb00a77SNathan Hawes ASSERT_EQ("//root/mappeddir2/a", S->getName()); 1420*ecb00a77SNathan Hawes 1421*ecb00a77SNathan Hawes // file contents in remapped directory 1422*ecb00a77SNathan Hawes OpenedF = O->openFileForRead("//root/mappeddir/a"); 1423*ecb00a77SNathan Hawes ASSERT_FALSE(OpenedF.getError()); 1424*ecb00a77SNathan Hawes OpenedS = (*OpenedF)->status(); 1425*ecb00a77SNathan Hawes ASSERT_FALSE(OpenedS.getError()); 1426*ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar/a", OpenedS->getName()); 1427*ecb00a77SNathan Hawes EXPECT_TRUE(OpenedS->IsVFSMapped); 1428*ecb00a77SNathan Hawes 1429*ecb00a77SNathan Hawes // file contents in remapped directory, with use-external-name=false 1430*ecb00a77SNathan Hawes OpenedF = O->openFileForRead("//root/mappeddir2/a"); 1431*ecb00a77SNathan Hawes ASSERT_FALSE(OpenedF.getError()); 1432*ecb00a77SNathan Hawes OpenedS = (*OpenedF)->status(); 1433*ecb00a77SNathan Hawes ASSERT_FALSE(OpenedS.getError()); 1434*ecb00a77SNathan Hawes EXPECT_EQ("//root/mappeddir2/a", OpenedS->getName()); 1435*ecb00a77SNathan Hawes EXPECT_TRUE(OpenedS->IsVFSMapped); 1436*ecb00a77SNathan Hawes 1437fc51490bSJonas Devlieghere // broken mapping 1438fc51490bSJonas Devlieghere EXPECT_EQ(O->status("//root/file2").getError(), 1439fc51490bSJonas Devlieghere llvm::errc::no_such_file_or_directory); 1440fc51490bSJonas Devlieghere EXPECT_EQ(0, NumDiagnostics); 1441fc51490bSJonas Devlieghere } 1442fc51490bSJonas Devlieghere 1443*ecb00a77SNathan Hawes TEST_F(VFSFromYAMLTest, MappedRoot) { 1444*ecb00a77SNathan Hawes IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1445*ecb00a77SNathan Hawes Lower->addDirectory("//root/foo/bar"); 1446*ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/bar/a"); 1447*ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::FileSystem> FS = 1448*ecb00a77SNathan Hawes getFromYAMLString("{ 'roots': [\n" 1449*ecb00a77SNathan Hawes "{\n" 1450*ecb00a77SNathan Hawes " 'type': 'directory-remap',\n" 1451*ecb00a77SNathan Hawes " 'name': '//mappedroot/',\n" 1452*ecb00a77SNathan Hawes " 'external-contents': '//root/foo/bar'\n" 1453*ecb00a77SNathan Hawes "}\n" 1454*ecb00a77SNathan Hawes "]\n" 1455*ecb00a77SNathan Hawes "}", 1456*ecb00a77SNathan Hawes Lower); 1457*ecb00a77SNathan Hawes ASSERT_TRUE(FS.get() != nullptr); 1458*ecb00a77SNathan Hawes 1459*ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1460*ecb00a77SNathan Hawes new vfs::OverlayFileSystem(Lower)); 1461*ecb00a77SNathan Hawes O->pushOverlay(FS); 1462*ecb00a77SNathan Hawes 1463*ecb00a77SNathan Hawes // file 1464*ecb00a77SNathan Hawes ErrorOr<vfs::Status> S = O->status("//mappedroot/a"); 1465*ecb00a77SNathan Hawes ASSERT_FALSE(S.getError()); 1466*ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar/a", S->getName()); 1467*ecb00a77SNathan Hawes EXPECT_TRUE(S->IsVFSMapped); 1468*ecb00a77SNathan Hawes 1469*ecb00a77SNathan Hawes ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a"); 1470*ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar/a", SLower->getName()); 1471*ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SLower)); 1472*ecb00a77SNathan Hawes EXPECT_FALSE(SLower->IsVFSMapped); 1473*ecb00a77SNathan Hawes 1474*ecb00a77SNathan Hawes // file after opening 1475*ecb00a77SNathan Hawes auto OpenedF = O->openFileForRead("//mappedroot/a"); 1476*ecb00a77SNathan Hawes ASSERT_FALSE(OpenedF.getError()); 1477*ecb00a77SNathan Hawes auto OpenedS = (*OpenedF)->status(); 1478*ecb00a77SNathan Hawes ASSERT_FALSE(OpenedS.getError()); 1479*ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar/a", OpenedS->getName()); 1480*ecb00a77SNathan Hawes EXPECT_TRUE(OpenedS->IsVFSMapped); 1481*ecb00a77SNathan Hawes 1482*ecb00a77SNathan Hawes EXPECT_EQ(0, NumDiagnostics); 1483*ecb00a77SNathan Hawes } 1484*ecb00a77SNathan Hawes 1485*ecb00a77SNathan Hawes TEST_F(VFSFromYAMLTest, RemappedDirectoryOverlay) { 1486*ecb00a77SNathan Hawes IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1487*ecb00a77SNathan Hawes Lower->addDirectory("//root/foo"); 1488*ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/a"); 1489*ecb00a77SNathan Hawes Lower->addDirectory("//root/bar"); 1490*ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/b"); 1491*ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/c"); 1492*ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::FileSystem> FS = 1493*ecb00a77SNathan Hawes getFromYAMLString("{ 'roots': [\n" 1494*ecb00a77SNathan Hawes "{\n" 1495*ecb00a77SNathan Hawes " 'type': 'directory',\n" 1496*ecb00a77SNathan Hawes " 'name': '//root/',\n" 1497*ecb00a77SNathan Hawes " 'contents': [ {\n" 1498*ecb00a77SNathan Hawes " 'type': 'directory-remap',\n" 1499*ecb00a77SNathan Hawes " 'name': 'bar',\n" 1500*ecb00a77SNathan Hawes " 'external-contents': '//root/foo'\n" 1501*ecb00a77SNathan Hawes " }\n" 1502*ecb00a77SNathan Hawes " ]\n" 1503*ecb00a77SNathan Hawes "}]}", 1504*ecb00a77SNathan Hawes Lower); 1505*ecb00a77SNathan Hawes ASSERT_TRUE(FS.get() != nullptr); 1506*ecb00a77SNathan Hawes 1507*ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1508*ecb00a77SNathan Hawes new vfs::OverlayFileSystem(Lower)); 1509*ecb00a77SNathan Hawes O->pushOverlay(FS); 1510*ecb00a77SNathan Hawes 1511*ecb00a77SNathan Hawes ErrorOr<vfs::Status> S = O->status("//root/foo"); 1512*ecb00a77SNathan Hawes ASSERT_FALSE(S.getError()); 1513*ecb00a77SNathan Hawes 1514*ecb00a77SNathan Hawes ErrorOr<vfs::Status> SS = O->status("//root/bar"); 1515*ecb00a77SNathan Hawes ASSERT_FALSE(SS.getError()); 1516*ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SS)); 1517*ecb00a77SNathan Hawes 1518*ecb00a77SNathan Hawes std::error_code EC; 1519*ecb00a77SNathan Hawes checkContents(O->dir_begin("//root/bar", EC), 1520*ecb00a77SNathan Hawes {"//root/foo/a", "//root/bar/b", "//root/bar/c"}); 1521*ecb00a77SNathan Hawes 1522*ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/b"); 1523*ecb00a77SNathan Hawes checkContents(O->dir_begin("//root/bar", EC), 1524*ecb00a77SNathan Hawes {"//root/foo/a", "//root/foo/b", "//root/bar/c"}); 1525*ecb00a77SNathan Hawes 1526*ecb00a77SNathan Hawes EXPECT_EQ(0, NumDiagnostics); 1527*ecb00a77SNathan Hawes } 1528*ecb00a77SNathan Hawes 1529*ecb00a77SNathan Hawes TEST_F(VFSFromYAMLTest, RemappedDirectoryOverlayNoExternalNames) { 1530*ecb00a77SNathan Hawes IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1531*ecb00a77SNathan Hawes Lower->addDirectory("//root/foo"); 1532*ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/a"); 1533*ecb00a77SNathan Hawes Lower->addDirectory("//root/bar"); 1534*ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/b"); 1535*ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/c"); 1536*ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::FileSystem> FS = 1537*ecb00a77SNathan Hawes getFromYAMLString("{ 'use-external-names': false,\n" 1538*ecb00a77SNathan Hawes " 'roots': [\n" 1539*ecb00a77SNathan Hawes "{\n" 1540*ecb00a77SNathan Hawes " 'type': 'directory',\n" 1541*ecb00a77SNathan Hawes " 'name': '//root/',\n" 1542*ecb00a77SNathan Hawes " 'contents': [ {\n" 1543*ecb00a77SNathan Hawes " 'type': 'directory-remap',\n" 1544*ecb00a77SNathan Hawes " 'name': 'bar',\n" 1545*ecb00a77SNathan Hawes " 'external-contents': '//root/foo'\n" 1546*ecb00a77SNathan Hawes " }\n" 1547*ecb00a77SNathan Hawes " ]\n" 1548*ecb00a77SNathan Hawes "}]}", 1549*ecb00a77SNathan Hawes Lower); 1550*ecb00a77SNathan Hawes ASSERT_TRUE(FS.get() != nullptr); 1551*ecb00a77SNathan Hawes 1552*ecb00a77SNathan Hawes ErrorOr<vfs::Status> S = FS->status("//root/foo"); 1553*ecb00a77SNathan Hawes ASSERT_FALSE(S.getError()); 1554*ecb00a77SNathan Hawes 1555*ecb00a77SNathan Hawes ErrorOr<vfs::Status> SS = FS->status("//root/bar"); 1556*ecb00a77SNathan Hawes ASSERT_FALSE(SS.getError()); 1557*ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SS)); 1558*ecb00a77SNathan Hawes 1559*ecb00a77SNathan Hawes std::error_code EC; 1560*ecb00a77SNathan Hawes checkContents(FS->dir_begin("//root/bar", EC), 1561*ecb00a77SNathan Hawes {"//root/bar/a", "//root/bar/b", "//root/bar/c"}); 1562*ecb00a77SNathan Hawes 1563*ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/b"); 1564*ecb00a77SNathan Hawes checkContents(FS->dir_begin("//root/bar", EC), 1565*ecb00a77SNathan Hawes {"//root/bar/a", "//root/bar/b", "//root/bar/c"}); 1566*ecb00a77SNathan Hawes 1567*ecb00a77SNathan Hawes EXPECT_EQ(0, NumDiagnostics); 1568*ecb00a77SNathan Hawes } 1569*ecb00a77SNathan Hawes 1570*ecb00a77SNathan Hawes TEST_F(VFSFromYAMLTest, RemappedDirectoryOverlayNoFallthrough) { 1571*ecb00a77SNathan Hawes IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1572*ecb00a77SNathan Hawes Lower->addDirectory("//root/foo"); 1573*ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/a"); 1574*ecb00a77SNathan Hawes Lower->addDirectory("//root/bar"); 1575*ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/b"); 1576*ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/c"); 1577*ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::FileSystem> FS = 1578*ecb00a77SNathan Hawes getFromYAMLString("{ 'fallthrough': false,\n" 1579*ecb00a77SNathan Hawes " 'roots': [\n" 1580*ecb00a77SNathan Hawes "{\n" 1581*ecb00a77SNathan Hawes " 'type': 'directory',\n" 1582*ecb00a77SNathan Hawes " 'name': '//root/',\n" 1583*ecb00a77SNathan Hawes " 'contents': [ {\n" 1584*ecb00a77SNathan Hawes " 'type': 'directory-remap',\n" 1585*ecb00a77SNathan Hawes " 'name': 'bar',\n" 1586*ecb00a77SNathan Hawes " 'external-contents': '//root/foo'\n" 1587*ecb00a77SNathan Hawes " }\n" 1588*ecb00a77SNathan Hawes " ]\n" 1589*ecb00a77SNathan Hawes "}]}", 1590*ecb00a77SNathan Hawes Lower); 1591*ecb00a77SNathan Hawes ASSERT_TRUE(FS.get() != nullptr); 1592*ecb00a77SNathan Hawes 1593*ecb00a77SNathan Hawes ErrorOr<vfs::Status> S = Lower->status("//root/foo"); 1594*ecb00a77SNathan Hawes ASSERT_FALSE(S.getError()); 1595*ecb00a77SNathan Hawes 1596*ecb00a77SNathan Hawes ErrorOr<vfs::Status> SS = FS->status("//root/bar"); 1597*ecb00a77SNathan Hawes ASSERT_FALSE(SS.getError()); 1598*ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SS)); 1599*ecb00a77SNathan Hawes 1600*ecb00a77SNathan Hawes std::error_code EC; 1601*ecb00a77SNathan Hawes checkContents(FS->dir_begin("//root/bar", EC), {"//root/foo/a"}); 1602*ecb00a77SNathan Hawes 1603*ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/b"); 1604*ecb00a77SNathan Hawes checkContents(FS->dir_begin("//root/bar", EC), 1605*ecb00a77SNathan Hawes {"//root/foo/a", "//root/foo/b"}); 1606*ecb00a77SNathan Hawes 1607*ecb00a77SNathan Hawes EXPECT_EQ(0, NumDiagnostics); 1608*ecb00a77SNathan Hawes } 1609*ecb00a77SNathan Hawes 1610fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, CaseInsensitive) { 1611fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1612fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a"); 1613fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1614fc51490bSJonas Devlieghere "{ 'case-sensitive': 'false',\n" 1615fc51490bSJonas Devlieghere " 'roots': [\n" 1616fc51490bSJonas Devlieghere "{\n" 1617fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1618fc51490bSJonas Devlieghere " 'name': '//root/',\n" 1619fc51490bSJonas Devlieghere " 'contents': [ {\n" 1620fc51490bSJonas Devlieghere " 'type': 'file',\n" 1621fc51490bSJonas Devlieghere " 'name': 'XX',\n" 1622fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n" 1623fc51490bSJonas Devlieghere " }\n" 1624fc51490bSJonas Devlieghere " ]\n" 1625fc51490bSJonas Devlieghere "}]}", 1626fc51490bSJonas Devlieghere Lower); 1627fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1628fc51490bSJonas Devlieghere 1629fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1630fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1631fc51490bSJonas Devlieghere O->pushOverlay(FS); 1632fc51490bSJonas Devlieghere 1633fc51490bSJonas Devlieghere ErrorOr<vfs::Status> S = O->status("//root/XX"); 1634fc51490bSJonas Devlieghere ASSERT_FALSE(S.getError()); 1635fc51490bSJonas Devlieghere 1636fc51490bSJonas Devlieghere ErrorOr<vfs::Status> SS = O->status("//root/xx"); 1637fc51490bSJonas Devlieghere ASSERT_FALSE(SS.getError()); 1638fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SS)); 1639fc51490bSJonas Devlieghere SS = O->status("//root/xX"); 1640fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SS)); 1641fc51490bSJonas Devlieghere SS = O->status("//root/Xx"); 1642fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SS)); 1643fc51490bSJonas Devlieghere EXPECT_EQ(0, NumDiagnostics); 1644fc51490bSJonas Devlieghere } 1645fc51490bSJonas Devlieghere 1646fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, CaseSensitive) { 1647fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1648fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a"); 1649fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1650fc51490bSJonas Devlieghere "{ 'case-sensitive': 'true',\n" 1651fc51490bSJonas Devlieghere " 'roots': [\n" 1652fc51490bSJonas Devlieghere "{\n" 1653fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1654fc51490bSJonas Devlieghere " 'name': '//root/',\n" 1655fc51490bSJonas Devlieghere " 'contents': [ {\n" 1656fc51490bSJonas Devlieghere " 'type': 'file',\n" 1657fc51490bSJonas Devlieghere " 'name': 'XX',\n" 1658fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n" 1659fc51490bSJonas Devlieghere " }\n" 1660fc51490bSJonas Devlieghere " ]\n" 1661fc51490bSJonas Devlieghere "}]}", 1662fc51490bSJonas Devlieghere Lower); 1663fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1664fc51490bSJonas Devlieghere 1665fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1666fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1667fc51490bSJonas Devlieghere O->pushOverlay(FS); 1668fc51490bSJonas Devlieghere 1669fc51490bSJonas Devlieghere ErrorOr<vfs::Status> SS = O->status("//root/xx"); 1670fc51490bSJonas Devlieghere EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory); 1671fc51490bSJonas Devlieghere SS = O->status("//root/xX"); 1672fc51490bSJonas Devlieghere EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory); 1673fc51490bSJonas Devlieghere SS = O->status("//root/Xx"); 1674fc51490bSJonas Devlieghere EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory); 1675fc51490bSJonas Devlieghere EXPECT_EQ(0, NumDiagnostics); 1676fc51490bSJonas Devlieghere } 1677fc51490bSJonas Devlieghere 1678fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, IllegalVFSFile) { 1679fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1680fc51490bSJonas Devlieghere 1681fc51490bSJonas Devlieghere // invalid YAML at top-level 1682fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower); 1683fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1684fc51490bSJonas Devlieghere // invalid YAML in roots 1685fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[}", Lower); 1686fc51490bSJonas Devlieghere // invalid YAML in directory 1687fc51490bSJonas Devlieghere FS = getFromYAMLString( 1688fc51490bSJonas Devlieghere "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}", 1689fc51490bSJonas Devlieghere Lower); 1690fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1691fc51490bSJonas Devlieghere 1692fc51490bSJonas Devlieghere // invalid configuration 1693fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower); 1694fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1695fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower); 1696fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1697fc51490bSJonas Devlieghere 1698fc51490bSJonas Devlieghere // invalid roots 1699fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':'' }", Lower); 1700fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1701fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':{} }", Lower); 1702fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1703fc51490bSJonas Devlieghere 1704fc51490bSJonas Devlieghere // invalid entries 1705fc51490bSJonas Devlieghere FS = getFromYAMLString( 1706fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower); 1707fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1708fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], " 1709fc51490bSJonas Devlieghere "'external-contents': 'other' }", 1710fc51490bSJonas Devlieghere Lower); 1711fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1712fc51490bSJonas Devlieghere FS = getFromYAMLString( 1713fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }", 1714fc51490bSJonas Devlieghere Lower); 1715fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1716fc51490bSJonas Devlieghere FS = getFromYAMLString( 1717fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }", 1718fc51490bSJonas Devlieghere Lower); 1719fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1720fc51490bSJonas Devlieghere FS = getFromYAMLString( 1721fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }", 1722fc51490bSJonas Devlieghere Lower); 1723fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1724fc51490bSJonas Devlieghere FS = getFromYAMLString( 1725fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }", 1726fc51490bSJonas Devlieghere Lower); 1727fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1728fc51490bSJonas Devlieghere FS = getFromYAMLString( 1729fc51490bSJonas Devlieghere "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }", 1730fc51490bSJonas Devlieghere Lower); 1731fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1732fc51490bSJonas Devlieghere 1733fc51490bSJonas Devlieghere // missing mandatory fields 1734fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower); 1735fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1736fc51490bSJonas Devlieghere FS = getFromYAMLString( 1737fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower); 1738fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1739fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower); 1740fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1741fc51490bSJonas Devlieghere 1742fc51490bSJonas Devlieghere // duplicate keys 1743fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower); 1744fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1745fc51490bSJonas Devlieghere FS = getFromYAMLString( 1746fc51490bSJonas Devlieghere "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }", 1747fc51490bSJonas Devlieghere Lower); 1748fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1749fc51490bSJonas Devlieghere FS = 1750fc51490bSJonas Devlieghere getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', " 1751fc51490bSJonas Devlieghere "'external-contents':'blah' } ] }", 1752fc51490bSJonas Devlieghere Lower); 1753fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1754fc51490bSJonas Devlieghere 1755fc51490bSJonas Devlieghere // missing version 1756fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'roots':[] }", Lower); 1757fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1758fc51490bSJonas Devlieghere 1759fc51490bSJonas Devlieghere // bad version number 1760fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower); 1761fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1762fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower); 1763fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1764fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower); 1765fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1766*ecb00a77SNathan Hawes 1767*ecb00a77SNathan Hawes // both 'external-contents' and 'contents' specified 1768*ecb00a77SNathan Hawes Lower->addDirectory("//root/external/dir"); 1769*ecb00a77SNathan Hawes FS = getFromYAMLString( 1770*ecb00a77SNathan Hawes "{ 'roots':[ \n" 1771*ecb00a77SNathan Hawes "{ 'type': 'directory', 'name': '//root/A', 'contents': [],\n" 1772*ecb00a77SNathan Hawes " 'external-contents': '//root/external/dir'}]}", 1773*ecb00a77SNathan Hawes Lower); 1774*ecb00a77SNathan Hawes EXPECT_EQ(nullptr, FS.get()); 1775*ecb00a77SNathan Hawes 1776*ecb00a77SNathan Hawes // 'directory-remap' with 'contents' 1777*ecb00a77SNathan Hawes FS = getFromYAMLString( 1778*ecb00a77SNathan Hawes "{ 'roots':[ \n" 1779*ecb00a77SNathan Hawes "{ 'type': 'directory-remap', 'name': '//root/A', 'contents': [] }]}", 1780*ecb00a77SNathan Hawes Lower); 1781*ecb00a77SNathan Hawes EXPECT_EQ(nullptr, FS.get()); 1782*ecb00a77SNathan Hawes 1783*ecb00a77SNathan Hawes EXPECT_EQ(26, NumDiagnostics); 1784fc51490bSJonas Devlieghere } 1785fc51490bSJonas Devlieghere 1786fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, UseExternalName) { 1787fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1788fc51490bSJonas Devlieghere Lower->addRegularFile("//root/external/file"); 1789fc51490bSJonas Devlieghere 1790fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = 1791fc51490bSJonas Devlieghere getFromYAMLString("{ 'roots': [\n" 1792fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/A',\n" 1793fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1794fc51490bSJonas Devlieghere " },\n" 1795fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/B',\n" 1796fc51490bSJonas Devlieghere " 'use-external-name': true,\n" 1797fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1798fc51490bSJonas Devlieghere " },\n" 1799fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/C',\n" 1800fc51490bSJonas Devlieghere " 'use-external-name': false,\n" 1801fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1802fc51490bSJonas Devlieghere " }\n" 1803fc51490bSJonas Devlieghere "] }", 1804fc51490bSJonas Devlieghere Lower); 1805fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1806fc51490bSJonas Devlieghere 1807fc51490bSJonas Devlieghere // default true 1808fc51490bSJonas Devlieghere EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName()); 1809fc51490bSJonas Devlieghere // explicit 1810fc51490bSJonas Devlieghere EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName()); 1811fc51490bSJonas Devlieghere EXPECT_EQ("//root/C", FS->status("//root/C")->getName()); 1812fc51490bSJonas Devlieghere 1813fc51490bSJonas Devlieghere // global configuration 1814fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'use-external-names': false,\n" 1815fc51490bSJonas Devlieghere " 'roots': [\n" 1816fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/A',\n" 1817fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1818fc51490bSJonas Devlieghere " },\n" 1819fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/B',\n" 1820fc51490bSJonas Devlieghere " 'use-external-name': true,\n" 1821fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1822fc51490bSJonas Devlieghere " },\n" 1823fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/C',\n" 1824fc51490bSJonas Devlieghere " 'use-external-name': false,\n" 1825fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1826fc51490bSJonas Devlieghere " }\n" 1827fc51490bSJonas Devlieghere "] }", 1828fc51490bSJonas Devlieghere Lower); 1829fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1830fc51490bSJonas Devlieghere 1831fc51490bSJonas Devlieghere // default 1832fc51490bSJonas Devlieghere EXPECT_EQ("//root/A", FS->status("//root/A")->getName()); 1833fc51490bSJonas Devlieghere // explicit 1834fc51490bSJonas Devlieghere EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName()); 1835fc51490bSJonas Devlieghere EXPECT_EQ("//root/C", FS->status("//root/C")->getName()); 1836fc51490bSJonas Devlieghere } 1837fc51490bSJonas Devlieghere 1838fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, MultiComponentPath) { 1839fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1840fc51490bSJonas Devlieghere Lower->addRegularFile("//root/other"); 1841fc51490bSJonas Devlieghere 1842fc51490bSJonas Devlieghere // file in roots 1843fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = 1844fc51490bSJonas Devlieghere getFromYAMLString("{ 'roots': [\n" 1845fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/path/to/file',\n" 1846fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]\n" 1847fc51490bSJonas Devlieghere "}", 1848fc51490bSJonas Devlieghere Lower); 1849fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1850fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError()); 1851fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError()); 1852fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError()); 1853fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError()); 1854fc51490bSJonas Devlieghere 1855fc51490bSJonas Devlieghere // at the start 1856fc51490bSJonas Devlieghere FS = getFromYAMLString( 1857fc51490bSJonas Devlieghere "{ 'roots': [\n" 1858fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': '//root/path/to',\n" 1859fc51490bSJonas Devlieghere " 'contents': [ { 'type': 'file', 'name': 'file',\n" 1860fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]}]\n" 1861fc51490bSJonas Devlieghere "}", 1862fc51490bSJonas Devlieghere Lower); 1863fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1864fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError()); 1865fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError()); 1866fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError()); 1867fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError()); 1868fc51490bSJonas Devlieghere 1869fc51490bSJonas Devlieghere // at the end 1870fc51490bSJonas Devlieghere FS = getFromYAMLString( 1871fc51490bSJonas Devlieghere "{ 'roots': [\n" 1872fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': '//root/',\n" 1873fc51490bSJonas Devlieghere " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n" 1874fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]}]\n" 1875fc51490bSJonas Devlieghere "}", 1876fc51490bSJonas Devlieghere Lower); 1877fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1878fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError()); 1879fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError()); 1880fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError()); 1881fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError()); 1882fc51490bSJonas Devlieghere } 1883fc51490bSJonas Devlieghere 1884fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, TrailingSlashes) { 1885fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1886fc51490bSJonas Devlieghere Lower->addRegularFile("//root/other"); 1887fc51490bSJonas Devlieghere 1888fc51490bSJonas Devlieghere // file in roots 1889fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1890fc51490bSJonas Devlieghere "{ 'roots': [\n" 1891fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': '//root/path/to////',\n" 1892fc51490bSJonas Devlieghere " 'contents': [ { 'type': 'file', 'name': 'file',\n" 1893fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]}]\n" 1894fc51490bSJonas Devlieghere "}", 1895fc51490bSJonas Devlieghere Lower); 1896fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1897fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError()); 1898fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError()); 1899fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError()); 1900fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError()); 1901fc51490bSJonas Devlieghere } 1902fc51490bSJonas Devlieghere 1903fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, DirectoryIteration) { 1904fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1905fc51490bSJonas Devlieghere Lower->addDirectory("//root/"); 1906fc51490bSJonas Devlieghere Lower->addDirectory("//root/foo"); 1907fc51490bSJonas Devlieghere Lower->addDirectory("//root/foo/bar"); 1908fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a"); 1909fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/b"); 1910fc51490bSJonas Devlieghere Lower->addRegularFile("//root/file3"); 1911fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1912fc51490bSJonas Devlieghere "{ 'use-external-names': false,\n" 1913fc51490bSJonas Devlieghere " 'roots': [\n" 1914fc51490bSJonas Devlieghere "{\n" 1915fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1916fc51490bSJonas Devlieghere " 'name': '//root/',\n" 1917fc51490bSJonas Devlieghere " 'contents': [ {\n" 1918fc51490bSJonas Devlieghere " 'type': 'file',\n" 1919fc51490bSJonas Devlieghere " 'name': 'file1',\n" 1920fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n" 1921fc51490bSJonas Devlieghere " },\n" 1922fc51490bSJonas Devlieghere " {\n" 1923fc51490bSJonas Devlieghere " 'type': 'file',\n" 1924fc51490bSJonas Devlieghere " 'name': 'file2',\n" 1925fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/b'\n" 1926fc51490bSJonas Devlieghere " }\n" 1927fc51490bSJonas Devlieghere " ]\n" 1928fc51490bSJonas Devlieghere "}\n" 1929fc51490bSJonas Devlieghere "]\n" 1930fc51490bSJonas Devlieghere "}", 1931fc51490bSJonas Devlieghere Lower); 1932fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1933fc51490bSJonas Devlieghere 1934fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1935fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1936fc51490bSJonas Devlieghere O->pushOverlay(FS); 1937fc51490bSJonas Devlieghere 1938fc51490bSJonas Devlieghere std::error_code EC; 1939fc51490bSJonas Devlieghere checkContents(O->dir_begin("//root/", EC), 1940fc51490bSJonas Devlieghere {"//root/file1", "//root/file2", "//root/file3", "//root/foo"}); 1941fc51490bSJonas Devlieghere 1942fc51490bSJonas Devlieghere checkContents(O->dir_begin("//root/foo/bar", EC), 1943fc51490bSJonas Devlieghere {"//root/foo/bar/a", "//root/foo/bar/b"}); 1944fc51490bSJonas Devlieghere } 1945fc51490bSJonas Devlieghere 1946fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, DirectoryIterationSameDirMultipleEntries) { 1947fc51490bSJonas Devlieghere // https://llvm.org/bugs/show_bug.cgi?id=27725 1948fc51490bSJonas Devlieghere if (!supportsSameDirMultipleYAMLEntries()) 1949fc51490bSJonas Devlieghere return; 1950fc51490bSJonas Devlieghere 1951fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1952fc51490bSJonas Devlieghere Lower->addDirectory("//root/zab"); 1953fc51490bSJonas Devlieghere Lower->addDirectory("//root/baz"); 1954fc51490bSJonas Devlieghere Lower->addRegularFile("//root/zab/a"); 1955fc51490bSJonas Devlieghere Lower->addRegularFile("//root/zab/b"); 1956fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1957fc51490bSJonas Devlieghere "{ 'use-external-names': false,\n" 1958fc51490bSJonas Devlieghere " 'roots': [\n" 1959fc51490bSJonas Devlieghere "{\n" 1960fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1961fc51490bSJonas Devlieghere " 'name': '//root/baz/',\n" 1962fc51490bSJonas Devlieghere " 'contents': [ {\n" 1963fc51490bSJonas Devlieghere " 'type': 'file',\n" 1964fc51490bSJonas Devlieghere " 'name': 'x',\n" 1965fc51490bSJonas Devlieghere " 'external-contents': '//root/zab/a'\n" 1966fc51490bSJonas Devlieghere " }\n" 1967fc51490bSJonas Devlieghere " ]\n" 1968fc51490bSJonas Devlieghere "},\n" 1969fc51490bSJonas Devlieghere "{\n" 1970fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1971fc51490bSJonas Devlieghere " 'name': '//root/baz/',\n" 1972fc51490bSJonas Devlieghere " 'contents': [ {\n" 1973fc51490bSJonas Devlieghere " 'type': 'file',\n" 1974fc51490bSJonas Devlieghere " 'name': 'y',\n" 1975fc51490bSJonas Devlieghere " 'external-contents': '//root/zab/b'\n" 1976fc51490bSJonas Devlieghere " }\n" 1977fc51490bSJonas Devlieghere " ]\n" 1978fc51490bSJonas Devlieghere "}\n" 1979fc51490bSJonas Devlieghere "]\n" 1980fc51490bSJonas Devlieghere "}", 1981fc51490bSJonas Devlieghere Lower); 1982fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1983fc51490bSJonas Devlieghere 1984fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1985fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1986fc51490bSJonas Devlieghere O->pushOverlay(FS); 1987fc51490bSJonas Devlieghere 1988fc51490bSJonas Devlieghere std::error_code EC; 1989fc51490bSJonas Devlieghere 1990fc51490bSJonas Devlieghere checkContents(O->dir_begin("//root/baz/", EC), 1991fc51490bSJonas Devlieghere {"//root/baz/x", "//root/baz/y"}); 1992fc51490bSJonas Devlieghere } 1993fc51490bSJonas Devlieghere 1994fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, RecursiveDirectoryIterationLevel) { 1995fc51490bSJonas Devlieghere 1996fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1997fc51490bSJonas Devlieghere Lower->addDirectory("//root/a"); 1998fc51490bSJonas Devlieghere Lower->addDirectory("//root/a/b"); 1999fc51490bSJonas Devlieghere Lower->addDirectory("//root/a/b/c"); 2000fc51490bSJonas Devlieghere Lower->addRegularFile("//root/a/b/c/file"); 2001fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 2002fc51490bSJonas Devlieghere "{ 'use-external-names': false,\n" 2003fc51490bSJonas Devlieghere " 'roots': [\n" 2004fc51490bSJonas Devlieghere "{\n" 2005fc51490bSJonas Devlieghere " 'type': 'directory',\n" 2006fc51490bSJonas Devlieghere " 'name': '//root/a/b/c/',\n" 2007fc51490bSJonas Devlieghere " 'contents': [ {\n" 2008fc51490bSJonas Devlieghere " 'type': 'file',\n" 2009fc51490bSJonas Devlieghere " 'name': 'file',\n" 2010fc51490bSJonas Devlieghere " 'external-contents': '//root/a/b/c/file'\n" 2011fc51490bSJonas Devlieghere " }\n" 2012fc51490bSJonas Devlieghere " ]\n" 2013fc51490bSJonas Devlieghere "},\n" 2014fc51490bSJonas Devlieghere "]\n" 2015fc51490bSJonas Devlieghere "}", 2016fc51490bSJonas Devlieghere Lower); 2017fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 2018fc51490bSJonas Devlieghere 2019fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 2020fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 2021fc51490bSJonas Devlieghere O->pushOverlay(FS); 2022fc51490bSJonas Devlieghere 2023fc51490bSJonas Devlieghere std::error_code EC; 2024fc51490bSJonas Devlieghere 2025fc51490bSJonas Devlieghere // Test recursive_directory_iterator level() 2026fc51490bSJonas Devlieghere vfs::recursive_directory_iterator I = vfs::recursive_directory_iterator( 2027fc51490bSJonas Devlieghere *O, "//root", EC), 2028fc51490bSJonas Devlieghere E; 2029fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 2030fc51490bSJonas Devlieghere for (int l = 0; I != E; I.increment(EC), ++l) { 2031fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 2032fc51490bSJonas Devlieghere EXPECT_EQ(I.level(), l); 2033fc51490bSJonas Devlieghere } 2034fc51490bSJonas Devlieghere EXPECT_EQ(I, E); 2035fc51490bSJonas Devlieghere } 2036fc51490bSJonas Devlieghere 2037fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, RelativePaths) { 2038fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 2039fc51490bSJonas Devlieghere // Filename at root level without a parent directory. 2040fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 2041fc51490bSJonas Devlieghere "{ 'roots': [\n" 2042fc51490bSJonas Devlieghere " { 'type': 'file', 'name': 'file-not-in-directory.h',\n" 2043fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 2044fc51490bSJonas Devlieghere " }\n" 2045fc51490bSJonas Devlieghere "] }", 2046fc51490bSJonas Devlieghere Lower); 2047fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 2048fc51490bSJonas Devlieghere 2049fc51490bSJonas Devlieghere // Relative file path. 2050fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots': [\n" 2051fc51490bSJonas Devlieghere " { 'type': 'file', 'name': 'relative/file/path.h',\n" 2052fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 2053fc51490bSJonas Devlieghere " }\n" 2054fc51490bSJonas Devlieghere "] }", 2055fc51490bSJonas Devlieghere Lower); 2056fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 2057fc51490bSJonas Devlieghere 2058fc51490bSJonas Devlieghere // Relative directory path. 2059fc51490bSJonas Devlieghere FS = getFromYAMLString( 2060fc51490bSJonas Devlieghere "{ 'roots': [\n" 2061fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': 'relative/directory/path.h',\n" 2062fc51490bSJonas Devlieghere " 'contents': []\n" 2063fc51490bSJonas Devlieghere " }\n" 2064fc51490bSJonas Devlieghere "] }", 2065fc51490bSJonas Devlieghere Lower); 2066fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 2067fc51490bSJonas Devlieghere 2068fc51490bSJonas Devlieghere EXPECT_EQ(3, NumDiagnostics); 2069fc51490bSJonas Devlieghere } 207091e13164SVolodymyr Sapsai 207191e13164SVolodymyr Sapsai TEST_F(VFSFromYAMLTest, NonFallthroughDirectoryIteration) { 207291e13164SVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 207391e13164SVolodymyr Sapsai Lower->addDirectory("//root/"); 207491e13164SVolodymyr Sapsai Lower->addRegularFile("//root/a"); 207591e13164SVolodymyr Sapsai Lower->addRegularFile("//root/b"); 207691e13164SVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 207791e13164SVolodymyr Sapsai "{ 'use-external-names': false,\n" 207891e13164SVolodymyr Sapsai " 'fallthrough': false,\n" 207991e13164SVolodymyr Sapsai " 'roots': [\n" 208091e13164SVolodymyr Sapsai "{\n" 208191e13164SVolodymyr Sapsai " 'type': 'directory',\n" 208291e13164SVolodymyr Sapsai " 'name': '//root/',\n" 208391e13164SVolodymyr Sapsai " 'contents': [ {\n" 208491e13164SVolodymyr Sapsai " 'type': 'file',\n" 208591e13164SVolodymyr Sapsai " 'name': 'c',\n" 208691e13164SVolodymyr Sapsai " 'external-contents': '//root/a'\n" 208791e13164SVolodymyr Sapsai " }\n" 208891e13164SVolodymyr Sapsai " ]\n" 208991e13164SVolodymyr Sapsai "}\n" 209091e13164SVolodymyr Sapsai "]\n" 209191e13164SVolodymyr Sapsai "}", 209291e13164SVolodymyr Sapsai Lower); 209391e13164SVolodymyr Sapsai ASSERT_TRUE(FS.get() != nullptr); 209491e13164SVolodymyr Sapsai 209591e13164SVolodymyr Sapsai std::error_code EC; 209691e13164SVolodymyr Sapsai checkContents(FS->dir_begin("//root/", EC), 209791e13164SVolodymyr Sapsai {"//root/c"}); 209891e13164SVolodymyr Sapsai } 209991e13164SVolodymyr Sapsai 210091e13164SVolodymyr Sapsai TEST_F(VFSFromYAMLTest, DirectoryIterationWithDuplicates) { 210191e13164SVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 210291e13164SVolodymyr Sapsai Lower->addDirectory("//root/"); 210391e13164SVolodymyr Sapsai Lower->addRegularFile("//root/a"); 210491e13164SVolodymyr Sapsai Lower->addRegularFile("//root/b"); 210591e13164SVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 210691e13164SVolodymyr Sapsai "{ 'use-external-names': false,\n" 210791e13164SVolodymyr Sapsai " 'roots': [\n" 210891e13164SVolodymyr Sapsai "{\n" 210991e13164SVolodymyr Sapsai " 'type': 'directory',\n" 211091e13164SVolodymyr Sapsai " 'name': '//root/',\n" 211191e13164SVolodymyr Sapsai " 'contents': [ {\n" 211291e13164SVolodymyr Sapsai " 'type': 'file',\n" 211391e13164SVolodymyr Sapsai " 'name': 'a',\n" 211491e13164SVolodymyr Sapsai " 'external-contents': '//root/a'\n" 211591e13164SVolodymyr Sapsai " }\n" 211691e13164SVolodymyr Sapsai " ]\n" 211791e13164SVolodymyr Sapsai "}\n" 211891e13164SVolodymyr Sapsai "]\n" 211991e13164SVolodymyr Sapsai "}", 212091e13164SVolodymyr Sapsai Lower); 212191e13164SVolodymyr Sapsai ASSERT_TRUE(FS.get() != nullptr); 212291e13164SVolodymyr Sapsai 212391e13164SVolodymyr Sapsai std::error_code EC; 212491e13164SVolodymyr Sapsai checkContents(FS->dir_begin("//root/", EC), 212591e13164SVolodymyr Sapsai {"//root/a", "//root/b"}); 212691e13164SVolodymyr Sapsai } 212791e13164SVolodymyr Sapsai 212891e13164SVolodymyr Sapsai TEST_F(VFSFromYAMLTest, DirectoryIterationErrorInVFSLayer) { 212991e13164SVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 213091e13164SVolodymyr Sapsai Lower->addDirectory("//root/"); 213191e13164SVolodymyr Sapsai Lower->addDirectory("//root/foo"); 213291e13164SVolodymyr Sapsai Lower->addRegularFile("//root/foo/a"); 213391e13164SVolodymyr Sapsai Lower->addRegularFile("//root/foo/b"); 213491e13164SVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 213591e13164SVolodymyr Sapsai "{ 'use-external-names': false,\n" 213691e13164SVolodymyr Sapsai " 'roots': [\n" 213791e13164SVolodymyr Sapsai "{\n" 213891e13164SVolodymyr Sapsai " 'type': 'directory',\n" 213991e13164SVolodymyr Sapsai " 'name': '//root/',\n" 214091e13164SVolodymyr Sapsai " 'contents': [ {\n" 214191e13164SVolodymyr Sapsai " 'type': 'file',\n" 214291e13164SVolodymyr Sapsai " 'name': 'bar/a',\n" 214391e13164SVolodymyr Sapsai " 'external-contents': '//root/foo/a'\n" 214491e13164SVolodymyr Sapsai " }\n" 214591e13164SVolodymyr Sapsai " ]\n" 214691e13164SVolodymyr Sapsai "}\n" 214791e13164SVolodymyr Sapsai "]\n" 214891e13164SVolodymyr Sapsai "}", 214991e13164SVolodymyr Sapsai Lower); 215091e13164SVolodymyr Sapsai ASSERT_TRUE(FS.get() != nullptr); 215191e13164SVolodymyr Sapsai 215291e13164SVolodymyr Sapsai std::error_code EC; 215391e13164SVolodymyr Sapsai checkContents(FS->dir_begin("//root/foo", EC), 215491e13164SVolodymyr Sapsai {"//root/foo/a", "//root/foo/b"}); 215591e13164SVolodymyr Sapsai } 21567610033fSVolodymyr Sapsai 21577610033fSVolodymyr Sapsai TEST_F(VFSFromYAMLTest, GetRealPath) { 21587610033fSVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 2159ab73426cSVolodymyr Sapsai Lower->addDirectory("//dir/"); 21607610033fSVolodymyr Sapsai Lower->addRegularFile("/foo"); 21617610033fSVolodymyr Sapsai Lower->addSymlink("/link"); 21627610033fSVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 21637610033fSVolodymyr Sapsai "{ 'use-external-names': false,\n" 21647610033fSVolodymyr Sapsai " 'roots': [\n" 21657610033fSVolodymyr Sapsai "{\n" 21667610033fSVolodymyr Sapsai " 'type': 'directory',\n" 2167ab73426cSVolodymyr Sapsai " 'name': '//root/',\n" 21687610033fSVolodymyr Sapsai " 'contents': [ {\n" 21697610033fSVolodymyr Sapsai " 'type': 'file',\n" 21707610033fSVolodymyr Sapsai " 'name': 'bar',\n" 21717610033fSVolodymyr Sapsai " 'external-contents': '/link'\n" 21727610033fSVolodymyr Sapsai " }\n" 21737610033fSVolodymyr Sapsai " ]\n" 21747610033fSVolodymyr Sapsai "},\n" 21757610033fSVolodymyr Sapsai "{\n" 21767610033fSVolodymyr Sapsai " 'type': 'directory',\n" 2177ab73426cSVolodymyr Sapsai " 'name': '//dir/',\n" 21787610033fSVolodymyr Sapsai " 'contents': []\n" 21797610033fSVolodymyr Sapsai "}\n" 21807610033fSVolodymyr Sapsai "]\n" 21817610033fSVolodymyr Sapsai "}", 21827610033fSVolodymyr Sapsai Lower); 21837610033fSVolodymyr Sapsai ASSERT_TRUE(FS.get() != nullptr); 21847610033fSVolodymyr Sapsai 21857610033fSVolodymyr Sapsai // Regular file present in underlying file system. 21867610033fSVolodymyr Sapsai SmallString<16> RealPath; 21877610033fSVolodymyr Sapsai EXPECT_FALSE(FS->getRealPath("/foo", RealPath)); 21887610033fSVolodymyr Sapsai EXPECT_EQ(RealPath.str(), "/foo"); 21897610033fSVolodymyr Sapsai 21907610033fSVolodymyr Sapsai // File present in YAML pointing to symlink in underlying file system. 2191ab73426cSVolodymyr Sapsai EXPECT_FALSE(FS->getRealPath("//root/bar", RealPath)); 21927610033fSVolodymyr Sapsai EXPECT_EQ(RealPath.str(), "/symlink"); 21937610033fSVolodymyr Sapsai 21947610033fSVolodymyr Sapsai // Directories should fall back to the underlying file system is possible. 2195ab73426cSVolodymyr Sapsai EXPECT_FALSE(FS->getRealPath("//dir/", RealPath)); 2196ab73426cSVolodymyr Sapsai EXPECT_EQ(RealPath.str(), "//dir/"); 21977610033fSVolodymyr Sapsai 21987610033fSVolodymyr Sapsai // Try a non-existing file. 21997610033fSVolodymyr Sapsai EXPECT_EQ(FS->getRealPath("/non_existing", RealPath), 22007610033fSVolodymyr Sapsai errc::no_such_file_or_directory); 22017610033fSVolodymyr Sapsai } 220221703543SJonas Devlieghere 220321703543SJonas Devlieghere TEST_F(VFSFromYAMLTest, WorkingDirectory) { 220421703543SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 220521703543SJonas Devlieghere Lower->addDirectory("//root/"); 220621703543SJonas Devlieghere Lower->addDirectory("//root/foo"); 220721703543SJonas Devlieghere Lower->addRegularFile("//root/foo/a"); 220821703543SJonas Devlieghere Lower->addRegularFile("//root/foo/b"); 220921703543SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 221021703543SJonas Devlieghere "{ 'use-external-names': false,\n" 221121703543SJonas Devlieghere " 'roots': [\n" 221221703543SJonas Devlieghere "{\n" 221321703543SJonas Devlieghere " 'type': 'directory',\n" 221421703543SJonas Devlieghere " 'name': '//root/bar',\n" 221521703543SJonas Devlieghere " 'contents': [ {\n" 221621703543SJonas Devlieghere " 'type': 'file',\n" 221721703543SJonas Devlieghere " 'name': 'a',\n" 221821703543SJonas Devlieghere " 'external-contents': '//root/foo/a'\n" 221921703543SJonas Devlieghere " }\n" 222021703543SJonas Devlieghere " ]\n" 222121703543SJonas Devlieghere "}\n" 222221703543SJonas Devlieghere "]\n" 222321703543SJonas Devlieghere "}", 222421703543SJonas Devlieghere Lower); 222521703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 222621703543SJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/bar"); 222721703543SJonas Devlieghere ASSERT_FALSE(EC); 222821703543SJonas Devlieghere 222921703543SJonas Devlieghere llvm::ErrorOr<std::string> WorkingDir = FS->getCurrentWorkingDirectory(); 223021703543SJonas Devlieghere ASSERT_TRUE(WorkingDir); 223121703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/bar"); 223221703543SJonas Devlieghere 223321703543SJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("./a"); 223421703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 223521703543SJonas Devlieghere EXPECT_TRUE(Status->isStatusKnown()); 223621703543SJonas Devlieghere EXPECT_FALSE(Status->isDirectory()); 223721703543SJonas Devlieghere EXPECT_TRUE(Status->isRegularFile()); 223821703543SJonas Devlieghere EXPECT_FALSE(Status->isSymlink()); 223921703543SJonas Devlieghere EXPECT_FALSE(Status->isOther()); 224021703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 224121703543SJonas Devlieghere 224221703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("bogus"); 224321703543SJonas Devlieghere ASSERT_TRUE(EC); 224421703543SJonas Devlieghere WorkingDir = FS->getCurrentWorkingDirectory(); 224521703543SJonas Devlieghere ASSERT_TRUE(WorkingDir); 224621703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/bar"); 224721703543SJonas Devlieghere 224821703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/"); 224921703543SJonas Devlieghere ASSERT_FALSE(EC); 225021703543SJonas Devlieghere WorkingDir = FS->getCurrentWorkingDirectory(); 225121703543SJonas Devlieghere ASSERT_TRUE(WorkingDir); 225221703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/"); 225321703543SJonas Devlieghere 225421703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("bar"); 225521703543SJonas Devlieghere ASSERT_FALSE(EC); 225621703543SJonas Devlieghere WorkingDir = FS->getCurrentWorkingDirectory(); 225721703543SJonas Devlieghere ASSERT_TRUE(WorkingDir); 225821703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/bar"); 225921703543SJonas Devlieghere } 226021703543SJonas Devlieghere 226121703543SJonas Devlieghere TEST_F(VFSFromYAMLTest, WorkingDirectoryFallthrough) { 226221703543SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 226321703543SJonas Devlieghere Lower->addDirectory("//root/"); 226421703543SJonas Devlieghere Lower->addDirectory("//root/foo"); 226521703543SJonas Devlieghere Lower->addRegularFile("//root/foo/a"); 226621703543SJonas Devlieghere Lower->addRegularFile("//root/foo/b"); 226721703543SJonas Devlieghere Lower->addRegularFile("//root/c"); 226821703543SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 226921703543SJonas Devlieghere "{ 'use-external-names': false,\n" 227021703543SJonas Devlieghere " 'roots': [\n" 227121703543SJonas Devlieghere "{\n" 227221703543SJonas Devlieghere " 'type': 'directory',\n" 227321703543SJonas Devlieghere " 'name': '//root/bar',\n" 227421703543SJonas Devlieghere " 'contents': [ {\n" 227521703543SJonas Devlieghere " 'type': 'file',\n" 227621703543SJonas Devlieghere " 'name': 'a',\n" 227721703543SJonas Devlieghere " 'external-contents': '//root/foo/a'\n" 227821703543SJonas Devlieghere " }\n" 227921703543SJonas Devlieghere " ]\n" 2280f2f77499SJonas Devlieghere "},\n" 2281f2f77499SJonas Devlieghere "{\n" 2282f2f77499SJonas Devlieghere " 'type': 'directory',\n" 2283f2f77499SJonas Devlieghere " 'name': '//root/bar/baz',\n" 2284f2f77499SJonas Devlieghere " 'contents': [ {\n" 2285f2f77499SJonas Devlieghere " 'type': 'file',\n" 2286f2f77499SJonas Devlieghere " 'name': 'a',\n" 2287f2f77499SJonas Devlieghere " 'external-contents': '//root/foo/a'\n" 2288f2f77499SJonas Devlieghere " }\n" 2289f2f77499SJonas Devlieghere " ]\n" 229021703543SJonas Devlieghere "}\n" 229121703543SJonas Devlieghere "]\n" 229221703543SJonas Devlieghere "}", 229321703543SJonas Devlieghere Lower); 229421703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 229521703543SJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/"); 229621703543SJonas Devlieghere ASSERT_FALSE(EC); 229721703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 229821703543SJonas Devlieghere 229921703543SJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("bar/a"); 230021703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 230121703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 230221703543SJonas Devlieghere 230321703543SJonas Devlieghere Status = FS->status("foo/a"); 230421703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 230521703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 230621703543SJonas Devlieghere 230721703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/bar"); 230821703543SJonas Devlieghere ASSERT_FALSE(EC); 230921703543SJonas Devlieghere 231021703543SJonas Devlieghere Status = FS->status("./a"); 231121703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 231221703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 231321703543SJonas Devlieghere 231421703543SJonas Devlieghere Status = FS->status("./b"); 231521703543SJonas Devlieghere ASSERT_TRUE(Status.getError()); 231621703543SJonas Devlieghere 231721703543SJonas Devlieghere Status = FS->status("./c"); 231821703543SJonas Devlieghere ASSERT_TRUE(Status.getError()); 231921703543SJonas Devlieghere 232021703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/"); 232121703543SJonas Devlieghere ASSERT_FALSE(EC); 232221703543SJonas Devlieghere 232321703543SJonas Devlieghere Status = FS->status("c"); 232421703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 232521703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 2326f2f77499SJonas Devlieghere 2327f2f77499SJonas Devlieghere Status = FS->status("./bar/baz/a"); 2328f2f77499SJonas Devlieghere ASSERT_FALSE(Status.getError()); 2329f2f77499SJonas Devlieghere EXPECT_TRUE(Status->exists()); 2330f2f77499SJonas Devlieghere 2331f2f77499SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/bar"); 2332f2f77499SJonas Devlieghere ASSERT_FALSE(EC); 2333f2f77499SJonas Devlieghere 2334f2f77499SJonas Devlieghere Status = FS->status("./baz/a"); 2335f2f77499SJonas Devlieghere ASSERT_FALSE(Status.getError()); 2336f2f77499SJonas Devlieghere EXPECT_TRUE(Status->exists()); 2337f2f77499SJonas Devlieghere 2338f2f77499SJonas Devlieghere Status = FS->status("../bar/baz/a"); 2339f2f77499SJonas Devlieghere ASSERT_FALSE(Status.getError()); 2340f2f77499SJonas Devlieghere EXPECT_TRUE(Status->exists()); 234121703543SJonas Devlieghere } 234221703543SJonas Devlieghere 234321703543SJonas Devlieghere TEST_F(VFSFromYAMLTest, WorkingDirectoryFallthroughInvalid) { 234421703543SJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 234521703543SJonas Devlieghere Lower->addDirectory("//root/"); 234621703543SJonas Devlieghere Lower->addDirectory("//root/foo"); 234721703543SJonas Devlieghere Lower->addRegularFile("//root/foo/a"); 234821703543SJonas Devlieghere Lower->addRegularFile("//root/foo/b"); 234921703543SJonas Devlieghere Lower->addRegularFile("//root/c"); 235021703543SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 235121703543SJonas Devlieghere "{ 'use-external-names': false,\n" 235221703543SJonas Devlieghere " 'roots': [\n" 235321703543SJonas Devlieghere "{\n" 235421703543SJonas Devlieghere " 'type': 'directory',\n" 235521703543SJonas Devlieghere " 'name': '//root/bar',\n" 235621703543SJonas Devlieghere " 'contents': [ {\n" 235721703543SJonas Devlieghere " 'type': 'file',\n" 235821703543SJonas Devlieghere " 'name': 'a',\n" 235921703543SJonas Devlieghere " 'external-contents': '//root/foo/a'\n" 236021703543SJonas Devlieghere " }\n" 236121703543SJonas Devlieghere " ]\n" 236221703543SJonas Devlieghere "}\n" 236321703543SJonas Devlieghere "]\n" 236421703543SJonas Devlieghere "}", 236521703543SJonas Devlieghere Lower); 236621703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 236721703543SJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/"); 236821703543SJonas Devlieghere ASSERT_FALSE(EC); 236921703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 237021703543SJonas Devlieghere 237121703543SJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("bar/a"); 237221703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 237321703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 237421703543SJonas Devlieghere 237521703543SJonas Devlieghere Status = FS->status("foo/a"); 23760be9ca7cSJonas Devlieghere ASSERT_FALSE(Status.getError()); 23770be9ca7cSJonas Devlieghere EXPECT_TRUE(Status->exists()); 23780be9ca7cSJonas Devlieghere } 23790be9ca7cSJonas Devlieghere 23800be9ca7cSJonas Devlieghere TEST_F(VFSFromYAMLTest, VirtualWorkingDirectory) { 23810be9ca7cSJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 23820be9ca7cSJonas Devlieghere Lower->addDirectory("//root/"); 23830be9ca7cSJonas Devlieghere Lower->addDirectory("//root/foo"); 23840be9ca7cSJonas Devlieghere Lower->addRegularFile("//root/foo/a"); 23850be9ca7cSJonas Devlieghere Lower->addRegularFile("//root/foo/b"); 23860be9ca7cSJonas Devlieghere Lower->addRegularFile("//root/c"); 23870be9ca7cSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 23880be9ca7cSJonas Devlieghere "{ 'use-external-names': false,\n" 23890be9ca7cSJonas Devlieghere " 'roots': [\n" 23900be9ca7cSJonas Devlieghere "{\n" 23910be9ca7cSJonas Devlieghere " 'type': 'directory',\n" 23920be9ca7cSJonas Devlieghere " 'name': '//root/bar',\n" 23930be9ca7cSJonas Devlieghere " 'contents': [ {\n" 23940be9ca7cSJonas Devlieghere " 'type': 'file',\n" 23950be9ca7cSJonas Devlieghere " 'name': 'a',\n" 23960be9ca7cSJonas Devlieghere " 'external-contents': '//root/foo/a'\n" 23970be9ca7cSJonas Devlieghere " }\n" 23980be9ca7cSJonas Devlieghere " ]\n" 23990be9ca7cSJonas Devlieghere "}\n" 24000be9ca7cSJonas Devlieghere "]\n" 24010be9ca7cSJonas Devlieghere "}", 24020be9ca7cSJonas Devlieghere Lower); 24030be9ca7cSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 24040be9ca7cSJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/bar"); 24050be9ca7cSJonas Devlieghere ASSERT_FALSE(EC); 24060be9ca7cSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 24070be9ca7cSJonas Devlieghere 24080be9ca7cSJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("a"); 24090be9ca7cSJonas Devlieghere ASSERT_FALSE(Status.getError()); 24100be9ca7cSJonas Devlieghere EXPECT_TRUE(Status->exists()); 241121703543SJonas Devlieghere } 241242df3e29SJonas Devlieghere 241342df3e29SJonas Devlieghere TEST_F(VFSFromYAMLTest, YAMLVFSWriterTest) { 2414fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 2415fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 2416fad75598SSergej Jaskiewicz TempFile _ab(TestDirectory.path("a, b")); 2417fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c")); 2418fad75598SSergej Jaskiewicz TempFile _cd(TestDirectory.path("c/d")); 2419fad75598SSergej Jaskiewicz TempDir _e(TestDirectory.path("e")); 2420fad75598SSergej Jaskiewicz TempDir _ef(TestDirectory.path("e/f")); 2421fad75598SSergej Jaskiewicz TempFile _g(TestDirectory.path("g")); 2422fad75598SSergej Jaskiewicz TempDir _h(TestDirectory.path("h")); 242342df3e29SJonas Devlieghere 242442df3e29SJonas Devlieghere vfs::YAMLVFSWriter VFSWriter; 2425fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a"); 2426fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ab.path(), "//root/a/b"); 2427fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_cd.path(), "//root/c/d"); 2428fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_e.path(), "//root/e"); 2429fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ef.path(), "//root/e/f"); 2430fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_g.path(), "//root/g"); 2431fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_h.path(), "//root/h"); 243242df3e29SJonas Devlieghere 243342df3e29SJonas Devlieghere std::string Buffer; 243442df3e29SJonas Devlieghere raw_string_ostream OS(Buffer); 243542df3e29SJonas Devlieghere VFSWriter.write(OS); 243642df3e29SJonas Devlieghere OS.flush(); 243742df3e29SJonas Devlieghere 243842df3e29SJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 243942df3e29SJonas Devlieghere Lower->addDirectory("//root/"); 244042df3e29SJonas Devlieghere Lower->addDirectory("//root/a"); 244142df3e29SJonas Devlieghere Lower->addRegularFile("//root/a/b"); 244242df3e29SJonas Devlieghere Lower->addDirectory("//root/b"); 244342df3e29SJonas Devlieghere Lower->addDirectory("//root/c"); 244442df3e29SJonas Devlieghere Lower->addRegularFile("//root/c/d"); 244542df3e29SJonas Devlieghere Lower->addDirectory("//root/e"); 244642df3e29SJonas Devlieghere Lower->addDirectory("//root/e/f"); 24475c145034SJan Korous Lower->addRegularFile("//root/g"); 24485c145034SJan Korous Lower->addDirectory("//root/h"); 244942df3e29SJonas Devlieghere 245042df3e29SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower); 245142df3e29SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 245242df3e29SJonas Devlieghere 2453fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_a.path())); 2454fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_ab.path())); 2455fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_c.path())); 2456fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_cd.path())); 2457fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_e.path())); 2458fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_ef.path())); 2459fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_g.path())); 2460fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_h.path())); 246142df3e29SJonas Devlieghere } 2462c0330bc0SJan Korous 246359ba19c5SJonas Devlieghere TEST_F(VFSFromYAMLTest, YAMLVFSWriterTest2) { 2464fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 2465fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 2466fad75598SSergej Jaskiewicz TempFile _ab(TestDirectory.path("a/b")); 2467fad75598SSergej Jaskiewicz TempDir _ac(TestDirectory.path("a/c")); 2468fad75598SSergej Jaskiewicz TempFile _acd(TestDirectory.path("a/c/d")); 2469fad75598SSergej Jaskiewicz TempFile _ace(TestDirectory.path("a/c/e")); 2470fad75598SSergej Jaskiewicz TempFile _acf(TestDirectory.path("a/c/f")); 2471fad75598SSergej Jaskiewicz TempDir _ag(TestDirectory.path("a/g")); 2472fad75598SSergej Jaskiewicz TempFile _agh(TestDirectory.path("a/g/h")); 247359ba19c5SJonas Devlieghere 247459ba19c5SJonas Devlieghere vfs::YAMLVFSWriter VFSWriter; 2475fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a"); 2476fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ab.path(), "//root/a/b"); 2477fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ac.path(), "//root/a/c"); 2478fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acd.path(), "//root/a/c/d"); 2479fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ace.path(), "//root/a/c/e"); 2480fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acf.path(), "//root/a/c/f"); 2481fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ag.path(), "//root/a/g"); 2482fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_agh.path(), "//root/a/g/h"); 248359ba19c5SJonas Devlieghere 248459ba19c5SJonas Devlieghere std::string Buffer; 248559ba19c5SJonas Devlieghere raw_string_ostream OS(Buffer); 248659ba19c5SJonas Devlieghere VFSWriter.write(OS); 248759ba19c5SJonas Devlieghere OS.flush(); 248859ba19c5SJonas Devlieghere 248959ba19c5SJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 249059ba19c5SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower); 2491759465eeSJan Korous EXPECT_TRUE(FS.get() != nullptr); 249259ba19c5SJonas Devlieghere } 249359ba19c5SJonas Devlieghere 249458bc507bSJonas Devlieghere TEST_F(VFSFromYAMLTest, YAMLVFSWriterTest3) { 2495fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 2496fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 2497fad75598SSergej Jaskiewicz TempFile _ab(TestDirectory.path("a/b")); 2498fad75598SSergej Jaskiewicz TempDir _ac(TestDirectory.path("a/c")); 2499fad75598SSergej Jaskiewicz TempDir _acd(TestDirectory.path("a/c/d")); 2500fad75598SSergej Jaskiewicz TempDir _acde(TestDirectory.path("a/c/d/e")); 2501fad75598SSergej Jaskiewicz TempFile _acdef(TestDirectory.path("a/c/d/e/f")); 2502fad75598SSergej Jaskiewicz TempFile _acdeg(TestDirectory.path("a/c/d/e/g")); 2503fad75598SSergej Jaskiewicz TempDir _ah(TestDirectory.path("a/h")); 2504fad75598SSergej Jaskiewicz TempFile _ahi(TestDirectory.path("a/h/i")); 250558bc507bSJonas Devlieghere 250658bc507bSJonas Devlieghere vfs::YAMLVFSWriter VFSWriter; 2507fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a"); 2508fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ab.path(), "//root/a/b"); 2509fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ac.path(), "//root/a/c"); 2510fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_acd.path(), "//root/a/c/d"); 2511fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_acde.path(), "//root/a/c/d/e"); 2512fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acdef.path(), "//root/a/c/d/e/f"); 2513fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acdeg.path(), "//root/a/c/d/e/g"); 2514fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ahi.path(), "//root/a/h"); 2515fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ahi.path(), "//root/a/h/i"); 251658bc507bSJonas Devlieghere 251758bc507bSJonas Devlieghere std::string Buffer; 251858bc507bSJonas Devlieghere raw_string_ostream OS(Buffer); 251958bc507bSJonas Devlieghere VFSWriter.write(OS); 252058bc507bSJonas Devlieghere OS.flush(); 252158bc507bSJonas Devlieghere 252258bc507bSJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 252358bc507bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower); 2524759465eeSJan Korous EXPECT_TRUE(FS.get() != nullptr); 252558bc507bSJonas Devlieghere } 252658bc507bSJonas Devlieghere 2527c0330bc0SJan Korous TEST_F(VFSFromYAMLTest, YAMLVFSWriterTestHandleDirs) { 2528fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 2529fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 2530fad75598SSergej Jaskiewicz TempDir _b(TestDirectory.path("b")); 2531fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c")); 2532c0330bc0SJan Korous 2533c0330bc0SJan Korous vfs::YAMLVFSWriter VFSWriter; 2534fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a"); 2535fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_b.path(), "//root/b"); 2536fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_c.path(), "//root/c"); 2537c0330bc0SJan Korous 2538c0330bc0SJan Korous std::string Buffer; 2539c0330bc0SJan Korous raw_string_ostream OS(Buffer); 2540c0330bc0SJan Korous VFSWriter.write(OS); 2541c0330bc0SJan Korous OS.flush(); 2542c0330bc0SJan Korous 2543c0330bc0SJan Korous // We didn't add a single file - only directories. 2544c0330bc0SJan Korous EXPECT_TRUE(Buffer.find("'type': 'file'") == std::string::npos); 2545c0330bc0SJan Korous 2546c0330bc0SJan Korous IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 2547c0330bc0SJan Korous Lower->addDirectory("//root/a"); 2548c0330bc0SJan Korous Lower->addDirectory("//root/b"); 2549c0330bc0SJan Korous Lower->addDirectory("//root/c"); 2550c0330bc0SJan Korous // canaries 2551c0330bc0SJan Korous Lower->addRegularFile("//root/a/a"); 2552c0330bc0SJan Korous Lower->addRegularFile("//root/b/b"); 2553c0330bc0SJan Korous Lower->addRegularFile("//root/c/c"); 2554c0330bc0SJan Korous 2555c0330bc0SJan Korous IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower); 2556c0330bc0SJan Korous ASSERT_TRUE(FS.get() != nullptr); 2557c0330bc0SJan Korous 2558fad75598SSergej Jaskiewicz EXPECT_FALSE(FS->exists(_a.path("a"))); 2559fad75598SSergej Jaskiewicz EXPECT_FALSE(FS->exists(_b.path("b"))); 2560fad75598SSergej Jaskiewicz EXPECT_FALSE(FS->exists(_c.path("c"))); 2561c0330bc0SJan Korous } 256275cd8d75SDuncan P. N. Exon Smith 256375cd8d75SDuncan P. N. Exon Smith TEST(VFSFromRemappedFilesTest, Basic) { 256475cd8d75SDuncan P. N. Exon Smith IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS = 256575cd8d75SDuncan P. N. Exon Smith new vfs::InMemoryFileSystem; 256675cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/b", 0, MemoryBuffer::getMemBuffer("contents of b")); 256775cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/c", 0, MemoryBuffer::getMemBuffer("contents of c")); 256875cd8d75SDuncan P. N. Exon Smith 256975cd8d75SDuncan P. N. Exon Smith std::vector<std::pair<std::string, std::string>> RemappedFiles = { 257075cd8d75SDuncan P. N. Exon Smith {"//root/a/a", "//root/b"}, 257175cd8d75SDuncan P. N. Exon Smith {"//root/a/b/c", "//root/c"}, 257275cd8d75SDuncan P. N. Exon Smith }; 257375cd8d75SDuncan P. N. Exon Smith auto RemappedFS = vfs::RedirectingFileSystem::create( 257475cd8d75SDuncan P. N. Exon Smith RemappedFiles, /*UseExternalNames=*/false, *BaseFS); 257575cd8d75SDuncan P. N. Exon Smith 257675cd8d75SDuncan P. N. Exon Smith auto StatA = RemappedFS->status("//root/a/a"); 257775cd8d75SDuncan P. N. Exon Smith auto StatB = RemappedFS->status("//root/a/b/c"); 257875cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatA); 257975cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatB); 258075cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/a/a", StatA->getName()); 258175cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/a/b/c", StatB->getName()); 258275cd8d75SDuncan P. N. Exon Smith 258375cd8d75SDuncan P. N. Exon Smith auto BufferA = RemappedFS->getBufferForFile("//root/a/a"); 258475cd8d75SDuncan P. N. Exon Smith auto BufferB = RemappedFS->getBufferForFile("//root/a/b/c"); 258575cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferA); 258675cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferB); 258775cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of b", (*BufferA)->getBuffer()); 258875cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of c", (*BufferB)->getBuffer()); 258975cd8d75SDuncan P. N. Exon Smith } 259075cd8d75SDuncan P. N. Exon Smith 259175cd8d75SDuncan P. N. Exon Smith TEST(VFSFromRemappedFilesTest, UseExternalNames) { 259275cd8d75SDuncan P. N. Exon Smith IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS = 259375cd8d75SDuncan P. N. Exon Smith new vfs::InMemoryFileSystem; 259475cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/b", 0, MemoryBuffer::getMemBuffer("contents of b")); 259575cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/c", 0, MemoryBuffer::getMemBuffer("contents of c")); 259675cd8d75SDuncan P. N. Exon Smith 259775cd8d75SDuncan P. N. Exon Smith std::vector<std::pair<std::string, std::string>> RemappedFiles = { 259875cd8d75SDuncan P. N. Exon Smith {"//root/a/a", "//root/b"}, 259975cd8d75SDuncan P. N. Exon Smith {"//root/a/b/c", "//root/c"}, 260075cd8d75SDuncan P. N. Exon Smith }; 260175cd8d75SDuncan P. N. Exon Smith auto RemappedFS = vfs::RedirectingFileSystem::create( 260275cd8d75SDuncan P. N. Exon Smith RemappedFiles, /*UseExternalNames=*/true, *BaseFS); 260375cd8d75SDuncan P. N. Exon Smith 260475cd8d75SDuncan P. N. Exon Smith auto StatA = RemappedFS->status("//root/a/a"); 260575cd8d75SDuncan P. N. Exon Smith auto StatB = RemappedFS->status("//root/a/b/c"); 260675cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatA); 260775cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatB); 260875cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/b", StatA->getName()); 260975cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/c", StatB->getName()); 261075cd8d75SDuncan P. N. Exon Smith 261175cd8d75SDuncan P. N. Exon Smith auto BufferA = RemappedFS->getBufferForFile("//root/a/a"); 261275cd8d75SDuncan P. N. Exon Smith auto BufferB = RemappedFS->getBufferForFile("//root/a/b/c"); 261375cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferA); 261475cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferB); 261575cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of b", (*BufferA)->getBuffer()); 261675cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of c", (*BufferB)->getBuffer()); 261775cd8d75SDuncan P. N. Exon Smith } 261875cd8d75SDuncan P. N. Exon Smith 261975cd8d75SDuncan P. N. Exon Smith TEST(VFSFromRemappedFilesTest, LastMappingWins) { 262075cd8d75SDuncan P. N. Exon Smith IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS = 262175cd8d75SDuncan P. N. Exon Smith new vfs::InMemoryFileSystem; 262275cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/b", 0, MemoryBuffer::getMemBuffer("contents of b")); 262375cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/c", 0, MemoryBuffer::getMemBuffer("contents of c")); 262475cd8d75SDuncan P. N. Exon Smith 262575cd8d75SDuncan P. N. Exon Smith std::vector<std::pair<std::string, std::string>> RemappedFiles = { 262675cd8d75SDuncan P. N. Exon Smith {"//root/a", "//root/b"}, 262775cd8d75SDuncan P. N. Exon Smith {"//root/a", "//root/c"}, 262875cd8d75SDuncan P. N. Exon Smith }; 262975cd8d75SDuncan P. N. Exon Smith auto RemappedFSKeepName = vfs::RedirectingFileSystem::create( 263075cd8d75SDuncan P. N. Exon Smith RemappedFiles, /*UseExternalNames=*/false, *BaseFS); 263175cd8d75SDuncan P. N. Exon Smith auto RemappedFSExternalName = vfs::RedirectingFileSystem::create( 263275cd8d75SDuncan P. N. Exon Smith RemappedFiles, /*UseExternalNames=*/true, *BaseFS); 263375cd8d75SDuncan P. N. Exon Smith 263475cd8d75SDuncan P. N. Exon Smith auto StatKeepA = RemappedFSKeepName->status("//root/a"); 263575cd8d75SDuncan P. N. Exon Smith auto StatExternalA = RemappedFSExternalName->status("//root/a"); 263675cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatKeepA); 263775cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatExternalA); 263875cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/a", StatKeepA->getName()); 263975cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/c", StatExternalA->getName()); 264075cd8d75SDuncan P. N. Exon Smith 264175cd8d75SDuncan P. N. Exon Smith auto BufferKeepA = RemappedFSKeepName->getBufferForFile("//root/a"); 264275cd8d75SDuncan P. N. Exon Smith auto BufferExternalA = RemappedFSExternalName->getBufferForFile("//root/a"); 264375cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferKeepA); 264475cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferExternalA); 264575cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of c", (*BufferKeepA)->getBuffer()); 264675cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of c", (*BufferExternalA)->getBuffer()); 264775cd8d75SDuncan P. N. Exon Smith } 2648