blob: d2f4a7d8f0284f23e7afe79477851ba2bbe0a26e [file] [log] [blame]
Ben Langmuirc8130a72014-02-20 21:59:23 +00001//===- unittests/Basic/VirtualFileSystem.cpp ---------------- VFS tests ---===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "clang/Basic/VirtualFileSystem.h"
Rafael Espindola71de0b62014-06-13 17:20:50 +000011#include "llvm/Support/Errc.h"
Ben Langmuird51ba0b2014-02-21 23:39:37 +000012#include "llvm/Support/MemoryBuffer.h"
Ben Langmuirc8130a72014-02-20 21:59:23 +000013#include "llvm/Support/Path.h"
Ben Langmuird51ba0b2014-02-21 23:39:37 +000014#include "llvm/Support/SourceMgr.h"
Ben Langmuirc8130a72014-02-20 21:59:23 +000015#include "gtest/gtest.h"
16#include <map>
Hans Wennborgdcfba332015-10-06 23:40:43 +000017
Ben Langmuirc8130a72014-02-20 21:59:23 +000018using namespace clang;
19using namespace llvm;
20using llvm::sys::fs::UniqueID;
21
22namespace {
Ben Langmuirf13302e2015-12-10 23:41:39 +000023struct DummyFile : public vfs::File {
24 vfs::Status S;
25 explicit DummyFile(vfs::Status S) : S(S) {}
26 llvm::ErrorOr<vfs::Status> status() override { return S; }
27 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
28 getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
29 bool IsVolatile) override {
30 llvm_unreachable("unimplemented");
31 }
Eugene Zelenko1660a5d2016-01-26 19:01:06 +000032 std::error_code close() override { return std::error_code(); }
Ben Langmuirf13302e2015-12-10 23:41:39 +000033};
34
Ben Langmuirc8130a72014-02-20 21:59:23 +000035class DummyFileSystem : public vfs::FileSystem {
36 int FSID; // used to produce UniqueIDs
37 int FileID; // used to produce UniqueIDs
38 std::map<std::string, vfs::Status> FilesAndDirs;
39
40 static int getNextFSID() {
41 static int Count = 0;
42 return Count++;
43 }
44
45public:
46 DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
47
Fariborz Jahanian5afc8692014-10-01 16:56:40 +000048 ErrorOr<vfs::Status> status(const Twine &Path) override {
Ben Langmuirc8130a72014-02-20 21:59:23 +000049 std::map<std::string, vfs::Status>::iterator I =
Ben Langmuird51ba0b2014-02-21 23:39:37 +000050 FilesAndDirs.find(Path.str());
Ben Langmuirc8130a72014-02-20 21:59:23 +000051 if (I == FilesAndDirs.end())
Rafael Espindola71de0b62014-06-13 17:20:50 +000052 return make_error_code(llvm::errc::no_such_file_or_directory);
Ben Langmuirc8130a72014-02-20 21:59:23 +000053 return I->second;
54 }
Benjamin Kramera8857962014-10-26 22:44:13 +000055 ErrorOr<std::unique_ptr<vfs::File>>
56 openFileForRead(const Twine &Path) override {
Ben Langmuirf13302e2015-12-10 23:41:39 +000057 auto S = status(Path);
58 if (S)
59 return std::unique_ptr<vfs::File>(new DummyFile{*S});
60 return S.getError();
Ben Langmuirc8130a72014-02-20 21:59:23 +000061 }
Benjamin Kramer7708b2a2015-10-05 13:55:20 +000062 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
63 return std::string();
64 }
65 std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
66 return std::error_code();
67 }
Ben Langmuirc8130a72014-02-20 21:59:23 +000068
Ben Langmuir740812b2014-06-24 19:37:16 +000069 struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
70 std::map<std::string, vfs::Status> &FilesAndDirs;
71 std::map<std::string, vfs::Status>::iterator I;
72 std::string Path;
Ben Langmuir7c9f6c82014-06-25 20:25:40 +000073 bool isInPath(StringRef S) {
74 if (Path.size() < S.size() && S.find(Path) == 0) {
75 auto LastSep = S.find_last_of('/');
76 if (LastSep == Path.size() || LastSep == Path.size()-1)
77 return true;
78 }
79 return false;
80 }
Ben Langmuir740812b2014-06-24 19:37:16 +000081 DirIterImpl(std::map<std::string, vfs::Status> &FilesAndDirs,
82 const Twine &_Path)
83 : FilesAndDirs(FilesAndDirs), I(FilesAndDirs.begin()),
84 Path(_Path.str()) {
85 for ( ; I != FilesAndDirs.end(); ++I) {
Ben Langmuir7c9f6c82014-06-25 20:25:40 +000086 if (isInPath(I->first)) {
Ben Langmuir740812b2014-06-24 19:37:16 +000087 CurrentEntry = I->second;
88 break;
89 }
90 }
91 }
92 std::error_code increment() override {
93 ++I;
94 for ( ; I != FilesAndDirs.end(); ++I) {
Ben Langmuir7c9f6c82014-06-25 20:25:40 +000095 if (isInPath(I->first)) {
Ben Langmuir740812b2014-06-24 19:37:16 +000096 CurrentEntry = I->second;
97 break;
98 }
99 }
100 if (I == FilesAndDirs.end())
101 CurrentEntry = vfs::Status();
102 return std::error_code();
103 }
104 };
105
106 vfs::directory_iterator dir_begin(const Twine &Dir,
107 std::error_code &EC) override {
108 return vfs::directory_iterator(
109 std::make_shared<DirIterImpl>(FilesAndDirs, Dir));
110 }
111
Ben Langmuirc8130a72014-02-20 21:59:23 +0000112 void addEntry(StringRef Path, const vfs::Status &Status) {
113 FilesAndDirs[Path] = Status;
114 }
115
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000116 void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
Benjamin Kramer268b51a2015-10-05 13:15:33 +0000117 vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
118 1024, sys::fs::file_type::regular_file, Perms);
Ben Langmuirc8130a72014-02-20 21:59:23 +0000119 addEntry(Path, S);
120 }
121
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000122 void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
Benjamin Kramer268b51a2015-10-05 13:15:33 +0000123 vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
124 0, sys::fs::file_type::directory_file, Perms);
Ben Langmuirc8130a72014-02-20 21:59:23 +0000125 addEntry(Path, S);
126 }
127
128 void addSymlink(StringRef Path) {
Benjamin Kramer268b51a2015-10-05 13:15:33 +0000129 vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
130 0, sys::fs::file_type::symlink_file, sys::fs::all_all);
Ben Langmuirc8130a72014-02-20 21:59:23 +0000131 addEntry(Path, S);
132 }
133};
134} // end anonymous namespace
135
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000136TEST(VirtualFileSystemTest, StatusQueries) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000137 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
Rafael Espindola8e650d72014-06-12 20:37:59 +0000138 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000139
140 D->addRegularFile("/foo");
141 Status = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000142 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000143 EXPECT_TRUE(Status->isStatusKnown());
144 EXPECT_FALSE(Status->isDirectory());
145 EXPECT_TRUE(Status->isRegularFile());
146 EXPECT_FALSE(Status->isSymlink());
147 EXPECT_FALSE(Status->isOther());
148 EXPECT_TRUE(Status->exists());
149
150 D->addDirectory("/bar");
151 Status = D->status("/bar");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000152 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000153 EXPECT_TRUE(Status->isStatusKnown());
154 EXPECT_TRUE(Status->isDirectory());
155 EXPECT_FALSE(Status->isRegularFile());
156 EXPECT_FALSE(Status->isSymlink());
157 EXPECT_FALSE(Status->isOther());
158 EXPECT_TRUE(Status->exists());
159
160 D->addSymlink("/baz");
161 Status = D->status("/baz");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000162 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000163 EXPECT_TRUE(Status->isStatusKnown());
164 EXPECT_FALSE(Status->isDirectory());
165 EXPECT_FALSE(Status->isRegularFile());
166 EXPECT_TRUE(Status->isSymlink());
167 EXPECT_FALSE(Status->isOther());
168 EXPECT_TRUE(Status->exists());
169
170 EXPECT_TRUE(Status->equivalent(*Status));
171 ErrorOr<vfs::Status> Status2 = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000172 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000173 EXPECT_FALSE(Status->equivalent(*Status2));
174}
175
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000176TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000177 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
Rafael Espindola8e650d72014-06-12 20:37:59 +0000178 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000179 EXPECT_FALSE(Status = D->status("/foo"));
180
181 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
182 EXPECT_FALSE(Status = O->status("/foo"));
183
184 D->addRegularFile("/foo");
185 Status = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000186 EXPECT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000187
Rafael Espindola8e650d72014-06-12 20:37:59 +0000188 ErrorOr<vfs::Status> Status2((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000189 Status2 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000190 EXPECT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000191 EXPECT_TRUE(Status->equivalent(*Status2));
192}
193
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000194TEST(VirtualFileSystemTest, OverlayFiles) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000195 IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
196 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
197 IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000198 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
199 new vfs::OverlayFileSystem(Base));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000200 O->pushOverlay(Middle);
201 O->pushOverlay(Top);
202
Rafael Espindola8e650d72014-06-12 20:37:59 +0000203 ErrorOr<vfs::Status> Status1((std::error_code())),
204 Status2((std::error_code())), Status3((std::error_code())),
205 StatusB((std::error_code())), StatusM((std::error_code())),
206 StatusT((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000207
208 Base->addRegularFile("/foo");
209 StatusB = Base->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000210 ASSERT_FALSE(StatusB.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000211 Status1 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000212 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000213 Middle->addRegularFile("/foo");
214 StatusM = Middle->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000215 ASSERT_FALSE(StatusM.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000216 Status2 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000217 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000218 Top->addRegularFile("/foo");
219 StatusT = Top->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000220 ASSERT_FALSE(StatusT.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000221 Status3 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000222 ASSERT_FALSE(Status3.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000223
224 EXPECT_TRUE(Status1->equivalent(*StatusB));
225 EXPECT_TRUE(Status2->equivalent(*StatusM));
226 EXPECT_TRUE(Status3->equivalent(*StatusT));
227
228 EXPECT_FALSE(Status1->equivalent(*Status2));
229 EXPECT_FALSE(Status2->equivalent(*Status3));
230 EXPECT_FALSE(Status1->equivalent(*Status3));
231}
232
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000233TEST(VirtualFileSystemTest, OverlayDirsNonMerged) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000234 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
235 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000236 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
237 new vfs::OverlayFileSystem(Lower));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000238 O->pushOverlay(Upper);
239
240 Lower->addDirectory("/lower-only");
241 Upper->addDirectory("/upper-only");
242
243 // non-merged paths should be the same
244 ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000245 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000246 ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000247 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000248 EXPECT_TRUE(Status1->equivalent(*Status2));
249
250 Status1 = Upper->status("/upper-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000251 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000252 Status2 = O->status("/upper-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000253 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000254 EXPECT_TRUE(Status1->equivalent(*Status2));
255}
256
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000257TEST(VirtualFileSystemTest, MergedDirPermissions) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000258 // merged directories get the permissions of the upper dir
259 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
260 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000261 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
262 new vfs::OverlayFileSystem(Lower));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000263 O->pushOverlay(Upper);
264
Rafael Espindola8e650d72014-06-12 20:37:59 +0000265 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000266 Lower->addDirectory("/both", sys::fs::owner_read);
267 Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
268 Status = O->status("/both");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000269 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000270 EXPECT_EQ(0740, Status->getPermissions());
271
272 // permissions (as usual) are not recursively applied
273 Lower->addRegularFile("/both/foo", sys::fs::owner_read);
274 Upper->addRegularFile("/both/bar", sys::fs::owner_write);
275 Status = O->status("/both/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000276 ASSERT_FALSE( Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000277 EXPECT_EQ(0400, Status->getPermissions());
278 Status = O->status("/both/bar");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000279 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000280 EXPECT_EQ(0200, Status->getPermissions());
281}
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000282
Ben Langmuir740812b2014-06-24 19:37:16 +0000283namespace {
284struct ScopedDir {
285 SmallString<128> Path;
286 ScopedDir(const Twine &Name, bool Unique=false) {
287 std::error_code EC;
288 if (Unique) {
289 EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
290 } else {
291 Path = Name.str();
292 EC = llvm::sys::fs::create_directory(Twine(Path));
293 }
294 if (EC)
295 Path = "";
296 EXPECT_FALSE(EC);
297 }
298 ~ScopedDir() {
299 if (Path != "")
300 EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
301 }
302 operator StringRef() { return Path.str(); }
303};
Hans Wennborgdcfba332015-10-06 23:40:43 +0000304} // end anonymous namespace
Ben Langmuir740812b2014-06-24 19:37:16 +0000305
306TEST(VirtualFileSystemTest, BasicRealFSIteration) {
307 ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
308 IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
309
310 std::error_code EC;
311 vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC);
312 ASSERT_FALSE(EC);
313 EXPECT_EQ(vfs::directory_iterator(), I); // empty directory is empty
314
315 ScopedDir _a(TestDirectory+"/a");
316 ScopedDir _ab(TestDirectory+"/a/b");
317 ScopedDir _c(TestDirectory+"/c");
318 ScopedDir _cd(TestDirectory+"/c/d");
319
320 I = FS->dir_begin(Twine(TestDirectory), EC);
321 ASSERT_FALSE(EC);
322 ASSERT_NE(vfs::directory_iterator(), I);
Ben Langmuirefb8b602014-06-24 21:08:13 +0000323 // Check either a or c, since we can't rely on the iteration order.
324 EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000325 I.increment(EC);
326 ASSERT_FALSE(EC);
327 ASSERT_NE(vfs::directory_iterator(), I);
Ben Langmuirefb8b602014-06-24 21:08:13 +0000328 EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000329 I.increment(EC);
330 EXPECT_EQ(vfs::directory_iterator(), I);
331}
332
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000333TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) {
334 ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
335 IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
336
337 std::error_code EC;
338 auto I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
339 ASSERT_FALSE(EC);
340 EXPECT_EQ(vfs::recursive_directory_iterator(), I); // empty directory is empty
341
342 ScopedDir _a(TestDirectory+"/a");
343 ScopedDir _ab(TestDirectory+"/a/b");
344 ScopedDir _c(TestDirectory+"/c");
345 ScopedDir _cd(TestDirectory+"/c/d");
346
347 I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
348 ASSERT_FALSE(EC);
349 ASSERT_NE(vfs::recursive_directory_iterator(), I);
350
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000351 std::vector<std::string> Contents;
352 for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
353 I.increment(EC)) {
354 Contents.push_back(I->getName());
355 }
356
357 // Check contents, which may be in any order
358 EXPECT_EQ(4U, Contents.size());
359 int Counts[4] = { 0, 0, 0, 0 };
360 for (const std::string &Name : Contents) {
361 ASSERT_FALSE(Name.empty());
362 int Index = Name[Name.size()-1] - 'a';
363 ASSERT_TRUE(Index >= 0 && Index < 4);
364 Counts[Index]++;
365 }
366 EXPECT_EQ(1, Counts[0]); // a
367 EXPECT_EQ(1, Counts[1]); // b
368 EXPECT_EQ(1, Counts[2]); // c
369 EXPECT_EQ(1, Counts[3]); // d
370}
371
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000372template <typename DirIter>
373static void checkContents(DirIter I, ArrayRef<StringRef> Expected) {
Ben Langmuir740812b2014-06-24 19:37:16 +0000374 std::error_code EC;
375 auto ExpectedIter = Expected.begin(), ExpectedEnd = Expected.end();
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000376 for (DirIter E;
Ben Langmuir740812b2014-06-24 19:37:16 +0000377 !EC && I != E && ExpectedIter != ExpectedEnd;
378 I.increment(EC), ++ExpectedIter)
379 EXPECT_EQ(*ExpectedIter, I->getName());
380
381 EXPECT_EQ(ExpectedEnd, ExpectedIter);
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000382 EXPECT_EQ(DirIter(), I);
Ben Langmuir740812b2014-06-24 19:37:16 +0000383}
384
385TEST(VirtualFileSystemTest, OverlayIteration) {
386 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
387 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
388 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
389 new vfs::OverlayFileSystem(Lower));
390 O->pushOverlay(Upper);
391
392 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000393 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000394
395 Lower->addRegularFile("/file1");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000396 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000397
398 Upper->addRegularFile("/file2");
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000399 checkContents(O->dir_begin("/", EC), {"/file2", "/file1"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000400
401 Lower->addDirectory("/dir1");
402 Lower->addRegularFile("/dir1/foo");
403 Upper->addDirectory("/dir2");
404 Upper->addRegularFile("/dir2/foo");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000405 checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo"));
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000406 checkContents(O->dir_begin("/", EC), {"/dir2", "/file2", "/dir1", "/file1"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000407}
408
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000409TEST(VirtualFileSystemTest, OverlayRecursiveIteration) {
410 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
411 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
412 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
413 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
414 new vfs::OverlayFileSystem(Lower));
415 O->pushOverlay(Middle);
416 O->pushOverlay(Upper);
417
418 std::error_code EC;
419 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
420 ArrayRef<StringRef>());
421
422 Lower->addRegularFile("/file1");
423 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
424 ArrayRef<StringRef>("/file1"));
425
426 Upper->addDirectory("/dir");
427 Upper->addRegularFile("/dir/file2");
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000428 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
429 {"/dir", "/dir/file2", "/file1"});
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000430
431 Lower->addDirectory("/dir1");
432 Lower->addRegularFile("/dir1/foo");
433 Lower->addDirectory("/dir1/a");
434 Lower->addRegularFile("/dir1/a/b");
435 Middle->addDirectory("/a");
436 Middle->addDirectory("/a/b");
437 Middle->addDirectory("/a/b/c");
438 Middle->addRegularFile("/a/b/c/d");
439 Middle->addRegularFile("/hiddenByUp");
440 Upper->addDirectory("/dir2");
441 Upper->addRegularFile("/dir2/foo");
442 Upper->addRegularFile("/hiddenByUp");
443 checkContents(vfs::recursive_directory_iterator(*O, "/dir2", EC),
444 ArrayRef<StringRef>("/dir2/foo"));
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000445 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
446 {"/dir", "/dir/file2", "/dir2", "/dir2/foo", "/hiddenByUp",
447 "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/dir1", "/dir1/a",
448 "/dir1/a/b", "/dir1/foo", "/file1"});
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000449}
450
Ben Langmuir740812b2014-06-24 19:37:16 +0000451TEST(VirtualFileSystemTest, ThreeLevelIteration) {
452 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
453 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
454 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
455 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
456 new vfs::OverlayFileSystem(Lower));
457 O->pushOverlay(Middle);
458 O->pushOverlay(Upper);
459
460 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000461 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000462
463 Middle->addRegularFile("/file2");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000464 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000465
466 Lower->addRegularFile("/file1");
467 Upper->addRegularFile("/file3");
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000468 checkContents(O->dir_begin("/", EC), {"/file3", "/file2", "/file1"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000469}
470
471TEST(VirtualFileSystemTest, HiddenInIteration) {
472 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
473 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
474 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
475 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
476 new vfs::OverlayFileSystem(Lower));
477 O->pushOverlay(Middle);
478 O->pushOverlay(Upper);
479
480 std::error_code EC;
481 Lower->addRegularFile("/onlyInLow", sys::fs::owner_read);
482 Lower->addRegularFile("/hiddenByMid", sys::fs::owner_read);
483 Lower->addRegularFile("/hiddenByUp", sys::fs::owner_read);
484 Middle->addRegularFile("/onlyInMid", sys::fs::owner_write);
485 Middle->addRegularFile("/hiddenByMid", sys::fs::owner_write);
486 Middle->addRegularFile("/hiddenByUp", sys::fs::owner_write);
487 Upper->addRegularFile("/onlyInUp", sys::fs::owner_all);
488 Upper->addRegularFile("/hiddenByUp", sys::fs::owner_all);
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000489 checkContents(
490 O->dir_begin("/", EC),
491 {"/hiddenByUp", "/onlyInUp", "/hiddenByMid", "/onlyInMid", "/onlyInLow"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000492
493 // Make sure we get the top-most entry
Ben Langmuirefb8b602014-06-24 21:08:13 +0000494 {
495 std::error_code EC;
496 vfs::directory_iterator I = O->dir_begin("/", EC), E;
497 for ( ; !EC && I != E; I.increment(EC))
498 if (I->getName() == "/hiddenByUp")
499 break;
500 ASSERT_NE(E, I);
501 EXPECT_EQ(sys::fs::owner_all, I->getPermissions());
502 }
503 {
504 std::error_code EC;
505 vfs::directory_iterator I = O->dir_begin("/", EC), E;
506 for ( ; !EC && I != E; I.increment(EC))
507 if (I->getName() == "/hiddenByMid")
508 break;
509 ASSERT_NE(E, I);
510 EXPECT_EQ(sys::fs::owner_write, I->getPermissions());
511 }
Ben Langmuir740812b2014-06-24 19:37:16 +0000512}
513
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000514class InMemoryFileSystemTest : public ::testing::Test {
515protected:
516 clang::vfs::InMemoryFileSystem FS;
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000517 clang::vfs::InMemoryFileSystem NormalizedFS;
518
519 InMemoryFileSystemTest()
520 : FS(/*UseNormalizedPaths=*/false),
521 NormalizedFS(/*UseNormalizedPaths=*/true) {}
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000522};
523
524TEST_F(InMemoryFileSystemTest, IsEmpty) {
525 auto Stat = FS.status("/a");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000526 ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000527 Stat = FS.status("/");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000528 ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000529}
530
531TEST_F(InMemoryFileSystemTest, WindowsPath) {
532 FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
533 auto Stat = FS.status("c:");
NAKAMURA Takumi4c33a1a2015-10-06 12:16:27 +0000534#if !defined(_WIN32)
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000535 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
NAKAMURA Takumi4c33a1a2015-10-06 12:16:27 +0000536#endif
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000537 Stat = FS.status("c:/windows/system128/foo.cpp");
538 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
539 FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
540 Stat = FS.status("d:/windows/foo.cpp");
541 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
542}
543
544TEST_F(InMemoryFileSystemTest, OverlayFile) {
545 FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000546 NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000547 auto Stat = FS.status("/");
548 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000549 Stat = FS.status("/.");
550 ASSERT_FALSE(Stat);
551 Stat = NormalizedFS.status("/.");
552 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000553 Stat = FS.status("/a");
554 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
555 ASSERT_EQ("/a", Stat->getName());
556}
557
Benjamin Kramer2e2351a2015-10-06 10:04:08 +0000558TEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) {
559 auto Buf = MemoryBuffer::getMemBuffer("a");
560 FS.addFileNoOwn("/a", 0, Buf.get());
561 auto Stat = FS.status("/a");
562 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
563 ASSERT_EQ("/a", Stat->getName());
564}
565
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000566TEST_F(InMemoryFileSystemTest, OpenFileForRead) {
567 FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000568 FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
569 FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
570 NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
571 NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
572 NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000573 auto File = FS.openFileForRead("/a");
574 ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
575 File = FS.openFileForRead("/a"); // Open again.
576 ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000577 File = NormalizedFS.openFileForRead("/././a"); // Open again.
578 ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000579 File = FS.openFileForRead("/");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000580 ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000581 File = FS.openFileForRead("/b");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000582 ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString();
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000583 File = FS.openFileForRead("./c");
584 ASSERT_FALSE(File);
585 File = FS.openFileForRead("e/../d");
586 ASSERT_FALSE(File);
587 File = NormalizedFS.openFileForRead("./c");
Benjamin Kramerd5e0b582015-10-07 08:32:50 +0000588 ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer());
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000589 File = NormalizedFS.openFileForRead("e/../d");
590 ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer());
591}
592
593TEST_F(InMemoryFileSystemTest, DuplicatedFile) {
594 ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
595 ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a")));
596 ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
597 ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b")));
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000598}
599
600TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
601 FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""));
602 FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer(""));
603
604 std::error_code EC;
605 vfs::directory_iterator I = FS.dir_begin("/", EC);
606 ASSERT_FALSE(EC);
607 ASSERT_EQ("/a", I->getName());
608 I.increment(EC);
609 ASSERT_FALSE(EC);
610 ASSERT_EQ("/b", I->getName());
611 I.increment(EC);
612 ASSERT_FALSE(EC);
613 ASSERT_EQ(vfs::directory_iterator(), I);
614
615 I = FS.dir_begin("/b", EC);
616 ASSERT_FALSE(EC);
617 ASSERT_EQ("/b/c", I->getName());
618 I.increment(EC);
619 ASSERT_FALSE(EC);
620 ASSERT_EQ(vfs::directory_iterator(), I);
621}
622
Benjamin Kramer1b8dbe32015-10-06 14:45:16 +0000623TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
624 FS.setCurrentWorkingDirectory("/b");
625 FS.addFile("c", 0, MemoryBuffer::getMemBuffer(""));
626
627 auto Stat = FS.status("/b/c");
628 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
629 ASSERT_EQ("c", Stat->getName());
630 ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
631
632 Stat = FS.status("c");
633 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
Benjamin Kramere9e76072016-01-09 16:33:16 +0000634
Benjamin Kramer730338b2016-01-10 10:36:59 +0000635 auto ReplaceBackslashes = [](std::string S) {
636 std::replace(S.begin(), S.end(), '\\', '/');
637 return S;
638 };
Benjamin Kramere9e76072016-01-09 16:33:16 +0000639 NormalizedFS.setCurrentWorkingDirectory("/b/c");
640 NormalizedFS.setCurrentWorkingDirectory(".");
Benjamin Kramer730338b2016-01-10 10:36:59 +0000641 ASSERT_EQ("/b/c", ReplaceBackslashes(
642 NormalizedFS.getCurrentWorkingDirectory().get()));
Benjamin Kramere9e76072016-01-09 16:33:16 +0000643 NormalizedFS.setCurrentWorkingDirectory("..");
Benjamin Kramer730338b2016-01-10 10:36:59 +0000644 ASSERT_EQ("/b", ReplaceBackslashes(
645 NormalizedFS.getCurrentWorkingDirectory().get()));
Benjamin Kramer1b8dbe32015-10-06 14:45:16 +0000646}
647
Ben Langmuir93853232014-03-05 21:32:20 +0000648// NOTE: in the tests below, we use '//root/' as our root directory, since it is
649// a legal *absolute* path on Windows as well as *nix.
Ben Langmuir97882e72014-02-24 20:56:37 +0000650class VFSFromYAMLTest : public ::testing::Test {
651public:
652 int NumDiagnostics;
Ben Langmuir93853232014-03-05 21:32:20 +0000653
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000654 void SetUp() override { NumDiagnostics = 0; }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000655
Ben Langmuir97882e72014-02-24 20:56:37 +0000656 static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
657 VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
658 ++Test->NumDiagnostics;
659 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000660
Ben Langmuir97882e72014-02-24 20:56:37 +0000661 IntrusiveRefCntPtr<vfs::FileSystem>
662 getFromYAMLRawString(StringRef Content,
663 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
Rafael Espindolad87f8d72014-08-27 20:03:29 +0000664 std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content);
Bruno Cardoso Lopesd878e282016-03-20 02:08:48 +0000665 return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, "", this,
Rafael Espindola91ac8df2014-08-17 23:27:13 +0000666 ExternalFS);
Ben Langmuir97882e72014-02-24 20:56:37 +0000667 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000668
Ben Langmuir97882e72014-02-24 20:56:37 +0000669 IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
670 StringRef Content,
671 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
672 std::string VersionPlusContent("{\n 'version':0,\n");
673 VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
674 return getFromYAMLRawString(VersionPlusContent, ExternalFS);
675 }
Ben Langmuir97882e72014-02-24 20:56:37 +0000676};
677
678TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000679 IntrusiveRefCntPtr<vfs::FileSystem> FS;
680 FS = getFromYAMLString("");
Alp Tokerf994cef2014-07-05 03:08:06 +0000681 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000682 FS = getFromYAMLString("[]");
Alp Tokerf994cef2014-07-05 03:08:06 +0000683 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000684 FS = getFromYAMLString("'string'");
Alp Tokerf994cef2014-07-05 03:08:06 +0000685 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000686 EXPECT_EQ(3, NumDiagnostics);
687}
688
Ben Langmuir97882e72014-02-24 20:56:37 +0000689TEST_F(VFSFromYAMLTest, MappedFiles) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000690 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000691 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000692 IntrusiveRefCntPtr<vfs::FileSystem> FS =
693 getFromYAMLString("{ 'roots': [\n"
694 "{\n"
695 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000696 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000697 " 'contents': [ {\n"
698 " 'type': 'file',\n"
699 " 'name': 'file1',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000700 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000701 " },\n"
702 " {\n"
703 " 'type': 'file',\n"
704 " 'name': 'file2',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000705 " 'external-contents': '//root/foo/b'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000706 " }\n"
707 " ]\n"
708 "}\n"
709 "]\n"
710 "}",
711 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000712 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000713
714 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
715 new vfs::OverlayFileSystem(Lower));
716 O->pushOverlay(FS);
717
718 // file
Ben Langmuir93853232014-03-05 21:32:20 +0000719 ErrorOr<vfs::Status> S = O->status("//root/file1");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000720 ASSERT_FALSE(S.getError());
Ben Langmuir93853232014-03-05 21:32:20 +0000721 EXPECT_EQ("//root/foo/bar/a", S->getName());
Ben Langmuirf13302e2015-12-10 23:41:39 +0000722 EXPECT_TRUE(S->IsVFSMapped);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000723
Ben Langmuir93853232014-03-05 21:32:20 +0000724 ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
725 EXPECT_EQ("//root/foo/bar/a", SLower->getName());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000726 EXPECT_TRUE(S->equivalent(*SLower));
Ben Langmuirf13302e2015-12-10 23:41:39 +0000727 EXPECT_FALSE(SLower->IsVFSMapped);
728
729 // file after opening
730 auto OpenedF = O->openFileForRead("//root/file1");
731 ASSERT_FALSE(OpenedF.getError());
732 auto OpenedS = (*OpenedF)->status();
733 ASSERT_FALSE(OpenedS.getError());
734 EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
735 EXPECT_TRUE(OpenedS->IsVFSMapped);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000736
737 // directory
Ben Langmuir93853232014-03-05 21:32:20 +0000738 S = O->status("//root/");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000739 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000740 EXPECT_TRUE(S->isDirectory());
Ben Langmuir93853232014-03-05 21:32:20 +0000741 EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000742
743 // broken mapping
Rafael Espindola71de0b62014-06-13 17:20:50 +0000744 EXPECT_EQ(O->status("//root/file2").getError(),
745 llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000746 EXPECT_EQ(0, NumDiagnostics);
747}
748
Ben Langmuir97882e72014-02-24 20:56:37 +0000749TEST_F(VFSFromYAMLTest, CaseInsensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000750 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000751 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000752 IntrusiveRefCntPtr<vfs::FileSystem> FS =
753 getFromYAMLString("{ 'case-sensitive': 'false',\n"
754 " 'roots': [\n"
755 "{\n"
756 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000757 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000758 " 'contents': [ {\n"
759 " 'type': 'file',\n"
760 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000761 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000762 " }\n"
763 " ]\n"
764 "}]}",
765 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000766 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000767
768 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
769 new vfs::OverlayFileSystem(Lower));
770 O->pushOverlay(FS);
771
Ben Langmuir93853232014-03-05 21:32:20 +0000772 ErrorOr<vfs::Status> S = O->status("//root/XX");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000773 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000774
Ben Langmuir93853232014-03-05 21:32:20 +0000775 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000776 ASSERT_FALSE(SS.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000777 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000778 SS = O->status("//root/xX");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000779 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000780 SS = O->status("//root/Xx");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000781 EXPECT_TRUE(S->equivalent(*SS));
782 EXPECT_EQ(0, NumDiagnostics);
783}
784
Ben Langmuir97882e72014-02-24 20:56:37 +0000785TEST_F(VFSFromYAMLTest, CaseSensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000786 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000787 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000788 IntrusiveRefCntPtr<vfs::FileSystem> FS =
789 getFromYAMLString("{ 'case-sensitive': 'true',\n"
790 " 'roots': [\n"
791 "{\n"
792 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000793 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000794 " 'contents': [ {\n"
795 " 'type': 'file',\n"
796 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000797 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000798 " }\n"
799 " ]\n"
800 "}]}",
801 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000802 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000803
804 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
805 new vfs::OverlayFileSystem(Lower));
806 O->pushOverlay(FS);
807
Ben Langmuir93853232014-03-05 21:32:20 +0000808 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000809 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000810 SS = O->status("//root/xX");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000811 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000812 SS = O->status("//root/Xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000813 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000814 EXPECT_EQ(0, NumDiagnostics);
815}
816
Ben Langmuir97882e72014-02-24 20:56:37 +0000817TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000818 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
819
820 // invalid YAML at top-level
821 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000822 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000823 // invalid YAML in roots
824 FS = getFromYAMLString("{ 'roots':[}", Lower);
825 // invalid YAML in directory
826 FS = getFromYAMLString(
827 "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
828 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000829 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000830
831 // invalid configuration
832 FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000833 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000834 FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000835 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000836
837 // invalid roots
838 FS = getFromYAMLString("{ 'roots':'' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000839 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000840 FS = getFromYAMLString("{ 'roots':{} }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000841 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000842
843 // invalid entries
844 FS = getFromYAMLString(
845 "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000846 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000847 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
848 "'external-contents': 'other' }",
849 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000850 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000851 FS = getFromYAMLString(
852 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
853 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000854 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000855 FS = getFromYAMLString(
856 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
857 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000858 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000859 FS = getFromYAMLString(
860 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
861 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000862 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000863 FS = getFromYAMLString(
864 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
865 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000866 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000867 FS = getFromYAMLString(
868 "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
869 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000870 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000871
872 // missing mandatory fields
873 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000874 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000875 FS = getFromYAMLString(
876 "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000877 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000878 FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000879 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000880
881 // duplicate keys
882 FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000883 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000884 FS = getFromYAMLString(
885 "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
886 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000887 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000888 FS =
889 getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
890 "'external-contents':'blah' } ] }",
891 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000892 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000893
894 // missing version
895 FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000896 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000897
898 // bad version number
899 FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000900 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000901 FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000902 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000903 FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000904 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000905 EXPECT_EQ(24, NumDiagnostics);
906}
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000907
Ben Langmuirb59cf672014-02-27 00:25:12 +0000908TEST_F(VFSFromYAMLTest, UseExternalName) {
909 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000910 Lower->addRegularFile("//root/external/file");
Ben Langmuirb59cf672014-02-27 00:25:12 +0000911
912 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
913 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000914 " { 'type': 'file', 'name': '//root/A',\n"
915 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000916 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000917 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000918 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000919 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000920 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000921 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000922 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000923 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000924 " }\n"
925 "] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000926 ASSERT_TRUE(nullptr != FS.get());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000927
928 // default true
Ben Langmuir93853232014-03-05 21:32:20 +0000929 EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000930 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000931 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
932 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000933
934 // global configuration
935 FS = getFromYAMLString(
936 "{ 'use-external-names': false,\n"
937 " 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000938 " { 'type': 'file', 'name': '//root/A',\n"
939 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000940 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000941 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000942 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000943 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000944 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000945 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000946 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000947 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000948 " }\n"
949 "] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000950 ASSERT_TRUE(nullptr != FS.get());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000951
952 // default
Ben Langmuir93853232014-03-05 21:32:20 +0000953 EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000954 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000955 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
956 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000957}
958
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000959TEST_F(VFSFromYAMLTest, MultiComponentPath) {
960 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000961 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000962
963 // file in roots
964 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
965 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000966 " { 'type': 'file', 'name': '//root/path/to/file',\n"
967 " 'external-contents': '//root/other' }]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000968 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000969 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000970 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
971 EXPECT_FALSE(FS->status("//root/path/to").getError());
972 EXPECT_FALSE(FS->status("//root/path").getError());
973 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000974
975 // at the start
976 FS = getFromYAMLString(
977 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000978 " { 'type': 'directory', 'name': '//root/path/to',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000979 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000980 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000981 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000982 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000983 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
984 EXPECT_FALSE(FS->status("//root/path/to").getError());
985 EXPECT_FALSE(FS->status("//root/path").getError());
986 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000987
988 // at the end
989 FS = getFromYAMLString(
990 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000991 " { 'type': 'directory', 'name': '//root/',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000992 " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000993 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000994 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000995 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000996 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
997 EXPECT_FALSE(FS->status("//root/path/to").getError());
998 EXPECT_FALSE(FS->status("//root/path").getError());
999 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001000}
1001
1002TEST_F(VFSFromYAMLTest, TrailingSlashes) {
1003 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +00001004 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001005
1006 // file in roots
1007 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
1008 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +00001009 " { 'type': 'directory', 'name': '//root/path/to////',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001010 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +00001011 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001012 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +00001013 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +00001014 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
1015 EXPECT_FALSE(FS->status("//root/path/to").getError());
1016 EXPECT_FALSE(FS->status("//root/path").getError());
1017 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001018}
Ben Langmuir740812b2014-06-24 19:37:16 +00001019
1020TEST_F(VFSFromYAMLTest, DirectoryIteration) {
1021 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1022 Lower->addDirectory("//root/");
1023 Lower->addDirectory("//root/foo");
1024 Lower->addDirectory("//root/foo/bar");
1025 Lower->addRegularFile("//root/foo/bar/a");
1026 Lower->addRegularFile("//root/foo/bar/b");
1027 Lower->addRegularFile("//root/file3");
1028 IntrusiveRefCntPtr<vfs::FileSystem> FS =
1029 getFromYAMLString("{ 'use-external-names': false,\n"
1030 " 'roots': [\n"
1031 "{\n"
1032 " 'type': 'directory',\n"
1033 " 'name': '//root/',\n"
1034 " 'contents': [ {\n"
1035 " 'type': 'file',\n"
1036 " 'name': 'file1',\n"
1037 " 'external-contents': '//root/foo/bar/a'\n"
1038 " },\n"
1039 " {\n"
1040 " 'type': 'file',\n"
1041 " 'name': 'file2',\n"
1042 " 'external-contents': '//root/foo/bar/b'\n"
1043 " }\n"
1044 " ]\n"
1045 "}\n"
1046 "]\n"
1047 "}",
1048 Lower);
Hans Wennborgdcfba332015-10-06 23:40:43 +00001049 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuir740812b2014-06-24 19:37:16 +00001050
1051 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1052 new vfs::OverlayFileSystem(Lower));
1053 O->pushOverlay(FS);
1054
1055 std::error_code EC;
Benjamin Kramer2a23e552016-01-10 10:45:19 +00001056 checkContents(O->dir_begin("//root/", EC),
1057 {"//root/file1", "//root/file2", "//root/file3", "//root/foo"});
Ben Langmuir740812b2014-06-24 19:37:16 +00001058
Benjamin Kramer2a23e552016-01-10 10:45:19 +00001059 checkContents(O->dir_begin("//root/foo/bar", EC),
1060 {"//root/foo/bar/a", "//root/foo/bar/b"});
Ben Langmuir740812b2014-06-24 19:37:16 +00001061}