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