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;
DummyFile__anon6124b8b40111::DummyFile35fc51490bSJonas Devlieghere explicit DummyFile(vfs::Status S) : S(S) {}
status__anon6124b8b40111::DummyFile36fc51490bSJonas Devlieghere llvm::ErrorOr<vfs::Status> status() override { return S; }
37fc51490bSJonas Devlieghere llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBuffer__anon6124b8b40111::DummyFile38fc51490bSJonas Devlieghere getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
39fc51490bSJonas Devlieghere bool IsVolatile) override {
40fc51490bSJonas Devlieghere llvm_unreachable("unimplemented");
41fc51490bSJonas Devlieghere }
close__anon6124b8b40111::DummyFile42fc51490bSJonas 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
getNextFSID()52fc51490bSJonas Devlieghere static int getNextFSID() {
53fc51490bSJonas Devlieghere static int Count = 0;
54fc51490bSJonas Devlieghere return Count++;
55fc51490bSJonas Devlieghere }
56fc51490bSJonas Devlieghere
57fc51490bSJonas Devlieghere public:
DummyFileSystem()58fc51490bSJonas Devlieghere DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
59fc51490bSJonas Devlieghere
status(const Twine & Path)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>>
openFileForRead(const Twine & Path)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 }
getCurrentWorkingDirectory() const73fc51490bSJonas Devlieghere llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
7421703543SJonas Devlieghere return WorkingDirectory;
75fc51490bSJonas Devlieghere }
setCurrentWorkingDirectory(const Twine & Path)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".
getRealPath(const Twine & Path,SmallVectorImpl<char> & Output) const8199538e89SSam 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;
isInPath__anon6124b8b40111::DummyFileSystem::DirIterImpl100fc51490bSJonas 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 }
DirIterImpl__anon6124b8b40111::DummyFileSystem::DirIterImpl108fc51490bSJonas 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 }
increment__anon6124b8b40111::DummyFileSystem::DirIterImpl120fc51490bSJonas 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
dir_begin(const Twine & Dir,std::error_code & EC)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
addEntry(StringRef Path,const vfs::Status & Status)141fc51490bSJonas Devlieghere void addEntry(StringRef Path, const vfs::Status &Status) {
142adcd0268SBenjamin Kramer FilesAndDirs[std::string(Path)] = Status;
143fc51490bSJonas Devlieghere }
144fc51490bSJonas Devlieghere
findEntry(const Twine & Path) const14521703543SJonas 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
addRegularFile(StringRef Path,sys::fs::perms Perms=sys::fs::all_all)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
addDirectory(StringRef Path,sys::fs::perms Perms=sys::fs::all_all)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
addSymlink(StringRef Path)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 }
17441255241SBen Barham
17541255241SBen Barham protected:
printImpl(raw_ostream & OS,PrintType Type,unsigned IndentLevel) const17641255241SBen Barham void printImpl(raw_ostream &OS, PrintType Type,
17741255241SBen Barham unsigned IndentLevel) const override {
17841255241SBen Barham printIndent(OS, IndentLevel);
17941255241SBen Barham OS << "DummyFileSystem (";
18041255241SBen Barham switch (Type) {
18141255241SBen Barham case vfs::FileSystem::PrintType::Summary:
18241255241SBen Barham OS << "Summary";
18341255241SBen Barham break;
18441255241SBen Barham case vfs::FileSystem::PrintType::Contents:
18541255241SBen Barham OS << "Contents";
18641255241SBen Barham break;
18741255241SBen Barham case vfs::FileSystem::PrintType::RecursiveContents:
18841255241SBen Barham OS << "RecursiveContents";
18941255241SBen Barham break;
19041255241SBen Barham }
19141255241SBen Barham OS << ")\n";
19241255241SBen Barham }
193fc51490bSJonas Devlieghere };
194fc51490bSJonas Devlieghere
19521703543SJonas Devlieghere class ErrorDummyFileSystem : public DummyFileSystem {
setCurrentWorkingDirectory(const Twine & Path)19621703543SJonas Devlieghere std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
19721703543SJonas Devlieghere return llvm::errc::no_such_file_or_directory;
19821703543SJonas Devlieghere }
19921703543SJonas Devlieghere };
20021703543SJonas Devlieghere
201fc51490bSJonas Devlieghere /// Replace back-slashes by front-slashes.
getPosixPath(const Twine & S)20235ab2a11SPaul Pluzhnikov std::string getPosixPath(const Twine &S) {
203fc51490bSJonas Devlieghere SmallString<128> Result;
204fc51490bSJonas Devlieghere llvm::sys::path::native(S, Result, llvm::sys::path::Style::posix);
205adcd0268SBenjamin Kramer return std::string(Result.str());
206fc51490bSJonas Devlieghere }
207fc51490bSJonas Devlieghere } // end anonymous namespace
208fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,StatusQueries)209fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, StatusQueries) {
210fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
211fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status((std::error_code()));
212fc51490bSJonas Devlieghere
213fc51490bSJonas Devlieghere D->addRegularFile("/foo");
214fc51490bSJonas Devlieghere Status = D->status("/foo");
215fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError());
216fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isStatusKnown());
217fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isDirectory());
218fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isRegularFile());
219fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isSymlink());
220fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isOther());
221fc51490bSJonas Devlieghere EXPECT_TRUE(Status->exists());
222fc51490bSJonas Devlieghere
223fc51490bSJonas Devlieghere D->addDirectory("/bar");
224fc51490bSJonas Devlieghere Status = D->status("/bar");
225fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError());
226fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isStatusKnown());
227fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isDirectory());
228fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isRegularFile());
229fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isSymlink());
230fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isOther());
231fc51490bSJonas Devlieghere EXPECT_TRUE(Status->exists());
232fc51490bSJonas Devlieghere
233fc51490bSJonas Devlieghere D->addSymlink("/baz");
234fc51490bSJonas Devlieghere Status = D->status("/baz");
235fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError());
236fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isStatusKnown());
237fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isDirectory());
238fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isRegularFile());
239fc51490bSJonas Devlieghere EXPECT_TRUE(Status->isSymlink());
240fc51490bSJonas Devlieghere EXPECT_FALSE(Status->isOther());
241fc51490bSJonas Devlieghere EXPECT_TRUE(Status->exists());
242fc51490bSJonas Devlieghere
243fc51490bSJonas Devlieghere EXPECT_TRUE(Status->equivalent(*Status));
244fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status2 = D->status("/foo");
245fc51490bSJonas Devlieghere ASSERT_FALSE(Status2.getError());
246fc51490bSJonas Devlieghere EXPECT_FALSE(Status->equivalent(*Status2));
247fc51490bSJonas Devlieghere }
248fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,BaseOnlyOverlay)249fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
250fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
251fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status((std::error_code()));
252fc51490bSJonas Devlieghere EXPECT_FALSE(Status = D->status("/foo"));
253fc51490bSJonas Devlieghere
254fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
255fc51490bSJonas Devlieghere EXPECT_FALSE(Status = O->status("/foo"));
256fc51490bSJonas Devlieghere
257fc51490bSJonas Devlieghere D->addRegularFile("/foo");
258fc51490bSJonas Devlieghere Status = D->status("/foo");
259fc51490bSJonas Devlieghere EXPECT_FALSE(Status.getError());
260fc51490bSJonas Devlieghere
261fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status2((std::error_code()));
262fc51490bSJonas Devlieghere Status2 = O->status("/foo");
263fc51490bSJonas Devlieghere EXPECT_FALSE(Status2.getError());
264fc51490bSJonas Devlieghere EXPECT_TRUE(Status->equivalent(*Status2));
265fc51490bSJonas Devlieghere }
266fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,GetRealPathInOverlay)267fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, GetRealPathInOverlay) {
268fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
269fc51490bSJonas Devlieghere Lower->addRegularFile("/foo");
270fc51490bSJonas Devlieghere Lower->addSymlink("/lower_link");
271fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
272fc51490bSJonas Devlieghere
273fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
274fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
275fc51490bSJonas Devlieghere O->pushOverlay(Upper);
276fc51490bSJonas Devlieghere
277fc51490bSJonas Devlieghere // Regular file.
278fc51490bSJonas Devlieghere SmallString<16> RealPath;
279fc51490bSJonas Devlieghere EXPECT_FALSE(O->getRealPath("/foo", RealPath));
280fc51490bSJonas Devlieghere EXPECT_EQ(RealPath.str(), "/foo");
281fc51490bSJonas Devlieghere
282fc51490bSJonas Devlieghere // Expect no error getting real path for symlink in lower overlay.
283fc51490bSJonas Devlieghere EXPECT_FALSE(O->getRealPath("/lower_link", RealPath));
284fc51490bSJonas Devlieghere EXPECT_EQ(RealPath.str(), "/symlink");
285fc51490bSJonas Devlieghere
286fc51490bSJonas Devlieghere // Try a non-existing link.
287fc51490bSJonas Devlieghere EXPECT_EQ(O->getRealPath("/upper_link", RealPath),
288fc51490bSJonas Devlieghere errc::no_such_file_or_directory);
289fc51490bSJonas Devlieghere
290fc51490bSJonas Devlieghere // Add a new symlink in upper.
291fc51490bSJonas Devlieghere Upper->addSymlink("/upper_link");
292fc51490bSJonas Devlieghere EXPECT_FALSE(O->getRealPath("/upper_link", RealPath));
293fc51490bSJonas Devlieghere EXPECT_EQ(RealPath.str(), "/symlink");
294fc51490bSJonas Devlieghere }
295fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,OverlayFiles)296fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, OverlayFiles) {
297fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
298fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
299fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
300fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
301fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Base));
302fc51490bSJonas Devlieghere O->pushOverlay(Middle);
303fc51490bSJonas Devlieghere O->pushOverlay(Top);
304fc51490bSJonas Devlieghere
305fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status1((std::error_code())),
306fc51490bSJonas Devlieghere Status2((std::error_code())), Status3((std::error_code())),
307fc51490bSJonas Devlieghere StatusB((std::error_code())), StatusM((std::error_code())),
308fc51490bSJonas Devlieghere StatusT((std::error_code()));
309fc51490bSJonas Devlieghere
310fc51490bSJonas Devlieghere Base->addRegularFile("/foo");
311fc51490bSJonas Devlieghere StatusB = Base->status("/foo");
312fc51490bSJonas Devlieghere ASSERT_FALSE(StatusB.getError());
313fc51490bSJonas Devlieghere Status1 = O->status("/foo");
314fc51490bSJonas Devlieghere ASSERT_FALSE(Status1.getError());
315fc51490bSJonas Devlieghere Middle->addRegularFile("/foo");
316fc51490bSJonas Devlieghere StatusM = Middle->status("/foo");
317fc51490bSJonas Devlieghere ASSERT_FALSE(StatusM.getError());
318fc51490bSJonas Devlieghere Status2 = O->status("/foo");
319fc51490bSJonas Devlieghere ASSERT_FALSE(Status2.getError());
320fc51490bSJonas Devlieghere Top->addRegularFile("/foo");
321fc51490bSJonas Devlieghere StatusT = Top->status("/foo");
322fc51490bSJonas Devlieghere ASSERT_FALSE(StatusT.getError());
323fc51490bSJonas Devlieghere Status3 = O->status("/foo");
324fc51490bSJonas Devlieghere ASSERT_FALSE(Status3.getError());
325fc51490bSJonas Devlieghere
326fc51490bSJonas Devlieghere EXPECT_TRUE(Status1->equivalent(*StatusB));
327fc51490bSJonas Devlieghere EXPECT_TRUE(Status2->equivalent(*StatusM));
328fc51490bSJonas Devlieghere EXPECT_TRUE(Status3->equivalent(*StatusT));
329fc51490bSJonas Devlieghere
330fc51490bSJonas Devlieghere EXPECT_FALSE(Status1->equivalent(*Status2));
331fc51490bSJonas Devlieghere EXPECT_FALSE(Status2->equivalent(*Status3));
332fc51490bSJonas Devlieghere EXPECT_FALSE(Status1->equivalent(*Status3));
333fc51490bSJonas Devlieghere }
334fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,OverlayDirsNonMerged)335fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, OverlayDirsNonMerged) {
336fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
337fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
338fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
339fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
340fc51490bSJonas Devlieghere O->pushOverlay(Upper);
341fc51490bSJonas Devlieghere
342fc51490bSJonas Devlieghere Lower->addDirectory("/lower-only");
343fc51490bSJonas Devlieghere Upper->addDirectory("/upper-only");
344fc51490bSJonas Devlieghere
345fc51490bSJonas Devlieghere // non-merged paths should be the same
346fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
347fc51490bSJonas Devlieghere ASSERT_FALSE(Status1.getError());
348fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
349fc51490bSJonas Devlieghere ASSERT_FALSE(Status2.getError());
350fc51490bSJonas Devlieghere EXPECT_TRUE(Status1->equivalent(*Status2));
351fc51490bSJonas Devlieghere
352fc51490bSJonas Devlieghere Status1 = Upper->status("/upper-only");
353fc51490bSJonas Devlieghere ASSERT_FALSE(Status1.getError());
354fc51490bSJonas Devlieghere Status2 = O->status("/upper-only");
355fc51490bSJonas Devlieghere ASSERT_FALSE(Status2.getError());
356fc51490bSJonas Devlieghere EXPECT_TRUE(Status1->equivalent(*Status2));
357fc51490bSJonas Devlieghere }
358fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,MergedDirPermissions)359fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, MergedDirPermissions) {
360fc51490bSJonas Devlieghere // merged directories get the permissions of the upper dir
361fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
362fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
363fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
364fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
365fc51490bSJonas Devlieghere O->pushOverlay(Upper);
366fc51490bSJonas Devlieghere
367fc51490bSJonas Devlieghere ErrorOr<vfs::Status> Status((std::error_code()));
368fc51490bSJonas Devlieghere Lower->addDirectory("/both", sys::fs::owner_read);
369fc51490bSJonas Devlieghere Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
370fc51490bSJonas Devlieghere Status = O->status("/both");
371fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError());
372fc51490bSJonas Devlieghere EXPECT_EQ(0740, Status->getPermissions());
373fc51490bSJonas Devlieghere
374fc51490bSJonas Devlieghere // permissions (as usual) are not recursively applied
375fc51490bSJonas Devlieghere Lower->addRegularFile("/both/foo", sys::fs::owner_read);
376fc51490bSJonas Devlieghere Upper->addRegularFile("/both/bar", sys::fs::owner_write);
377fc51490bSJonas Devlieghere Status = O->status("/both/foo");
378fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError());
379fc51490bSJonas Devlieghere EXPECT_EQ(0400, Status->getPermissions());
380fc51490bSJonas Devlieghere Status = O->status("/both/bar");
381fc51490bSJonas Devlieghere ASSERT_FALSE(Status.getError());
382fc51490bSJonas Devlieghere EXPECT_EQ(0200, Status->getPermissions());
383fc51490bSJonas Devlieghere }
384fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,OverlayIterator)385efe21088SJonas Devlieghere TEST(VirtualFileSystemTest, OverlayIterator) {
386efe21088SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
387efe21088SJonas Devlieghere Lower->addRegularFile("/foo");
388efe21088SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
389efe21088SJonas Devlieghere
390efe21088SJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
391efe21088SJonas Devlieghere new vfs::OverlayFileSystem(Lower));
392efe21088SJonas Devlieghere O->pushOverlay(Upper);
393efe21088SJonas Devlieghere
394efe21088SJonas Devlieghere ErrorOr<vfs::Status> Status((std::error_code()));
395efe21088SJonas Devlieghere {
396efe21088SJonas Devlieghere auto it = O->overlays_begin();
397efe21088SJonas Devlieghere auto end = O->overlays_end();
398efe21088SJonas Devlieghere
399efe21088SJonas Devlieghere EXPECT_NE(it, end);
400efe21088SJonas Devlieghere
401efe21088SJonas Devlieghere Status = (*it)->status("/foo");
402efe21088SJonas Devlieghere ASSERT_TRUE(Status.getError());
403efe21088SJonas Devlieghere
404efe21088SJonas Devlieghere it++;
405efe21088SJonas Devlieghere EXPECT_NE(it, end);
406efe21088SJonas Devlieghere
407efe21088SJonas Devlieghere Status = (*it)->status("/foo");
408efe21088SJonas Devlieghere ASSERT_FALSE(Status.getError());
409efe21088SJonas Devlieghere EXPECT_TRUE(Status->exists());
410efe21088SJonas Devlieghere
411efe21088SJonas Devlieghere it++;
412efe21088SJonas Devlieghere EXPECT_EQ(it, end);
413efe21088SJonas Devlieghere }
414efe21088SJonas Devlieghere
415efe21088SJonas Devlieghere {
416efe21088SJonas Devlieghere auto it = O->overlays_rbegin();
417efe21088SJonas Devlieghere auto end = O->overlays_rend();
418efe21088SJonas Devlieghere
419efe21088SJonas Devlieghere EXPECT_NE(it, end);
420efe21088SJonas Devlieghere
421efe21088SJonas Devlieghere Status = (*it)->status("/foo");
422efe21088SJonas Devlieghere ASSERT_FALSE(Status.getError());
423efe21088SJonas Devlieghere EXPECT_TRUE(Status->exists());
424efe21088SJonas Devlieghere
425efe21088SJonas Devlieghere it++;
426efe21088SJonas Devlieghere EXPECT_NE(it, end);
427efe21088SJonas Devlieghere
428efe21088SJonas Devlieghere Status = (*it)->status("/foo");
429efe21088SJonas Devlieghere ASSERT_TRUE(Status.getError());
430efe21088SJonas Devlieghere
431efe21088SJonas Devlieghere it++;
432efe21088SJonas Devlieghere EXPECT_EQ(it, end);
433efe21088SJonas Devlieghere }
434efe21088SJonas Devlieghere }
435efe21088SJonas Devlieghere
TEST(VirtualFileSystemTest,BasicRealFSIteration)436fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BasicRealFSIteration) {
437fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
438fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
439fc51490bSJonas Devlieghere
440fc51490bSJonas Devlieghere std::error_code EC;
441fad75598SSergej Jaskiewicz vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory.path()), EC);
442fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
443fc51490bSJonas Devlieghere EXPECT_EQ(vfs::directory_iterator(), I); // empty directory is empty
444fc51490bSJonas Devlieghere
445fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a"));
446fad75598SSergej Jaskiewicz TempDir _ab(TestDirectory.path("a/b"));
447fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c"));
448fad75598SSergej Jaskiewicz TempDir _cd(TestDirectory.path("c/d"));
449fc51490bSJonas Devlieghere
450fad75598SSergej Jaskiewicz I = FS->dir_begin(Twine(TestDirectory.path()), EC);
451fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
452fc51490bSJonas Devlieghere ASSERT_NE(vfs::directory_iterator(), I);
453fc51490bSJonas Devlieghere // Check either a or c, since we can't rely on the iteration order.
454fc51490bSJonas Devlieghere EXPECT_TRUE(I->path().endswith("a") || I->path().endswith("c"));
455fc51490bSJonas Devlieghere I.increment(EC);
456fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
457fc51490bSJonas Devlieghere ASSERT_NE(vfs::directory_iterator(), I);
458fc51490bSJonas Devlieghere EXPECT_TRUE(I->path().endswith("a") || I->path().endswith("c"));
459fc51490bSJonas Devlieghere I.increment(EC);
460fc51490bSJonas Devlieghere EXPECT_EQ(vfs::directory_iterator(), I);
461fc51490bSJonas Devlieghere }
462fc51490bSJonas Devlieghere
46362ab1a1aSSam McCall #ifdef LLVM_ON_UNIX
TEST(VirtualFileSystemTest,MultipleWorkingDirs)46415e475e2SSam McCall TEST(VirtualFileSystemTest, MultipleWorkingDirs) {
46515e475e2SSam McCall // Our root contains a/aa, b/bb, c, where c is a link to a/.
46615e475e2SSam McCall // Run tests both in root/b/ and root/c/ (to test "normal" and symlink dirs).
46715e475e2SSam McCall // Interleave operations to show the working directories are independent.
468fad75598SSergej Jaskiewicz TempDir Root("r", /*Unique*/ true);
469fad75598SSergej Jaskiewicz TempDir ADir(Root.path("a"));
470fad75598SSergej Jaskiewicz TempDir BDir(Root.path("b"));
471fad75598SSergej Jaskiewicz TempLink C(ADir.path(), Root.path("c"));
472fad75598SSergej Jaskiewicz TempFile AA(ADir.path("aa"), "", "aaaa");
473fad75598SSergej Jaskiewicz TempFile BB(BDir.path("bb"), "", "bbbb");
47415e475e2SSam McCall std::unique_ptr<vfs::FileSystem> BFS = vfs::createPhysicalFileSystem(),
47515e475e2SSam McCall CFS = vfs::createPhysicalFileSystem();
47615e475e2SSam McCall
477fad75598SSergej Jaskiewicz ASSERT_FALSE(BFS->setCurrentWorkingDirectory(BDir.path()));
478fad75598SSergej Jaskiewicz ASSERT_FALSE(CFS->setCurrentWorkingDirectory(C.path()));
479fad75598SSergej Jaskiewicz EXPECT_EQ(BDir.path(), *BFS->getCurrentWorkingDirectory());
480fad75598SSergej Jaskiewicz EXPECT_EQ(C.path(), *CFS->getCurrentWorkingDirectory());
48115e475e2SSam McCall
48215e475e2SSam McCall // openFileForRead(), indirectly.
48315e475e2SSam McCall auto BBuf = BFS->getBufferForFile("bb");
48415e475e2SSam McCall ASSERT_TRUE(BBuf);
48515e475e2SSam McCall EXPECT_EQ("bbbb", (*BBuf)->getBuffer());
48615e475e2SSam McCall
48715e475e2SSam McCall auto ABuf = CFS->getBufferForFile("aa");
48815e475e2SSam McCall ASSERT_TRUE(ABuf);
48915e475e2SSam McCall EXPECT_EQ("aaaa", (*ABuf)->getBuffer());
49015e475e2SSam McCall
49115e475e2SSam McCall // status()
49215e475e2SSam McCall auto BStat = BFS->status("bb");
49315e475e2SSam McCall ASSERT_TRUE(BStat);
49415e475e2SSam McCall EXPECT_EQ("bb", BStat->getName());
49515e475e2SSam McCall
49615e475e2SSam McCall auto AStat = CFS->status("aa");
49715e475e2SSam McCall ASSERT_TRUE(AStat);
49815e475e2SSam McCall EXPECT_EQ("aa", AStat->getName()); // unresolved name
49915e475e2SSam McCall
50015e475e2SSam McCall // getRealPath()
50115e475e2SSam McCall SmallString<128> BPath;
50215e475e2SSam McCall ASSERT_FALSE(BFS->getRealPath("bb", BPath));
503fad75598SSergej Jaskiewicz EXPECT_EQ(BB.path(), BPath);
50415e475e2SSam McCall
50515e475e2SSam McCall SmallString<128> APath;
50615e475e2SSam McCall ASSERT_FALSE(CFS->getRealPath("aa", APath));
507fad75598SSergej Jaskiewicz EXPECT_EQ(AA.path(), APath); // Reports resolved name.
50815e475e2SSam McCall
50915e475e2SSam McCall // dir_begin
51015e475e2SSam McCall std::error_code EC;
51115e475e2SSam McCall auto BIt = BFS->dir_begin(".", EC);
51215e475e2SSam McCall ASSERT_FALSE(EC);
51315e475e2SSam McCall ASSERT_NE(BIt, vfs::directory_iterator());
514fad75598SSergej Jaskiewicz EXPECT_EQ((BDir.path() + "/./bb").str(), BIt->path());
51515e475e2SSam McCall BIt.increment(EC);
51615e475e2SSam McCall ASSERT_FALSE(EC);
51715e475e2SSam McCall ASSERT_EQ(BIt, vfs::directory_iterator());
51815e475e2SSam McCall
51915e475e2SSam McCall auto CIt = CFS->dir_begin(".", EC);
52015e475e2SSam McCall ASSERT_FALSE(EC);
52115e475e2SSam McCall ASSERT_NE(CIt, vfs::directory_iterator());
522fad75598SSergej Jaskiewicz EXPECT_EQ((ADir.path() + "/./aa").str(),
523fad75598SSergej Jaskiewicz CIt->path()); // Partly resolved name!
52415e475e2SSam McCall CIt.increment(EC); // Because likely to read through this path.
52515e475e2SSam McCall ASSERT_FALSE(EC);
52615e475e2SSam McCall ASSERT_EQ(CIt, vfs::directory_iterator());
52715e475e2SSam McCall }
52815e475e2SSam McCall
TEST(VirtualFileSystemTest,BrokenSymlinkRealFSIteration)529fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) {
530fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
531fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
532fc51490bSJonas Devlieghere
533fad75598SSergej Jaskiewicz TempLink _a("no_such_file", TestDirectory.path("a"));
534fad75598SSergej Jaskiewicz TempDir _b(TestDirectory.path("b"));
535fad75598SSergej Jaskiewicz TempLink _c("no_such_file", TestDirectory.path("c"));
536fc51490bSJonas Devlieghere
537fc51490bSJonas Devlieghere // Should get no iteration error, but a stat error for the broken symlinks.
538fc51490bSJonas Devlieghere std::map<std::string, std::error_code> StatResults;
539fc51490bSJonas Devlieghere std::error_code EC;
540fad75598SSergej Jaskiewicz for (vfs::directory_iterator
541fad75598SSergej Jaskiewicz I = FS->dir_begin(Twine(TestDirectory.path()), EC),
542fad75598SSergej Jaskiewicz E;
543fc51490bSJonas Devlieghere I != E; I.increment(EC)) {
544fc51490bSJonas Devlieghere EXPECT_FALSE(EC);
545adcd0268SBenjamin Kramer StatResults[std::string(sys::path::filename(I->path()))] =
546fc51490bSJonas Devlieghere FS->status(I->path()).getError();
547fc51490bSJonas Devlieghere }
548fc51490bSJonas Devlieghere EXPECT_THAT(
549fc51490bSJonas Devlieghere StatResults,
550fc51490bSJonas Devlieghere ElementsAre(
551fc51490bSJonas Devlieghere Pair("a", std::make_error_code(std::errc::no_such_file_or_directory)),
552fc51490bSJonas Devlieghere Pair("b", std::error_code()),
553fc51490bSJonas Devlieghere Pair("c",
554fc51490bSJonas Devlieghere std::make_error_code(std::errc::no_such_file_or_directory))));
555fc51490bSJonas Devlieghere }
556fc51490bSJonas Devlieghere #endif
557fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,BasicRealFSRecursiveIteration)558fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) {
559fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
560fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
561fc51490bSJonas Devlieghere
562fc51490bSJonas Devlieghere std::error_code EC;
563fad75598SSergej Jaskiewicz auto I =
564fad75598SSergej Jaskiewicz vfs::recursive_directory_iterator(*FS, Twine(TestDirectory.path()), EC);
565fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
566fc51490bSJonas Devlieghere EXPECT_EQ(vfs::recursive_directory_iterator(), I); // empty directory is empty
567fc51490bSJonas Devlieghere
568fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a"));
569fad75598SSergej Jaskiewicz TempDir _ab(TestDirectory.path("a/b"));
570fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c"));
571fad75598SSergej Jaskiewicz TempDir _cd(TestDirectory.path("c/d"));
572fc51490bSJonas Devlieghere
573fad75598SSergej Jaskiewicz I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory.path()), EC);
574fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
575fc51490bSJonas Devlieghere ASSERT_NE(vfs::recursive_directory_iterator(), I);
576fc51490bSJonas Devlieghere
577fc51490bSJonas Devlieghere std::vector<std::string> Contents;
578fc51490bSJonas Devlieghere for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
579fc51490bSJonas Devlieghere I.increment(EC)) {
580adcd0268SBenjamin Kramer Contents.push_back(std::string(I->path()));
581fc51490bSJonas Devlieghere }
582fc51490bSJonas Devlieghere
583fc51490bSJonas Devlieghere // Check contents, which may be in any order
584fc51490bSJonas Devlieghere EXPECT_EQ(4U, Contents.size());
585fc51490bSJonas Devlieghere int Counts[4] = {0, 0, 0, 0};
586fc51490bSJonas Devlieghere for (const std::string &Name : Contents) {
587fc51490bSJonas Devlieghere ASSERT_FALSE(Name.empty());
588fc51490bSJonas Devlieghere int Index = Name[Name.size() - 1] - 'a';
58938ac4093SArchibald Elliott ASSERT_GE(Index, 0);
59038ac4093SArchibald Elliott ASSERT_LT(Index, 4);
591fc51490bSJonas Devlieghere Counts[Index]++;
592fc51490bSJonas Devlieghere }
593fc51490bSJonas Devlieghere EXPECT_EQ(1, Counts[0]); // a
594fc51490bSJonas Devlieghere EXPECT_EQ(1, Counts[1]); // b
595fc51490bSJonas Devlieghere EXPECT_EQ(1, Counts[2]); // c
596fc51490bSJonas Devlieghere EXPECT_EQ(1, Counts[3]); // d
597fc51490bSJonas Devlieghere }
598fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,BasicRealFSRecursiveIterationNoPush)59941fb951fSJonas Devlieghere TEST(VirtualFileSystemTest, BasicRealFSRecursiveIterationNoPush) {
600fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
60141fb951fSJonas Devlieghere
602fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a"));
603fad75598SSergej Jaskiewicz TempDir _ab(TestDirectory.path("a/b"));
604fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c"));
605fad75598SSergej Jaskiewicz TempDir _cd(TestDirectory.path("c/d"));
606fad75598SSergej Jaskiewicz TempDir _e(TestDirectory.path("e"));
607fad75598SSergej Jaskiewicz TempDir _ef(TestDirectory.path("e/f"));
608fad75598SSergej Jaskiewicz TempDir _g(TestDirectory.path("g"));
60941fb951fSJonas Devlieghere
61041fb951fSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
61141fb951fSJonas Devlieghere
61241fb951fSJonas Devlieghere // Test that calling no_push on entries without subdirectories has no effect.
61341fb951fSJonas Devlieghere {
61441fb951fSJonas Devlieghere std::error_code EC;
615fad75598SSergej Jaskiewicz auto I =
616fad75598SSergej Jaskiewicz vfs::recursive_directory_iterator(*FS, Twine(TestDirectory.path()), EC);
61741fb951fSJonas Devlieghere ASSERT_FALSE(EC);
61841fb951fSJonas Devlieghere
61941fb951fSJonas Devlieghere std::vector<std::string> Contents;
62041fb951fSJonas Devlieghere for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
62141fb951fSJonas Devlieghere I.increment(EC)) {
622adcd0268SBenjamin Kramer Contents.push_back(std::string(I->path()));
62341fb951fSJonas Devlieghere char last = I->path().back();
62441fb951fSJonas Devlieghere switch (last) {
62541fb951fSJonas Devlieghere case 'b':
62641fb951fSJonas Devlieghere case 'd':
62741fb951fSJonas Devlieghere case 'f':
62841fb951fSJonas Devlieghere case 'g':
62941fb951fSJonas Devlieghere I.no_push();
63041fb951fSJonas Devlieghere break;
63141fb951fSJonas Devlieghere default:
63241fb951fSJonas Devlieghere break;
63341fb951fSJonas Devlieghere }
63441fb951fSJonas Devlieghere }
63541fb951fSJonas Devlieghere EXPECT_EQ(7U, Contents.size());
63641fb951fSJonas Devlieghere }
63741fb951fSJonas Devlieghere
63841fb951fSJonas Devlieghere // Test that calling no_push skips subdirectories.
63941fb951fSJonas Devlieghere {
64041fb951fSJonas Devlieghere std::error_code EC;
641fad75598SSergej Jaskiewicz auto I =
642fad75598SSergej Jaskiewicz vfs::recursive_directory_iterator(*FS, Twine(TestDirectory.path()), EC);
64341fb951fSJonas Devlieghere ASSERT_FALSE(EC);
64441fb951fSJonas Devlieghere
64541fb951fSJonas Devlieghere std::vector<std::string> Contents;
64641fb951fSJonas Devlieghere for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
64741fb951fSJonas Devlieghere I.increment(EC)) {
648adcd0268SBenjamin Kramer Contents.push_back(std::string(I->path()));
64941fb951fSJonas Devlieghere char last = I->path().back();
65041fb951fSJonas Devlieghere switch (last) {
65141fb951fSJonas Devlieghere case 'a':
65241fb951fSJonas Devlieghere case 'c':
65341fb951fSJonas Devlieghere case 'e':
65441fb951fSJonas Devlieghere I.no_push();
65541fb951fSJonas Devlieghere break;
65641fb951fSJonas Devlieghere default:
65741fb951fSJonas Devlieghere break;
65841fb951fSJonas Devlieghere }
65941fb951fSJonas Devlieghere }
66041fb951fSJonas Devlieghere
66141fb951fSJonas Devlieghere // Check contents, which may be in any order
66241fb951fSJonas Devlieghere EXPECT_EQ(4U, Contents.size());
66341fb951fSJonas Devlieghere int Counts[7] = {0, 0, 0, 0, 0, 0, 0};
66441fb951fSJonas Devlieghere for (const std::string &Name : Contents) {
66541fb951fSJonas Devlieghere ASSERT_FALSE(Name.empty());
66641fb951fSJonas Devlieghere int Index = Name[Name.size() - 1] - 'a';
66738ac4093SArchibald Elliott ASSERT_GE(Index, 0);
66838ac4093SArchibald Elliott ASSERT_LT(Index, 7);
66941fb951fSJonas Devlieghere Counts[Index]++;
67041fb951fSJonas Devlieghere }
67141fb951fSJonas Devlieghere EXPECT_EQ(1, Counts[0]); // a
67241fb951fSJonas Devlieghere EXPECT_EQ(0, Counts[1]); // b
67341fb951fSJonas Devlieghere EXPECT_EQ(1, Counts[2]); // c
67441fb951fSJonas Devlieghere EXPECT_EQ(0, Counts[3]); // d
67541fb951fSJonas Devlieghere EXPECT_EQ(1, Counts[4]); // e
67641fb951fSJonas Devlieghere EXPECT_EQ(0, Counts[5]); // f
67741fb951fSJonas Devlieghere EXPECT_EQ(1, Counts[6]); // g
67841fb951fSJonas Devlieghere }
67941fb951fSJonas Devlieghere }
68041fb951fSJonas Devlieghere
681fc51490bSJonas Devlieghere #ifdef LLVM_ON_UNIX
TEST(VirtualFileSystemTest,BrokenSymlinkRealFSRecursiveIteration)682fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) {
683fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
684fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
685fc51490bSJonas Devlieghere
686fad75598SSergej Jaskiewicz TempLink _a("no_such_file", TestDirectory.path("a"));
687fad75598SSergej Jaskiewicz TempDir _b(TestDirectory.path("b"));
688fad75598SSergej Jaskiewicz TempLink _ba("no_such_file", TestDirectory.path("b/a"));
689fad75598SSergej Jaskiewicz TempDir _bb(TestDirectory.path("b/b"));
690fad75598SSergej Jaskiewicz TempLink _bc("no_such_file", TestDirectory.path("b/c"));
691fad75598SSergej Jaskiewicz TempLink _c("no_such_file", TestDirectory.path("c"));
692fad75598SSergej Jaskiewicz TempDir _d(TestDirectory.path("d"));
693fad75598SSergej Jaskiewicz TempDir _dd(TestDirectory.path("d/d"));
694fad75598SSergej Jaskiewicz TempDir _ddd(TestDirectory.path("d/d/d"));
695fad75598SSergej Jaskiewicz TempLink _e("no_such_file", TestDirectory.path("e"));
696fc51490bSJonas Devlieghere
697fc51490bSJonas Devlieghere std::vector<std::string> VisitedBrokenSymlinks;
698fc51490bSJonas Devlieghere std::vector<std::string> VisitedNonBrokenSymlinks;
699fc51490bSJonas Devlieghere std::error_code EC;
700fad75598SSergej Jaskiewicz for (vfs::recursive_directory_iterator
701fad75598SSergej Jaskiewicz I(*FS, Twine(TestDirectory.path()), EC),
702fad75598SSergej Jaskiewicz E;
703fc51490bSJonas Devlieghere I != E; I.increment(EC)) {
704fc51490bSJonas Devlieghere EXPECT_FALSE(EC);
705fc51490bSJonas Devlieghere (FS->status(I->path()) ? VisitedNonBrokenSymlinks : VisitedBrokenSymlinks)
706adcd0268SBenjamin Kramer .push_back(std::string(I->path()));
707fc51490bSJonas Devlieghere }
708fc51490bSJonas Devlieghere
709fc51490bSJonas Devlieghere // Check visited file names.
710fc51490bSJonas Devlieghere EXPECT_THAT(VisitedBrokenSymlinks,
711fad75598SSergej Jaskiewicz UnorderedElementsAre(_a.path().str(), _ba.path().str(),
712fad75598SSergej Jaskiewicz _bc.path().str(), _c.path().str(),
713fad75598SSergej Jaskiewicz _e.path().str()));
714fc51490bSJonas Devlieghere EXPECT_THAT(VisitedNonBrokenSymlinks,
715fad75598SSergej Jaskiewicz UnorderedElementsAre(_b.path().str(), _bb.path().str(),
716fad75598SSergej Jaskiewicz _d.path().str(), _dd.path().str(),
717fad75598SSergej Jaskiewicz _ddd.path().str()));
718fc51490bSJonas Devlieghere }
719fc51490bSJonas Devlieghere #endif
720fc51490bSJonas Devlieghere
721fc51490bSJonas Devlieghere template <typename DirIter>
checkContents(DirIter I,ArrayRef<StringRef> ExpectedOut)722fc51490bSJonas Devlieghere static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) {
723fc51490bSJonas Devlieghere std::error_code EC;
724fc51490bSJonas Devlieghere SmallVector<StringRef, 4> Expected(ExpectedOut.begin(), ExpectedOut.end());
725fc51490bSJonas Devlieghere SmallVector<std::string, 4> InputToCheck;
726fc51490bSJonas Devlieghere
727fc51490bSJonas Devlieghere // Do not rely on iteration order to check for contents, sort both
728fc51490bSJonas Devlieghere // content vectors before comparison.
729fc51490bSJonas Devlieghere for (DirIter E; !EC && I != E; I.increment(EC))
730adcd0268SBenjamin Kramer InputToCheck.push_back(std::string(I->path()));
731fc51490bSJonas Devlieghere
732fc51490bSJonas Devlieghere llvm::sort(InputToCheck);
733fc51490bSJonas Devlieghere llvm::sort(Expected);
734fc51490bSJonas Devlieghere EXPECT_EQ(InputToCheck.size(), Expected.size());
735fc51490bSJonas Devlieghere
736fc51490bSJonas Devlieghere unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
737fc51490bSJonas Devlieghere for (unsigned Idx = 0; Idx != LastElt; ++Idx)
738fc51490bSJonas Devlieghere EXPECT_EQ(StringRef(InputToCheck[Idx]), Expected[Idx]);
739fc51490bSJonas Devlieghere }
740fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,OverlayIteration)741fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, OverlayIteration) {
742fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
743fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
744fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
745fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
746fc51490bSJonas Devlieghere O->pushOverlay(Upper);
747fc51490bSJonas Devlieghere
748fc51490bSJonas Devlieghere std::error_code EC;
749fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
750fc51490bSJonas Devlieghere
751fc51490bSJonas Devlieghere Lower->addRegularFile("/file1");
752fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1"));
753fc51490bSJonas Devlieghere
754fc51490bSJonas Devlieghere Upper->addRegularFile("/file2");
755fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), {"/file2", "/file1"});
756fc51490bSJonas Devlieghere
757fc51490bSJonas Devlieghere Lower->addDirectory("/dir1");
758fc51490bSJonas Devlieghere Lower->addRegularFile("/dir1/foo");
759fc51490bSJonas Devlieghere Upper->addDirectory("/dir2");
760fc51490bSJonas Devlieghere Upper->addRegularFile("/dir2/foo");
761fc51490bSJonas Devlieghere checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo"));
762fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), {"/dir2", "/file2", "/dir1", "/file1"});
763fc51490bSJonas Devlieghere }
764fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,OverlayRecursiveIteration)765fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, OverlayRecursiveIteration) {
766fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
767fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
768fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
769fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
770fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
771fc51490bSJonas Devlieghere O->pushOverlay(Middle);
772fc51490bSJonas Devlieghere O->pushOverlay(Upper);
773fc51490bSJonas Devlieghere
774fc51490bSJonas Devlieghere std::error_code EC;
775fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
776fc51490bSJonas Devlieghere ArrayRef<StringRef>());
777fc51490bSJonas Devlieghere
778fc51490bSJonas Devlieghere Lower->addRegularFile("/file1");
779fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
780fc51490bSJonas Devlieghere ArrayRef<StringRef>("/file1"));
781fc51490bSJonas Devlieghere
782fc51490bSJonas Devlieghere Upper->addDirectory("/dir");
783fc51490bSJonas Devlieghere Upper->addRegularFile("/dir/file2");
784fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
785fc51490bSJonas Devlieghere {"/dir", "/dir/file2", "/file1"});
786fc51490bSJonas Devlieghere
787fc51490bSJonas Devlieghere Lower->addDirectory("/dir1");
788fc51490bSJonas Devlieghere Lower->addRegularFile("/dir1/foo");
789fc51490bSJonas Devlieghere Lower->addDirectory("/dir1/a");
790fc51490bSJonas Devlieghere Lower->addRegularFile("/dir1/a/b");
791fc51490bSJonas Devlieghere Middle->addDirectory("/a");
792fc51490bSJonas Devlieghere Middle->addDirectory("/a/b");
793fc51490bSJonas Devlieghere Middle->addDirectory("/a/b/c");
794fc51490bSJonas Devlieghere Middle->addRegularFile("/a/b/c/d");
795fc51490bSJonas Devlieghere Middle->addRegularFile("/hiddenByUp");
796fc51490bSJonas Devlieghere Upper->addDirectory("/dir2");
797fc51490bSJonas Devlieghere Upper->addRegularFile("/dir2/foo");
798fc51490bSJonas Devlieghere Upper->addRegularFile("/hiddenByUp");
799fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/dir2", EC),
800fc51490bSJonas Devlieghere ArrayRef<StringRef>("/dir2/foo"));
801fc51490bSJonas Devlieghere checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
802fc51490bSJonas Devlieghere {"/dir", "/dir/file2", "/dir2", "/dir2/foo", "/hiddenByUp",
803fc51490bSJonas Devlieghere "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/dir1", "/dir1/a",
804fc51490bSJonas Devlieghere "/dir1/a/b", "/dir1/foo", "/file1"});
805fc51490bSJonas Devlieghere }
806fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,ThreeLevelIteration)807fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, ThreeLevelIteration) {
808fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
809fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
810fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
811fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
812fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
813fc51490bSJonas Devlieghere O->pushOverlay(Middle);
814fc51490bSJonas Devlieghere O->pushOverlay(Upper);
815fc51490bSJonas Devlieghere
816fc51490bSJonas Devlieghere std::error_code EC;
817fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
818fc51490bSJonas Devlieghere
819fc51490bSJonas Devlieghere Middle->addRegularFile("/file2");
820fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2"));
821fc51490bSJonas Devlieghere
822fc51490bSJonas Devlieghere Lower->addRegularFile("/file1");
823fc51490bSJonas Devlieghere Upper->addRegularFile("/file3");
824fc51490bSJonas Devlieghere checkContents(O->dir_begin("/", EC), {"/file3", "/file2", "/file1"});
825fc51490bSJonas Devlieghere }
826fc51490bSJonas Devlieghere
TEST(VirtualFileSystemTest,HiddenInIteration)827fc51490bSJonas Devlieghere TEST(VirtualFileSystemTest, HiddenInIteration) {
828fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
829fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
830fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
831fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
832fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
833fc51490bSJonas Devlieghere O->pushOverlay(Middle);
834fc51490bSJonas Devlieghere O->pushOverlay(Upper);
835fc51490bSJonas Devlieghere
836fc51490bSJonas Devlieghere std::error_code EC;
837fc51490bSJonas Devlieghere Lower->addRegularFile("/onlyInLow");
838fc51490bSJonas Devlieghere Lower->addDirectory("/hiddenByMid");
839fc51490bSJonas Devlieghere Lower->addDirectory("/hiddenByUp");
840fc51490bSJonas Devlieghere Middle->addRegularFile("/onlyInMid");
841fc51490bSJonas Devlieghere Middle->addRegularFile("/hiddenByMid");
842fc51490bSJonas Devlieghere Middle->addDirectory("/hiddenByUp");
843fc51490bSJonas Devlieghere Upper->addRegularFile("/onlyInUp");
844fc51490bSJonas Devlieghere Upper->addRegularFile("/hiddenByUp");
845fc51490bSJonas Devlieghere checkContents(
846fc51490bSJonas Devlieghere O->dir_begin("/", EC),
847fc51490bSJonas Devlieghere {"/hiddenByUp", "/onlyInUp", "/hiddenByMid", "/onlyInMid", "/onlyInLow"});
848fc51490bSJonas Devlieghere
849fc51490bSJonas Devlieghere // Make sure we get the top-most entry
850fc51490bSJonas Devlieghere {
851fc51490bSJonas Devlieghere std::error_code EC;
852fc51490bSJonas Devlieghere vfs::directory_iterator I = O->dir_begin("/", EC), E;
853fc51490bSJonas Devlieghere for (; !EC && I != E; I.increment(EC))
854fc51490bSJonas Devlieghere if (I->path() == "/hiddenByUp")
855fc51490bSJonas Devlieghere break;
856fc51490bSJonas Devlieghere ASSERT_NE(E, I);
857fc51490bSJonas Devlieghere EXPECT_EQ(sys::fs::file_type::regular_file, I->type());
858fc51490bSJonas Devlieghere }
859fc51490bSJonas Devlieghere {
860fc51490bSJonas Devlieghere std::error_code EC;
861fc51490bSJonas Devlieghere vfs::directory_iterator I = O->dir_begin("/", EC), E;
862fc51490bSJonas Devlieghere for (; !EC && I != E; I.increment(EC))
863fc51490bSJonas Devlieghere if (I->path() == "/hiddenByMid")
864fc51490bSJonas Devlieghere break;
865fc51490bSJonas Devlieghere ASSERT_NE(E, I);
866fc51490bSJonas Devlieghere EXPECT_EQ(sys::fs::file_type::regular_file, I->type());
867fc51490bSJonas Devlieghere }
868fc51490bSJonas Devlieghere }
869fc51490bSJonas Devlieghere
TEST(OverlayFileSystemTest,PrintOutput)87041255241SBen Barham TEST(OverlayFileSystemTest, PrintOutput) {
87141255241SBen Barham auto Dummy = makeIntrusiveRefCnt<DummyFileSystem>();
87241255241SBen Barham auto Overlay1 = makeIntrusiveRefCnt<vfs::OverlayFileSystem>(Dummy);
87341255241SBen Barham Overlay1->pushOverlay(Dummy);
87441255241SBen Barham auto Overlay2 = makeIntrusiveRefCnt<vfs::OverlayFileSystem>(Overlay1);
87541255241SBen Barham Overlay2->pushOverlay(Dummy);
87641255241SBen Barham
87741255241SBen Barham SmallString<0> Output;
87841255241SBen Barham raw_svector_ostream OuputStream{Output};
87941255241SBen Barham
88041255241SBen Barham Overlay2->print(OuputStream, vfs::FileSystem::PrintType::Summary);
88141255241SBen Barham ASSERT_EQ("OverlayFileSystem\n", Output);
88241255241SBen Barham
88341255241SBen Barham Output.clear();
88441255241SBen Barham Overlay2->print(OuputStream, vfs::FileSystem::PrintType::Contents);
88541255241SBen Barham ASSERT_EQ("OverlayFileSystem\n"
88641255241SBen Barham " DummyFileSystem (Summary)\n"
88741255241SBen Barham " OverlayFileSystem\n",
88841255241SBen Barham Output);
88941255241SBen Barham
89041255241SBen Barham Output.clear();
89141255241SBen Barham Overlay2->print(OuputStream, vfs::FileSystem::PrintType::RecursiveContents);
89241255241SBen Barham ASSERT_EQ("OverlayFileSystem\n"
89341255241SBen Barham " DummyFileSystem (RecursiveContents)\n"
89441255241SBen Barham " OverlayFileSystem\n"
89541255241SBen Barham " DummyFileSystem (RecursiveContents)\n"
89641255241SBen Barham " DummyFileSystem (RecursiveContents)\n",
89741255241SBen Barham Output);
89841255241SBen Barham }
89941255241SBen Barham
TEST(ProxyFileSystemTest,Basic)900937a1047SMichael J. Spencer TEST(ProxyFileSystemTest, Basic) {
901937a1047SMichael J. Spencer IntrusiveRefCntPtr<vfs::InMemoryFileSystem> Base(
902937a1047SMichael J. Spencer new vfs::InMemoryFileSystem());
903937a1047SMichael J. Spencer vfs::ProxyFileSystem PFS(Base);
904937a1047SMichael J. Spencer
905937a1047SMichael J. Spencer Base->addFile("/a", 0, MemoryBuffer::getMemBuffer("test"));
906937a1047SMichael J. Spencer
907937a1047SMichael J. Spencer auto Stat = PFS.status("/a");
908937a1047SMichael J. Spencer ASSERT_FALSE(Stat.getError());
909937a1047SMichael J. Spencer
910937a1047SMichael J. Spencer auto File = PFS.openFileForRead("/a");
911937a1047SMichael J. Spencer ASSERT_FALSE(File.getError());
912937a1047SMichael J. Spencer EXPECT_EQ("test", (*(*File)->getBuffer("ignored"))->getBuffer());
913937a1047SMichael J. Spencer
914937a1047SMichael J. Spencer std::error_code EC;
915937a1047SMichael J. Spencer vfs::directory_iterator I = PFS.dir_begin("/", EC);
916937a1047SMichael J. Spencer ASSERT_FALSE(EC);
917937a1047SMichael J. Spencer ASSERT_EQ("/a", I->path());
918937a1047SMichael J. Spencer I.increment(EC);
919937a1047SMichael J. Spencer ASSERT_FALSE(EC);
920937a1047SMichael J. Spencer ASSERT_EQ(vfs::directory_iterator(), I);
921937a1047SMichael J. Spencer
922937a1047SMichael J. Spencer ASSERT_FALSE(PFS.setCurrentWorkingDirectory("/"));
923937a1047SMichael J. Spencer
924937a1047SMichael J. Spencer auto PWD = PFS.getCurrentWorkingDirectory();
925937a1047SMichael J. Spencer ASSERT_FALSE(PWD.getError());
92635ab2a11SPaul Pluzhnikov ASSERT_EQ("/", getPosixPath(*PWD));
927937a1047SMichael J. Spencer
928937a1047SMichael J. Spencer SmallString<16> Path;
929937a1047SMichael J. Spencer ASSERT_FALSE(PFS.getRealPath("a", Path));
93035ab2a11SPaul Pluzhnikov ASSERT_EQ("/a", getPosixPath(Path));
931937a1047SMichael J. Spencer
932937a1047SMichael J. Spencer bool Local = true;
933937a1047SMichael J. Spencer ASSERT_FALSE(PFS.isLocal("/a", Local));
9342a5a0ad1SMichael J. Spencer EXPECT_FALSE(Local);
935937a1047SMichael J. Spencer }
936937a1047SMichael J. Spencer
937fc51490bSJonas Devlieghere class InMemoryFileSystemTest : public ::testing::Test {
938fc51490bSJonas Devlieghere protected:
939fc51490bSJonas Devlieghere llvm::vfs::InMemoryFileSystem FS;
940fc51490bSJonas Devlieghere llvm::vfs::InMemoryFileSystem NormalizedFS;
941fc51490bSJonas Devlieghere
InMemoryFileSystemTest()942fc51490bSJonas Devlieghere InMemoryFileSystemTest()
943fc51490bSJonas Devlieghere : FS(/*UseNormalizedPaths=*/false),
944fc51490bSJonas Devlieghere NormalizedFS(/*UseNormalizedPaths=*/true) {}
945fc51490bSJonas Devlieghere };
946fc51490bSJonas Devlieghere
947fc51490bSJonas Devlieghere MATCHER_P2(IsHardLinkTo, FS, Target, "") {
948fc51490bSJonas Devlieghere StringRef From = arg;
949fc51490bSJonas Devlieghere StringRef To = Target;
950fc51490bSJonas Devlieghere auto OpenedFrom = FS->openFileForRead(From);
951fc51490bSJonas Devlieghere auto OpenedTo = FS->openFileForRead(To);
952fc51490bSJonas Devlieghere return !OpenedFrom.getError() && !OpenedTo.getError() &&
953fc51490bSJonas Devlieghere (*OpenedFrom)->status()->getUniqueID() ==
954fc51490bSJonas Devlieghere (*OpenedTo)->status()->getUniqueID();
955fc51490bSJonas Devlieghere }
956fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,IsEmpty)957fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, IsEmpty) {
958fc51490bSJonas Devlieghere auto Stat = FS.status("/a");
959fc51490bSJonas Devlieghere ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
960fc51490bSJonas Devlieghere Stat = FS.status("/");
961fc51490bSJonas Devlieghere ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
962fc51490bSJonas Devlieghere }
963fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,WindowsPath)964fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, WindowsPath) {
965fc51490bSJonas Devlieghere FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
966fc51490bSJonas Devlieghere auto Stat = FS.status("c:");
967fc51490bSJonas Devlieghere #if !defined(_WIN32)
968fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
969fc51490bSJonas Devlieghere #endif
970fc51490bSJonas Devlieghere Stat = FS.status("c:/windows/system128/foo.cpp");
971fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
972fc51490bSJonas Devlieghere FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
973fc51490bSJonas Devlieghere Stat = FS.status("d:/windows/foo.cpp");
974fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
975fc51490bSJonas Devlieghere }
976fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,OverlayFile)977fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, OverlayFile) {
978fc51490bSJonas Devlieghere FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
979fc51490bSJonas Devlieghere NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
980fc51490bSJonas Devlieghere auto Stat = FS.status("/");
981fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
982fc51490bSJonas Devlieghere Stat = FS.status("/.");
983fc51490bSJonas Devlieghere ASSERT_FALSE(Stat);
984fc51490bSJonas Devlieghere Stat = NormalizedFS.status("/.");
985fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
986fc51490bSJonas Devlieghere Stat = FS.status("/a");
987fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
988fc51490bSJonas Devlieghere ASSERT_EQ("/a", Stat->getName());
989fc51490bSJonas Devlieghere }
990fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,OverlayFileNoOwn)991fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) {
992fc51490bSJonas Devlieghere auto Buf = MemoryBuffer::getMemBuffer("a");
993e763e032SDuncan P. N. Exon Smith FS.addFileNoOwn("/a", 0, *Buf);
994fc51490bSJonas Devlieghere auto Stat = FS.status("/a");
995fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
996fc51490bSJonas Devlieghere ASSERT_EQ("/a", Stat->getName());
997fc51490bSJonas Devlieghere }
998fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,OpenFileForRead)999fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, OpenFileForRead) {
1000fc51490bSJonas Devlieghere FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
1001fc51490bSJonas Devlieghere FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
1002fc51490bSJonas Devlieghere FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
1003fc51490bSJonas Devlieghere NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
1004fc51490bSJonas Devlieghere NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
1005fc51490bSJonas Devlieghere NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
1006fc51490bSJonas Devlieghere auto File = FS.openFileForRead("/a");
1007fc51490bSJonas Devlieghere ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
1008fc51490bSJonas Devlieghere File = FS.openFileForRead("/a"); // Open again.
1009fc51490bSJonas Devlieghere ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
1010fc51490bSJonas Devlieghere File = NormalizedFS.openFileForRead("/././a"); // Open again.
1011fc51490bSJonas Devlieghere ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
1012fc51490bSJonas Devlieghere File = FS.openFileForRead("/");
1013fc51490bSJonas Devlieghere ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString();
1014fc51490bSJonas Devlieghere File = FS.openFileForRead("/b");
1015fc51490bSJonas Devlieghere ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString();
1016fc51490bSJonas Devlieghere File = FS.openFileForRead("./c");
1017fc51490bSJonas Devlieghere ASSERT_FALSE(File);
1018fc51490bSJonas Devlieghere File = FS.openFileForRead("e/../d");
1019fc51490bSJonas Devlieghere ASSERT_FALSE(File);
1020fc51490bSJonas Devlieghere File = NormalizedFS.openFileForRead("./c");
1021fc51490bSJonas Devlieghere ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer());
1022fc51490bSJonas Devlieghere File = NormalizedFS.openFileForRead("e/../d");
1023fc51490bSJonas Devlieghere ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer());
1024fc51490bSJonas Devlieghere }
1025fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,DuplicatedFile)1026fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, DuplicatedFile) {
1027fc51490bSJonas Devlieghere ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
1028fc51490bSJonas Devlieghere ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a")));
1029fc51490bSJonas Devlieghere ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
1030fc51490bSJonas Devlieghere ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b")));
1031fc51490bSJonas Devlieghere }
1032fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,DirectoryIteration)1033fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
1034fc51490bSJonas Devlieghere FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""));
1035fc51490bSJonas Devlieghere FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer(""));
1036fc51490bSJonas Devlieghere
1037fc51490bSJonas Devlieghere std::error_code EC;
1038fc51490bSJonas Devlieghere vfs::directory_iterator I = FS.dir_begin("/", EC);
1039fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
1040fc51490bSJonas Devlieghere ASSERT_EQ("/a", I->path());
1041fc51490bSJonas Devlieghere I.increment(EC);
1042fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
1043fc51490bSJonas Devlieghere ASSERT_EQ("/b", I->path());
1044fc51490bSJonas Devlieghere I.increment(EC);
1045fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
1046fc51490bSJonas Devlieghere ASSERT_EQ(vfs::directory_iterator(), I);
1047fc51490bSJonas Devlieghere
1048fc51490bSJonas Devlieghere I = FS.dir_begin("/b", EC);
1049fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
1050fc51490bSJonas Devlieghere // When on Windows, we end up with "/b\\c" as the name. Convert to Posix
1051fc51490bSJonas Devlieghere // path for the sake of the comparison.
1052adcd0268SBenjamin Kramer ASSERT_EQ("/b/c", getPosixPath(std::string(I->path())));
1053fc51490bSJonas Devlieghere I.increment(EC);
1054fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
1055fc51490bSJonas Devlieghere ASSERT_EQ(vfs::directory_iterator(), I);
1056fc51490bSJonas Devlieghere }
1057fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,WorkingDirectory)1058fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
1059fc51490bSJonas Devlieghere FS.setCurrentWorkingDirectory("/b");
1060fc51490bSJonas Devlieghere FS.addFile("c", 0, MemoryBuffer::getMemBuffer(""));
1061fc51490bSJonas Devlieghere
1062fc51490bSJonas Devlieghere auto Stat = FS.status("/b/c");
1063fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1064fc51490bSJonas Devlieghere ASSERT_EQ("/b/c", Stat->getName());
1065fc51490bSJonas Devlieghere ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
1066fc51490bSJonas Devlieghere
1067fc51490bSJonas Devlieghere Stat = FS.status("c");
1068fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1069fc51490bSJonas Devlieghere
1070fc51490bSJonas Devlieghere NormalizedFS.setCurrentWorkingDirectory("/b/c");
1071fc51490bSJonas Devlieghere NormalizedFS.setCurrentWorkingDirectory(".");
1072fc51490bSJonas Devlieghere ASSERT_EQ("/b/c",
1073fc51490bSJonas Devlieghere getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get()));
1074fc51490bSJonas Devlieghere NormalizedFS.setCurrentWorkingDirectory("..");
1075fc51490bSJonas Devlieghere ASSERT_EQ("/b",
1076fc51490bSJonas Devlieghere getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get()));
1077fc51490bSJonas Devlieghere }
1078fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,IsLocal)1079cbb5c868SJonas Devlieghere TEST_F(InMemoryFileSystemTest, IsLocal) {
1080cbb5c868SJonas Devlieghere FS.setCurrentWorkingDirectory("/b");
1081cbb5c868SJonas Devlieghere FS.addFile("c", 0, MemoryBuffer::getMemBuffer(""));
1082cbb5c868SJonas Devlieghere
1083cbb5c868SJonas Devlieghere std::error_code EC;
1084cbb5c868SJonas Devlieghere bool IsLocal = true;
1085cbb5c868SJonas Devlieghere EC = FS.isLocal("c", IsLocal);
1086cbb5c868SJonas Devlieghere ASSERT_FALSE(EC);
1087cbb5c868SJonas Devlieghere ASSERT_FALSE(IsLocal);
1088cbb5c868SJonas Devlieghere }
1089cbb5c868SJonas Devlieghere
1090fc51490bSJonas Devlieghere #if !defined(_WIN32)
TEST_F(InMemoryFileSystemTest,GetRealPath)1091fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, GetRealPath) {
1092fc51490bSJonas Devlieghere SmallString<16> Path;
1093fc51490bSJonas Devlieghere EXPECT_EQ(FS.getRealPath("b", Path), errc::operation_not_permitted);
1094fc51490bSJonas Devlieghere
1095fc51490bSJonas Devlieghere auto GetRealPath = [this](StringRef P) {
1096fc51490bSJonas Devlieghere SmallString<16> Output;
1097fc51490bSJonas Devlieghere auto EC = FS.getRealPath(P, Output);
1098fc51490bSJonas Devlieghere EXPECT_FALSE(EC);
1099b2924d99SJonas Devlieghere return std::string(Output);
1100fc51490bSJonas Devlieghere };
1101fc51490bSJonas Devlieghere
1102fc51490bSJonas Devlieghere FS.setCurrentWorkingDirectory("a");
1103fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("b"), "a/b");
1104fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("../b"), "b");
1105fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("b/./c"), "a/b/c");
1106fc51490bSJonas Devlieghere
1107fc51490bSJonas Devlieghere FS.setCurrentWorkingDirectory("/a");
1108fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("b"), "/a/b");
1109fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("../b"), "/b");
1110fc51490bSJonas Devlieghere EXPECT_EQ(GetRealPath("b/./c"), "/a/b/c");
1111fc51490bSJonas Devlieghere }
1112fc51490bSJonas Devlieghere #endif // _WIN32
1113fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddFileWithUser)1114fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileWithUser) {
1115fc51490bSJonas Devlieghere FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), 0xFEEDFACE);
1116fc51490bSJonas Devlieghere auto Stat = FS.status("/a");
1117fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1118fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory());
1119fc51490bSJonas Devlieghere ASSERT_EQ(0xFEEDFACE, Stat->getUser());
1120fc51490bSJonas Devlieghere Stat = FS.status("/a/b");
1121fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1122fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory());
1123fc51490bSJonas Devlieghere ASSERT_EQ(0xFEEDFACE, Stat->getUser());
1124fc51490bSJonas Devlieghere Stat = FS.status("/a/b/c");
1125fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1126fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile());
1127fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions());
1128fc51490bSJonas Devlieghere ASSERT_EQ(0xFEEDFACE, Stat->getUser());
1129fc51490bSJonas Devlieghere }
1130fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddFileWithGroup)1131fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileWithGroup) {
1132fc51490bSJonas Devlieghere FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, 0xDABBAD00);
1133fc51490bSJonas Devlieghere auto Stat = FS.status("/a");
1134fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1135fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory());
1136fc51490bSJonas Devlieghere ASSERT_EQ(0xDABBAD00, Stat->getGroup());
1137fc51490bSJonas Devlieghere Stat = FS.status("/a/b");
1138fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory());
1139fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1140fc51490bSJonas Devlieghere ASSERT_EQ(0xDABBAD00, Stat->getGroup());
1141fc51490bSJonas Devlieghere Stat = FS.status("/a/b/c");
1142fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1143fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile());
1144fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions());
1145fc51490bSJonas Devlieghere ASSERT_EQ(0xDABBAD00, Stat->getGroup());
1146fc51490bSJonas Devlieghere }
1147fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddFileWithFileType)1148fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileWithFileType) {
1149fc51490bSJonas Devlieghere FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, None,
1150fc51490bSJonas Devlieghere sys::fs::file_type::socket_file);
1151fc51490bSJonas Devlieghere auto Stat = FS.status("/a");
1152fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1153fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory());
1154fc51490bSJonas Devlieghere Stat = FS.status("/a/b");
1155fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1156fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory());
1157fc51490bSJonas Devlieghere Stat = FS.status("/a/b/c");
1158fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1159fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::file_type::socket_file, Stat->getType());
1160fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions());
1161fc51490bSJonas Devlieghere }
1162fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddFileWithPerms)1163fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileWithPerms) {
1164fc51490bSJonas Devlieghere FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, None, None,
1165fc51490bSJonas Devlieghere sys::fs::perms::owner_read | sys::fs::perms::owner_write);
1166fc51490bSJonas Devlieghere auto Stat = FS.status("/a");
1167fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1168fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory());
1169fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write |
1170fc51490bSJonas Devlieghere sys::fs::perms::owner_exe,
1171fc51490bSJonas Devlieghere Stat->getPermissions());
1172fc51490bSJonas Devlieghere Stat = FS.status("/a/b");
1173fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1174fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory());
1175fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write |
1176fc51490bSJonas Devlieghere sys::fs::perms::owner_exe,
1177fc51490bSJonas Devlieghere Stat->getPermissions());
1178fc51490bSJonas Devlieghere Stat = FS.status("/a/b/c");
1179fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1180fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile());
1181fc51490bSJonas Devlieghere ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write,
1182fc51490bSJonas Devlieghere Stat->getPermissions());
1183fc51490bSJonas Devlieghere }
1184fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddDirectoryThenAddChild)1185fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddDirectoryThenAddChild) {
1186fc51490bSJonas Devlieghere FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""), /*User=*/None,
1187fc51490bSJonas Devlieghere /*Group=*/None, sys::fs::file_type::directory_file);
1188fc51490bSJonas Devlieghere FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("abc"), /*User=*/None,
1189fc51490bSJonas Devlieghere /*Group=*/None, sys::fs::file_type::regular_file);
1190fc51490bSJonas Devlieghere auto Stat = FS.status("/a");
1191fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1192fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isDirectory());
1193fc51490bSJonas Devlieghere Stat = FS.status("/a/b");
1194fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
1195fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile());
1196fc51490bSJonas Devlieghere }
1197fc51490bSJonas Devlieghere
1198fc51490bSJonas Devlieghere // Test that the name returned by status() is in the same form as the path that
1199fc51490bSJonas Devlieghere // was requested (to match the behavior of RealFileSystem).
TEST_F(InMemoryFileSystemTest,StatusName)1200fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, StatusName) {
1201fc51490bSJonas Devlieghere NormalizedFS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"),
1202fc51490bSJonas Devlieghere /*User=*/None,
1203fc51490bSJonas Devlieghere /*Group=*/None, sys::fs::file_type::regular_file);
1204fc51490bSJonas Devlieghere NormalizedFS.setCurrentWorkingDirectory("/a/b");
1205fc51490bSJonas Devlieghere
1206fc51490bSJonas Devlieghere // Access using InMemoryFileSystem::status.
1207fc51490bSJonas Devlieghere auto Stat = NormalizedFS.status("../b/c");
1208fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n"
1209fc51490bSJonas Devlieghere << NormalizedFS.toString();
1210fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile());
1211fc51490bSJonas Devlieghere ASSERT_EQ("../b/c", Stat->getName());
1212fc51490bSJonas Devlieghere
1213fc51490bSJonas Devlieghere // Access using InMemoryFileAdaptor::status.
1214fc51490bSJonas Devlieghere auto File = NormalizedFS.openFileForRead("../b/c");
1215fc51490bSJonas Devlieghere ASSERT_FALSE(File.getError()) << File.getError() << "\n"
1216fc51490bSJonas Devlieghere << NormalizedFS.toString();
1217fc51490bSJonas Devlieghere Stat = (*File)->status();
1218fc51490bSJonas Devlieghere ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n"
1219fc51490bSJonas Devlieghere << NormalizedFS.toString();
1220fc51490bSJonas Devlieghere ASSERT_TRUE(Stat->isRegularFile());
1221fc51490bSJonas Devlieghere ASSERT_EQ("../b/c", Stat->getName());
1222fc51490bSJonas Devlieghere
1223fc51490bSJonas Devlieghere // Access using a directory iterator.
1224fc51490bSJonas Devlieghere std::error_code EC;
1225fc51490bSJonas Devlieghere llvm::vfs::directory_iterator It = NormalizedFS.dir_begin("../b", EC);
1226fc51490bSJonas Devlieghere // When on Windows, we end up with "../b\\c" as the name. Convert to Posix
1227fc51490bSJonas Devlieghere // path for the sake of the comparison.
1228adcd0268SBenjamin Kramer ASSERT_EQ("../b/c", getPosixPath(std::string(It->path())));
1229fc51490bSJonas Devlieghere }
1230fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddHardLinkToFile)1231fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
1232fc51490bSJonas Devlieghere StringRef FromLink = "/path/to/FROM/link";
1233fc51490bSJonas Devlieghere StringRef Target = "/path/to/TO/file";
1234fc51490bSJonas Devlieghere FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
1235fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(FromLink, Target));
1236fc51490bSJonas Devlieghere EXPECT_THAT(FromLink, IsHardLinkTo(&FS, Target));
123738ac4093SArchibald Elliott EXPECT_EQ(FS.status(FromLink)->getSize(), FS.status(Target)->getSize());
123838ac4093SArchibald Elliott EXPECT_EQ(FS.getBufferForFile(FromLink)->get()->getBuffer(),
1239fc51490bSJonas Devlieghere FS.getBufferForFile(Target)->get()->getBuffer());
1240fc51490bSJonas Devlieghere }
1241fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddHardLinkInChainPattern)1242fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) {
1243fc51490bSJonas Devlieghere StringRef Link0 = "/path/to/0/link";
1244fc51490bSJonas Devlieghere StringRef Link1 = "/path/to/1/link";
1245fc51490bSJonas Devlieghere StringRef Link2 = "/path/to/2/link";
1246fc51490bSJonas Devlieghere StringRef Target = "/path/to/target";
1247fc51490bSJonas Devlieghere FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target file"));
1248fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link2, Target));
1249fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link1, Link2));
1250fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link0, Link1));
1251fc51490bSJonas Devlieghere EXPECT_THAT(Link0, IsHardLinkTo(&FS, Target));
1252fc51490bSJonas Devlieghere EXPECT_THAT(Link1, IsHardLinkTo(&FS, Target));
1253fc51490bSJonas Devlieghere EXPECT_THAT(Link2, IsHardLinkTo(&FS, Target));
1254fc51490bSJonas Devlieghere }
1255fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddHardLinkToAFileThatWasNotAddedBefore)1256fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) {
1257fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink("/path/to/link", "/path/to/target"));
1258fc51490bSJonas Devlieghere }
1259fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddHardLinkFromAFileThatWasAddedBefore)1260fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) {
1261fc51490bSJonas Devlieghere StringRef Link = "/path/to/link";
1262fc51490bSJonas Devlieghere StringRef Target = "/path/to/target";
1263fc51490bSJonas Devlieghere FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
1264fc51490bSJonas Devlieghere FS.addFile(Link, 0, MemoryBuffer::getMemBuffer("content of link"));
1265fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink(Link, Target));
1266fc51490bSJonas Devlieghere }
1267fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddSameHardLinkMoreThanOnce)1268fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) {
1269fc51490bSJonas Devlieghere StringRef Link = "/path/to/link";
1270fc51490bSJonas Devlieghere StringRef Target = "/path/to/target";
1271fc51490bSJonas Devlieghere FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
1272fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link, Target));
1273fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink(Link, Target));
1274fc51490bSJonas Devlieghere }
1275fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddFileInPlaceOfAHardLinkWithSameContent)1276fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) {
1277fc51490bSJonas Devlieghere StringRef Link = "/path/to/link";
1278fc51490bSJonas Devlieghere StringRef Target = "/path/to/target";
1279fc51490bSJonas Devlieghere StringRef Content = "content of target";
1280fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
1281fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link, Target));
1282fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(Content)));
1283fc51490bSJonas Devlieghere }
1284fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddFileInPlaceOfAHardLinkWithDifferentContent)1285fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) {
1286fc51490bSJonas Devlieghere StringRef Link = "/path/to/link";
1287fc51490bSJonas Devlieghere StringRef Target = "/path/to/target";
1288fc51490bSJonas Devlieghere StringRef Content = "content of target";
1289fc51490bSJonas Devlieghere StringRef LinkContent = "different content of link";
1290fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
1291fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink(Link, Target));
1292fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(LinkContent)));
1293fc51490bSJonas Devlieghere }
1294fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddHardLinkToADirectory)1295fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) {
1296fc51490bSJonas Devlieghere StringRef Dir = "path/to/dummy/dir";
1297fc51490bSJonas Devlieghere StringRef Link = "/path/to/link";
1298fc51490bSJonas Devlieghere StringRef File = "path/to/dummy/dir/target";
1299fc51490bSJonas Devlieghere StringRef Content = "content of target";
1300fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(File, 0, MemoryBuffer::getMemBuffer(Content)));
1301fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink(Link, Dir));
1302fc51490bSJonas Devlieghere }
1303fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddHardLinkToASymlink)1304*a44c6453SJan Svoboda TEST_F(InMemoryFileSystemTest, AddHardLinkToASymlink) {
1305*a44c6453SJan Svoboda EXPECT_TRUE(FS.addFile("/file", 0, MemoryBuffer::getMemBuffer("content")));
1306*a44c6453SJan Svoboda EXPECT_TRUE(FS.addSymbolicLink("/symlink", "/file", 0));
1307*a44c6453SJan Svoboda EXPECT_TRUE(FS.addHardLink("/hardlink", "/symlink"));
1308*a44c6453SJan Svoboda EXPECT_EQ((*FS.getBufferForFile("/hardlink"))->getBuffer(), "content");
1309*a44c6453SJan Svoboda }
1310*a44c6453SJan Svoboda
TEST_F(InMemoryFileSystemTest,AddHardLinkFromADirectory)1311fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkFromADirectory) {
1312fc51490bSJonas Devlieghere StringRef Dir = "path/to/dummy/dir";
1313fc51490bSJonas Devlieghere StringRef Target = "path/to/dummy/dir/target";
1314fc51490bSJonas Devlieghere StringRef Content = "content of target";
1315fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
1316fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink(Dir, Target));
1317fc51490bSJonas Devlieghere }
1318fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,AddHardLinkUnderAFile)1319fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, AddHardLinkUnderAFile) {
1320fc51490bSJonas Devlieghere StringRef CommonContent = "content string";
1321fc51490bSJonas Devlieghere FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer(CommonContent));
1322fc51490bSJonas Devlieghere FS.addFile("/c/d", 0, MemoryBuffer::getMemBuffer(CommonContent));
1323fc51490bSJonas Devlieghere EXPECT_FALSE(FS.addHardLink("/c/d/e", "/a/b"));
1324fc51490bSJonas Devlieghere }
1325fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,RecursiveIterationWithHardLink)1326fc51490bSJonas Devlieghere TEST_F(InMemoryFileSystemTest, RecursiveIterationWithHardLink) {
1327fc51490bSJonas Devlieghere std::error_code EC;
1328fc51490bSJonas Devlieghere FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("content string"));
1329fc51490bSJonas Devlieghere EXPECT_TRUE(FS.addHardLink("/c/d", "/a/b"));
1330fc51490bSJonas Devlieghere auto I = vfs::recursive_directory_iterator(FS, "/", EC);
1331fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
1332fc51490bSJonas Devlieghere std::vector<std::string> Nodes;
1333fc51490bSJonas Devlieghere for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
1334fc51490bSJonas Devlieghere I.increment(EC)) {
1335adcd0268SBenjamin Kramer Nodes.push_back(getPosixPath(std::string(I->path())));
1336fc51490bSJonas Devlieghere }
1337fc51490bSJonas Devlieghere EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/a", "/a/b", "/c", "/c/d"));
1338fc51490bSJonas Devlieghere }
1339fc51490bSJonas Devlieghere
TEST_F(InMemoryFileSystemTest,UniqueID)134022555bafSSam McCall TEST_F(InMemoryFileSystemTest, UniqueID) {
134122555bafSSam McCall ASSERT_TRUE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("text")));
134222555bafSSam McCall ASSERT_TRUE(FS.addFile("/c/d", 0, MemoryBuffer::getMemBuffer("text")));
134322555bafSSam McCall ASSERT_TRUE(FS.addHardLink("/e/f", "/a/b"));
134422555bafSSam McCall
134522555bafSSam McCall EXPECT_EQ(FS.status("/a/b")->getUniqueID(), FS.status("/a/b")->getUniqueID());
134622555bafSSam McCall EXPECT_NE(FS.status("/a/b")->getUniqueID(), FS.status("/c/d")->getUniqueID());
134722555bafSSam McCall EXPECT_EQ(FS.status("/a/b")->getUniqueID(), FS.status("/e/f")->getUniqueID());
134822555bafSSam McCall EXPECT_EQ(FS.status("/a")->getUniqueID(), FS.status("/a")->getUniqueID());
134922555bafSSam McCall EXPECT_NE(FS.status("/a")->getUniqueID(), FS.status("/c")->getUniqueID());
135022555bafSSam McCall EXPECT_NE(FS.status("/a")->getUniqueID(), FS.status("/e")->getUniqueID());
135122555bafSSam McCall
135222555bafSSam McCall // Recreating the "same" FS yields the same UniqueIDs.
135335ab2a11SPaul Pluzhnikov // Note: FS2 should match FS with respect to path normalization.
135435ab2a11SPaul Pluzhnikov vfs::InMemoryFileSystem FS2(/*UseNormalizedPath=*/false);
135522555bafSSam McCall ASSERT_TRUE(FS2.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("text")));
135622555bafSSam McCall EXPECT_EQ(FS.status("/a/b")->getUniqueID(),
135722555bafSSam McCall FS2.status("/a/b")->getUniqueID());
135822555bafSSam McCall EXPECT_EQ(FS.status("/a")->getUniqueID(), FS2.status("/a")->getUniqueID());
135922555bafSSam McCall }
136022555bafSSam McCall
TEST_F(InMemoryFileSystemTest,AddSymlinkToAFile)1361*a44c6453SJan Svoboda TEST_F(InMemoryFileSystemTest, AddSymlinkToAFile) {
1362*a44c6453SJan Svoboda EXPECT_TRUE(
1363*a44c6453SJan Svoboda FS.addFile("/some/file", 0, MemoryBuffer::getMemBuffer("contents")));
1364*a44c6453SJan Svoboda EXPECT_TRUE(FS.addSymbolicLink("/other/file/link", "/some/file", 0));
1365*a44c6453SJan Svoboda ErrorOr<vfs::Status> Stat = FS.status("/some/file");
1366*a44c6453SJan Svoboda EXPECT_TRUE(Stat->isRegularFile());
1367*a44c6453SJan Svoboda }
1368*a44c6453SJan Svoboda
TEST_F(InMemoryFileSystemTest,AddSymlinkToADirectory)1369*a44c6453SJan Svoboda TEST_F(InMemoryFileSystemTest, AddSymlinkToADirectory) {
1370*a44c6453SJan Svoboda EXPECT_TRUE(FS.addSymbolicLink("/link", "/target", 0));
1371*a44c6453SJan Svoboda EXPECT_TRUE(
1372*a44c6453SJan Svoboda FS.addFile("/target/foo.h", 0, MemoryBuffer::getMemBuffer("foo")));
1373*a44c6453SJan Svoboda ErrorOr<vfs::Status> Stat = FS.status("/link/foo.h");
1374*a44c6453SJan Svoboda EXPECT_TRUE(Stat);
1375*a44c6453SJan Svoboda EXPECT_EQ((*Stat).getName(), "/link/foo.h");
1376*a44c6453SJan Svoboda EXPECT_TRUE(Stat->isRegularFile());
1377*a44c6453SJan Svoboda }
1378*a44c6453SJan Svoboda
TEST_F(InMemoryFileSystemTest,AddSymlinkToASymlink)1379*a44c6453SJan Svoboda TEST_F(InMemoryFileSystemTest, AddSymlinkToASymlink) {
1380*a44c6453SJan Svoboda EXPECT_TRUE(FS.addSymbolicLink("/first", "/second", 0));
1381*a44c6453SJan Svoboda EXPECT_TRUE(FS.addSymbolicLink("/second", "/third", 0));
1382*a44c6453SJan Svoboda EXPECT_TRUE(FS.addFile("/third", 0, MemoryBuffer::getMemBuffer("")));
1383*a44c6453SJan Svoboda ErrorOr<vfs::Status> Stat = FS.status("/first");
1384*a44c6453SJan Svoboda EXPECT_TRUE(Stat);
1385*a44c6453SJan Svoboda EXPECT_EQ((*Stat).getName(), "/first");
1386*a44c6453SJan Svoboda // Follow-through symlinks by default. This matches RealFileSystem's
1387*a44c6453SJan Svoboda // semantics.
1388*a44c6453SJan Svoboda EXPECT_TRUE(Stat->isRegularFile());
1389*a44c6453SJan Svoboda Stat = FS.status("/second");
1390*a44c6453SJan Svoboda EXPECT_TRUE(Stat);
1391*a44c6453SJan Svoboda EXPECT_EQ((*Stat).getName(), "/second");
1392*a44c6453SJan Svoboda EXPECT_TRUE(Stat->isRegularFile());
1393*a44c6453SJan Svoboda Stat = FS.status("/third");
1394*a44c6453SJan Svoboda EXPECT_TRUE(Stat);
1395*a44c6453SJan Svoboda EXPECT_EQ((*Stat).getName(), "/third");
1396*a44c6453SJan Svoboda EXPECT_TRUE(Stat->isRegularFile());
1397*a44c6453SJan Svoboda }
1398*a44c6453SJan Svoboda
TEST_F(InMemoryFileSystemTest,AddRecursiveSymlink)1399*a44c6453SJan Svoboda TEST_F(InMemoryFileSystemTest, AddRecursiveSymlink) {
1400*a44c6453SJan Svoboda EXPECT_TRUE(FS.addSymbolicLink("/link-a", "/link-b", 0));
1401*a44c6453SJan Svoboda EXPECT_TRUE(FS.addSymbolicLink("/link-b", "/link-a", 0));
1402*a44c6453SJan Svoboda ErrorOr<vfs::Status> Stat = FS.status("/link-a/foo");
1403*a44c6453SJan Svoboda EXPECT_FALSE(Stat);
1404*a44c6453SJan Svoboda EXPECT_EQ(Stat.getError(), errc::no_such_file_or_directory);
1405*a44c6453SJan Svoboda }
1406*a44c6453SJan Svoboda
TEST_F(InMemoryFileSystemTest,DirectoryIteratorWithSymlinkToAFile)1407*a44c6453SJan Svoboda TEST_F(InMemoryFileSystemTest, DirectoryIteratorWithSymlinkToAFile) {
1408*a44c6453SJan Svoboda std::error_code EC;
1409*a44c6453SJan Svoboda
1410*a44c6453SJan Svoboda EXPECT_TRUE(FS.addFile("/file", 0, MemoryBuffer::getMemBuffer("")));
1411*a44c6453SJan Svoboda EXPECT_TRUE(FS.addSymbolicLink("/symlink", "/file", 0));
1412*a44c6453SJan Svoboda
1413*a44c6453SJan Svoboda vfs::directory_iterator I = FS.dir_begin("/", EC), E;
1414*a44c6453SJan Svoboda ASSERT_FALSE(EC);
1415*a44c6453SJan Svoboda
1416*a44c6453SJan Svoboda std::vector<std::string> Nodes;
1417*a44c6453SJan Svoboda for (; !EC && I != E; I.increment(EC))
1418*a44c6453SJan Svoboda Nodes.push_back(getPosixPath(std::string(I->path())));
1419*a44c6453SJan Svoboda
1420*a44c6453SJan Svoboda EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/file", "/file"));
1421*a44c6453SJan Svoboda }
1422*a44c6453SJan Svoboda
TEST_F(InMemoryFileSystemTest,RecursiveDirectoryIteratorWithSymlinkToADir)1423*a44c6453SJan Svoboda TEST_F(InMemoryFileSystemTest, RecursiveDirectoryIteratorWithSymlinkToADir) {
1424*a44c6453SJan Svoboda std::error_code EC;
1425*a44c6453SJan Svoboda
1426*a44c6453SJan Svoboda EXPECT_TRUE(FS.addFile("/dir/file", 0, MemoryBuffer::getMemBuffer("")));
1427*a44c6453SJan Svoboda EXPECT_TRUE(FS.addSymbolicLink("/dir_symlink", "/dir", 0));
1428*a44c6453SJan Svoboda
1429*a44c6453SJan Svoboda vfs::recursive_directory_iterator I(FS, "/", EC), E;
1430*a44c6453SJan Svoboda ASSERT_FALSE(EC);
1431*a44c6453SJan Svoboda
1432*a44c6453SJan Svoboda std::vector<std::string> Nodes;
1433*a44c6453SJan Svoboda for (; !EC && I != E; I.increment(EC))
1434*a44c6453SJan Svoboda Nodes.push_back(getPosixPath(std::string(I->path())));
1435*a44c6453SJan Svoboda
1436*a44c6453SJan Svoboda EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/dir", "/dir/file", "/dir",
1437*a44c6453SJan Svoboda "/dir/file"));
1438*a44c6453SJan Svoboda }
1439*a44c6453SJan Svoboda
1440fc51490bSJonas Devlieghere // NOTE: in the tests below, we use '//root/' as our root directory, since it is
1441fc51490bSJonas Devlieghere // a legal *absolute* path on Windows as well as *nix.
1442fc51490bSJonas Devlieghere class VFSFromYAMLTest : public ::testing::Test {
1443fc51490bSJonas Devlieghere public:
1444fc51490bSJonas Devlieghere int NumDiagnostics;
1445fc51490bSJonas Devlieghere
SetUp()1446fc51490bSJonas Devlieghere void SetUp() override { NumDiagnostics = 0; }
1447fc51490bSJonas Devlieghere
CountingDiagHandler(const SMDiagnostic &,void * Context)1448fc51490bSJonas Devlieghere static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
1449fc51490bSJonas Devlieghere VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
1450fc51490bSJonas Devlieghere ++Test->NumDiagnostics;
1451fc51490bSJonas Devlieghere }
1452fc51490bSJonas Devlieghere
1453a22eda54SDuncan P. N. Exon Smith std::unique_ptr<vfs::FileSystem>
getFromYAMLRawString(StringRef Content,IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS)1454fc51490bSJonas Devlieghere getFromYAMLRawString(StringRef Content,
1455fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
1456fc51490bSJonas Devlieghere std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content);
1457fc51490bSJonas Devlieghere return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, "", this,
1458fc51490bSJonas Devlieghere ExternalFS);
1459fc51490bSJonas Devlieghere }
1460fc51490bSJonas Devlieghere
getFromYAMLString(StringRef Content,IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS=new DummyFileSystem ())1461a22eda54SDuncan P. N. Exon Smith std::unique_ptr<vfs::FileSystem> getFromYAMLString(
1462fc51490bSJonas Devlieghere StringRef Content,
1463fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
1464fc51490bSJonas Devlieghere std::string VersionPlusContent("{\n 'version':0,\n");
1465fc51490bSJonas Devlieghere VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
1466fc51490bSJonas Devlieghere return getFromYAMLRawString(VersionPlusContent, ExternalFS);
1467fc51490bSJonas Devlieghere }
1468fc51490bSJonas Devlieghere
1469fc51490bSJonas Devlieghere // This is intended as a "XFAIL" for windows hosts.
supportsSameDirMultipleYAMLEntries()1470fc51490bSJonas Devlieghere bool supportsSameDirMultipleYAMLEntries() {
1471fc51490bSJonas Devlieghere Triple Host(Triple::normalize(sys::getProcessTriple()));
1472fc51490bSJonas Devlieghere return !Host.isOSWindows();
1473fc51490bSJonas Devlieghere }
1474fc51490bSJonas Devlieghere };
1475fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,BasicVFSFromYAML)1476fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
1477fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS;
1478fc51490bSJonas Devlieghere FS = getFromYAMLString("");
1479fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1480fc51490bSJonas Devlieghere FS = getFromYAMLString("[]");
1481fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1482fc51490bSJonas Devlieghere FS = getFromYAMLString("'string'");
1483fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1484fc51490bSJonas Devlieghere EXPECT_EQ(3, NumDiagnostics);
1485fc51490bSJonas Devlieghere }
1486fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,MappedFiles)1487fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, MappedFiles) {
1488fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1489ecb00a77SNathan Hawes Lower->addDirectory("//root/foo/bar");
1490fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a");
1491fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
1492fc51490bSJonas Devlieghere "{ 'roots': [\n"
1493fc51490bSJonas Devlieghere "{\n"
1494fc51490bSJonas Devlieghere " 'type': 'directory',\n"
1495fc51490bSJonas Devlieghere " 'name': '//root/',\n"
1496fc51490bSJonas Devlieghere " 'contents': [ {\n"
1497fc51490bSJonas Devlieghere " 'type': 'file',\n"
1498fc51490bSJonas Devlieghere " 'name': 'file1',\n"
1499fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n"
1500fc51490bSJonas Devlieghere " },\n"
1501fc51490bSJonas Devlieghere " {\n"
1502fc51490bSJonas Devlieghere " 'type': 'file',\n"
1503fc51490bSJonas Devlieghere " 'name': 'file2',\n"
1504fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/b'\n"
1505ecb00a77SNathan Hawes " },\n"
1506ecb00a77SNathan Hawes " {\n"
1507ecb00a77SNathan Hawes " 'type': 'directory-remap',\n"
1508ecb00a77SNathan Hawes " 'name': 'mappeddir',\n"
1509ecb00a77SNathan Hawes " 'external-contents': '//root/foo/bar'\n"
1510ecb00a77SNathan Hawes " },\n"
1511ecb00a77SNathan Hawes " {\n"
1512ecb00a77SNathan Hawes " 'type': 'directory-remap',\n"
1513ecb00a77SNathan Hawes " 'name': 'mappeddir2',\n"
1514ecb00a77SNathan Hawes " 'use-external-name': false,\n"
1515ecb00a77SNathan Hawes " 'external-contents': '//root/foo/bar'\n"
1516fc51490bSJonas Devlieghere " }\n"
1517fc51490bSJonas Devlieghere " ]\n"
1518fc51490bSJonas Devlieghere "}\n"
1519fc51490bSJonas Devlieghere "]\n"
1520fc51490bSJonas Devlieghere "}",
1521fc51490bSJonas Devlieghere Lower);
152238ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
1523fc51490bSJonas Devlieghere
1524fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1525fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
1526fc51490bSJonas Devlieghere O->pushOverlay(FS);
1527fc51490bSJonas Devlieghere
1528fc51490bSJonas Devlieghere // file
1529fc51490bSJonas Devlieghere ErrorOr<vfs::Status> S = O->status("//root/file1");
1530fc51490bSJonas Devlieghere ASSERT_FALSE(S.getError());
1531fc51490bSJonas Devlieghere EXPECT_EQ("//root/foo/bar/a", S->getName());
1532f65b0b5dSBen Barham EXPECT_TRUE(S->IsVFSMapped);
1533fe2478d4SBen Barham EXPECT_TRUE(S->ExposesExternalVFSPath);
1534fc51490bSJonas Devlieghere
1535fc51490bSJonas Devlieghere ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
1536fc51490bSJonas Devlieghere EXPECT_EQ("//root/foo/bar/a", SLower->getName());
1537fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SLower));
1538f65b0b5dSBen Barham EXPECT_FALSE(SLower->IsVFSMapped);
1539fe2478d4SBen Barham EXPECT_FALSE(SLower->ExposesExternalVFSPath);
1540fc51490bSJonas Devlieghere
1541fc51490bSJonas Devlieghere // file after opening
1542fc51490bSJonas Devlieghere auto OpenedF = O->openFileForRead("//root/file1");
1543fc51490bSJonas Devlieghere ASSERT_FALSE(OpenedF.getError());
1544fc51490bSJonas Devlieghere auto OpenedS = (*OpenedF)->status();
1545fc51490bSJonas Devlieghere ASSERT_FALSE(OpenedS.getError());
1546fc51490bSJonas Devlieghere EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
1547f65b0b5dSBen Barham EXPECT_TRUE(OpenedS->IsVFSMapped);
1548fe2478d4SBen Barham EXPECT_TRUE(OpenedS->ExposesExternalVFSPath);
1549fc51490bSJonas Devlieghere
1550fc51490bSJonas Devlieghere // directory
1551fc51490bSJonas Devlieghere S = O->status("//root/");
1552fc51490bSJonas Devlieghere ASSERT_FALSE(S.getError());
1553fc51490bSJonas Devlieghere EXPECT_TRUE(S->isDirectory());
1554fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
1555fc51490bSJonas Devlieghere
1556ecb00a77SNathan Hawes // remapped directory
1557ecb00a77SNathan Hawes S = O->status("//root/mappeddir");
1558ecb00a77SNathan Hawes ASSERT_FALSE(S.getError());
1559ecb00a77SNathan Hawes EXPECT_TRUE(S->isDirectory());
1560f65b0b5dSBen Barham EXPECT_TRUE(S->IsVFSMapped);
1561fe2478d4SBen Barham EXPECT_TRUE(S->ExposesExternalVFSPath);
1562ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*O->status("//root/foo/bar")));
1563ecb00a77SNathan Hawes
1564ecb00a77SNathan Hawes SLower = O->status("//root/foo/bar");
1565ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar", SLower->getName());
1566ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SLower));
1567f65b0b5dSBen Barham EXPECT_FALSE(SLower->IsVFSMapped);
1568fe2478d4SBen Barham EXPECT_FALSE(SLower->ExposesExternalVFSPath);
1569ecb00a77SNathan Hawes
1570ecb00a77SNathan Hawes // file in remapped directory
1571ecb00a77SNathan Hawes S = O->status("//root/mappeddir/a");
1572ecb00a77SNathan Hawes ASSERT_FALSE(S.getError());
1573fe2478d4SBen Barham EXPECT_FALSE(S->isDirectory());
1574fe2478d4SBen Barham EXPECT_TRUE(S->IsVFSMapped);
1575fe2478d4SBen Barham EXPECT_TRUE(S->ExposesExternalVFSPath);
1576fe2478d4SBen Barham EXPECT_EQ("//root/foo/bar/a", S->getName());
1577ecb00a77SNathan Hawes
1578ecb00a77SNathan Hawes // file in remapped directory, with use-external-name=false
1579ecb00a77SNathan Hawes S = O->status("//root/mappeddir2/a");
1580ecb00a77SNathan Hawes ASSERT_FALSE(S.getError());
1581fe2478d4SBen Barham EXPECT_FALSE(S->isDirectory());
1582fe2478d4SBen Barham EXPECT_TRUE(S->IsVFSMapped);
1583fe2478d4SBen Barham EXPECT_FALSE(S->ExposesExternalVFSPath);
1584fe2478d4SBen Barham EXPECT_EQ("//root/mappeddir2/a", S->getName());
1585ecb00a77SNathan Hawes
1586ecb00a77SNathan Hawes // file contents in remapped directory
1587ecb00a77SNathan Hawes OpenedF = O->openFileForRead("//root/mappeddir/a");
1588ecb00a77SNathan Hawes ASSERT_FALSE(OpenedF.getError());
1589ecb00a77SNathan Hawes OpenedS = (*OpenedF)->status();
1590ecb00a77SNathan Hawes ASSERT_FALSE(OpenedS.getError());
1591ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
1592f65b0b5dSBen Barham EXPECT_TRUE(OpenedS->IsVFSMapped);
1593fe2478d4SBen Barham EXPECT_TRUE(OpenedS->ExposesExternalVFSPath);
1594ecb00a77SNathan Hawes
1595ecb00a77SNathan Hawes // file contents in remapped directory, with use-external-name=false
1596ecb00a77SNathan Hawes OpenedF = O->openFileForRead("//root/mappeddir2/a");
1597ecb00a77SNathan Hawes ASSERT_FALSE(OpenedF.getError());
1598ecb00a77SNathan Hawes OpenedS = (*OpenedF)->status();
1599ecb00a77SNathan Hawes ASSERT_FALSE(OpenedS.getError());
1600ecb00a77SNathan Hawes EXPECT_EQ("//root/mappeddir2/a", OpenedS->getName());
1601f65b0b5dSBen Barham EXPECT_TRUE(OpenedS->IsVFSMapped);
1602fe2478d4SBen Barham EXPECT_FALSE(OpenedS->ExposesExternalVFSPath);
1603ecb00a77SNathan Hawes
1604fc51490bSJonas Devlieghere // broken mapping
1605fc51490bSJonas Devlieghere EXPECT_EQ(O->status("//root/file2").getError(),
1606fc51490bSJonas Devlieghere llvm::errc::no_such_file_or_directory);
1607fc51490bSJonas Devlieghere EXPECT_EQ(0, NumDiagnostics);
1608fc51490bSJonas Devlieghere }
1609fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,MappedRoot)1610ecb00a77SNathan Hawes TEST_F(VFSFromYAMLTest, MappedRoot) {
1611ecb00a77SNathan Hawes IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1612ecb00a77SNathan Hawes Lower->addDirectory("//root/foo/bar");
1613ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/bar/a");
1614ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::FileSystem> FS =
1615ecb00a77SNathan Hawes getFromYAMLString("{ 'roots': [\n"
1616ecb00a77SNathan Hawes "{\n"
1617ecb00a77SNathan Hawes " 'type': 'directory-remap',\n"
1618ecb00a77SNathan Hawes " 'name': '//mappedroot/',\n"
1619ecb00a77SNathan Hawes " 'external-contents': '//root/foo/bar'\n"
1620ecb00a77SNathan Hawes "}\n"
1621ecb00a77SNathan Hawes "]\n"
1622ecb00a77SNathan Hawes "}",
1623ecb00a77SNathan Hawes Lower);
162438ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
1625ecb00a77SNathan Hawes
1626ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1627ecb00a77SNathan Hawes new vfs::OverlayFileSystem(Lower));
1628ecb00a77SNathan Hawes O->pushOverlay(FS);
1629ecb00a77SNathan Hawes
1630ecb00a77SNathan Hawes // file
1631ecb00a77SNathan Hawes ErrorOr<vfs::Status> S = O->status("//mappedroot/a");
1632ecb00a77SNathan Hawes ASSERT_FALSE(S.getError());
1633ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar/a", S->getName());
1634f65b0b5dSBen Barham EXPECT_TRUE(S->IsVFSMapped);
1635fe2478d4SBen Barham EXPECT_TRUE(S->ExposesExternalVFSPath);
1636ecb00a77SNathan Hawes
1637ecb00a77SNathan Hawes ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
1638ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar/a", SLower->getName());
1639ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SLower));
1640f65b0b5dSBen Barham EXPECT_FALSE(SLower->IsVFSMapped);
1641fe2478d4SBen Barham EXPECT_FALSE(SLower->ExposesExternalVFSPath);
1642ecb00a77SNathan Hawes
1643ecb00a77SNathan Hawes // file after opening
1644ecb00a77SNathan Hawes auto OpenedF = O->openFileForRead("//mappedroot/a");
1645ecb00a77SNathan Hawes ASSERT_FALSE(OpenedF.getError());
1646ecb00a77SNathan Hawes auto OpenedS = (*OpenedF)->status();
1647ecb00a77SNathan Hawes ASSERT_FALSE(OpenedS.getError());
1648ecb00a77SNathan Hawes EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
1649f65b0b5dSBen Barham EXPECT_TRUE(OpenedS->IsVFSMapped);
1650fe2478d4SBen Barham EXPECT_TRUE(OpenedS->ExposesExternalVFSPath);
1651ecb00a77SNathan Hawes
1652ecb00a77SNathan Hawes EXPECT_EQ(0, NumDiagnostics);
1653ecb00a77SNathan Hawes }
1654ecb00a77SNathan Hawes
TEST_F(VFSFromYAMLTest,RemappedDirectoryOverlay)1655ecb00a77SNathan Hawes TEST_F(VFSFromYAMLTest, RemappedDirectoryOverlay) {
1656ecb00a77SNathan Hawes IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1657ecb00a77SNathan Hawes Lower->addDirectory("//root/foo");
1658ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/a");
1659ecb00a77SNathan Hawes Lower->addDirectory("//root/bar");
1660ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/b");
1661ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/c");
1662ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::FileSystem> FS =
1663ecb00a77SNathan Hawes getFromYAMLString("{ 'roots': [\n"
1664ecb00a77SNathan Hawes "{\n"
1665ecb00a77SNathan Hawes " 'type': 'directory',\n"
1666ecb00a77SNathan Hawes " 'name': '//root/',\n"
1667ecb00a77SNathan Hawes " 'contents': [ {\n"
1668ecb00a77SNathan Hawes " 'type': 'directory-remap',\n"
1669ecb00a77SNathan Hawes " 'name': 'bar',\n"
1670ecb00a77SNathan Hawes " 'external-contents': '//root/foo'\n"
1671ecb00a77SNathan Hawes " }\n"
1672ecb00a77SNathan Hawes " ]\n"
1673ecb00a77SNathan Hawes "}]}",
1674ecb00a77SNathan Hawes Lower);
167538ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
1676ecb00a77SNathan Hawes
1677ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1678ecb00a77SNathan Hawes new vfs::OverlayFileSystem(Lower));
1679ecb00a77SNathan Hawes O->pushOverlay(FS);
1680ecb00a77SNathan Hawes
1681ecb00a77SNathan Hawes ErrorOr<vfs::Status> S = O->status("//root/foo");
1682ecb00a77SNathan Hawes ASSERT_FALSE(S.getError());
1683ecb00a77SNathan Hawes
1684ecb00a77SNathan Hawes ErrorOr<vfs::Status> SS = O->status("//root/bar");
1685ecb00a77SNathan Hawes ASSERT_FALSE(SS.getError());
1686ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SS));
1687ecb00a77SNathan Hawes
1688ecb00a77SNathan Hawes std::error_code EC;
1689ecb00a77SNathan Hawes checkContents(O->dir_begin("//root/bar", EC),
1690ecb00a77SNathan Hawes {"//root/foo/a", "//root/bar/b", "//root/bar/c"});
1691ecb00a77SNathan Hawes
1692ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/b");
1693ecb00a77SNathan Hawes checkContents(O->dir_begin("//root/bar", EC),
1694ecb00a77SNathan Hawes {"//root/foo/a", "//root/foo/b", "//root/bar/c"});
1695ecb00a77SNathan Hawes
1696ecb00a77SNathan Hawes EXPECT_EQ(0, NumDiagnostics);
1697ecb00a77SNathan Hawes }
1698ecb00a77SNathan Hawes
TEST_F(VFSFromYAMLTest,RemappedDirectoryOverlayNoExternalNames)1699ecb00a77SNathan Hawes TEST_F(VFSFromYAMLTest, RemappedDirectoryOverlayNoExternalNames) {
1700ecb00a77SNathan Hawes IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1701ecb00a77SNathan Hawes Lower->addDirectory("//root/foo");
1702ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/a");
1703ecb00a77SNathan Hawes Lower->addDirectory("//root/bar");
1704ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/b");
1705ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/c");
1706ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::FileSystem> FS =
1707ecb00a77SNathan Hawes getFromYAMLString("{ 'use-external-names': false,\n"
1708ecb00a77SNathan Hawes " 'roots': [\n"
1709ecb00a77SNathan Hawes "{\n"
1710ecb00a77SNathan Hawes " 'type': 'directory',\n"
1711ecb00a77SNathan Hawes " 'name': '//root/',\n"
1712ecb00a77SNathan Hawes " 'contents': [ {\n"
1713ecb00a77SNathan Hawes " 'type': 'directory-remap',\n"
1714ecb00a77SNathan Hawes " 'name': 'bar',\n"
1715ecb00a77SNathan Hawes " 'external-contents': '//root/foo'\n"
1716ecb00a77SNathan Hawes " }\n"
1717ecb00a77SNathan Hawes " ]\n"
1718ecb00a77SNathan Hawes "}]}",
1719ecb00a77SNathan Hawes Lower);
172038ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
1721ecb00a77SNathan Hawes
1722ecb00a77SNathan Hawes ErrorOr<vfs::Status> S = FS->status("//root/foo");
1723ecb00a77SNathan Hawes ASSERT_FALSE(S.getError());
1724ecb00a77SNathan Hawes
1725ecb00a77SNathan Hawes ErrorOr<vfs::Status> SS = FS->status("//root/bar");
1726ecb00a77SNathan Hawes ASSERT_FALSE(SS.getError());
1727ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SS));
1728ecb00a77SNathan Hawes
1729ecb00a77SNathan Hawes std::error_code EC;
1730ecb00a77SNathan Hawes checkContents(FS->dir_begin("//root/bar", EC),
1731ecb00a77SNathan Hawes {"//root/bar/a", "//root/bar/b", "//root/bar/c"});
1732ecb00a77SNathan Hawes
1733ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/b");
1734ecb00a77SNathan Hawes checkContents(FS->dir_begin("//root/bar", EC),
1735ecb00a77SNathan Hawes {"//root/bar/a", "//root/bar/b", "//root/bar/c"});
1736ecb00a77SNathan Hawes
1737ecb00a77SNathan Hawes EXPECT_EQ(0, NumDiagnostics);
1738ecb00a77SNathan Hawes }
1739ecb00a77SNathan Hawes
TEST_F(VFSFromYAMLTest,RemappedDirectoryOverlayNoFallthrough)1740ecb00a77SNathan Hawes TEST_F(VFSFromYAMLTest, RemappedDirectoryOverlayNoFallthrough) {
1741ecb00a77SNathan Hawes IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1742ecb00a77SNathan Hawes Lower->addDirectory("//root/foo");
1743ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/a");
1744ecb00a77SNathan Hawes Lower->addDirectory("//root/bar");
1745ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/b");
1746ecb00a77SNathan Hawes Lower->addRegularFile("//root/bar/c");
1747ecb00a77SNathan Hawes IntrusiveRefCntPtr<vfs::FileSystem> FS =
1748ecb00a77SNathan Hawes getFromYAMLString("{ 'fallthrough': false,\n"
1749ecb00a77SNathan Hawes " 'roots': [\n"
1750ecb00a77SNathan Hawes "{\n"
1751ecb00a77SNathan Hawes " 'type': 'directory',\n"
1752ecb00a77SNathan Hawes " 'name': '//root/',\n"
1753ecb00a77SNathan Hawes " 'contents': [ {\n"
1754ecb00a77SNathan Hawes " 'type': 'directory-remap',\n"
1755ecb00a77SNathan Hawes " 'name': 'bar',\n"
1756ecb00a77SNathan Hawes " 'external-contents': '//root/foo'\n"
1757ecb00a77SNathan Hawes " }\n"
1758ecb00a77SNathan Hawes " ]\n"
1759ecb00a77SNathan Hawes "}]}",
1760ecb00a77SNathan Hawes Lower);
176138ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
1762ecb00a77SNathan Hawes
1763ecb00a77SNathan Hawes ErrorOr<vfs::Status> S = Lower->status("//root/foo");
1764ecb00a77SNathan Hawes ASSERT_FALSE(S.getError());
1765ecb00a77SNathan Hawes
1766ecb00a77SNathan Hawes ErrorOr<vfs::Status> SS = FS->status("//root/bar");
1767ecb00a77SNathan Hawes ASSERT_FALSE(SS.getError());
1768ecb00a77SNathan Hawes EXPECT_TRUE(S->equivalent(*SS));
1769ecb00a77SNathan Hawes
1770ecb00a77SNathan Hawes std::error_code EC;
1771ecb00a77SNathan Hawes checkContents(FS->dir_begin("//root/bar", EC), {"//root/foo/a"});
1772ecb00a77SNathan Hawes
1773ecb00a77SNathan Hawes Lower->addRegularFile("//root/foo/b");
1774ecb00a77SNathan Hawes checkContents(FS->dir_begin("//root/bar", EC),
1775ecb00a77SNathan Hawes {"//root/foo/a", "//root/foo/b"});
1776ecb00a77SNathan Hawes
1777ecb00a77SNathan Hawes EXPECT_EQ(0, NumDiagnostics);
1778ecb00a77SNathan Hawes }
1779ecb00a77SNathan Hawes
TEST_F(VFSFromYAMLTest,ReturnsRequestedPathVFSMiss)178086e2af80SKeith Smiley TEST_F(VFSFromYAMLTest, ReturnsRequestedPathVFSMiss) {
178186e2af80SKeith Smiley IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS(
178286e2af80SKeith Smiley new vfs::InMemoryFileSystem);
178386e2af80SKeith Smiley BaseFS->addFile("//root/foo/a", 0,
178486e2af80SKeith Smiley MemoryBuffer::getMemBuffer("contents of a"));
178586e2af80SKeith Smiley ASSERT_FALSE(BaseFS->setCurrentWorkingDirectory("//root/foo"));
178686e2af80SKeith Smiley auto RemappedFS = vfs::RedirectingFileSystem::create(
178786e2af80SKeith Smiley {}, /*UseExternalNames=*/false, *BaseFS);
178886e2af80SKeith Smiley
178986e2af80SKeith Smiley auto OpenedF = RemappedFS->openFileForRead("a");
179086e2af80SKeith Smiley ASSERT_FALSE(OpenedF.getError());
179186e2af80SKeith Smiley llvm::ErrorOr<std::string> Name = (*OpenedF)->getName();
179286e2af80SKeith Smiley ASSERT_FALSE(Name.getError());
179386e2af80SKeith Smiley EXPECT_EQ("a", Name.get());
179486e2af80SKeith Smiley
179586e2af80SKeith Smiley auto OpenedS = (*OpenedF)->status();
179686e2af80SKeith Smiley ASSERT_FALSE(OpenedS.getError());
179786e2af80SKeith Smiley EXPECT_EQ("a", OpenedS->getName());
1798f65b0b5dSBen Barham EXPECT_FALSE(OpenedS->IsVFSMapped);
1799fe2478d4SBen Barham EXPECT_FALSE(OpenedS->ExposesExternalVFSPath);
180086e2af80SKeith Smiley
180186e2af80SKeith Smiley auto DirectS = RemappedFS->status("a");
180286e2af80SKeith Smiley ASSERT_FALSE(DirectS.getError());
180386e2af80SKeith Smiley EXPECT_EQ("a", DirectS->getName());
1804f65b0b5dSBen Barham EXPECT_FALSE(DirectS->IsVFSMapped);
1805fe2478d4SBen Barham EXPECT_FALSE(DirectS->ExposesExternalVFSPath);
180686e2af80SKeith Smiley
180786e2af80SKeith Smiley EXPECT_EQ(0, NumDiagnostics);
180886e2af80SKeith Smiley }
180986e2af80SKeith Smiley
TEST_F(VFSFromYAMLTest,ReturnsExternalPathVFSHit)181086e2af80SKeith Smiley TEST_F(VFSFromYAMLTest, ReturnsExternalPathVFSHit) {
181186e2af80SKeith Smiley IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS(
181286e2af80SKeith Smiley new vfs::InMemoryFileSystem);
181386e2af80SKeith Smiley BaseFS->addFile("//root/foo/realname", 0,
181486e2af80SKeith Smiley MemoryBuffer::getMemBuffer("contents of a"));
181586e2af80SKeith Smiley auto FS =
181686e2af80SKeith Smiley getFromYAMLString("{ 'use-external-names': true,\n"
181786e2af80SKeith Smiley " 'roots': [\n"
181886e2af80SKeith Smiley "{\n"
181986e2af80SKeith Smiley " 'type': 'directory',\n"
182086e2af80SKeith Smiley " 'name': '//root/foo',\n"
182186e2af80SKeith Smiley " 'contents': [ {\n"
182286e2af80SKeith Smiley " 'type': 'file',\n"
182386e2af80SKeith Smiley " 'name': 'vfsname',\n"
182486e2af80SKeith Smiley " 'external-contents': 'realname'\n"
182586e2af80SKeith Smiley " }\n"
182686e2af80SKeith Smiley " ]\n"
182786e2af80SKeith Smiley "}]}",
182886e2af80SKeith Smiley BaseFS);
182986e2af80SKeith Smiley ASSERT_FALSE(FS->setCurrentWorkingDirectory("//root/foo"));
183086e2af80SKeith Smiley
183186e2af80SKeith Smiley auto OpenedF = FS->openFileForRead("vfsname");
183286e2af80SKeith Smiley ASSERT_FALSE(OpenedF.getError());
183386e2af80SKeith Smiley llvm::ErrorOr<std::string> Name = (*OpenedF)->getName();
183486e2af80SKeith Smiley ASSERT_FALSE(Name.getError());
183586e2af80SKeith Smiley EXPECT_EQ("realname", Name.get());
183686e2af80SKeith Smiley
183786e2af80SKeith Smiley auto OpenedS = (*OpenedF)->status();
183886e2af80SKeith Smiley ASSERT_FALSE(OpenedS.getError());
183986e2af80SKeith Smiley EXPECT_EQ("realname", OpenedS->getName());
1840f65b0b5dSBen Barham EXPECT_TRUE(OpenedS->IsVFSMapped);
1841fe2478d4SBen Barham EXPECT_TRUE(OpenedS->ExposesExternalVFSPath);
184286e2af80SKeith Smiley
184386e2af80SKeith Smiley auto DirectS = FS->status("vfsname");
184486e2af80SKeith Smiley ASSERT_FALSE(DirectS.getError());
184586e2af80SKeith Smiley EXPECT_EQ("realname", DirectS->getName());
1846f65b0b5dSBen Barham EXPECT_TRUE(DirectS->IsVFSMapped);
1847fe2478d4SBen Barham EXPECT_TRUE(DirectS->ExposesExternalVFSPath);
184886e2af80SKeith Smiley
184986e2af80SKeith Smiley EXPECT_EQ(0, NumDiagnostics);
185086e2af80SKeith Smiley }
185186e2af80SKeith Smiley
TEST_F(VFSFromYAMLTest,ReturnsInternalPathVFSHit)185286e2af80SKeith Smiley TEST_F(VFSFromYAMLTest, ReturnsInternalPathVFSHit) {
185386e2af80SKeith Smiley IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS(
185486e2af80SKeith Smiley new vfs::InMemoryFileSystem);
185586e2af80SKeith Smiley BaseFS->addFile("//root/foo/realname", 0,
185686e2af80SKeith Smiley MemoryBuffer::getMemBuffer("contents of a"));
185786e2af80SKeith Smiley auto FS =
185886e2af80SKeith Smiley getFromYAMLString("{ 'use-external-names': false,\n"
185986e2af80SKeith Smiley " 'roots': [\n"
186086e2af80SKeith Smiley "{\n"
186186e2af80SKeith Smiley " 'type': 'directory',\n"
186286e2af80SKeith Smiley " 'name': '//root/foo',\n"
186386e2af80SKeith Smiley " 'contents': [ {\n"
186486e2af80SKeith Smiley " 'type': 'file',\n"
186586e2af80SKeith Smiley " 'name': 'vfsname',\n"
186686e2af80SKeith Smiley " 'external-contents': 'realname'\n"
186786e2af80SKeith Smiley " }\n"
186886e2af80SKeith Smiley " ]\n"
186986e2af80SKeith Smiley "}]}",
187086e2af80SKeith Smiley BaseFS);
187186e2af80SKeith Smiley ASSERT_FALSE(FS->setCurrentWorkingDirectory("//root/foo"));
187286e2af80SKeith Smiley
187386e2af80SKeith Smiley auto OpenedF = FS->openFileForRead("vfsname");
187486e2af80SKeith Smiley ASSERT_FALSE(OpenedF.getError());
187586e2af80SKeith Smiley llvm::ErrorOr<std::string> Name = (*OpenedF)->getName();
187686e2af80SKeith Smiley ASSERT_FALSE(Name.getError());
187786e2af80SKeith Smiley EXPECT_EQ("vfsname", Name.get());
187886e2af80SKeith Smiley
187986e2af80SKeith Smiley auto OpenedS = (*OpenedF)->status();
188086e2af80SKeith Smiley ASSERT_FALSE(OpenedS.getError());
188186e2af80SKeith Smiley EXPECT_EQ("vfsname", OpenedS->getName());
1882f65b0b5dSBen Barham EXPECT_TRUE(OpenedS->IsVFSMapped);
1883fe2478d4SBen Barham EXPECT_FALSE(OpenedS->ExposesExternalVFSPath);
188486e2af80SKeith Smiley
188586e2af80SKeith Smiley auto DirectS = FS->status("vfsname");
188686e2af80SKeith Smiley ASSERT_FALSE(DirectS.getError());
188786e2af80SKeith Smiley EXPECT_EQ("vfsname", DirectS->getName());
1888f65b0b5dSBen Barham EXPECT_TRUE(DirectS->IsVFSMapped);
1889fe2478d4SBen Barham EXPECT_FALSE(DirectS->ExposesExternalVFSPath);
189086e2af80SKeith Smiley
189186e2af80SKeith Smiley EXPECT_EQ(0, NumDiagnostics);
189286e2af80SKeith Smiley }
189386e2af80SKeith Smiley
TEST_F(VFSFromYAMLTest,CaseInsensitive)1894fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, CaseInsensitive) {
1895fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1896fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a");
1897fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
1898fc51490bSJonas Devlieghere "{ 'case-sensitive': 'false',\n"
1899fc51490bSJonas Devlieghere " 'roots': [\n"
1900fc51490bSJonas Devlieghere "{\n"
1901fc51490bSJonas Devlieghere " 'type': 'directory',\n"
1902fc51490bSJonas Devlieghere " 'name': '//root/',\n"
1903fc51490bSJonas Devlieghere " 'contents': [ {\n"
1904fc51490bSJonas Devlieghere " 'type': 'file',\n"
1905fc51490bSJonas Devlieghere " 'name': 'XX',\n"
1906fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n"
1907fc51490bSJonas Devlieghere " }\n"
1908fc51490bSJonas Devlieghere " ]\n"
1909fc51490bSJonas Devlieghere "}]}",
1910fc51490bSJonas Devlieghere Lower);
191138ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
1912fc51490bSJonas Devlieghere
1913fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1914fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
1915fc51490bSJonas Devlieghere O->pushOverlay(FS);
1916fc51490bSJonas Devlieghere
1917fc51490bSJonas Devlieghere ErrorOr<vfs::Status> S = O->status("//root/XX");
1918fc51490bSJonas Devlieghere ASSERT_FALSE(S.getError());
1919fc51490bSJonas Devlieghere
1920fc51490bSJonas Devlieghere ErrorOr<vfs::Status> SS = O->status("//root/xx");
1921fc51490bSJonas Devlieghere ASSERT_FALSE(SS.getError());
1922fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SS));
1923fc51490bSJonas Devlieghere SS = O->status("//root/xX");
1924fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SS));
1925fc51490bSJonas Devlieghere SS = O->status("//root/Xx");
1926fc51490bSJonas Devlieghere EXPECT_TRUE(S->equivalent(*SS));
1927fc51490bSJonas Devlieghere EXPECT_EQ(0, NumDiagnostics);
1928fc51490bSJonas Devlieghere }
1929fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,CaseSensitive)1930fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, CaseSensitive) {
1931fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1932fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a");
1933fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
1934fc51490bSJonas Devlieghere "{ 'case-sensitive': 'true',\n"
1935fc51490bSJonas Devlieghere " 'roots': [\n"
1936fc51490bSJonas Devlieghere "{\n"
1937fc51490bSJonas Devlieghere " 'type': 'directory',\n"
1938fc51490bSJonas Devlieghere " 'name': '//root/',\n"
1939fc51490bSJonas Devlieghere " 'contents': [ {\n"
1940fc51490bSJonas Devlieghere " 'type': 'file',\n"
1941fc51490bSJonas Devlieghere " 'name': 'XX',\n"
1942fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n"
1943fc51490bSJonas Devlieghere " }\n"
1944fc51490bSJonas Devlieghere " ]\n"
1945fc51490bSJonas Devlieghere "}]}",
1946fc51490bSJonas Devlieghere Lower);
194738ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
1948fc51490bSJonas Devlieghere
1949fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1950fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
1951fc51490bSJonas Devlieghere O->pushOverlay(FS);
1952fc51490bSJonas Devlieghere
1953fc51490bSJonas Devlieghere ErrorOr<vfs::Status> SS = O->status("//root/xx");
1954fc51490bSJonas Devlieghere EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
1955fc51490bSJonas Devlieghere SS = O->status("//root/xX");
1956fc51490bSJonas Devlieghere EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
1957fc51490bSJonas Devlieghere SS = O->status("//root/Xx");
1958fc51490bSJonas Devlieghere EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
1959fc51490bSJonas Devlieghere EXPECT_EQ(0, NumDiagnostics);
1960fc51490bSJonas Devlieghere }
1961fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,IllegalVFSFile)1962fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
1963fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1964fc51490bSJonas Devlieghere
1965fc51490bSJonas Devlieghere // invalid YAML at top-level
1966fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
1967fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1968fc51490bSJonas Devlieghere // invalid YAML in roots
1969fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[}", Lower);
1970fc51490bSJonas Devlieghere // invalid YAML in directory
1971fc51490bSJonas Devlieghere FS = getFromYAMLString(
1972fc51490bSJonas Devlieghere "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
1973fc51490bSJonas Devlieghere Lower);
1974fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1975fc51490bSJonas Devlieghere
1976fc51490bSJonas Devlieghere // invalid configuration
1977fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
1978fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1979fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
1980fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1981fc51490bSJonas Devlieghere
1982fc51490bSJonas Devlieghere // invalid roots
1983fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':'' }", Lower);
1984fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1985fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':{} }", Lower);
1986fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1987fc51490bSJonas Devlieghere
1988fc51490bSJonas Devlieghere // invalid entries
1989fc51490bSJonas Devlieghere FS = getFromYAMLString(
1990fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
1991fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1992fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
1993fc51490bSJonas Devlieghere "'external-contents': 'other' }",
1994fc51490bSJonas Devlieghere Lower);
1995fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
1996fc51490bSJonas Devlieghere FS = getFromYAMLString(
1997fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
1998fc51490bSJonas Devlieghere Lower);
1999fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2000fc51490bSJonas Devlieghere FS = getFromYAMLString(
2001fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
2002fc51490bSJonas Devlieghere Lower);
2003fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2004fc51490bSJonas Devlieghere FS = getFromYAMLString(
2005fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
2006fc51490bSJonas Devlieghere Lower);
2007fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2008fc51490bSJonas Devlieghere FS = getFromYAMLString(
2009fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
2010fc51490bSJonas Devlieghere Lower);
2011fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2012fc51490bSJonas Devlieghere FS = getFromYAMLString(
2013fc51490bSJonas Devlieghere "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
2014fc51490bSJonas Devlieghere Lower);
2015fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2016fc51490bSJonas Devlieghere
2017fc51490bSJonas Devlieghere // missing mandatory fields
2018fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
2019fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2020fc51490bSJonas Devlieghere FS = getFromYAMLString(
2021fc51490bSJonas Devlieghere "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
2022fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2023fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
2024fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2025fc51490bSJonas Devlieghere
2026fc51490bSJonas Devlieghere // duplicate keys
2027fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
2028fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2029fc51490bSJonas Devlieghere FS = getFromYAMLString(
2030fc51490bSJonas Devlieghere "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
2031fc51490bSJonas Devlieghere Lower);
2032fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2033fc51490bSJonas Devlieghere FS =
2034fc51490bSJonas Devlieghere getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
2035fc51490bSJonas Devlieghere "'external-contents':'blah' } ] }",
2036fc51490bSJonas Devlieghere Lower);
2037fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2038fc51490bSJonas Devlieghere
2039fc51490bSJonas Devlieghere // missing version
2040fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
2041fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2042fc51490bSJonas Devlieghere
2043fc51490bSJonas Devlieghere // bad version number
2044fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
2045fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2046fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
2047fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2048fc51490bSJonas Devlieghere FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
2049fc51490bSJonas Devlieghere EXPECT_EQ(nullptr, FS.get());
2050ecb00a77SNathan Hawes
2051ecb00a77SNathan Hawes // both 'external-contents' and 'contents' specified
2052ecb00a77SNathan Hawes Lower->addDirectory("//root/external/dir");
2053ecb00a77SNathan Hawes FS = getFromYAMLString(
2054ecb00a77SNathan Hawes "{ 'roots':[ \n"
2055ecb00a77SNathan Hawes "{ 'type': 'directory', 'name': '//root/A', 'contents': [],\n"
2056ecb00a77SNathan Hawes " 'external-contents': '//root/external/dir'}]}",
2057ecb00a77SNathan Hawes Lower);
2058ecb00a77SNathan Hawes EXPECT_EQ(nullptr, FS.get());
2059ecb00a77SNathan Hawes
2060ecb00a77SNathan Hawes // 'directory-remap' with 'contents'
2061ecb00a77SNathan Hawes FS = getFromYAMLString(
2062ecb00a77SNathan Hawes "{ 'roots':[ \n"
2063ecb00a77SNathan Hawes "{ 'type': 'directory-remap', 'name': '//root/A', 'contents': [] }]}",
2064ecb00a77SNathan Hawes Lower);
2065ecb00a77SNathan Hawes EXPECT_EQ(nullptr, FS.get());
2066ecb00a77SNathan Hawes
2067502f14d6SBen Barham // invalid redirect kind
2068502f14d6SBen Barham FS = getFromYAMLString("{ 'redirecting-with': 'none', 'roots': [{\n"
2069502f14d6SBen Barham " 'type': 'directory-remap',\n"
2070502f14d6SBen Barham " 'name': '//root/A',\n"
2071502f14d6SBen Barham " 'external-contents': '//root/B' }]}",
2072502f14d6SBen Barham Lower);
2073502f14d6SBen Barham EXPECT_EQ(nullptr, FS.get());
2074502f14d6SBen Barham
2075502f14d6SBen Barham // redirect and fallthrough passed
2076502f14d6SBen Barham FS = getFromYAMLString("{ 'redirecting-with': 'fallthrough',\n"
2077502f14d6SBen Barham " 'fallthrough': true,\n"
2078502f14d6SBen Barham " 'roots': [{\n"
2079502f14d6SBen Barham " 'type': 'directory-remap',\n"
2080502f14d6SBen Barham " 'name': '//root/A',\n"
2081502f14d6SBen Barham " 'external-contents': '//root/B' }]}",
2082502f14d6SBen Barham Lower);
2083502f14d6SBen Barham EXPECT_EQ(nullptr, FS.get());
2084502f14d6SBen Barham
2085502f14d6SBen Barham EXPECT_EQ(28, NumDiagnostics);
2086fc51490bSJonas Devlieghere }
2087fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,UseExternalName)2088fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, UseExternalName) {
2089fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
2090fc51490bSJonas Devlieghere Lower->addRegularFile("//root/external/file");
2091fc51490bSJonas Devlieghere
2092fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS =
2093fc51490bSJonas Devlieghere getFromYAMLString("{ 'roots': [\n"
2094fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/A',\n"
2095fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n"
2096fc51490bSJonas Devlieghere " },\n"
2097fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/B',\n"
2098fc51490bSJonas Devlieghere " 'use-external-name': true,\n"
2099fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n"
2100fc51490bSJonas Devlieghere " },\n"
2101fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/C',\n"
2102fc51490bSJonas Devlieghere " 'use-external-name': false,\n"
2103fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n"
2104fc51490bSJonas Devlieghere " }\n"
2105fc51490bSJonas Devlieghere "] }",
2106fc51490bSJonas Devlieghere Lower);
210738ac4093SArchibald Elliott ASSERT_NE(nullptr, FS.get());
2108fc51490bSJonas Devlieghere
2109fc51490bSJonas Devlieghere // default true
2110fc51490bSJonas Devlieghere EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
2111fc51490bSJonas Devlieghere // explicit
2112fc51490bSJonas Devlieghere EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
2113fc51490bSJonas Devlieghere EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
2114fc51490bSJonas Devlieghere
2115fc51490bSJonas Devlieghere // global configuration
2116fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'use-external-names': false,\n"
2117fc51490bSJonas Devlieghere " 'roots': [\n"
2118fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/A',\n"
2119fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n"
2120fc51490bSJonas Devlieghere " },\n"
2121fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/B',\n"
2122fc51490bSJonas Devlieghere " 'use-external-name': true,\n"
2123fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n"
2124fc51490bSJonas Devlieghere " },\n"
2125fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/C',\n"
2126fc51490bSJonas Devlieghere " 'use-external-name': false,\n"
2127fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n"
2128fc51490bSJonas Devlieghere " }\n"
2129fc51490bSJonas Devlieghere "] }",
2130fc51490bSJonas Devlieghere Lower);
213138ac4093SArchibald Elliott ASSERT_NE(nullptr, FS.get());
2132fc51490bSJonas Devlieghere
2133fc51490bSJonas Devlieghere // default
2134fc51490bSJonas Devlieghere EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
2135fc51490bSJonas Devlieghere // explicit
2136fc51490bSJonas Devlieghere EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
2137fc51490bSJonas Devlieghere EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
2138fc51490bSJonas Devlieghere }
2139fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,MultiComponentPath)2140fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, MultiComponentPath) {
2141fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
2142fc51490bSJonas Devlieghere Lower->addRegularFile("//root/other");
2143fc51490bSJonas Devlieghere
2144fc51490bSJonas Devlieghere // file in roots
2145fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS =
2146fc51490bSJonas Devlieghere getFromYAMLString("{ 'roots': [\n"
2147fc51490bSJonas Devlieghere " { 'type': 'file', 'name': '//root/path/to/file',\n"
2148fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]\n"
2149fc51490bSJonas Devlieghere "}",
2150fc51490bSJonas Devlieghere Lower);
215138ac4093SArchibald Elliott ASSERT_NE(nullptr, FS.get());
2152fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError());
2153fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError());
2154fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError());
2155fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError());
2156fc51490bSJonas Devlieghere
2157fc51490bSJonas Devlieghere // at the start
2158fc51490bSJonas Devlieghere FS = getFromYAMLString(
2159fc51490bSJonas Devlieghere "{ 'roots': [\n"
2160fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': '//root/path/to',\n"
2161fc51490bSJonas Devlieghere " 'contents': [ { 'type': 'file', 'name': 'file',\n"
2162fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]}]\n"
2163fc51490bSJonas Devlieghere "}",
2164fc51490bSJonas Devlieghere Lower);
216538ac4093SArchibald Elliott ASSERT_NE(nullptr, FS.get());
2166fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError());
2167fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError());
2168fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError());
2169fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError());
2170fc51490bSJonas Devlieghere
2171fc51490bSJonas Devlieghere // at the end
2172fc51490bSJonas Devlieghere FS = getFromYAMLString(
2173fc51490bSJonas Devlieghere "{ 'roots': [\n"
2174fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': '//root/',\n"
2175fc51490bSJonas Devlieghere " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
2176fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]}]\n"
2177fc51490bSJonas Devlieghere "}",
2178fc51490bSJonas Devlieghere Lower);
217938ac4093SArchibald Elliott ASSERT_NE(nullptr, FS.get());
2180fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError());
2181fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError());
2182fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError());
2183fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError());
2184fc51490bSJonas Devlieghere }
2185fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,TrailingSlashes)2186fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, TrailingSlashes) {
2187fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
2188fc51490bSJonas Devlieghere Lower->addRegularFile("//root/other");
2189fc51490bSJonas Devlieghere
2190fc51490bSJonas Devlieghere // file in roots
2191fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
2192fc51490bSJonas Devlieghere "{ 'roots': [\n"
2193fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': '//root/path/to////',\n"
2194fc51490bSJonas Devlieghere " 'contents': [ { 'type': 'file', 'name': 'file',\n"
2195fc51490bSJonas Devlieghere " 'external-contents': '//root/other' }]}]\n"
2196fc51490bSJonas Devlieghere "}",
2197fc51490bSJonas Devlieghere Lower);
219838ac4093SArchibald Elliott ASSERT_NE(nullptr, FS.get());
2199fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to/file").getError());
2200fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path/to").getError());
2201fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/path").getError());
2202fc51490bSJonas Devlieghere EXPECT_FALSE(FS->status("//root/").getError());
2203fc51490bSJonas Devlieghere }
2204fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,DirectoryIteration)2205fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, DirectoryIteration) {
2206fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
2207fc51490bSJonas Devlieghere Lower->addDirectory("//root/");
2208fc51490bSJonas Devlieghere Lower->addDirectory("//root/foo");
2209fc51490bSJonas Devlieghere Lower->addDirectory("//root/foo/bar");
2210fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/a");
2211fc51490bSJonas Devlieghere Lower->addRegularFile("//root/foo/bar/b");
2212fc51490bSJonas Devlieghere Lower->addRegularFile("//root/file3");
2213fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
2214fc51490bSJonas Devlieghere "{ 'use-external-names': false,\n"
2215fc51490bSJonas Devlieghere " 'roots': [\n"
2216fc51490bSJonas Devlieghere "{\n"
2217fc51490bSJonas Devlieghere " 'type': 'directory',\n"
2218fc51490bSJonas Devlieghere " 'name': '//root/',\n"
2219fc51490bSJonas Devlieghere " 'contents': [ {\n"
2220fc51490bSJonas Devlieghere " 'type': 'file',\n"
2221fc51490bSJonas Devlieghere " 'name': 'file1',\n"
2222fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/a'\n"
2223fc51490bSJonas Devlieghere " },\n"
2224fc51490bSJonas Devlieghere " {\n"
2225fc51490bSJonas Devlieghere " 'type': 'file',\n"
2226fc51490bSJonas Devlieghere " 'name': 'file2',\n"
2227fc51490bSJonas Devlieghere " 'external-contents': '//root/foo/bar/b'\n"
2228fc51490bSJonas Devlieghere " }\n"
2229fc51490bSJonas Devlieghere " ]\n"
2230fc51490bSJonas Devlieghere "}\n"
2231fc51490bSJonas Devlieghere "]\n"
2232fc51490bSJonas Devlieghere "}",
2233fc51490bSJonas Devlieghere Lower);
223438ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
2235fc51490bSJonas Devlieghere
2236fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
2237fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
2238fc51490bSJonas Devlieghere O->pushOverlay(FS);
2239fc51490bSJonas Devlieghere
2240fc51490bSJonas Devlieghere std::error_code EC;
2241fc51490bSJonas Devlieghere checkContents(O->dir_begin("//root/", EC),
2242fc51490bSJonas Devlieghere {"//root/file1", "//root/file2", "//root/file3", "//root/foo"});
2243fc51490bSJonas Devlieghere
2244fc51490bSJonas Devlieghere checkContents(O->dir_begin("//root/foo/bar", EC),
2245fc51490bSJonas Devlieghere {"//root/foo/bar/a", "//root/foo/bar/b"});
2246fc51490bSJonas Devlieghere }
2247fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,DirectoryIterationSameDirMultipleEntries)2248fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, DirectoryIterationSameDirMultipleEntries) {
2249fc51490bSJonas Devlieghere // https://llvm.org/bugs/show_bug.cgi?id=27725
2250fc51490bSJonas Devlieghere if (!supportsSameDirMultipleYAMLEntries())
22516aa8a836SPaul Robinson GTEST_SKIP();
2252fc51490bSJonas Devlieghere
2253fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
2254fc51490bSJonas Devlieghere Lower->addDirectory("//root/zab");
2255fc51490bSJonas Devlieghere Lower->addDirectory("//root/baz");
2256fc51490bSJonas Devlieghere Lower->addRegularFile("//root/zab/a");
2257fc51490bSJonas Devlieghere Lower->addRegularFile("//root/zab/b");
2258fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
2259fc51490bSJonas Devlieghere "{ 'use-external-names': false,\n"
2260fc51490bSJonas Devlieghere " 'roots': [\n"
2261fc51490bSJonas Devlieghere "{\n"
2262fc51490bSJonas Devlieghere " 'type': 'directory',\n"
2263fc51490bSJonas Devlieghere " 'name': '//root/baz/',\n"
2264fc51490bSJonas Devlieghere " 'contents': [ {\n"
2265fc51490bSJonas Devlieghere " 'type': 'file',\n"
2266fc51490bSJonas Devlieghere " 'name': 'x',\n"
2267fc51490bSJonas Devlieghere " 'external-contents': '//root/zab/a'\n"
2268fc51490bSJonas Devlieghere " }\n"
2269fc51490bSJonas Devlieghere " ]\n"
2270fc51490bSJonas Devlieghere "},\n"
2271fc51490bSJonas Devlieghere "{\n"
2272fc51490bSJonas Devlieghere " 'type': 'directory',\n"
2273fc51490bSJonas Devlieghere " 'name': '//root/baz/',\n"
2274fc51490bSJonas Devlieghere " 'contents': [ {\n"
2275fc51490bSJonas Devlieghere " 'type': 'file',\n"
2276fc51490bSJonas Devlieghere " 'name': 'y',\n"
2277fc51490bSJonas Devlieghere " 'external-contents': '//root/zab/b'\n"
2278fc51490bSJonas Devlieghere " }\n"
2279fc51490bSJonas Devlieghere " ]\n"
2280fc51490bSJonas Devlieghere "}\n"
2281fc51490bSJonas Devlieghere "]\n"
2282fc51490bSJonas Devlieghere "}",
2283fc51490bSJonas Devlieghere Lower);
228438ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
2285fc51490bSJonas Devlieghere
2286fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
2287fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
2288fc51490bSJonas Devlieghere O->pushOverlay(FS);
2289fc51490bSJonas Devlieghere
2290fc51490bSJonas Devlieghere std::error_code EC;
2291fc51490bSJonas Devlieghere
2292fc51490bSJonas Devlieghere checkContents(O->dir_begin("//root/baz/", EC),
2293fc51490bSJonas Devlieghere {"//root/baz/x", "//root/baz/y"});
2294fc51490bSJonas Devlieghere }
2295fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,RecursiveDirectoryIterationLevel)2296fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, RecursiveDirectoryIterationLevel) {
2297fc51490bSJonas Devlieghere
2298fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
2299fc51490bSJonas Devlieghere Lower->addDirectory("//root/a");
2300fc51490bSJonas Devlieghere Lower->addDirectory("//root/a/b");
2301fc51490bSJonas Devlieghere Lower->addDirectory("//root/a/b/c");
2302fc51490bSJonas Devlieghere Lower->addRegularFile("//root/a/b/c/file");
2303fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
2304fc51490bSJonas Devlieghere "{ 'use-external-names': false,\n"
2305fc51490bSJonas Devlieghere " 'roots': [\n"
2306fc51490bSJonas Devlieghere "{\n"
2307fc51490bSJonas Devlieghere " 'type': 'directory',\n"
2308fc51490bSJonas Devlieghere " 'name': '//root/a/b/c/',\n"
2309fc51490bSJonas Devlieghere " 'contents': [ {\n"
2310fc51490bSJonas Devlieghere " 'type': 'file',\n"
2311fc51490bSJonas Devlieghere " 'name': 'file',\n"
2312fc51490bSJonas Devlieghere " 'external-contents': '//root/a/b/c/file'\n"
2313fc51490bSJonas Devlieghere " }\n"
2314fc51490bSJonas Devlieghere " ]\n"
2315fc51490bSJonas Devlieghere "},\n"
2316fc51490bSJonas Devlieghere "]\n"
2317fc51490bSJonas Devlieghere "}",
2318fc51490bSJonas Devlieghere Lower);
231938ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
2320fc51490bSJonas Devlieghere
2321fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
2322fc51490bSJonas Devlieghere new vfs::OverlayFileSystem(Lower));
2323fc51490bSJonas Devlieghere O->pushOverlay(FS);
2324fc51490bSJonas Devlieghere
2325fc51490bSJonas Devlieghere std::error_code EC;
2326fc51490bSJonas Devlieghere
2327fc51490bSJonas Devlieghere // Test recursive_directory_iterator level()
2328fc51490bSJonas Devlieghere vfs::recursive_directory_iterator I = vfs::recursive_directory_iterator(
2329fc51490bSJonas Devlieghere *O, "//root", EC),
2330fc51490bSJonas Devlieghere E;
2331fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
2332fc51490bSJonas Devlieghere for (int l = 0; I != E; I.increment(EC), ++l) {
2333fc51490bSJonas Devlieghere ASSERT_FALSE(EC);
2334fc51490bSJonas Devlieghere EXPECT_EQ(I.level(), l);
2335fc51490bSJonas Devlieghere }
2336fc51490bSJonas Devlieghere EXPECT_EQ(I, E);
2337fc51490bSJonas Devlieghere }
2338fc51490bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,RelativePaths)2339fc51490bSJonas Devlieghere TEST_F(VFSFromYAMLTest, RelativePaths) {
2340fc51490bSJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
23414f61749eSRichard Howell std::error_code EC;
23424f61749eSRichard Howell SmallString<128> CWD;
23434f61749eSRichard Howell EC = llvm::sys::fs::current_path(CWD);
23444f61749eSRichard Howell ASSERT_FALSE(EC);
23454f61749eSRichard Howell
2346fc51490bSJonas Devlieghere // Filename at root level without a parent directory.
2347fc51490bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
2348fc51490bSJonas Devlieghere "{ 'roots': [\n"
2349fc51490bSJonas Devlieghere " { 'type': 'file', 'name': 'file-not-in-directory.h',\n"
2350fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n"
2351fc51490bSJonas Devlieghere " }\n"
2352fc51490bSJonas Devlieghere "] }",
2353fc51490bSJonas Devlieghere Lower);
23544f61749eSRichard Howell ASSERT_TRUE(FS.get() != nullptr);
23554f61749eSRichard Howell SmallString<128> ExpectedPathNotInDir("file-not-in-directory.h");
23564f61749eSRichard Howell llvm::sys::fs::make_absolute(ExpectedPathNotInDir);
23574f61749eSRichard Howell checkContents(FS->dir_begin(CWD, EC), {ExpectedPathNotInDir});
2358fc51490bSJonas Devlieghere
2359fc51490bSJonas Devlieghere // Relative file path.
2360fc51490bSJonas Devlieghere FS = getFromYAMLString("{ 'roots': [\n"
23614f61749eSRichard Howell " { 'type': 'file', 'name': 'relative/path.h',\n"
2362fc51490bSJonas Devlieghere " 'external-contents': '//root/external/file'\n"
2363fc51490bSJonas Devlieghere " }\n"
2364fc51490bSJonas Devlieghere "] }",
2365fc51490bSJonas Devlieghere Lower);
23664f61749eSRichard Howell ASSERT_TRUE(FS.get() != nullptr);
23674f61749eSRichard Howell SmallString<128> Parent("relative");
23684f61749eSRichard Howell llvm::sys::fs::make_absolute(Parent);
23694f61749eSRichard Howell auto I = FS->dir_begin(Parent, EC);
23704f61749eSRichard Howell ASSERT_FALSE(EC);
23714f61749eSRichard Howell // Convert to POSIX path for comparison of windows paths
23724f61749eSRichard Howell ASSERT_EQ("relative/path.h",
23734f61749eSRichard Howell getPosixPath(std::string(I->path().substr(CWD.size() + 1))));
2374fc51490bSJonas Devlieghere
2375fc51490bSJonas Devlieghere // Relative directory path.
2376fc51490bSJonas Devlieghere FS = getFromYAMLString(
2377fc51490bSJonas Devlieghere "{ 'roots': [\n"
2378fc51490bSJonas Devlieghere " { 'type': 'directory', 'name': 'relative/directory/path.h',\n"
2379fc51490bSJonas Devlieghere " 'contents': []\n"
2380fc51490bSJonas Devlieghere " }\n"
2381fc51490bSJonas Devlieghere "] }",
2382fc51490bSJonas Devlieghere Lower);
23834f61749eSRichard Howell ASSERT_TRUE(FS.get() != nullptr);
23844f61749eSRichard Howell SmallString<128> Root("relative/directory");
23854f61749eSRichard Howell llvm::sys::fs::make_absolute(Root);
23864f61749eSRichard Howell I = FS->dir_begin(Root, EC);
23874f61749eSRichard Howell ASSERT_FALSE(EC);
23884f61749eSRichard Howell ASSERT_EQ("path.h", std::string(I->path().substr(Root.size() + 1)));
2389fc51490bSJonas Devlieghere
23904f61749eSRichard Howell EXPECT_EQ(0, NumDiagnostics);
2391fc51490bSJonas Devlieghere }
239291e13164SVolodymyr Sapsai
TEST_F(VFSFromYAMLTest,NonFallthroughDirectoryIteration)239391e13164SVolodymyr Sapsai TEST_F(VFSFromYAMLTest, NonFallthroughDirectoryIteration) {
239491e13164SVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
239591e13164SVolodymyr Sapsai Lower->addDirectory("//root/");
239691e13164SVolodymyr Sapsai Lower->addRegularFile("//root/a");
239791e13164SVolodymyr Sapsai Lower->addRegularFile("//root/b");
239891e13164SVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
239991e13164SVolodymyr Sapsai "{ 'use-external-names': false,\n"
240091e13164SVolodymyr Sapsai " 'fallthrough': false,\n"
240191e13164SVolodymyr Sapsai " 'roots': [\n"
240291e13164SVolodymyr Sapsai "{\n"
240391e13164SVolodymyr Sapsai " 'type': 'directory',\n"
240491e13164SVolodymyr Sapsai " 'name': '//root/',\n"
240591e13164SVolodymyr Sapsai " 'contents': [ {\n"
240691e13164SVolodymyr Sapsai " 'type': 'file',\n"
240791e13164SVolodymyr Sapsai " 'name': 'c',\n"
240891e13164SVolodymyr Sapsai " 'external-contents': '//root/a'\n"
240991e13164SVolodymyr Sapsai " }\n"
241091e13164SVolodymyr Sapsai " ]\n"
241191e13164SVolodymyr Sapsai "}\n"
241291e13164SVolodymyr Sapsai "]\n"
241391e13164SVolodymyr Sapsai "}",
241491e13164SVolodymyr Sapsai Lower);
241538ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
241691e13164SVolodymyr Sapsai
241791e13164SVolodymyr Sapsai std::error_code EC;
241891e13164SVolodymyr Sapsai checkContents(FS->dir_begin("//root/", EC),
241991e13164SVolodymyr Sapsai {"//root/c"});
242091e13164SVolodymyr Sapsai }
242191e13164SVolodymyr Sapsai
TEST_F(VFSFromYAMLTest,DirectoryIterationWithDuplicates)242291e13164SVolodymyr Sapsai TEST_F(VFSFromYAMLTest, DirectoryIterationWithDuplicates) {
242391e13164SVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
242491e13164SVolodymyr Sapsai Lower->addDirectory("//root/");
242591e13164SVolodymyr Sapsai Lower->addRegularFile("//root/a");
242691e13164SVolodymyr Sapsai Lower->addRegularFile("//root/b");
242791e13164SVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
242891e13164SVolodymyr Sapsai "{ 'use-external-names': false,\n"
242991e13164SVolodymyr Sapsai " 'roots': [\n"
243091e13164SVolodymyr Sapsai "{\n"
243191e13164SVolodymyr Sapsai " 'type': 'directory',\n"
243291e13164SVolodymyr Sapsai " 'name': '//root/',\n"
243391e13164SVolodymyr Sapsai " 'contents': [ {\n"
243491e13164SVolodymyr Sapsai " 'type': 'file',\n"
243591e13164SVolodymyr Sapsai " 'name': 'a',\n"
243691e13164SVolodymyr Sapsai " 'external-contents': '//root/a'\n"
243791e13164SVolodymyr Sapsai " }\n"
243891e13164SVolodymyr Sapsai " ]\n"
243991e13164SVolodymyr Sapsai "}\n"
244091e13164SVolodymyr Sapsai "]\n"
244191e13164SVolodymyr Sapsai "}",
244291e13164SVolodymyr Sapsai Lower);
244338ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
244491e13164SVolodymyr Sapsai
244591e13164SVolodymyr Sapsai std::error_code EC;
244691e13164SVolodymyr Sapsai checkContents(FS->dir_begin("//root/", EC),
244791e13164SVolodymyr Sapsai {"//root/a", "//root/b"});
244891e13164SVolodymyr Sapsai }
244991e13164SVolodymyr Sapsai
TEST_F(VFSFromYAMLTest,DirectoryIterationErrorInVFSLayer)245091e13164SVolodymyr Sapsai TEST_F(VFSFromYAMLTest, DirectoryIterationErrorInVFSLayer) {
245191e13164SVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
245291e13164SVolodymyr Sapsai Lower->addDirectory("//root/");
245391e13164SVolodymyr Sapsai Lower->addDirectory("//root/foo");
245491e13164SVolodymyr Sapsai Lower->addRegularFile("//root/foo/a");
245591e13164SVolodymyr Sapsai Lower->addRegularFile("//root/foo/b");
245691e13164SVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
245791e13164SVolodymyr Sapsai "{ 'use-external-names': false,\n"
245891e13164SVolodymyr Sapsai " 'roots': [\n"
245991e13164SVolodymyr Sapsai "{\n"
246091e13164SVolodymyr Sapsai " 'type': 'directory',\n"
246191e13164SVolodymyr Sapsai " 'name': '//root/',\n"
246291e13164SVolodymyr Sapsai " 'contents': [ {\n"
246391e13164SVolodymyr Sapsai " 'type': 'file',\n"
246491e13164SVolodymyr Sapsai " 'name': 'bar/a',\n"
246591e13164SVolodymyr Sapsai " 'external-contents': '//root/foo/a'\n"
246691e13164SVolodymyr Sapsai " }\n"
246791e13164SVolodymyr Sapsai " ]\n"
246891e13164SVolodymyr Sapsai "}\n"
246991e13164SVolodymyr Sapsai "]\n"
247091e13164SVolodymyr Sapsai "}",
247191e13164SVolodymyr Sapsai Lower);
247238ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
247391e13164SVolodymyr Sapsai
247491e13164SVolodymyr Sapsai std::error_code EC;
247591e13164SVolodymyr Sapsai checkContents(FS->dir_begin("//root/foo", EC),
247691e13164SVolodymyr Sapsai {"//root/foo/a", "//root/foo/b"});
247791e13164SVolodymyr Sapsai }
24787610033fSVolodymyr Sapsai
TEST_F(VFSFromYAMLTest,GetRealPath)24797610033fSVolodymyr Sapsai TEST_F(VFSFromYAMLTest, GetRealPath) {
24807610033fSVolodymyr Sapsai IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
2481ab73426cSVolodymyr Sapsai Lower->addDirectory("//dir/");
24827610033fSVolodymyr Sapsai Lower->addRegularFile("/foo");
24837610033fSVolodymyr Sapsai Lower->addSymlink("/link");
24847610033fSVolodymyr Sapsai IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
24857610033fSVolodymyr Sapsai "{ 'use-external-names': false,\n"
24867610033fSVolodymyr Sapsai " 'roots': [\n"
24877610033fSVolodymyr Sapsai "{\n"
24887610033fSVolodymyr Sapsai " 'type': 'directory',\n"
2489ab73426cSVolodymyr Sapsai " 'name': '//root/',\n"
24907610033fSVolodymyr Sapsai " 'contents': [ {\n"
24917610033fSVolodymyr Sapsai " 'type': 'file',\n"
24927610033fSVolodymyr Sapsai " 'name': 'bar',\n"
24937610033fSVolodymyr Sapsai " 'external-contents': '/link'\n"
24947610033fSVolodymyr Sapsai " }\n"
24957610033fSVolodymyr Sapsai " ]\n"
24967610033fSVolodymyr Sapsai "},\n"
24977610033fSVolodymyr Sapsai "{\n"
24987610033fSVolodymyr Sapsai " 'type': 'directory',\n"
2499ab73426cSVolodymyr Sapsai " 'name': '//dir/',\n"
25007610033fSVolodymyr Sapsai " 'contents': []\n"
25017610033fSVolodymyr Sapsai "}\n"
25027610033fSVolodymyr Sapsai "]\n"
25037610033fSVolodymyr Sapsai "}",
25047610033fSVolodymyr Sapsai Lower);
250538ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
25067610033fSVolodymyr Sapsai
25077610033fSVolodymyr Sapsai // Regular file present in underlying file system.
25087610033fSVolodymyr Sapsai SmallString<16> RealPath;
25097610033fSVolodymyr Sapsai EXPECT_FALSE(FS->getRealPath("/foo", RealPath));
25107610033fSVolodymyr Sapsai EXPECT_EQ(RealPath.str(), "/foo");
25117610033fSVolodymyr Sapsai
25127610033fSVolodymyr Sapsai // File present in YAML pointing to symlink in underlying file system.
2513ab73426cSVolodymyr Sapsai EXPECT_FALSE(FS->getRealPath("//root/bar", RealPath));
25147610033fSVolodymyr Sapsai EXPECT_EQ(RealPath.str(), "/symlink");
25157610033fSVolodymyr Sapsai
25167610033fSVolodymyr Sapsai // Directories should fall back to the underlying file system is possible.
2517ab73426cSVolodymyr Sapsai EXPECT_FALSE(FS->getRealPath("//dir/", RealPath));
2518ab73426cSVolodymyr Sapsai EXPECT_EQ(RealPath.str(), "//dir/");
25197610033fSVolodymyr Sapsai
25207610033fSVolodymyr Sapsai // Try a non-existing file.
25217610033fSVolodymyr Sapsai EXPECT_EQ(FS->getRealPath("/non_existing", RealPath),
25227610033fSVolodymyr Sapsai errc::no_such_file_or_directory);
25237610033fSVolodymyr Sapsai }
252421703543SJonas Devlieghere
TEST_F(VFSFromYAMLTest,WorkingDirectory)252521703543SJonas Devlieghere TEST_F(VFSFromYAMLTest, WorkingDirectory) {
252621703543SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
252721703543SJonas Devlieghere Lower->addDirectory("//root/");
252821703543SJonas Devlieghere Lower->addDirectory("//root/foo");
252921703543SJonas Devlieghere Lower->addRegularFile("//root/foo/a");
253021703543SJonas Devlieghere Lower->addRegularFile("//root/foo/b");
253121703543SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
253221703543SJonas Devlieghere "{ 'use-external-names': false,\n"
253321703543SJonas Devlieghere " 'roots': [\n"
253421703543SJonas Devlieghere "{\n"
253521703543SJonas Devlieghere " 'type': 'directory',\n"
253621703543SJonas Devlieghere " 'name': '//root/bar',\n"
253721703543SJonas Devlieghere " 'contents': [ {\n"
253821703543SJonas Devlieghere " 'type': 'file',\n"
253921703543SJonas Devlieghere " 'name': 'a',\n"
254021703543SJonas Devlieghere " 'external-contents': '//root/foo/a'\n"
254121703543SJonas Devlieghere " }\n"
254221703543SJonas Devlieghere " ]\n"
254321703543SJonas Devlieghere "}\n"
254421703543SJonas Devlieghere "]\n"
254521703543SJonas Devlieghere "}",
254621703543SJonas Devlieghere Lower);
254738ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
254821703543SJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/bar");
254921703543SJonas Devlieghere ASSERT_FALSE(EC);
255021703543SJonas Devlieghere
255121703543SJonas Devlieghere llvm::ErrorOr<std::string> WorkingDir = FS->getCurrentWorkingDirectory();
255221703543SJonas Devlieghere ASSERT_TRUE(WorkingDir);
255321703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/bar");
255421703543SJonas Devlieghere
255521703543SJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("./a");
255621703543SJonas Devlieghere ASSERT_FALSE(Status.getError());
255721703543SJonas Devlieghere EXPECT_TRUE(Status->isStatusKnown());
255821703543SJonas Devlieghere EXPECT_FALSE(Status->isDirectory());
255921703543SJonas Devlieghere EXPECT_TRUE(Status->isRegularFile());
256021703543SJonas Devlieghere EXPECT_FALSE(Status->isSymlink());
256121703543SJonas Devlieghere EXPECT_FALSE(Status->isOther());
256221703543SJonas Devlieghere EXPECT_TRUE(Status->exists());
256321703543SJonas Devlieghere
256421703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("bogus");
256521703543SJonas Devlieghere ASSERT_TRUE(EC);
256621703543SJonas Devlieghere WorkingDir = FS->getCurrentWorkingDirectory();
256721703543SJonas Devlieghere ASSERT_TRUE(WorkingDir);
256821703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/bar");
256921703543SJonas Devlieghere
257021703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/");
257121703543SJonas Devlieghere ASSERT_FALSE(EC);
257221703543SJonas Devlieghere WorkingDir = FS->getCurrentWorkingDirectory();
257321703543SJonas Devlieghere ASSERT_TRUE(WorkingDir);
257421703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/");
257521703543SJonas Devlieghere
257621703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("bar");
257721703543SJonas Devlieghere ASSERT_FALSE(EC);
257821703543SJonas Devlieghere WorkingDir = FS->getCurrentWorkingDirectory();
257921703543SJonas Devlieghere ASSERT_TRUE(WorkingDir);
258021703543SJonas Devlieghere EXPECT_EQ(*WorkingDir, "//root/bar");
258121703543SJonas Devlieghere }
258221703543SJonas Devlieghere
TEST_F(VFSFromYAMLTest,WorkingDirectoryFallthrough)258321703543SJonas Devlieghere TEST_F(VFSFromYAMLTest, WorkingDirectoryFallthrough) {
258421703543SJonas Devlieghere IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
258521703543SJonas Devlieghere Lower->addDirectory("//root/");
258621703543SJonas Devlieghere Lower->addDirectory("//root/foo");
258721703543SJonas Devlieghere Lower->addRegularFile("//root/foo/a");
258821703543SJonas Devlieghere Lower->addRegularFile("//root/foo/b");
258921703543SJonas Devlieghere Lower->addRegularFile("//root/c");
259021703543SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
259121703543SJonas Devlieghere "{ 'use-external-names': false,\n"
259221703543SJonas Devlieghere " 'roots': [\n"
259321703543SJonas Devlieghere "{\n"
259421703543SJonas Devlieghere " 'type': 'directory',\n"
259521703543SJonas Devlieghere " 'name': '//root/bar',\n"
259621703543SJonas Devlieghere " 'contents': [ {\n"
259721703543SJonas Devlieghere " 'type': 'file',\n"
259821703543SJonas Devlieghere " 'name': 'a',\n"
259921703543SJonas Devlieghere " 'external-contents': '//root/foo/a'\n"
260021703543SJonas Devlieghere " }\n"
260121703543SJonas Devlieghere " ]\n"
2602f2f77499SJonas Devlieghere "},\n"
2603f2f77499SJonas Devlieghere "{\n"
2604f2f77499SJonas Devlieghere " 'type': 'directory',\n"
2605f2f77499SJonas Devlieghere " 'name': '//root/bar/baz',\n"
2606f2f77499SJonas Devlieghere " 'contents': [ {\n"
2607f2f77499SJonas Devlieghere " 'type': 'file',\n"
2608f2f77499SJonas Devlieghere " 'name': 'a',\n"
2609f2f77499SJonas Devlieghere " 'external-contents': '//root/foo/a'\n"
2610f2f77499SJonas Devlieghere " }\n"
2611f2f77499SJonas Devlieghere " ]\n"
261221703543SJonas Devlieghere "}\n"
261321703543SJonas Devlieghere "]\n"
261421703543SJonas Devlieghere "}",
261521703543SJonas Devlieghere Lower);
261638ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
261721703543SJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/");
261821703543SJonas Devlieghere ASSERT_FALSE(EC);
261938ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
262021703543SJonas Devlieghere
262121703543SJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("bar/a");
262221703543SJonas Devlieghere ASSERT_FALSE(Status.getError());
262321703543SJonas Devlieghere EXPECT_TRUE(Status->exists());
262421703543SJonas Devlieghere
262521703543SJonas Devlieghere Status = FS->status("foo/a");
262621703543SJonas Devlieghere ASSERT_FALSE(Status.getError());
262721703543SJonas Devlieghere EXPECT_TRUE(Status->exists());
262821703543SJonas Devlieghere
262921703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/bar");
263021703543SJonas Devlieghere ASSERT_FALSE(EC);
263121703543SJonas Devlieghere
263221703543SJonas Devlieghere Status = FS->status("./a");
263321703543SJonas Devlieghere ASSERT_FALSE(Status.getError());
263421703543SJonas Devlieghere EXPECT_TRUE(Status->exists());
263521703543SJonas Devlieghere
263621703543SJonas Devlieghere Status = FS->status("./b");
263721703543SJonas Devlieghere ASSERT_TRUE(Status.getError());
263821703543SJonas Devlieghere
263921703543SJonas Devlieghere Status = FS->status("./c");
264021703543SJonas Devlieghere ASSERT_TRUE(Status.getError());
264121703543SJonas Devlieghere
264221703543SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/");
264321703543SJonas Devlieghere ASSERT_FALSE(EC);
264421703543SJonas Devlieghere
264521703543SJonas Devlieghere Status = FS->status("c");
264621703543SJonas Devlieghere ASSERT_FALSE(Status.getError());
264721703543SJonas Devlieghere EXPECT_TRUE(Status->exists());
2648f2f77499SJonas Devlieghere
2649f2f77499SJonas Devlieghere Status = FS->status("./bar/baz/a");
2650f2f77499SJonas Devlieghere ASSERT_FALSE(Status.getError());
2651f2f77499SJonas Devlieghere EXPECT_TRUE(Status->exists());
2652f2f77499SJonas Devlieghere
2653f2f77499SJonas Devlieghere EC = FS->setCurrentWorkingDirectory("//root/bar");
2654f2f77499SJonas Devlieghere ASSERT_FALSE(EC);
2655f2f77499SJonas Devlieghere
2656f2f77499SJonas Devlieghere Status = FS->status("./baz/a");
2657f2f77499SJonas Devlieghere ASSERT_FALSE(Status.getError());
2658f2f77499SJonas Devlieghere EXPECT_TRUE(Status->exists());
2659f2f77499SJonas Devlieghere
2660f2f77499SJonas Devlieghere Status = FS->status("../bar/baz/a");
2661f2f77499SJonas Devlieghere ASSERT_FALSE(Status.getError());
2662f2f77499SJonas Devlieghere EXPECT_TRUE(Status->exists());
266321703543SJonas Devlieghere }
266421703543SJonas Devlieghere
TEST_F(VFSFromYAMLTest,WorkingDirectoryFallthroughInvalid)266521703543SJonas Devlieghere TEST_F(VFSFromYAMLTest, WorkingDirectoryFallthroughInvalid) {
266621703543SJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem());
266721703543SJonas Devlieghere Lower->addDirectory("//root/");
266821703543SJonas Devlieghere Lower->addDirectory("//root/foo");
266921703543SJonas Devlieghere Lower->addRegularFile("//root/foo/a");
267021703543SJonas Devlieghere Lower->addRegularFile("//root/foo/b");
267121703543SJonas Devlieghere Lower->addRegularFile("//root/c");
267221703543SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
267321703543SJonas Devlieghere "{ 'use-external-names': false,\n"
267421703543SJonas Devlieghere " 'roots': [\n"
267521703543SJonas Devlieghere "{\n"
267621703543SJonas Devlieghere " 'type': 'directory',\n"
267721703543SJonas Devlieghere " 'name': '//root/bar',\n"
267821703543SJonas Devlieghere " 'contents': [ {\n"
267921703543SJonas Devlieghere " 'type': 'file',\n"
268021703543SJonas Devlieghere " 'name': 'a',\n"
268121703543SJonas Devlieghere " 'external-contents': '//root/foo/a'\n"
268221703543SJonas Devlieghere " }\n"
268321703543SJonas Devlieghere " ]\n"
268421703543SJonas Devlieghere "}\n"
268521703543SJonas Devlieghere "]\n"
268621703543SJonas Devlieghere "}",
268721703543SJonas Devlieghere Lower);
268838ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
268921703543SJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/");
269021703543SJonas Devlieghere ASSERT_FALSE(EC);
269138ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
269221703543SJonas Devlieghere
269321703543SJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("bar/a");
269421703543SJonas Devlieghere ASSERT_FALSE(Status.getError());
269521703543SJonas Devlieghere EXPECT_TRUE(Status->exists());
269621703543SJonas Devlieghere
269721703543SJonas Devlieghere Status = FS->status("foo/a");
26980be9ca7cSJonas Devlieghere ASSERT_FALSE(Status.getError());
26990be9ca7cSJonas Devlieghere EXPECT_TRUE(Status->exists());
27000be9ca7cSJonas Devlieghere }
27010be9ca7cSJonas Devlieghere
TEST_F(VFSFromYAMLTest,VirtualWorkingDirectory)27020be9ca7cSJonas Devlieghere TEST_F(VFSFromYAMLTest, VirtualWorkingDirectory) {
27030be9ca7cSJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem());
27040be9ca7cSJonas Devlieghere Lower->addDirectory("//root/");
27050be9ca7cSJonas Devlieghere Lower->addDirectory("//root/foo");
27060be9ca7cSJonas Devlieghere Lower->addRegularFile("//root/foo/a");
27070be9ca7cSJonas Devlieghere Lower->addRegularFile("//root/foo/b");
27080be9ca7cSJonas Devlieghere Lower->addRegularFile("//root/c");
27090be9ca7cSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
27100be9ca7cSJonas Devlieghere "{ 'use-external-names': false,\n"
27110be9ca7cSJonas Devlieghere " 'roots': [\n"
27120be9ca7cSJonas Devlieghere "{\n"
27130be9ca7cSJonas Devlieghere " 'type': 'directory',\n"
27140be9ca7cSJonas Devlieghere " 'name': '//root/bar',\n"
27150be9ca7cSJonas Devlieghere " 'contents': [ {\n"
27160be9ca7cSJonas Devlieghere " 'type': 'file',\n"
27170be9ca7cSJonas Devlieghere " 'name': 'a',\n"
27180be9ca7cSJonas Devlieghere " 'external-contents': '//root/foo/a'\n"
27190be9ca7cSJonas Devlieghere " }\n"
27200be9ca7cSJonas Devlieghere " ]\n"
27210be9ca7cSJonas Devlieghere "}\n"
27220be9ca7cSJonas Devlieghere "]\n"
27230be9ca7cSJonas Devlieghere "}",
27240be9ca7cSJonas Devlieghere Lower);
272538ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
27260be9ca7cSJonas Devlieghere std::error_code EC = FS->setCurrentWorkingDirectory("//root/bar");
27270be9ca7cSJonas Devlieghere ASSERT_FALSE(EC);
272838ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
27290be9ca7cSJonas Devlieghere
27300be9ca7cSJonas Devlieghere llvm::ErrorOr<vfs::Status> Status = FS->status("a");
27310be9ca7cSJonas Devlieghere ASSERT_FALSE(Status.getError());
27320be9ca7cSJonas Devlieghere EXPECT_TRUE(Status->exists());
273321703543SJonas Devlieghere }
273442df3e29SJonas Devlieghere
TEST_F(VFSFromYAMLTest,YAMLVFSWriterTest)273542df3e29SJonas Devlieghere TEST_F(VFSFromYAMLTest, YAMLVFSWriterTest) {
2736fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
2737fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a"));
2738fad75598SSergej Jaskiewicz TempFile _ab(TestDirectory.path("a, b"));
2739fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c"));
2740fad75598SSergej Jaskiewicz TempFile _cd(TestDirectory.path("c/d"));
2741fad75598SSergej Jaskiewicz TempDir _e(TestDirectory.path("e"));
2742fad75598SSergej Jaskiewicz TempDir _ef(TestDirectory.path("e/f"));
2743fad75598SSergej Jaskiewicz TempFile _g(TestDirectory.path("g"));
2744fad75598SSergej Jaskiewicz TempDir _h(TestDirectory.path("h"));
274542df3e29SJonas Devlieghere
274642df3e29SJonas Devlieghere vfs::YAMLVFSWriter VFSWriter;
2747fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a");
2748fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ab.path(), "//root/a/b");
2749fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_cd.path(), "//root/c/d");
2750fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_e.path(), "//root/e");
2751fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ef.path(), "//root/e/f");
2752fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_g.path(), "//root/g");
2753fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_h.path(), "//root/h");
275442df3e29SJonas Devlieghere
275542df3e29SJonas Devlieghere std::string Buffer;
275642df3e29SJonas Devlieghere raw_string_ostream OS(Buffer);
275742df3e29SJonas Devlieghere VFSWriter.write(OS);
275842df3e29SJonas Devlieghere OS.flush();
275942df3e29SJonas Devlieghere
276042df3e29SJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem());
276142df3e29SJonas Devlieghere Lower->addDirectory("//root/");
276242df3e29SJonas Devlieghere Lower->addDirectory("//root/a");
276342df3e29SJonas Devlieghere Lower->addRegularFile("//root/a/b");
276442df3e29SJonas Devlieghere Lower->addDirectory("//root/b");
276542df3e29SJonas Devlieghere Lower->addDirectory("//root/c");
276642df3e29SJonas Devlieghere Lower->addRegularFile("//root/c/d");
276742df3e29SJonas Devlieghere Lower->addDirectory("//root/e");
276842df3e29SJonas Devlieghere Lower->addDirectory("//root/e/f");
27695c145034SJan Korous Lower->addRegularFile("//root/g");
27705c145034SJan Korous Lower->addDirectory("//root/h");
277142df3e29SJonas Devlieghere
277242df3e29SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower);
277338ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
277442df3e29SJonas Devlieghere
2775fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_a.path()));
2776fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_ab.path()));
2777fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_c.path()));
2778fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_cd.path()));
2779fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_e.path()));
2780fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_ef.path()));
2781fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_g.path()));
2782fad75598SSergej Jaskiewicz EXPECT_TRUE(FS->exists(_h.path()));
278342df3e29SJonas Devlieghere }
2784c0330bc0SJan Korous
TEST_F(VFSFromYAMLTest,YAMLVFSWriterTest2)278559ba19c5SJonas Devlieghere TEST_F(VFSFromYAMLTest, YAMLVFSWriterTest2) {
2786fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
2787fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a"));
2788fad75598SSergej Jaskiewicz TempFile _ab(TestDirectory.path("a/b"));
2789fad75598SSergej Jaskiewicz TempDir _ac(TestDirectory.path("a/c"));
2790fad75598SSergej Jaskiewicz TempFile _acd(TestDirectory.path("a/c/d"));
2791fad75598SSergej Jaskiewicz TempFile _ace(TestDirectory.path("a/c/e"));
2792fad75598SSergej Jaskiewicz TempFile _acf(TestDirectory.path("a/c/f"));
2793fad75598SSergej Jaskiewicz TempDir _ag(TestDirectory.path("a/g"));
2794fad75598SSergej Jaskiewicz TempFile _agh(TestDirectory.path("a/g/h"));
279559ba19c5SJonas Devlieghere
279659ba19c5SJonas Devlieghere vfs::YAMLVFSWriter VFSWriter;
2797fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a");
2798fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ab.path(), "//root/a/b");
2799fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ac.path(), "//root/a/c");
2800fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acd.path(), "//root/a/c/d");
2801fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ace.path(), "//root/a/c/e");
2802fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acf.path(), "//root/a/c/f");
2803fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ag.path(), "//root/a/g");
2804fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_agh.path(), "//root/a/g/h");
280559ba19c5SJonas Devlieghere
280659ba19c5SJonas Devlieghere std::string Buffer;
280759ba19c5SJonas Devlieghere raw_string_ostream OS(Buffer);
280859ba19c5SJonas Devlieghere VFSWriter.write(OS);
280959ba19c5SJonas Devlieghere OS.flush();
281059ba19c5SJonas Devlieghere
281159ba19c5SJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem());
281259ba19c5SJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower);
281338ac4093SArchibald Elliott EXPECT_NE(FS.get(), nullptr);
281459ba19c5SJonas Devlieghere }
281559ba19c5SJonas Devlieghere
TEST_F(VFSFromYAMLTest,YAMLVFSWriterTest3)281658bc507bSJonas Devlieghere TEST_F(VFSFromYAMLTest, YAMLVFSWriterTest3) {
2817fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
2818fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a"));
2819fad75598SSergej Jaskiewicz TempFile _ab(TestDirectory.path("a/b"));
2820fad75598SSergej Jaskiewicz TempDir _ac(TestDirectory.path("a/c"));
2821fad75598SSergej Jaskiewicz TempDir _acd(TestDirectory.path("a/c/d"));
2822fad75598SSergej Jaskiewicz TempDir _acde(TestDirectory.path("a/c/d/e"));
2823fad75598SSergej Jaskiewicz TempFile _acdef(TestDirectory.path("a/c/d/e/f"));
2824fad75598SSergej Jaskiewicz TempFile _acdeg(TestDirectory.path("a/c/d/e/g"));
2825fad75598SSergej Jaskiewicz TempDir _ah(TestDirectory.path("a/h"));
2826fad75598SSergej Jaskiewicz TempFile _ahi(TestDirectory.path("a/h/i"));
282758bc507bSJonas Devlieghere
282858bc507bSJonas Devlieghere vfs::YAMLVFSWriter VFSWriter;
2829fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a");
2830fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ab.path(), "//root/a/b");
2831fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ac.path(), "//root/a/c");
2832fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_acd.path(), "//root/a/c/d");
2833fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_acde.path(), "//root/a/c/d/e");
2834fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acdef.path(), "//root/a/c/d/e/f");
2835fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_acdeg.path(), "//root/a/c/d/e/g");
2836fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_ahi.path(), "//root/a/h");
2837fad75598SSergej Jaskiewicz VFSWriter.addFileMapping(_ahi.path(), "//root/a/h/i");
283858bc507bSJonas Devlieghere
283958bc507bSJonas Devlieghere std::string Buffer;
284058bc507bSJonas Devlieghere raw_string_ostream OS(Buffer);
284158bc507bSJonas Devlieghere VFSWriter.write(OS);
284258bc507bSJonas Devlieghere OS.flush();
284358bc507bSJonas Devlieghere
284458bc507bSJonas Devlieghere IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem());
284558bc507bSJonas Devlieghere IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower);
284638ac4093SArchibald Elliott EXPECT_NE(FS.get(), nullptr);
284758bc507bSJonas Devlieghere }
284858bc507bSJonas Devlieghere
TEST_F(VFSFromYAMLTest,YAMLVFSWriterTestHandleDirs)2849c0330bc0SJan Korous TEST_F(VFSFromYAMLTest, YAMLVFSWriterTestHandleDirs) {
2850fad75598SSergej Jaskiewicz TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
2851fad75598SSergej Jaskiewicz TempDir _a(TestDirectory.path("a"));
2852fad75598SSergej Jaskiewicz TempDir _b(TestDirectory.path("b"));
2853fad75598SSergej Jaskiewicz TempDir _c(TestDirectory.path("c"));
2854c0330bc0SJan Korous
2855c0330bc0SJan Korous vfs::YAMLVFSWriter VFSWriter;
2856fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_a.path(), "//root/a");
2857fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_b.path(), "//root/b");
2858fad75598SSergej Jaskiewicz VFSWriter.addDirectoryMapping(_c.path(), "//root/c");
2859c0330bc0SJan Korous
2860c0330bc0SJan Korous std::string Buffer;
2861c0330bc0SJan Korous raw_string_ostream OS(Buffer);
2862c0330bc0SJan Korous VFSWriter.write(OS);
2863c0330bc0SJan Korous OS.flush();
2864c0330bc0SJan Korous
2865c0330bc0SJan Korous // We didn't add a single file - only directories.
286638ac4093SArchibald Elliott EXPECT_EQ(Buffer.find("'type': 'file'"), std::string::npos);
2867c0330bc0SJan Korous
2868c0330bc0SJan Korous IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem());
2869c0330bc0SJan Korous Lower->addDirectory("//root/a");
2870c0330bc0SJan Korous Lower->addDirectory("//root/b");
2871c0330bc0SJan Korous Lower->addDirectory("//root/c");
2872c0330bc0SJan Korous // canaries
2873c0330bc0SJan Korous Lower->addRegularFile("//root/a/a");
2874c0330bc0SJan Korous Lower->addRegularFile("//root/b/b");
2875c0330bc0SJan Korous Lower->addRegularFile("//root/c/c");
2876c0330bc0SJan Korous
2877c0330bc0SJan Korous IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLRawString(Buffer, Lower);
287838ac4093SArchibald Elliott ASSERT_NE(FS.get(), nullptr);
2879c0330bc0SJan Korous
2880fad75598SSergej Jaskiewicz EXPECT_FALSE(FS->exists(_a.path("a")));
2881fad75598SSergej Jaskiewicz EXPECT_FALSE(FS->exists(_b.path("b")));
2882fad75598SSergej Jaskiewicz EXPECT_FALSE(FS->exists(_c.path("c")));
2883c0330bc0SJan Korous }
288475cd8d75SDuncan P. N. Exon Smith
TEST_F(VFSFromYAMLTest,RedirectingWith)2885502f14d6SBen Barham TEST_F(VFSFromYAMLTest, RedirectingWith) {
2886502f14d6SBen Barham IntrusiveRefCntPtr<DummyFileSystem> Both(new DummyFileSystem());
2887502f14d6SBen Barham Both->addDirectory("//root/a");
2888502f14d6SBen Barham Both->addRegularFile("//root/a/f");
2889502f14d6SBen Barham Both->addDirectory("//root/b");
2890502f14d6SBen Barham Both->addRegularFile("//root/b/f");
2891502f14d6SBen Barham
2892502f14d6SBen Barham IntrusiveRefCntPtr<DummyFileSystem> AOnly(new DummyFileSystem());
2893502f14d6SBen Barham AOnly->addDirectory("//root/a");
2894502f14d6SBen Barham AOnly->addRegularFile("//root/a/f");
2895502f14d6SBen Barham
2896502f14d6SBen Barham IntrusiveRefCntPtr<DummyFileSystem> BOnly(new DummyFileSystem());
2897502f14d6SBen Barham BOnly->addDirectory("//root/b");
2898502f14d6SBen Barham BOnly->addRegularFile("//root/b/f");
2899502f14d6SBen Barham
2900502f14d6SBen Barham auto BaseStr = std::string(" 'roots': [\n"
2901502f14d6SBen Barham " {\n"
2902502f14d6SBen Barham " 'type': 'directory-remap',\n"
2903502f14d6SBen Barham " 'name': '//root/a',\n"
2904502f14d6SBen Barham " 'external-contents': '//root/b'\n"
2905502f14d6SBen Barham " }\n"
2906502f14d6SBen Barham " ]\n"
2907502f14d6SBen Barham "}");
2908502f14d6SBen Barham auto FallthroughStr = "{ 'redirecting-with': 'fallthrough',\n" + BaseStr;
2909502f14d6SBen Barham auto FallbackStr = "{ 'redirecting-with': 'fallback',\n" + BaseStr;
2910502f14d6SBen Barham auto RedirectOnlyStr = "{ 'redirecting-with': 'redirect-only',\n" + BaseStr;
2911502f14d6SBen Barham
2912502f14d6SBen Barham auto ExpectPath = [&](vfs::FileSystem &FS, StringRef Expected,
2913502f14d6SBen Barham StringRef Message) {
2914502f14d6SBen Barham auto AF = FS.openFileForRead("//root/a/f");
2915502f14d6SBen Barham ASSERT_FALSE(AF.getError()) << Message;
2916502f14d6SBen Barham auto AFName = (*AF)->getName();
2917502f14d6SBen Barham ASSERT_FALSE(AFName.getError()) << Message;
2918502f14d6SBen Barham EXPECT_EQ(Expected.str(), AFName.get()) << Message;
2919502f14d6SBen Barham
2920502f14d6SBen Barham auto AS = FS.status("//root/a/f");
2921502f14d6SBen Barham ASSERT_FALSE(AS.getError()) << Message;
2922502f14d6SBen Barham EXPECT_EQ(Expected.str(), AS->getName()) << Message;
2923502f14d6SBen Barham };
2924502f14d6SBen Barham
2925502f14d6SBen Barham auto ExpectFailure = [&](vfs::FileSystem &FS, StringRef Message) {
2926502f14d6SBen Barham EXPECT_TRUE(FS.openFileForRead("//root/a/f").getError()) << Message;
2927502f14d6SBen Barham EXPECT_TRUE(FS.status("//root/a/f").getError()) << Message;
2928502f14d6SBen Barham };
2929502f14d6SBen Barham
2930502f14d6SBen Barham {
2931502f14d6SBen Barham // `f` in both `a` and `b`
2932502f14d6SBen Barham
2933502f14d6SBen Barham // `fallthrough` tries `external-name` first, so should be `b`
2934502f14d6SBen Barham IntrusiveRefCntPtr<vfs::FileSystem> Fallthrough =
2935502f14d6SBen Barham getFromYAMLString(FallthroughStr, Both);
2936502f14d6SBen Barham ASSERT_TRUE(Fallthrough.get() != nullptr);
2937502f14d6SBen Barham ExpectPath(*Fallthrough, "//root/b/f", "fallthrough, both exist");
2938502f14d6SBen Barham
2939502f14d6SBen Barham // `fallback` tries the original name first, so should be `a`
2940502f14d6SBen Barham IntrusiveRefCntPtr<vfs::FileSystem> Fallback =
2941502f14d6SBen Barham getFromYAMLString(FallbackStr, Both);
2942502f14d6SBen Barham ASSERT_TRUE(Fallback.get() != nullptr);
2943502f14d6SBen Barham ExpectPath(*Fallback, "//root/a/f", "fallback, both exist");
2944502f14d6SBen Barham
2945502f14d6SBen Barham // `redirect-only` is the same as `fallthrough` but doesn't try the
2946502f14d6SBen Barham // original on failure, so no change here (ie. `b`)
2947502f14d6SBen Barham IntrusiveRefCntPtr<vfs::FileSystem> Redirect =
2948502f14d6SBen Barham getFromYAMLString(RedirectOnlyStr, Both);
2949502f14d6SBen Barham ASSERT_TRUE(Redirect.get() != nullptr);
2950502f14d6SBen Barham ExpectPath(*Redirect, "//root/b/f", "redirect-only, both exist");
2951502f14d6SBen Barham }
2952502f14d6SBen Barham
2953502f14d6SBen Barham {
2954502f14d6SBen Barham // `f` in `a` only
2955502f14d6SBen Barham
2956502f14d6SBen Barham // Fallthrough to the original path, `a`
2957502f14d6SBen Barham IntrusiveRefCntPtr<vfs::FileSystem> Fallthrough =
2958502f14d6SBen Barham getFromYAMLString(FallthroughStr, AOnly);
2959502f14d6SBen Barham ASSERT_TRUE(Fallthrough.get() != nullptr);
2960502f14d6SBen Barham ExpectPath(*Fallthrough, "//root/a/f", "fallthrough, a only");
2961502f14d6SBen Barham
2962502f14d6SBen Barham // Original first, so still `a`
2963502f14d6SBen Barham IntrusiveRefCntPtr<vfs::FileSystem> Fallback =
2964502f14d6SBen Barham getFromYAMLString(FallbackStr, AOnly);
2965502f14d6SBen Barham ASSERT_TRUE(Fallback.get() != nullptr);
2966502f14d6SBen Barham ExpectPath(*Fallback, "//root/a/f", "fallback, a only");
2967502f14d6SBen Barham
2968502f14d6SBen Barham // Fails since no fallthrough
2969502f14d6SBen Barham IntrusiveRefCntPtr<vfs::FileSystem> Redirect =
2970502f14d6SBen Barham getFromYAMLString(RedirectOnlyStr, AOnly);
2971502f14d6SBen Barham ASSERT_TRUE(Redirect.get() != nullptr);
2972502f14d6SBen Barham ExpectFailure(*Redirect, "redirect-only, a only");
2973502f14d6SBen Barham }
2974502f14d6SBen Barham
2975502f14d6SBen Barham {
2976502f14d6SBen Barham // `f` in `b` only
2977502f14d6SBen Barham
2978502f14d6SBen Barham // Tries `b` first (no fallthrough)
2979502f14d6SBen Barham IntrusiveRefCntPtr<vfs::FileSystem> Fallthrough =
2980502f14d6SBen Barham getFromYAMLString(FallthroughStr, BOnly);
2981502f14d6SBen Barham ASSERT_TRUE(Fallthrough.get() != nullptr);
2982502f14d6SBen Barham ExpectPath(*Fallthrough, "//root/b/f", "fallthrough, b only");
2983502f14d6SBen Barham
2984502f14d6SBen Barham // Tries original first but then fallsback to `b`
2985502f14d6SBen Barham IntrusiveRefCntPtr<vfs::FileSystem> Fallback =
2986502f14d6SBen Barham getFromYAMLString(FallbackStr, BOnly);
2987502f14d6SBen Barham ASSERT_TRUE(Fallback.get() != nullptr);
2988502f14d6SBen Barham ExpectPath(*Fallback, "//root/b/f", "fallback, b only");
2989502f14d6SBen Barham
2990502f14d6SBen Barham // Redirect exists, so uses it (`b`)
2991502f14d6SBen Barham IntrusiveRefCntPtr<vfs::FileSystem> Redirect =
2992502f14d6SBen Barham getFromYAMLString(RedirectOnlyStr, BOnly);
2993502f14d6SBen Barham ASSERT_TRUE(Redirect.get() != nullptr);
2994502f14d6SBen Barham ExpectPath(*Redirect, "//root/b/f", "redirect-only, b only");
2995502f14d6SBen Barham }
2996502f14d6SBen Barham
2997502f14d6SBen Barham EXPECT_EQ(0, NumDiagnostics);
2998502f14d6SBen Barham }
2999502f14d6SBen Barham
TEST(VFSFromRemappedFilesTest,Basic)300075cd8d75SDuncan P. N. Exon Smith TEST(VFSFromRemappedFilesTest, Basic) {
300175cd8d75SDuncan P. N. Exon Smith IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS =
300275cd8d75SDuncan P. N. Exon Smith new vfs::InMemoryFileSystem;
300375cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/b", 0, MemoryBuffer::getMemBuffer("contents of b"));
300475cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/c", 0, MemoryBuffer::getMemBuffer("contents of c"));
300575cd8d75SDuncan P. N. Exon Smith
300675cd8d75SDuncan P. N. Exon Smith std::vector<std::pair<std::string, std::string>> RemappedFiles = {
300775cd8d75SDuncan P. N. Exon Smith {"//root/a/a", "//root/b"},
300875cd8d75SDuncan P. N. Exon Smith {"//root/a/b/c", "//root/c"},
300975cd8d75SDuncan P. N. Exon Smith };
301075cd8d75SDuncan P. N. Exon Smith auto RemappedFS = vfs::RedirectingFileSystem::create(
301175cd8d75SDuncan P. N. Exon Smith RemappedFiles, /*UseExternalNames=*/false, *BaseFS);
301275cd8d75SDuncan P. N. Exon Smith
301375cd8d75SDuncan P. N. Exon Smith auto StatA = RemappedFS->status("//root/a/a");
301475cd8d75SDuncan P. N. Exon Smith auto StatB = RemappedFS->status("//root/a/b/c");
301575cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatA);
301675cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatB);
301775cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/a/a", StatA->getName());
301875cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/a/b/c", StatB->getName());
301975cd8d75SDuncan P. N. Exon Smith
302075cd8d75SDuncan P. N. Exon Smith auto BufferA = RemappedFS->getBufferForFile("//root/a/a");
302175cd8d75SDuncan P. N. Exon Smith auto BufferB = RemappedFS->getBufferForFile("//root/a/b/c");
302275cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferA);
302375cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferB);
302475cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of b", (*BufferA)->getBuffer());
302575cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of c", (*BufferB)->getBuffer());
302675cd8d75SDuncan P. N. Exon Smith }
302775cd8d75SDuncan P. N. Exon Smith
TEST(VFSFromRemappedFilesTest,UseExternalNames)302875cd8d75SDuncan P. N. Exon Smith TEST(VFSFromRemappedFilesTest, UseExternalNames) {
302975cd8d75SDuncan P. N. Exon Smith IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS =
303075cd8d75SDuncan P. N. Exon Smith new vfs::InMemoryFileSystem;
303175cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/b", 0, MemoryBuffer::getMemBuffer("contents of b"));
303275cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/c", 0, MemoryBuffer::getMemBuffer("contents of c"));
303375cd8d75SDuncan P. N. Exon Smith
303475cd8d75SDuncan P. N. Exon Smith std::vector<std::pair<std::string, std::string>> RemappedFiles = {
303575cd8d75SDuncan P. N. Exon Smith {"//root/a/a", "//root/b"},
303675cd8d75SDuncan P. N. Exon Smith {"//root/a/b/c", "//root/c"},
303775cd8d75SDuncan P. N. Exon Smith };
303875cd8d75SDuncan P. N. Exon Smith auto RemappedFS = vfs::RedirectingFileSystem::create(
303975cd8d75SDuncan P. N. Exon Smith RemappedFiles, /*UseExternalNames=*/true, *BaseFS);
304075cd8d75SDuncan P. N. Exon Smith
304175cd8d75SDuncan P. N. Exon Smith auto StatA = RemappedFS->status("//root/a/a");
304275cd8d75SDuncan P. N. Exon Smith auto StatB = RemappedFS->status("//root/a/b/c");
304375cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatA);
304475cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatB);
304575cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/b", StatA->getName());
304675cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/c", StatB->getName());
304775cd8d75SDuncan P. N. Exon Smith
304875cd8d75SDuncan P. N. Exon Smith auto BufferA = RemappedFS->getBufferForFile("//root/a/a");
304975cd8d75SDuncan P. N. Exon Smith auto BufferB = RemappedFS->getBufferForFile("//root/a/b/c");
305075cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferA);
305175cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferB);
305275cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of b", (*BufferA)->getBuffer());
305375cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of c", (*BufferB)->getBuffer());
305475cd8d75SDuncan P. N. Exon Smith }
305575cd8d75SDuncan P. N. Exon Smith
TEST(VFSFromRemappedFilesTest,LastMappingWins)305675cd8d75SDuncan P. N. Exon Smith TEST(VFSFromRemappedFilesTest, LastMappingWins) {
305775cd8d75SDuncan P. N. Exon Smith IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS =
305875cd8d75SDuncan P. N. Exon Smith new vfs::InMemoryFileSystem;
305975cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/b", 0, MemoryBuffer::getMemBuffer("contents of b"));
306075cd8d75SDuncan P. N. Exon Smith BaseFS->addFile("//root/c", 0, MemoryBuffer::getMemBuffer("contents of c"));
306175cd8d75SDuncan P. N. Exon Smith
306275cd8d75SDuncan P. N. Exon Smith std::vector<std::pair<std::string, std::string>> RemappedFiles = {
306375cd8d75SDuncan P. N. Exon Smith {"//root/a", "//root/b"},
306475cd8d75SDuncan P. N. Exon Smith {"//root/a", "//root/c"},
306575cd8d75SDuncan P. N. Exon Smith };
306675cd8d75SDuncan P. N. Exon Smith auto RemappedFSKeepName = vfs::RedirectingFileSystem::create(
306775cd8d75SDuncan P. N. Exon Smith RemappedFiles, /*UseExternalNames=*/false, *BaseFS);
306875cd8d75SDuncan P. N. Exon Smith auto RemappedFSExternalName = vfs::RedirectingFileSystem::create(
306975cd8d75SDuncan P. N. Exon Smith RemappedFiles, /*UseExternalNames=*/true, *BaseFS);
307075cd8d75SDuncan P. N. Exon Smith
307175cd8d75SDuncan P. N. Exon Smith auto StatKeepA = RemappedFSKeepName->status("//root/a");
307275cd8d75SDuncan P. N. Exon Smith auto StatExternalA = RemappedFSExternalName->status("//root/a");
307375cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatKeepA);
307475cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(StatExternalA);
307575cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/a", StatKeepA->getName());
307675cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("//root/c", StatExternalA->getName());
307775cd8d75SDuncan P. N. Exon Smith
307875cd8d75SDuncan P. N. Exon Smith auto BufferKeepA = RemappedFSKeepName->getBufferForFile("//root/a");
307975cd8d75SDuncan P. N. Exon Smith auto BufferExternalA = RemappedFSExternalName->getBufferForFile("//root/a");
308075cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferKeepA);
308175cd8d75SDuncan P. N. Exon Smith ASSERT_TRUE(BufferExternalA);
308275cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of c", (*BufferKeepA)->getBuffer());
308375cd8d75SDuncan P. N. Exon Smith EXPECT_EQ("contents of c", (*BufferExternalA)->getBuffer());
308475cd8d75SDuncan P. N. Exon Smith }
308541255241SBen Barham
TEST(RedirectingFileSystemTest,PrintOutput)308641255241SBen Barham TEST(RedirectingFileSystemTest, PrintOutput) {
308741255241SBen Barham auto Buffer =
308841255241SBen Barham MemoryBuffer::getMemBuffer("{\n"
308941255241SBen Barham " 'version': 0,\n"
309041255241SBen Barham " 'roots': [\n"
309141255241SBen Barham " {\n"
309241255241SBen Barham " 'type': 'directory-remap',\n"
309341255241SBen Barham " 'name': '/dremap',\n"
309441255241SBen Barham " 'external-contents': '/a',\n"
309541255241SBen Barham " },"
309641255241SBen Barham " {\n"
309741255241SBen Barham " 'type': 'directory',\n"
309841255241SBen Barham " 'name': '/vdir',\n"
309941255241SBen Barham " 'contents': ["
310041255241SBen Barham " {\n"
310141255241SBen Barham " 'type': 'directory-remap',\n"
310241255241SBen Barham " 'name': 'dremap',\n"
310341255241SBen Barham " 'external-contents': '/b'\n"
310441255241SBen Barham " 'use-external-name': 'true'\n"
310541255241SBen Barham " },\n"
310641255241SBen Barham " {\n"
310741255241SBen Barham " 'type': 'file',\n"
310841255241SBen Barham " 'name': 'vfile',\n"
310941255241SBen Barham " 'external-contents': '/c'\n"
311041255241SBen Barham " 'use-external-name': 'false'\n"
311141255241SBen Barham " }]\n"
311241255241SBen Barham " }]\n"
311341255241SBen Barham "}");
311441255241SBen Barham
311541255241SBen Barham auto Dummy = makeIntrusiveRefCnt<DummyFileSystem>();
311641255241SBen Barham auto Redirecting = vfs::RedirectingFileSystem::create(
311741255241SBen Barham std::move(Buffer), nullptr, "", nullptr, Dummy);
311841255241SBen Barham
311941255241SBen Barham SmallString<0> Output;
312041255241SBen Barham raw_svector_ostream OuputStream{Output};
312141255241SBen Barham
312241255241SBen Barham Redirecting->print(OuputStream, vfs::FileSystem::PrintType::Summary);
312341255241SBen Barham ASSERT_EQ("RedirectingFileSystem (UseExternalNames: true)\n", Output);
312441255241SBen Barham
312541255241SBen Barham Output.clear();
312641255241SBen Barham Redirecting->print(OuputStream, vfs::FileSystem::PrintType::Contents);
312741255241SBen Barham ASSERT_EQ("RedirectingFileSystem (UseExternalNames: true)\n"
312841255241SBen Barham "'/'\n"
312941255241SBen Barham " 'dremap' -> '/a'\n"
313041255241SBen Barham " 'vdir'\n"
313141255241SBen Barham " 'dremap' -> '/b' (UseExternalName: true)\n"
313241255241SBen Barham " 'vfile' -> '/c' (UseExternalName: false)\n"
313341255241SBen Barham "ExternalFS:\n"
313441255241SBen Barham " DummyFileSystem (Summary)\n",
313541255241SBen Barham Output);
313641255241SBen Barham
313741255241SBen Barham Output.clear();
313841255241SBen Barham Redirecting->print(OuputStream, vfs::FileSystem::PrintType::Contents, 1);
313941255241SBen Barham ASSERT_EQ(" RedirectingFileSystem (UseExternalNames: true)\n"
314041255241SBen Barham " '/'\n"
314141255241SBen Barham " 'dremap' -> '/a'\n"
314241255241SBen Barham " 'vdir'\n"
314341255241SBen Barham " 'dremap' -> '/b' (UseExternalName: true)\n"
314441255241SBen Barham " 'vfile' -> '/c' (UseExternalName: false)\n"
314541255241SBen Barham " ExternalFS:\n"
314641255241SBen Barham " DummyFileSystem (Summary)\n",
314741255241SBen Barham Output);
314841255241SBen Barham
314941255241SBen Barham Output.clear();
315041255241SBen Barham Redirecting->print(OuputStream,
315141255241SBen Barham vfs::FileSystem::PrintType::RecursiveContents);
315241255241SBen Barham ASSERT_EQ("RedirectingFileSystem (UseExternalNames: true)\n"
315341255241SBen Barham "'/'\n"
315441255241SBen Barham " 'dremap' -> '/a'\n"
315541255241SBen Barham " 'vdir'\n"
315641255241SBen Barham " 'dremap' -> '/b' (UseExternalName: true)\n"
315741255241SBen Barham " 'vfile' -> '/c' (UseExternalName: false)\n"
315841255241SBen Barham "ExternalFS:\n"
315941255241SBen Barham " DummyFileSystem (RecursiveContents)\n",
316041255241SBen Barham Output);
316141255241SBen Barham }
3162