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"); 942*e763e032SDuncan 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 1295fc51490bSJonas Devlieghere IntrusiveRefCntPtr<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 1303fc51490bSJonas Devlieghere IntrusiveRefCntPtr<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()); 1331fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a"); 1332fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1333fc51490bSJonas Devlieghere "{ 'roots': [\n" 1334fc51490bSJonas Devlieghere "{\n" 1335fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1336fc51490bSJonas Devlieghere " 'name': '//root/',\n" 1337fc51490bSJonas Devlieghere " 'contents': [ {\n" 1338fc51490bSJonas Devlieghere " 'type': 'file',\n" 1339fc51490bSJonas Devlieghere " 'name': 'file1',\n" 1340fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n" 1341fc51490bSJonas Devlieghere " },\n" 1342fc51490bSJonas Devlieghere " {\n" 1343fc51490bSJonas Devlieghere " 'type': 'file',\n" 1344fc51490bSJonas Devlieghere " 'name': 'file2',\n" 1345fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/b'\n" 1346fc51490bSJonas Devlieghere " }\n" 1347fc51490bSJonas Devlieghere " ]\n" 1348fc51490bSJonas Devlieghere "}\n" 1349fc51490bSJonas Devlieghere "]\n" 1350fc51490bSJonas Devlieghere "}", 1351fc51490bSJonas Devlieghere Lower); 1352fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1353fc51490bSJonas Devlieghere 1354fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1355fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1356fc51490bSJonas Devlieghere O->pushOverlay(FS); 1357fc51490bSJonas Devlieghere 1358fc51490bSJonas Devlieghere // file 1359fc51490bSJonas Devlieghere ErrorOr<vfs::Status> S = O->status("//root/file1"); 1360fc51490bSJonas Devlieghere ASSERT_FALSE(S.getError()); 1361fc51490bSJonas Devlieghere EXPECT_EQ("//root/foo/bar/a", S->getName()); 1362fc51490bSJonas Devlieghere EXPECT_TRUE(S->IsVFSMapped); 1363fc51490bSJonas Devlieghere 1364fc51490bSJonas Devlieghere ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a"); 1365fc51490bSJonas Devlieghere EXPECT_EQ("//root/foo/bar/a", SLower->getName()); 1366fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SLower)); 1367fc51490bSJonas Devlieghere EXPECT_FALSE(SLower->IsVFSMapped); 1368fc51490bSJonas Devlieghere 1369fc51490bSJonas Devlieghere // file after opening 1370fc51490bSJonas Devlieghere auto OpenedF = O->openFileForRead("//root/file1"); 1371fc51490bSJonas Devlieghere ASSERT_FALSE(OpenedF.getError()); 1372fc51490bSJonas Devlieghere auto OpenedS = (*OpenedF)->status(); 1373fc51490bSJonas Devlieghere ASSERT_FALSE(OpenedS.getError()); 1374fc51490bSJonas Devlieghere EXPECT_EQ("//root/foo/bar/a", OpenedS->getName()); 1375fc51490bSJonas Devlieghere EXPECT_TRUE(OpenedS->IsVFSMapped); 1376fc51490bSJonas Devlieghere 1377fc51490bSJonas Devlieghere // directory 1378fc51490bSJonas Devlieghere S = O->status("//root/"); 1379fc51490bSJonas Devlieghere ASSERT_FALSE(S.getError()); 1380fc51490bSJonas Devlieghere EXPECT_TRUE(S->isDirectory()); 1381fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID 1382fc51490bSJonas Devlieghere 1383fc51490bSJonas Devlieghere // broken mapping 1384fc51490bSJonas Devlieghere EXPECT_EQ(O->status("//root/file2").getError(), 1385fc51490bSJonas Devlieghere llvm::errc::no_such_file_or_directory); 1386fc51490bSJonas Devlieghere EXPECT_EQ(0, NumDiagnostics); 1387fc51490bSJonas Devlieghere } 1388fc51490bSJonas Devlieghere 1389fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, CaseInsensitive) { 1390fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1391fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a"); 1392fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1393fc51490bSJonas Devlieghere "{ 'case-sensitive': 'false',\n" 1394fc51490bSJonas Devlieghere " 'roots': [\n" 1395fc51490bSJonas Devlieghere "{\n" 1396fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1397fc51490bSJonas Devlieghere " 'name': '//root/',\n" 1398fc51490bSJonas Devlieghere " 'contents': [ {\n" 1399fc51490bSJonas Devlieghere " 'type': 'file',\n" 1400fc51490bSJonas Devlieghere " 'name': 'XX',\n" 1401fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n" 1402fc51490bSJonas Devlieghere " }\n" 1403fc51490bSJonas Devlieghere " ]\n" 1404fc51490bSJonas Devlieghere "}]}", 1405fc51490bSJonas Devlieghere Lower); 1406fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1407fc51490bSJonas Devlieghere 1408fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1409fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1410fc51490bSJonas Devlieghere O->pushOverlay(FS); 1411fc51490bSJonas Devlieghere 1412fc51490bSJonas Devlieghere ErrorOr<vfs::Status> S = O->status("//root/XX"); 1413fc51490bSJonas Devlieghere ASSERT_FALSE(S.getError()); 1414fc51490bSJonas Devlieghere 1415fc51490bSJonas Devlieghere ErrorOr<vfs::Status> SS = O->status("//root/xx"); 1416fc51490bSJonas Devlieghere ASSERT_FALSE(SS.getError()); 1417fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SS)); 1418fc51490bSJonas Devlieghere SS = O->status("//root/xX"); 1419fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SS)); 1420fc51490bSJonas Devlieghere SS = O->status("//root/Xx"); 1421fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SS)); 1422fc51490bSJonas Devlieghere EXPECT_EQ(0, NumDiagnostics); 1423fc51490bSJonas Devlieghere } 1424fc51490bSJonas Devlieghere 1425fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, CaseSensitive) { 1426fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1427fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a"); 1428fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1429fc51490bSJonas Devlieghere "{ 'case-sensitive': 'true',\n" 1430fc51490bSJonas Devlieghere " 'roots': [\n" 1431fc51490bSJonas Devlieghere "{\n" 1432fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1433fc51490bSJonas Devlieghere " 'name': '//root/',\n" 1434fc51490bSJonas Devlieghere " 'contents': [ {\n" 1435fc51490bSJonas Devlieghere " 'type': 'file',\n" 1436fc51490bSJonas Devlieghere " 'name': 'XX',\n" 1437fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n" 1438fc51490bSJonas Devlieghere " }\n" 1439fc51490bSJonas Devlieghere " ]\n" 1440fc51490bSJonas Devlieghere "}]}", 1441fc51490bSJonas Devlieghere Lower); 1442fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1443fc51490bSJonas Devlieghere 1444fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1445fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1446fc51490bSJonas Devlieghere O->pushOverlay(FS); 1447fc51490bSJonas Devlieghere 1448fc51490bSJonas Devlieghere ErrorOr<vfs::Status> SS = O->status("//root/xx"); 1449fc51490bSJonas Devlieghere EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory); 1450fc51490bSJonas Devlieghere SS = O->status("//root/xX"); 1451fc51490bSJonas Devlieghere EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory); 1452fc51490bSJonas Devlieghere SS = O->status("//root/Xx"); 1453fc51490bSJonas Devlieghere EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory); 1454fc51490bSJonas Devlieghere EXPECT_EQ(0, NumDiagnostics); 1455fc51490bSJonas Devlieghere } 1456fc51490bSJonas Devlieghere 1457fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, IllegalVFSFile) { 1458fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1459fc51490bSJonas Devlieghere 1460fc51490bSJonas Devlieghere // invalid YAML at top-level 1461fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower); 1462fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1463fc51490bSJonas Devlieghere // invalid YAML in roots 1464fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[}", Lower); 1465fc51490bSJonas Devlieghere // invalid YAML in directory 1466fc51490bSJonas Devlieghere FS = getFromYAMLString( 1467fc51490bSJonas Devlieghere "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}", 1468fc51490bSJonas Devlieghere Lower); 1469fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1470fc51490bSJonas Devlieghere 1471fc51490bSJonas Devlieghere // invalid configuration 1472fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower); 1473fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1474fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower); 1475fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1476fc51490bSJonas Devlieghere 1477fc51490bSJonas Devlieghere // invalid roots 1478fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':'' }", Lower); 1479fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1480fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':{} }", Lower); 1481fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1482fc51490bSJonas Devlieghere 1483fc51490bSJonas Devlieghere // invalid entries 1484fc51490bSJonas Devlieghere FS = getFromYAMLString( 1485fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower); 1486fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1487fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], " 1488fc51490bSJonas Devlieghere "'external-contents': 'other' }", 1489fc51490bSJonas Devlieghere Lower); 1490fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1491fc51490bSJonas Devlieghere FS = getFromYAMLString( 1492fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }", 1493fc51490bSJonas Devlieghere Lower); 1494fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1495fc51490bSJonas Devlieghere FS = getFromYAMLString( 1496fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }", 1497fc51490bSJonas Devlieghere Lower); 1498fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1499fc51490bSJonas Devlieghere FS = getFromYAMLString( 1500fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }", 1501fc51490bSJonas Devlieghere Lower); 1502fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1503fc51490bSJonas Devlieghere FS = getFromYAMLString( 1504fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }", 1505fc51490bSJonas Devlieghere Lower); 1506fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1507fc51490bSJonas Devlieghere FS = getFromYAMLString( 1508fc51490bSJonas Devlieghere "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }", 1509fc51490bSJonas Devlieghere Lower); 1510fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1511fc51490bSJonas Devlieghere 1512fc51490bSJonas Devlieghere // missing mandatory fields 1513fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower); 1514fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1515fc51490bSJonas Devlieghere FS = getFromYAMLString( 1516fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower); 1517fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1518fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower); 1519fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1520fc51490bSJonas Devlieghere 1521fc51490bSJonas Devlieghere // duplicate keys 1522fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower); 1523fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1524fc51490bSJonas Devlieghere FS = getFromYAMLString( 1525fc51490bSJonas Devlieghere "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }", 1526fc51490bSJonas Devlieghere Lower); 1527fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1528fc51490bSJonas Devlieghere FS = 1529fc51490bSJonas Devlieghere getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', " 1530fc51490bSJonas Devlieghere "'external-contents':'blah' } ] }", 1531fc51490bSJonas Devlieghere Lower); 1532fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1533fc51490bSJonas Devlieghere 1534fc51490bSJonas Devlieghere // missing version 1535fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'roots':[] }", Lower); 1536fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1537fc51490bSJonas Devlieghere 1538fc51490bSJonas Devlieghere // bad version number 1539fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower); 1540fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1541fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower); 1542fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1543fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower); 1544fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1545fc51490bSJonas Devlieghere EXPECT_EQ(24, NumDiagnostics); 1546fc51490bSJonas Devlieghere } 1547fc51490bSJonas Devlieghere 1548fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, UseExternalName) { 1549fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1550fc51490bSJonas Devlieghere Lower->addRegularFile("//root/external/file"); 1551fc51490bSJonas Devlieghere 1552fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = 1553fc51490bSJonas Devlieghere getFromYAMLString("{ 'roots': [\n" 1554fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/A',\n" 1555fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1556fc51490bSJonas Devlieghere " },\n" 1557fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/B',\n" 1558fc51490bSJonas Devlieghere " 'use-external-name': true,\n" 1559fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1560fc51490bSJonas Devlieghere " },\n" 1561fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/C',\n" 1562fc51490bSJonas Devlieghere " 'use-external-name': false,\n" 1563fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1564fc51490bSJonas Devlieghere " }\n" 1565fc51490bSJonas Devlieghere "] }", 1566fc51490bSJonas Devlieghere Lower); 1567fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1568fc51490bSJonas Devlieghere 1569fc51490bSJonas Devlieghere // default true 1570fc51490bSJonas Devlieghere EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName()); 1571fc51490bSJonas Devlieghere // explicit 1572fc51490bSJonas Devlieghere EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName()); 1573fc51490bSJonas Devlieghere EXPECT_EQ("//root/C", FS->status("//root/C")->getName()); 1574fc51490bSJonas Devlieghere 1575fc51490bSJonas Devlieghere // global configuration 1576fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'use-external-names': false,\n" 1577fc51490bSJonas Devlieghere " 'roots': [\n" 1578fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/A',\n" 1579fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1580fc51490bSJonas Devlieghere " },\n" 1581fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/B',\n" 1582fc51490bSJonas Devlieghere " 'use-external-name': true,\n" 1583fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1584fc51490bSJonas Devlieghere " },\n" 1585fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/C',\n" 1586fc51490bSJonas Devlieghere " 'use-external-name': false,\n" 1587fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1588fc51490bSJonas Devlieghere " }\n" 1589fc51490bSJonas Devlieghere "] }", 1590fc51490bSJonas Devlieghere Lower); 1591fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1592fc51490bSJonas Devlieghere 1593fc51490bSJonas Devlieghere // default 1594fc51490bSJonas Devlieghere EXPECT_EQ("//root/A", FS->status("//root/A")->getName()); 1595fc51490bSJonas Devlieghere // explicit 1596fc51490bSJonas Devlieghere EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName()); 1597fc51490bSJonas Devlieghere EXPECT_EQ("//root/C", FS->status("//root/C")->getName()); 1598fc51490bSJonas Devlieghere } 1599fc51490bSJonas Devlieghere 1600fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, MultiComponentPath) { 1601fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1602fc51490bSJonas Devlieghere Lower->addRegularFile("//root/other"); 1603fc51490bSJonas Devlieghere 1604fc51490bSJonas Devlieghere // file in roots 1605fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = 1606fc51490bSJonas Devlieghere getFromYAMLString("{ 'roots': [\n" 1607fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/path/to/file',\n" 1608fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]\n" 1609fc51490bSJonas Devlieghere "}", 1610fc51490bSJonas Devlieghere Lower); 1611fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1612fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError()); 1613fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError()); 1614fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError()); 1615fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError()); 1616fc51490bSJonas Devlieghere 1617fc51490bSJonas Devlieghere // at the start 1618fc51490bSJonas Devlieghere FS = getFromYAMLString( 1619fc51490bSJonas Devlieghere "{ 'roots': [\n" 1620fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': '//root/path/to',\n" 1621fc51490bSJonas Devlieghere " 'contents': [ { 'type': 'file', 'name': 'file',\n" 1622fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]}]\n" 1623fc51490bSJonas Devlieghere "}", 1624fc51490bSJonas Devlieghere Lower); 1625fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1626fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError()); 1627fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError()); 1628fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError()); 1629fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError()); 1630fc51490bSJonas Devlieghere 1631fc51490bSJonas Devlieghere // at the end 1632fc51490bSJonas Devlieghere FS = getFromYAMLString( 1633fc51490bSJonas Devlieghere "{ 'roots': [\n" 1634fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': '//root/',\n" 1635fc51490bSJonas Devlieghere " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n" 1636fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]}]\n" 1637fc51490bSJonas Devlieghere "}", 1638fc51490bSJonas Devlieghere Lower); 1639fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1640fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError()); 1641fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError()); 1642fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError()); 1643fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError()); 1644fc51490bSJonas Devlieghere } 1645fc51490bSJonas Devlieghere 1646fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, TrailingSlashes) { 1647fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1648fc51490bSJonas Devlieghere Lower->addRegularFile("//root/other"); 1649fc51490bSJonas Devlieghere 1650fc51490bSJonas Devlieghere // file in roots 1651fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1652fc51490bSJonas Devlieghere "{ 'roots': [\n" 1653fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': '//root/path/to////',\n" 1654fc51490bSJonas Devlieghere " 'contents': [ { 'type': 'file', 'name': 'file',\n" 1655fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]}]\n" 1656fc51490bSJonas Devlieghere "}", 1657fc51490bSJonas Devlieghere Lower); 1658fc51490bSJonas Devlieghere ASSERT_TRUE(nullptr != FS.get()); 1659fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError()); 1660fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError()); 1661fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError()); 1662fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError()); 1663fc51490bSJonas Devlieghere } 1664fc51490bSJonas Devlieghere 1665fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, DirectoryIteration) { 1666fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1667fc51490bSJonas Devlieghere Lower->addDirectory("//root/"); 1668fc51490bSJonas Devlieghere Lower->addDirectory("//root/foo"); 1669fc51490bSJonas Devlieghere Lower->addDirectory("//root/foo/bar"); 1670fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a"); 1671fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/b"); 1672fc51490bSJonas Devlieghere Lower->addRegularFile("//root/file3"); 1673fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1674fc51490bSJonas Devlieghere "{ 'use-external-names': false,\n" 1675fc51490bSJonas Devlieghere " 'roots': [\n" 1676fc51490bSJonas Devlieghere "{\n" 1677fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1678fc51490bSJonas Devlieghere " 'name': '//root/',\n" 1679fc51490bSJonas Devlieghere " 'contents': [ {\n" 1680fc51490bSJonas Devlieghere " 'type': 'file',\n" 1681fc51490bSJonas Devlieghere " 'name': 'file1',\n" 1682fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n" 1683fc51490bSJonas Devlieghere " },\n" 1684fc51490bSJonas Devlieghere " {\n" 1685fc51490bSJonas Devlieghere " 'type': 'file',\n" 1686fc51490bSJonas Devlieghere " 'name': 'file2',\n" 1687fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/b'\n" 1688fc51490bSJonas Devlieghere " }\n" 1689fc51490bSJonas Devlieghere " ]\n" 1690fc51490bSJonas Devlieghere "}\n" 1691fc51490bSJonas Devlieghere "]\n" 1692fc51490bSJonas Devlieghere "}", 1693fc51490bSJonas Devlieghere Lower); 1694fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1695fc51490bSJonas Devlieghere 1696fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1697fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1698fc51490bSJonas Devlieghere O->pushOverlay(FS); 1699fc51490bSJonas Devlieghere 1700fc51490bSJonas Devlieghere std::error_code EC; 1701fc51490bSJonas Devlieghere checkContents(O->dir_begin("//root/", EC), 1702fc51490bSJonas Devlieghere {"//root/file1", "//root/file2", "//root/file3", "//root/foo"}); 1703fc51490bSJonas Devlieghere 1704fc51490bSJonas Devlieghere checkContents(O->dir_begin("//root/foo/bar", EC), 1705fc51490bSJonas Devlieghere {"//root/foo/bar/a", "//root/foo/bar/b"}); 1706fc51490bSJonas Devlieghere } 1707fc51490bSJonas Devlieghere 1708fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, DirectoryIterationSameDirMultipleEntries) { 1709fc51490bSJonas Devlieghere // https://llvm.org/bugs/show_bug.cgi?id=27725 1710fc51490bSJonas Devlieghere if (!supportsSameDirMultipleYAMLEntries()) 1711fc51490bSJonas Devlieghere return; 1712fc51490bSJonas Devlieghere 1713fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1714fc51490bSJonas Devlieghere Lower->addDirectory("//root/zab"); 1715fc51490bSJonas Devlieghere Lower->addDirectory("//root/baz"); 1716fc51490bSJonas Devlieghere Lower->addRegularFile("//root/zab/a"); 1717fc51490bSJonas Devlieghere Lower->addRegularFile("//root/zab/b"); 1718fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1719fc51490bSJonas Devlieghere "{ 'use-external-names': false,\n" 1720fc51490bSJonas Devlieghere " 'roots': [\n" 1721fc51490bSJonas Devlieghere "{\n" 1722fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1723fc51490bSJonas Devlieghere " 'name': '//root/baz/',\n" 1724fc51490bSJonas Devlieghere " 'contents': [ {\n" 1725fc51490bSJonas Devlieghere " 'type': 'file',\n" 1726fc51490bSJonas Devlieghere " 'name': 'x',\n" 1727fc51490bSJonas Devlieghere " 'external-contents': '//root/zab/a'\n" 1728fc51490bSJonas Devlieghere " }\n" 1729fc51490bSJonas Devlieghere " ]\n" 1730fc51490bSJonas Devlieghere "},\n" 1731fc51490bSJonas Devlieghere "{\n" 1732fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1733fc51490bSJonas Devlieghere " 'name': '//root/baz/',\n" 1734fc51490bSJonas Devlieghere " 'contents': [ {\n" 1735fc51490bSJonas Devlieghere " 'type': 'file',\n" 1736fc51490bSJonas Devlieghere " 'name': 'y',\n" 1737fc51490bSJonas Devlieghere " 'external-contents': '//root/zab/b'\n" 1738fc51490bSJonas Devlieghere " }\n" 1739fc51490bSJonas Devlieghere " ]\n" 1740fc51490bSJonas Devlieghere "}\n" 1741fc51490bSJonas Devlieghere "]\n" 1742fc51490bSJonas Devlieghere "}", 1743fc51490bSJonas Devlieghere Lower); 1744fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1745fc51490bSJonas Devlieghere 1746fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1747fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1748fc51490bSJonas Devlieghere O->pushOverlay(FS); 1749fc51490bSJonas Devlieghere 1750fc51490bSJonas Devlieghere std::error_code EC; 1751fc51490bSJonas Devlieghere 1752fc51490bSJonas Devlieghere checkContents(O->dir_begin("//root/baz/", EC), 1753fc51490bSJonas Devlieghere {"//root/baz/x", "//root/baz/y"}); 1754fc51490bSJonas Devlieghere } 1755fc51490bSJonas Devlieghere 1756fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, RecursiveDirectoryIterationLevel) { 1757fc51490bSJonas Devlieghere 1758fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1759fc51490bSJonas Devlieghere Lower->addDirectory("//root/a"); 1760fc51490bSJonas Devlieghere Lower->addDirectory("//root/a/b"); 1761fc51490bSJonas Devlieghere Lower->addDirectory("//root/a/b/c"); 1762fc51490bSJonas Devlieghere Lower->addRegularFile("//root/a/b/c/file"); 1763fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1764fc51490bSJonas Devlieghere "{ 'use-external-names': false,\n" 1765fc51490bSJonas Devlieghere " 'roots': [\n" 1766fc51490bSJonas Devlieghere "{\n" 1767fc51490bSJonas Devlieghere " 'type': 'directory',\n" 1768fc51490bSJonas Devlieghere " 'name': '//root/a/b/c/',\n" 1769fc51490bSJonas Devlieghere " 'contents': [ {\n" 1770fc51490bSJonas Devlieghere " 'type': 'file',\n" 1771fc51490bSJonas Devlieghere " 'name': 'file',\n" 1772fc51490bSJonas Devlieghere " 'external-contents': '//root/a/b/c/file'\n" 1773fc51490bSJonas Devlieghere " }\n" 1774fc51490bSJonas Devlieghere " ]\n" 1775fc51490bSJonas Devlieghere "},\n" 1776fc51490bSJonas Devlieghere "]\n" 1777fc51490bSJonas Devlieghere "}", 1778fc51490bSJonas Devlieghere Lower); 1779fc51490bSJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 1780fc51490bSJonas Devlieghere 1781fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O( 1782fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower)); 1783fc51490bSJonas Devlieghere O->pushOverlay(FS); 1784fc51490bSJonas Devlieghere 1785fc51490bSJonas Devlieghere std::error_code EC; 1786fc51490bSJonas Devlieghere 1787fc51490bSJonas Devlieghere // Test recursive_directory_iterator level() 1788fc51490bSJonas Devlieghere vfs::recursive_directory_iterator I = vfs::recursive_directory_iterator( 1789fc51490bSJonas Devlieghere *O, "//root", EC), 1790fc51490bSJonas Devlieghere E; 1791fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 1792fc51490bSJonas Devlieghere for (int l = 0; I != E; I.increment(EC), ++l) { 1793fc51490bSJonas Devlieghere ASSERT_FALSE(EC); 1794fc51490bSJonas Devlieghere EXPECT_EQ(I.level(), l); 1795fc51490bSJonas Devlieghere } 1796fc51490bSJonas Devlieghere EXPECT_EQ(I, E); 1797fc51490bSJonas Devlieghere } 1798fc51490bSJonas Devlieghere 1799fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, RelativePaths) { 1800fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1801fc51490bSJonas Devlieghere // Filename at root level without a parent directory. 1802fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 1803fc51490bSJonas Devlieghere "{ 'roots': [\n" 1804fc51490bSJonas Devlieghere " { 'type': 'file', 'name': 'file-not-in-directory.h',\n" 1805fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1806fc51490bSJonas Devlieghere " }\n" 1807fc51490bSJonas Devlieghere "] }", 1808fc51490bSJonas Devlieghere Lower); 1809fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1810fc51490bSJonas Devlieghere 1811fc51490bSJonas Devlieghere // Relative file path. 1812fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots': [\n" 1813fc51490bSJonas Devlieghere " { 'type': 'file', 'name': 'relative/file/path.h',\n" 1814fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n" 1815fc51490bSJonas Devlieghere " }\n" 1816fc51490bSJonas Devlieghere "] }", 1817fc51490bSJonas Devlieghere Lower); 1818fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1819fc51490bSJonas Devlieghere 1820fc51490bSJonas Devlieghere // Relative directory path. 1821fc51490bSJonas Devlieghere FS = getFromYAMLString( 1822fc51490bSJonas Devlieghere "{ 'roots': [\n" 1823fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': 'relative/directory/path.h',\n" 1824fc51490bSJonas Devlieghere " 'contents': []\n" 1825fc51490bSJonas Devlieghere " }\n" 1826fc51490bSJonas Devlieghere "] }", 1827fc51490bSJonas Devlieghere Lower); 1828fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get()); 1829fc51490bSJonas Devlieghere 1830fc51490bSJonas Devlieghere EXPECT_EQ(3, NumDiagnostics); 1831fc51490bSJonas Devlieghere } 183291e13164SVolodymyr Sapsai 183391e13164SVolodymyr Sapsai TEST_F(VFSFromYAMLTest, NonFallthroughDirectoryIteration) { 183491e13164SVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 183591e13164SVolodymyr Sapsai Lower->addDirectory("//root/"); 183691e13164SVolodymyr Sapsai Lower->addRegularFile("//root/a"); 183791e13164SVolodymyr Sapsai Lower->addRegularFile("//root/b"); 183891e13164SVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 183991e13164SVolodymyr Sapsai "{ 'use-external-names': false,\n" 184091e13164SVolodymyr Sapsai " 'fallthrough': false,\n" 184191e13164SVolodymyr Sapsai " 'roots': [\n" 184291e13164SVolodymyr Sapsai "{\n" 184391e13164SVolodymyr Sapsai " 'type': 'directory',\n" 184491e13164SVolodymyr Sapsai " 'name': '//root/',\n" 184591e13164SVolodymyr Sapsai " 'contents': [ {\n" 184691e13164SVolodymyr Sapsai " 'type': 'file',\n" 184791e13164SVolodymyr Sapsai " 'name': 'c',\n" 184891e13164SVolodymyr Sapsai " 'external-contents': '//root/a'\n" 184991e13164SVolodymyr Sapsai " }\n" 185091e13164SVolodymyr Sapsai " ]\n" 185191e13164SVolodymyr Sapsai "}\n" 185291e13164SVolodymyr Sapsai "]\n" 185391e13164SVolodymyr Sapsai "}", 185491e13164SVolodymyr Sapsai Lower); 185591e13164SVolodymyr Sapsai ASSERT_TRUE(FS.get() != nullptr); 185691e13164SVolodymyr Sapsai 185791e13164SVolodymyr Sapsai std::error_code EC; 185891e13164SVolodymyr Sapsai checkContents(FS->dir_begin("//root/", EC), 185991e13164SVolodymyr Sapsai {"//root/c"}); 186091e13164SVolodymyr Sapsai } 186191e13164SVolodymyr Sapsai 186291e13164SVolodymyr Sapsai TEST_F(VFSFromYAMLTest, DirectoryIterationWithDuplicates) { 186391e13164SVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 186491e13164SVolodymyr Sapsai Lower->addDirectory("//root/"); 186591e13164SVolodymyr Sapsai Lower->addRegularFile("//root/a"); 186691e13164SVolodymyr Sapsai Lower->addRegularFile("//root/b"); 186791e13164SVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 186891e13164SVolodymyr Sapsai "{ 'use-external-names': false,\n" 186991e13164SVolodymyr Sapsai " 'roots': [\n" 187091e13164SVolodymyr Sapsai "{\n" 187191e13164SVolodymyr Sapsai " 'type': 'directory',\n" 187291e13164SVolodymyr Sapsai " 'name': '//root/',\n" 187391e13164SVolodymyr Sapsai " 'contents': [ {\n" 187491e13164SVolodymyr Sapsai " 'type': 'file',\n" 187591e13164SVolodymyr Sapsai " 'name': 'a',\n" 187691e13164SVolodymyr Sapsai " 'external-contents': '//root/a'\n" 187791e13164SVolodymyr Sapsai " }\n" 187891e13164SVolodymyr Sapsai " ]\n" 187991e13164SVolodymyr Sapsai "}\n" 188091e13164SVolodymyr Sapsai "]\n" 188191e13164SVolodymyr Sapsai "}", 188291e13164SVolodymyr Sapsai Lower); 188391e13164SVolodymyr Sapsai ASSERT_TRUE(FS.get() != nullptr); 188491e13164SVolodymyr Sapsai 188591e13164SVolodymyr Sapsai std::error_code EC; 188691e13164SVolodymyr Sapsai checkContents(FS->dir_begin("//root/", EC), 188791e13164SVolodymyr Sapsai {"//root/a", "//root/b"}); 188891e13164SVolodymyr Sapsai } 188991e13164SVolodymyr Sapsai 189091e13164SVolodymyr Sapsai TEST_F(VFSFromYAMLTest, DirectoryIterationErrorInVFSLayer) { 189191e13164SVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 189291e13164SVolodymyr Sapsai Lower->addDirectory("//root/"); 189391e13164SVolodymyr Sapsai Lower->addDirectory("//root/foo"); 189491e13164SVolodymyr Sapsai Lower->addRegularFile("//root/foo/a"); 189591e13164SVolodymyr Sapsai Lower->addRegularFile("//root/foo/b"); 189691e13164SVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 189791e13164SVolodymyr Sapsai "{ 'use-external-names': false,\n" 189891e13164SVolodymyr Sapsai " 'roots': [\n" 189991e13164SVolodymyr Sapsai "{\n" 190091e13164SVolodymyr Sapsai " 'type': 'directory',\n" 190191e13164SVolodymyr Sapsai " 'name': '//root/',\n" 190291e13164SVolodymyr Sapsai " 'contents': [ {\n" 190391e13164SVolodymyr Sapsai " 'type': 'file',\n" 190491e13164SVolodymyr Sapsai " 'name': 'bar/a',\n" 190591e13164SVolodymyr Sapsai " 'external-contents': '//root/foo/a'\n" 190691e13164SVolodymyr Sapsai " }\n" 190791e13164SVolodymyr Sapsai " ]\n" 190891e13164SVolodymyr Sapsai "}\n" 190991e13164SVolodymyr Sapsai "]\n" 191091e13164SVolodymyr Sapsai "}", 191191e13164SVolodymyr Sapsai Lower); 191291e13164SVolodymyr Sapsai ASSERT_TRUE(FS.get() != nullptr); 191391e13164SVolodymyr Sapsai 191491e13164SVolodymyr Sapsai std::error_code EC; 191591e13164SVolodymyr Sapsai checkContents(FS->dir_begin("//root/foo", EC), 191691e13164SVolodymyr Sapsai {"//root/foo/a", "//root/foo/b"}); 191791e13164SVolodymyr Sapsai } 19187610033fSVolodymyr Sapsai 19197610033fSVolodymyr Sapsai TEST_F(VFSFromYAMLTest, GetRealPath) { 19207610033fSVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 1921ab73426cSVolodymyr Sapsai Lower->addDirectory("//dir/"); 19227610033fSVolodymyr Sapsai Lower->addRegularFile("/foo"); 19237610033fSVolodymyr Sapsai Lower->addSymlink("/link"); 19247610033fSVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 19257610033fSVolodymyr Sapsai "{ 'use-external-names': false,\n" 19267610033fSVolodymyr Sapsai " 'roots': [\n" 19277610033fSVolodymyr Sapsai "{\n" 19287610033fSVolodymyr Sapsai " 'type': 'directory',\n" 1929ab73426cSVolodymyr Sapsai " 'name': '//root/',\n" 19307610033fSVolodymyr Sapsai " 'contents': [ {\n" 19317610033fSVolodymyr Sapsai " 'type': 'file',\n" 19327610033fSVolodymyr Sapsai " 'name': 'bar',\n" 19337610033fSVolodymyr Sapsai " 'external-contents': '/link'\n" 19347610033fSVolodymyr Sapsai " }\n" 19357610033fSVolodymyr Sapsai " ]\n" 19367610033fSVolodymyr Sapsai "},\n" 19377610033fSVolodymyr Sapsai "{\n" 19387610033fSVolodymyr Sapsai " 'type': 'directory',\n" 1939ab73426cSVolodymyr Sapsai " 'name': '//dir/',\n" 19407610033fSVolodymyr Sapsai " 'contents': []\n" 19417610033fSVolodymyr Sapsai "}\n" 19427610033fSVolodymyr Sapsai "]\n" 19437610033fSVolodymyr Sapsai "}", 19447610033fSVolodymyr Sapsai Lower); 19457610033fSVolodymyr Sapsai ASSERT_TRUE(FS.get() != nullptr); 19467610033fSVolodymyr Sapsai 19477610033fSVolodymyr Sapsai // Regular file present in underlying file system. 19487610033fSVolodymyr Sapsai SmallString<16> RealPath; 19497610033fSVolodymyr Sapsai EXPECT_FALSE(FS->getRealPath("/foo", RealPath)); 19507610033fSVolodymyr Sapsai EXPECT_EQ(RealPath.str(), "/foo"); 19517610033fSVolodymyr Sapsai 19527610033fSVolodymyr Sapsai // File present in YAML pointing to symlink in underlying file system. 1953ab73426cSVolodymyr Sapsai EXPECT_FALSE(FS->getRealPath("//root/bar", RealPath)); 19547610033fSVolodymyr Sapsai EXPECT_EQ(RealPath.str(), "/symlink"); 19557610033fSVolodymyr Sapsai 19567610033fSVolodymyr Sapsai // Directories should fall back to the underlying file system is possible. 1957ab73426cSVolodymyr Sapsai EXPECT_FALSE(FS->getRealPath("//dir/", RealPath)); 1958ab73426cSVolodymyr Sapsai EXPECT_EQ(RealPath.str(), "//dir/"); 19597610033fSVolodymyr Sapsai 19607610033fSVolodymyr Sapsai // Try a non-existing file. 19617610033fSVolodymyr Sapsai EXPECT_EQ(FS->getRealPath("/non_existing", RealPath), 19627610033fSVolodymyr Sapsai errc::no_such_file_or_directory); 19637610033fSVolodymyr Sapsai } 196421703543SJonas Devlieghere 196521703543SJonas Devlieghere TEST_F(VFSFromYAMLTest, WorkingDirectory) { 196621703543SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 196721703543SJonas Devlieghere Lower->addDirectory("//root/"); 196821703543SJonas Devlieghere Lower->addDirectory("//root/foo"); 196921703543SJonas Devlieghere Lower->addRegularFile("//root/foo/a"); 197021703543SJonas Devlieghere Lower->addRegularFile("//root/foo/b"); 197121703543SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 197221703543SJonas Devlieghere "{ 'use-external-names': false,\n" 197321703543SJonas Devlieghere " 'roots': [\n" 197421703543SJonas Devlieghere "{\n" 197521703543SJonas Devlieghere " 'type': 'directory',\n" 197621703543SJonas Devlieghere " 'name': '//root/bar',\n" 197721703543SJonas Devlieghere " 'contents': [ {\n" 197821703543SJonas Devlieghere " 'type': 'file',\n" 197921703543SJonas Devlieghere " 'name': 'a',\n" 198021703543SJonas Devlieghere " 'external-contents': '//root/foo/a'\n" 198121703543SJonas Devlieghere " }\n" 198221703543SJonas Devlieghere " ]\n" 198321703543SJonas Devlieghere "}\n" 198421703543SJonas Devlieghere "]\n" 198521703543SJonas Devlieghere "}", 198621703543SJonas Devlieghere Lower); 198721703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 198821703543SJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/bar"); 198921703543SJonas Devlieghere ASSERT_FALSE(EC); 199021703543SJonas Devlieghere 199121703543SJonas Devlieghere llvm::ErrorOr<std::string> WorkingDir = FS->getCurrentWorkingDirectory(); 199221703543SJonas Devlieghere ASSERT_TRUE(WorkingDir); 199321703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/bar"); 199421703543SJonas Devlieghere 199521703543SJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("./a"); 199621703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 199721703543SJonas Devlieghere EXPECT_TRUE(Status->isStatusKnown()); 199821703543SJonas Devlieghere EXPECT_FALSE(Status->isDirectory()); 199921703543SJonas Devlieghere EXPECT_TRUE(Status->isRegularFile()); 200021703543SJonas Devlieghere EXPECT_FALSE(Status->isSymlink()); 200121703543SJonas Devlieghere EXPECT_FALSE(Status->isOther()); 200221703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 200321703543SJonas Devlieghere 200421703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("bogus"); 200521703543SJonas Devlieghere ASSERT_TRUE(EC); 200621703543SJonas Devlieghere WorkingDir = FS->getCurrentWorkingDirectory(); 200721703543SJonas Devlieghere ASSERT_TRUE(WorkingDir); 200821703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/bar"); 200921703543SJonas Devlieghere 201021703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/"); 201121703543SJonas Devlieghere ASSERT_FALSE(EC); 201221703543SJonas Devlieghere WorkingDir = FS->getCurrentWorkingDirectory(); 201321703543SJonas Devlieghere ASSERT_TRUE(WorkingDir); 201421703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/"); 201521703543SJonas Devlieghere 201621703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("bar"); 201721703543SJonas Devlieghere ASSERT_FALSE(EC); 201821703543SJonas Devlieghere WorkingDir = FS->getCurrentWorkingDirectory(); 201921703543SJonas Devlieghere ASSERT_TRUE(WorkingDir); 202021703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/bar"); 202121703543SJonas Devlieghere } 202221703543SJonas Devlieghere 202321703543SJonas Devlieghere TEST_F(VFSFromYAMLTest, WorkingDirectoryFallthrough) { 202421703543SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem()); 202521703543SJonas Devlieghere Lower->addDirectory("//root/"); 202621703543SJonas Devlieghere Lower->addDirectory("//root/foo"); 202721703543SJonas Devlieghere Lower->addRegularFile("//root/foo/a"); 202821703543SJonas Devlieghere Lower->addRegularFile("//root/foo/b"); 202921703543SJonas Devlieghere Lower->addRegularFile("//root/c"); 203021703543SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 203121703543SJonas Devlieghere "{ 'use-external-names': false,\n" 203221703543SJonas Devlieghere " 'roots': [\n" 203321703543SJonas Devlieghere "{\n" 203421703543SJonas Devlieghere " 'type': 'directory',\n" 203521703543SJonas Devlieghere " 'name': '//root/bar',\n" 203621703543SJonas Devlieghere " 'contents': [ {\n" 203721703543SJonas Devlieghere " 'type': 'file',\n" 203821703543SJonas Devlieghere " 'name': 'a',\n" 203921703543SJonas Devlieghere " 'external-contents': '//root/foo/a'\n" 204021703543SJonas Devlieghere " }\n" 204121703543SJonas Devlieghere " ]\n" 2042f2f77499SJonas Devlieghere "},\n" 2043f2f77499SJonas Devlieghere "{\n" 2044f2f77499SJonas Devlieghere " 'type': 'directory',\n" 2045f2f77499SJonas Devlieghere " 'name': '//root/bar/baz',\n" 2046f2f77499SJonas Devlieghere " 'contents': [ {\n" 2047f2f77499SJonas Devlieghere " 'type': 'file',\n" 2048f2f77499SJonas Devlieghere " 'name': 'a',\n" 2049f2f77499SJonas Devlieghere " 'external-contents': '//root/foo/a'\n" 2050f2f77499SJonas Devlieghere " }\n" 2051f2f77499SJonas Devlieghere " ]\n" 205221703543SJonas Devlieghere "}\n" 205321703543SJonas Devlieghere "]\n" 205421703543SJonas Devlieghere "}", 205521703543SJonas Devlieghere Lower); 205621703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 205721703543SJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/"); 205821703543SJonas Devlieghere ASSERT_FALSE(EC); 205921703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 206021703543SJonas Devlieghere 206121703543SJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("bar/a"); 206221703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 206321703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 206421703543SJonas Devlieghere 206521703543SJonas Devlieghere Status = FS->status("foo/a"); 206621703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 206721703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 206821703543SJonas Devlieghere 206921703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/bar"); 207021703543SJonas Devlieghere ASSERT_FALSE(EC); 207121703543SJonas Devlieghere 207221703543SJonas Devlieghere Status = FS->status("./a"); 207321703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 207421703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 207521703543SJonas Devlieghere 207621703543SJonas Devlieghere Status = FS->status("./b"); 207721703543SJonas Devlieghere ASSERT_TRUE(Status.getError()); 207821703543SJonas Devlieghere 207921703543SJonas Devlieghere Status = FS->status("./c"); 208021703543SJonas Devlieghere ASSERT_TRUE(Status.getError()); 208121703543SJonas Devlieghere 208221703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/"); 208321703543SJonas Devlieghere ASSERT_FALSE(EC); 208421703543SJonas Devlieghere 208521703543SJonas Devlieghere Status = FS->status("c"); 208621703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 208721703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 2088f2f77499SJonas Devlieghere 2089f2f77499SJonas Devlieghere Status = FS->status("./bar/baz/a"); 2090f2f77499SJonas Devlieghere ASSERT_FALSE(Status.getError()); 2091f2f77499SJonas Devlieghere EXPECT_TRUE(Status->exists()); 2092f2f77499SJonas Devlieghere 2093f2f77499SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/bar"); 2094f2f77499SJonas Devlieghere ASSERT_FALSE(EC); 2095f2f77499SJonas Devlieghere 2096f2f77499SJonas Devlieghere Status = FS->status("./baz/a"); 2097f2f77499SJonas Devlieghere ASSERT_FALSE(Status.getError()); 2098f2f77499SJonas Devlieghere EXPECT_TRUE(Status->exists()); 2099f2f77499SJonas Devlieghere 2100f2f77499SJonas Devlieghere Status = FS->status("../bar/baz/a"); 2101f2f77499SJonas Devlieghere ASSERT_FALSE(Status.getError()); 2102f2f77499SJonas Devlieghere EXPECT_TRUE(Status->exists()); 210321703543SJonas Devlieghere } 210421703543SJonas Devlieghere 210521703543SJonas Devlieghere TEST_F(VFSFromYAMLTest, WorkingDirectoryFallthroughInvalid) { 210621703543SJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 210721703543SJonas Devlieghere Lower->addDirectory("//root/"); 210821703543SJonas Devlieghere Lower->addDirectory("//root/foo"); 210921703543SJonas Devlieghere Lower->addRegularFile("//root/foo/a"); 211021703543SJonas Devlieghere Lower->addRegularFile("//root/foo/b"); 211121703543SJonas Devlieghere Lower->addRegularFile("//root/c"); 211221703543SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString( 211321703543SJonas Devlieghere "{ 'use-external-names': false,\n" 211421703543SJonas Devlieghere " 'roots': [\n" 211521703543SJonas Devlieghere "{\n" 211621703543SJonas Devlieghere " 'type': 'directory',\n" 211721703543SJonas Devlieghere " 'name': '//root/bar',\n" 211821703543SJonas Devlieghere " 'contents': [ {\n" 211921703543SJonas Devlieghere " 'type': 'file',\n" 212021703543SJonas Devlieghere " 'name': 'a',\n" 212121703543SJonas Devlieghere " 'external-contents': '//root/foo/a'\n" 212221703543SJonas Devlieghere " }\n" 212321703543SJonas Devlieghere " ]\n" 212421703543SJonas Devlieghere "}\n" 212521703543SJonas Devlieghere "]\n" 212621703543SJonas Devlieghere "}", 212721703543SJonas Devlieghere Lower); 212821703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 212921703543SJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/"); 213021703543SJonas Devlieghere ASSERT_FALSE(EC); 213121703543SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 213221703543SJonas Devlieghere 213321703543SJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("bar/a"); 213421703543SJonas Devlieghere ASSERT_FALSE(Status.getError()); 213521703543SJonas Devlieghere EXPECT_TRUE(Status->exists()); 213621703543SJonas Devlieghere 213721703543SJonas Devlieghere Status = FS->status("foo/a"); 213821703543SJonas Devlieghere ASSERT_TRUE(Status.getError()); 213921703543SJonas Devlieghere } 214042df3e29SJonas Devlieghere 214142df3e29SJonas Devlieghere TEST_F(VFSFromYAMLTest, YAMLVFSWriterTest) { 2142fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 2143fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 2144fad75598SSergej Jaskiewicz TempFile _ab(TestDirectory.path("a, b")); 2145fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c")); 2146fad75598SSergej Jaskiewicz TempFile _cd(TestDirectory.path("c/d")); 2147fad75598SSergej Jaskiewicz TempDir _e(TestDirectory.path("e")); 2148fad75598SSergej Jaskiewicz TempDir _ef(TestDirectory.path("e/f")); 2149fad75598SSergej Jaskiewicz TempFile _g(TestDirectory.path("g")); 2150fad75598SSergej Jaskiewicz TempDir _h(TestDirectory.path("h")); 215142df3e29SJonas Devlieghere 215242df3e29SJonas Devlieghere vfs::YAMLVFSWriter VFSWriter; 2153fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a"); 2154fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ab.path(), "//root/a/b"); 2155fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_cd.path(), "//root/c/d"); 2156fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_e.path(), "//root/e"); 2157fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ef.path(), "//root/e/f"); 2158fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_g.path(), "//root/g"); 2159fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_h.path(), "//root/h"); 216042df3e29SJonas Devlieghere 216142df3e29SJonas Devlieghere std::string Buffer; 216242df3e29SJonas Devlieghere raw_string_ostream OS(Buffer); 216342df3e29SJonas Devlieghere VFSWriter.write(OS); 216442df3e29SJonas Devlieghere OS.flush(); 216542df3e29SJonas Devlieghere 216642df3e29SJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 216742df3e29SJonas Devlieghere Lower->addDirectory("//root/"); 216842df3e29SJonas Devlieghere Lower->addDirectory("//root/a"); 216942df3e29SJonas Devlieghere Lower->addRegularFile("//root/a/b"); 217042df3e29SJonas Devlieghere Lower->addDirectory("//root/b"); 217142df3e29SJonas Devlieghere Lower->addDirectory("//root/c"); 217242df3e29SJonas Devlieghere Lower->addRegularFile("//root/c/d"); 217342df3e29SJonas Devlieghere Lower->addDirectory("//root/e"); 217442df3e29SJonas Devlieghere Lower->addDirectory("//root/e/f"); 21755c145034SJan Korous Lower->addRegularFile("//root/g"); 21765c145034SJan Korous Lower->addDirectory("//root/h"); 217742df3e29SJonas Devlieghere 217842df3e29SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower); 217942df3e29SJonas Devlieghere ASSERT_TRUE(FS.get() != nullptr); 218042df3e29SJonas Devlieghere 2181fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_a.path())); 2182fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_ab.path())); 2183fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_c.path())); 2184fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_cd.path())); 2185fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_e.path())); 2186fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_ef.path())); 2187fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_g.path())); 2188fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_h.path())); 218942df3e29SJonas Devlieghere } 2190c0330bc0SJan Korous 219159ba19c5SJonas Devlieghere TEST_F(VFSFromYAMLTest, YAMLVFSWriterTest2) { 2192fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 2193fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 2194fad75598SSergej Jaskiewicz TempFile _ab(TestDirectory.path("a/b")); 2195fad75598SSergej Jaskiewicz TempDir _ac(TestDirectory.path("a/c")); 2196fad75598SSergej Jaskiewicz TempFile _acd(TestDirectory.path("a/c/d")); 2197fad75598SSergej Jaskiewicz TempFile _ace(TestDirectory.path("a/c/e")); 2198fad75598SSergej Jaskiewicz TempFile _acf(TestDirectory.path("a/c/f")); 2199fad75598SSergej Jaskiewicz TempDir _ag(TestDirectory.path("a/g")); 2200fad75598SSergej Jaskiewicz TempFile _agh(TestDirectory.path("a/g/h")); 220159ba19c5SJonas Devlieghere 220259ba19c5SJonas Devlieghere vfs::YAMLVFSWriter VFSWriter; 2203fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a"); 2204fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ab.path(), "//root/a/b"); 2205fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ac.path(), "//root/a/c"); 2206fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acd.path(), "//root/a/c/d"); 2207fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ace.path(), "//root/a/c/e"); 2208fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acf.path(), "//root/a/c/f"); 2209fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ag.path(), "//root/a/g"); 2210fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_agh.path(), "//root/a/g/h"); 221159ba19c5SJonas Devlieghere 221259ba19c5SJonas Devlieghere std::string Buffer; 221359ba19c5SJonas Devlieghere raw_string_ostream OS(Buffer); 221459ba19c5SJonas Devlieghere VFSWriter.write(OS); 221559ba19c5SJonas Devlieghere OS.flush(); 221659ba19c5SJonas Devlieghere 221759ba19c5SJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 221859ba19c5SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower); 2219759465eeSJan Korous EXPECT_TRUE(FS.get() != nullptr); 222059ba19c5SJonas Devlieghere } 222159ba19c5SJonas Devlieghere 222258bc507bSJonas Devlieghere TEST_F(VFSFromYAMLTest, YAMLVFSWriterTest3) { 2223fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 2224fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 2225fad75598SSergej Jaskiewicz TempFile _ab(TestDirectory.path("a/b")); 2226fad75598SSergej Jaskiewicz TempDir _ac(TestDirectory.path("a/c")); 2227fad75598SSergej Jaskiewicz TempDir _acd(TestDirectory.path("a/c/d")); 2228fad75598SSergej Jaskiewicz TempDir _acde(TestDirectory.path("a/c/d/e")); 2229fad75598SSergej Jaskiewicz TempFile _acdef(TestDirectory.path("a/c/d/e/f")); 2230fad75598SSergej Jaskiewicz TempFile _acdeg(TestDirectory.path("a/c/d/e/g")); 2231fad75598SSergej Jaskiewicz TempDir _ah(TestDirectory.path("a/h")); 2232fad75598SSergej Jaskiewicz TempFile _ahi(TestDirectory.path("a/h/i")); 223358bc507bSJonas Devlieghere 223458bc507bSJonas Devlieghere vfs::YAMLVFSWriter VFSWriter; 2235fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a"); 2236fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ab.path(), "//root/a/b"); 2237fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ac.path(), "//root/a/c"); 2238fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_acd.path(), "//root/a/c/d"); 2239fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_acde.path(), "//root/a/c/d/e"); 2240fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acdef.path(), "//root/a/c/d/e/f"); 2241fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acdeg.path(), "//root/a/c/d/e/g"); 2242fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ahi.path(), "//root/a/h"); 2243fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ahi.path(), "//root/a/h/i"); 224458bc507bSJonas Devlieghere 224558bc507bSJonas Devlieghere std::string Buffer; 224658bc507bSJonas Devlieghere raw_string_ostream OS(Buffer); 224758bc507bSJonas Devlieghere VFSWriter.write(OS); 224858bc507bSJonas Devlieghere OS.flush(); 224958bc507bSJonas Devlieghere 225058bc507bSJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 225158bc507bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower); 2252759465eeSJan Korous EXPECT_TRUE(FS.get() != nullptr); 225358bc507bSJonas Devlieghere } 225458bc507bSJonas Devlieghere 2255c0330bc0SJan Korous TEST_F(VFSFromYAMLTest, YAMLVFSWriterTestHandleDirs) { 2256fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true); 2257fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a")); 2258fad75598SSergej Jaskiewicz TempDir _b(TestDirectory.path("b")); 2259fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c")); 2260c0330bc0SJan Korous 2261c0330bc0SJan Korous vfs::YAMLVFSWriter VFSWriter; 2262fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a"); 2263fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_b.path(), "//root/b"); 2264fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_c.path(), "//root/c"); 2265c0330bc0SJan Korous 2266c0330bc0SJan Korous std::string Buffer; 2267c0330bc0SJan Korous raw_string_ostream OS(Buffer); 2268c0330bc0SJan Korous VFSWriter.write(OS); 2269c0330bc0SJan Korous OS.flush(); 2270c0330bc0SJan Korous 2271c0330bc0SJan Korous // We didn't add a single file - only directories. 2272c0330bc0SJan Korous EXPECT_TRUE(Buffer.find("'type': 'file'") == std::string::npos); 2273c0330bc0SJan Korous 2274c0330bc0SJan Korous IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem()); 2275c0330bc0SJan Korous Lower->addDirectory("//root/a"); 2276c0330bc0SJan Korous Lower->addDirectory("//root/b"); 2277c0330bc0SJan Korous Lower->addDirectory("//root/c"); 2278c0330bc0SJan Korous // canaries 2279c0330bc0SJan Korous Lower->addRegularFile("//root/a/a"); 2280c0330bc0SJan Korous Lower->addRegularFile("//root/b/b"); 2281c0330bc0SJan Korous Lower->addRegularFile("//root/c/c"); 2282c0330bc0SJan Korous 2283c0330bc0SJan Korous IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower); 2284c0330bc0SJan Korous ASSERT_TRUE(FS.get() != nullptr); 2285c0330bc0SJan Korous 2286fad75598SSergej Jaskiewicz EXPECT_FALSE(FS->exists(_a.path("a"))); 2287fad75598SSergej Jaskiewicz EXPECT_FALSE(FS->exists(_b.path("b"))); 2288fad75598SSergej Jaskiewicz EXPECT_FALSE(FS->exists(_c.path("c"))); 2289c0330bc0SJan Korous } 2290