blob: b8e675e75fab0ab87a6fb22cad5530aaf8b8689f [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>
Bruno Cardoso Lopes29ebd492016-05-11 20:58:47 +0000373static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) {
Ben Langmuir740812b2014-06-24 19:37:16 +0000374 std::error_code EC;
Bruno Cardoso Lopes29ebd492016-05-11 20:58:47 +0000375 SmallVector<StringRef, 4> Expected(ExpectedOut.begin(), ExpectedOut.end());
376 SmallVector<std::string, 4> InputToCheck;
Ben Langmuir740812b2014-06-24 19:37:16 +0000377
Bruno Cardoso Lopes29ebd492016-05-11 20:58:47 +0000378 // Do not rely on iteration order to check for contents, sort both
379 // content vectors before comparison.
380 for (DirIter E; !EC && I != E; I.increment(EC))
381 InputToCheck.push_back(I->getName());
382
383 std::sort(InputToCheck.begin(), InputToCheck.end());
384 std::sort(Expected.begin(), Expected.end());
385 EXPECT_EQ(InputToCheck.size(), Expected.size());
386
387 unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
388 for (unsigned Idx = 0; Idx != LastElt; ++Idx)
389 EXPECT_EQ(Expected[Idx], StringRef(InputToCheck[Idx]));
Ben Langmuir740812b2014-06-24 19:37:16 +0000390}
391
392TEST(VirtualFileSystemTest, OverlayIteration) {
393 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
394 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
395 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
396 new vfs::OverlayFileSystem(Lower));
397 O->pushOverlay(Upper);
398
399 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000400 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000401
402 Lower->addRegularFile("/file1");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000403 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000404
405 Upper->addRegularFile("/file2");
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000406 checkContents(O->dir_begin("/", EC), {"/file2", "/file1"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000407
408 Lower->addDirectory("/dir1");
409 Lower->addRegularFile("/dir1/foo");
410 Upper->addDirectory("/dir2");
411 Upper->addRegularFile("/dir2/foo");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000412 checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo"));
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000413 checkContents(O->dir_begin("/", EC), {"/dir2", "/file2", "/dir1", "/file1"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000414}
415
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000416TEST(VirtualFileSystemTest, OverlayRecursiveIteration) {
417 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
418 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
419 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
420 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
421 new vfs::OverlayFileSystem(Lower));
422 O->pushOverlay(Middle);
423 O->pushOverlay(Upper);
424
425 std::error_code EC;
426 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
427 ArrayRef<StringRef>());
428
429 Lower->addRegularFile("/file1");
430 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
431 ArrayRef<StringRef>("/file1"));
432
433 Upper->addDirectory("/dir");
434 Upper->addRegularFile("/dir/file2");
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000435 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
436 {"/dir", "/dir/file2", "/file1"});
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000437
438 Lower->addDirectory("/dir1");
439 Lower->addRegularFile("/dir1/foo");
440 Lower->addDirectory("/dir1/a");
441 Lower->addRegularFile("/dir1/a/b");
442 Middle->addDirectory("/a");
443 Middle->addDirectory("/a/b");
444 Middle->addDirectory("/a/b/c");
445 Middle->addRegularFile("/a/b/c/d");
446 Middle->addRegularFile("/hiddenByUp");
447 Upper->addDirectory("/dir2");
448 Upper->addRegularFile("/dir2/foo");
449 Upper->addRegularFile("/hiddenByUp");
450 checkContents(vfs::recursive_directory_iterator(*O, "/dir2", EC),
451 ArrayRef<StringRef>("/dir2/foo"));
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000452 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
453 {"/dir", "/dir/file2", "/dir2", "/dir2/foo", "/hiddenByUp",
454 "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/dir1", "/dir1/a",
455 "/dir1/a/b", "/dir1/foo", "/file1"});
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000456}
457
Ben Langmuir740812b2014-06-24 19:37:16 +0000458TEST(VirtualFileSystemTest, ThreeLevelIteration) {
459 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
460 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
461 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
462 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
463 new vfs::OverlayFileSystem(Lower));
464 O->pushOverlay(Middle);
465 O->pushOverlay(Upper);
466
467 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000468 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000469
470 Middle->addRegularFile("/file2");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000471 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000472
473 Lower->addRegularFile("/file1");
474 Upper->addRegularFile("/file3");
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000475 checkContents(O->dir_begin("/", EC), {"/file3", "/file2", "/file1"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000476}
477
478TEST(VirtualFileSystemTest, HiddenInIteration) {
479 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
480 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
481 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
482 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
483 new vfs::OverlayFileSystem(Lower));
484 O->pushOverlay(Middle);
485 O->pushOverlay(Upper);
486
487 std::error_code EC;
488 Lower->addRegularFile("/onlyInLow", sys::fs::owner_read);
489 Lower->addRegularFile("/hiddenByMid", sys::fs::owner_read);
490 Lower->addRegularFile("/hiddenByUp", sys::fs::owner_read);
491 Middle->addRegularFile("/onlyInMid", sys::fs::owner_write);
492 Middle->addRegularFile("/hiddenByMid", sys::fs::owner_write);
493 Middle->addRegularFile("/hiddenByUp", sys::fs::owner_write);
494 Upper->addRegularFile("/onlyInUp", sys::fs::owner_all);
495 Upper->addRegularFile("/hiddenByUp", sys::fs::owner_all);
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000496 checkContents(
497 O->dir_begin("/", EC),
498 {"/hiddenByUp", "/onlyInUp", "/hiddenByMid", "/onlyInMid", "/onlyInLow"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000499
500 // Make sure we get the top-most entry
Ben Langmuirefb8b602014-06-24 21:08:13 +0000501 {
502 std::error_code EC;
503 vfs::directory_iterator I = O->dir_begin("/", EC), E;
504 for ( ; !EC && I != E; I.increment(EC))
505 if (I->getName() == "/hiddenByUp")
506 break;
507 ASSERT_NE(E, I);
508 EXPECT_EQ(sys::fs::owner_all, I->getPermissions());
509 }
510 {
511 std::error_code EC;
512 vfs::directory_iterator I = O->dir_begin("/", EC), E;
513 for ( ; !EC && I != E; I.increment(EC))
514 if (I->getName() == "/hiddenByMid")
515 break;
516 ASSERT_NE(E, I);
517 EXPECT_EQ(sys::fs::owner_write, I->getPermissions());
518 }
Ben Langmuir740812b2014-06-24 19:37:16 +0000519}
520
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000521class InMemoryFileSystemTest : public ::testing::Test {
522protected:
523 clang::vfs::InMemoryFileSystem FS;
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000524 clang::vfs::InMemoryFileSystem NormalizedFS;
525
526 InMemoryFileSystemTest()
527 : FS(/*UseNormalizedPaths=*/false),
528 NormalizedFS(/*UseNormalizedPaths=*/true) {}
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000529};
530
531TEST_F(InMemoryFileSystemTest, IsEmpty) {
532 auto Stat = FS.status("/a");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000533 ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000534 Stat = FS.status("/");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000535 ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000536}
537
538TEST_F(InMemoryFileSystemTest, WindowsPath) {
539 FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
540 auto Stat = FS.status("c:");
NAKAMURA Takumi4c33a1a2015-10-06 12:16:27 +0000541#if !defined(_WIN32)
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000542 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
NAKAMURA Takumi4c33a1a2015-10-06 12:16:27 +0000543#endif
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000544 Stat = FS.status("c:/windows/system128/foo.cpp");
545 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
546 FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
547 Stat = FS.status("d:/windows/foo.cpp");
548 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
549}
550
551TEST_F(InMemoryFileSystemTest, OverlayFile) {
552 FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000553 NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000554 auto Stat = FS.status("/");
555 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000556 Stat = FS.status("/.");
557 ASSERT_FALSE(Stat);
558 Stat = NormalizedFS.status("/.");
559 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000560 Stat = FS.status("/a");
561 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
562 ASSERT_EQ("/a", Stat->getName());
563}
564
Benjamin Kramer2e2351a2015-10-06 10:04:08 +0000565TEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) {
566 auto Buf = MemoryBuffer::getMemBuffer("a");
567 FS.addFileNoOwn("/a", 0, Buf.get());
568 auto Stat = FS.status("/a");
569 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
570 ASSERT_EQ("/a", Stat->getName());
571}
572
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000573TEST_F(InMemoryFileSystemTest, OpenFileForRead) {
574 FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000575 FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
576 FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
577 NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
578 NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
579 NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000580 auto File = FS.openFileForRead("/a");
581 ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
582 File = FS.openFileForRead("/a"); // Open again.
583 ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000584 File = NormalizedFS.openFileForRead("/././a"); // Open again.
585 ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000586 File = FS.openFileForRead("/");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000587 ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000588 File = FS.openFileForRead("/b");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000589 ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString();
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000590 File = FS.openFileForRead("./c");
591 ASSERT_FALSE(File);
592 File = FS.openFileForRead("e/../d");
593 ASSERT_FALSE(File);
594 File = NormalizedFS.openFileForRead("./c");
Benjamin Kramerd5e0b582015-10-07 08:32:50 +0000595 ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer());
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000596 File = NormalizedFS.openFileForRead("e/../d");
597 ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer());
598}
599
600TEST_F(InMemoryFileSystemTest, DuplicatedFile) {
601 ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
602 ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a")));
603 ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
604 ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b")));
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000605}
606
607TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
608 FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""));
609 FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer(""));
610
611 std::error_code EC;
612 vfs::directory_iterator I = FS.dir_begin("/", EC);
613 ASSERT_FALSE(EC);
614 ASSERT_EQ("/a", I->getName());
615 I.increment(EC);
616 ASSERT_FALSE(EC);
617 ASSERT_EQ("/b", I->getName());
618 I.increment(EC);
619 ASSERT_FALSE(EC);
620 ASSERT_EQ(vfs::directory_iterator(), I);
621
622 I = FS.dir_begin("/b", EC);
623 ASSERT_FALSE(EC);
624 ASSERT_EQ("/b/c", I->getName());
625 I.increment(EC);
626 ASSERT_FALSE(EC);
627 ASSERT_EQ(vfs::directory_iterator(), I);
628}
629
Benjamin Kramer1b8dbe32015-10-06 14:45:16 +0000630TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
631 FS.setCurrentWorkingDirectory("/b");
632 FS.addFile("c", 0, MemoryBuffer::getMemBuffer(""));
633
634 auto Stat = FS.status("/b/c");
635 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
636 ASSERT_EQ("c", Stat->getName());
637 ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
638
639 Stat = FS.status("c");
640 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
Benjamin Kramere9e76072016-01-09 16:33:16 +0000641
Benjamin Kramer730338b2016-01-10 10:36:59 +0000642 auto ReplaceBackslashes = [](std::string S) {
643 std::replace(S.begin(), S.end(), '\\', '/');
644 return S;
645 };
Benjamin Kramere9e76072016-01-09 16:33:16 +0000646 NormalizedFS.setCurrentWorkingDirectory("/b/c");
647 NormalizedFS.setCurrentWorkingDirectory(".");
Benjamin Kramer730338b2016-01-10 10:36:59 +0000648 ASSERT_EQ("/b/c", ReplaceBackslashes(
649 NormalizedFS.getCurrentWorkingDirectory().get()));
Benjamin Kramere9e76072016-01-09 16:33:16 +0000650 NormalizedFS.setCurrentWorkingDirectory("..");
Benjamin Kramer730338b2016-01-10 10:36:59 +0000651 ASSERT_EQ("/b", ReplaceBackslashes(
652 NormalizedFS.getCurrentWorkingDirectory().get()));
Benjamin Kramer1b8dbe32015-10-06 14:45:16 +0000653}
654
Ben Langmuir93853232014-03-05 21:32:20 +0000655// NOTE: in the tests below, we use '//root/' as our root directory, since it is
656// a legal *absolute* path on Windows as well as *nix.
Ben Langmuir97882e72014-02-24 20:56:37 +0000657class VFSFromYAMLTest : public ::testing::Test {
658public:
659 int NumDiagnostics;
Ben Langmuir93853232014-03-05 21:32:20 +0000660
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000661 void SetUp() override { NumDiagnostics = 0; }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000662
Ben Langmuir97882e72014-02-24 20:56:37 +0000663 static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
664 VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
665 ++Test->NumDiagnostics;
666 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000667
Ben Langmuir97882e72014-02-24 20:56:37 +0000668 IntrusiveRefCntPtr<vfs::FileSystem>
669 getFromYAMLRawString(StringRef Content,
670 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
Rafael Espindolad87f8d72014-08-27 20:03:29 +0000671 std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content);
Bruno Cardoso Lopesd878e282016-03-20 02:08:48 +0000672 return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, "", this,
Rafael Espindola91ac8df2014-08-17 23:27:13 +0000673 ExternalFS);
Ben Langmuir97882e72014-02-24 20:56:37 +0000674 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000675
Ben Langmuir97882e72014-02-24 20:56:37 +0000676 IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
677 StringRef Content,
678 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
679 std::string VersionPlusContent("{\n 'version':0,\n");
680 VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
681 return getFromYAMLRawString(VersionPlusContent, ExternalFS);
682 }
Ben Langmuir97882e72014-02-24 20:56:37 +0000683};
684
685TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000686 IntrusiveRefCntPtr<vfs::FileSystem> FS;
687 FS = getFromYAMLString("");
Alp Tokerf994cef2014-07-05 03:08:06 +0000688 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000689 FS = getFromYAMLString("[]");
Alp Tokerf994cef2014-07-05 03:08:06 +0000690 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000691 FS = getFromYAMLString("'string'");
Alp Tokerf994cef2014-07-05 03:08:06 +0000692 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000693 EXPECT_EQ(3, NumDiagnostics);
694}
695
Ben Langmuir97882e72014-02-24 20:56:37 +0000696TEST_F(VFSFromYAMLTest, MappedFiles) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000697 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000698 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000699 IntrusiveRefCntPtr<vfs::FileSystem> FS =
700 getFromYAMLString("{ 'roots': [\n"
701 "{\n"
702 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000703 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000704 " 'contents': [ {\n"
705 " 'type': 'file',\n"
706 " 'name': 'file1',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000707 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000708 " },\n"
709 " {\n"
710 " 'type': 'file',\n"
711 " 'name': 'file2',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000712 " 'external-contents': '//root/foo/b'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000713 " }\n"
714 " ]\n"
715 "}\n"
716 "]\n"
717 "}",
718 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000719 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000720
721 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
722 new vfs::OverlayFileSystem(Lower));
723 O->pushOverlay(FS);
724
725 // file
Ben Langmuir93853232014-03-05 21:32:20 +0000726 ErrorOr<vfs::Status> S = O->status("//root/file1");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000727 ASSERT_FALSE(S.getError());
Ben Langmuir93853232014-03-05 21:32:20 +0000728 EXPECT_EQ("//root/foo/bar/a", S->getName());
Ben Langmuirf13302e2015-12-10 23:41:39 +0000729 EXPECT_TRUE(S->IsVFSMapped);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000730
Ben Langmuir93853232014-03-05 21:32:20 +0000731 ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
732 EXPECT_EQ("//root/foo/bar/a", SLower->getName());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000733 EXPECT_TRUE(S->equivalent(*SLower));
Ben Langmuirf13302e2015-12-10 23:41:39 +0000734 EXPECT_FALSE(SLower->IsVFSMapped);
735
736 // file after opening
737 auto OpenedF = O->openFileForRead("//root/file1");
738 ASSERT_FALSE(OpenedF.getError());
739 auto OpenedS = (*OpenedF)->status();
740 ASSERT_FALSE(OpenedS.getError());
741 EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
742 EXPECT_TRUE(OpenedS->IsVFSMapped);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000743
744 // directory
Ben Langmuir93853232014-03-05 21:32:20 +0000745 S = O->status("//root/");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000746 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000747 EXPECT_TRUE(S->isDirectory());
Ben Langmuir93853232014-03-05 21:32:20 +0000748 EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000749
750 // broken mapping
Rafael Espindola71de0b62014-06-13 17:20:50 +0000751 EXPECT_EQ(O->status("//root/file2").getError(),
752 llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000753 EXPECT_EQ(0, NumDiagnostics);
754}
755
Ben Langmuir97882e72014-02-24 20:56:37 +0000756TEST_F(VFSFromYAMLTest, CaseInsensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000757 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000758 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000759 IntrusiveRefCntPtr<vfs::FileSystem> FS =
760 getFromYAMLString("{ 'case-sensitive': 'false',\n"
761 " 'roots': [\n"
762 "{\n"
763 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000764 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000765 " 'contents': [ {\n"
766 " 'type': 'file',\n"
767 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000768 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000769 " }\n"
770 " ]\n"
771 "}]}",
772 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000773 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000774
775 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
776 new vfs::OverlayFileSystem(Lower));
777 O->pushOverlay(FS);
778
Ben Langmuir93853232014-03-05 21:32:20 +0000779 ErrorOr<vfs::Status> S = O->status("//root/XX");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000780 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000781
Ben Langmuir93853232014-03-05 21:32:20 +0000782 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000783 ASSERT_FALSE(SS.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000784 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000785 SS = O->status("//root/xX");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000786 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000787 SS = O->status("//root/Xx");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000788 EXPECT_TRUE(S->equivalent(*SS));
789 EXPECT_EQ(0, NumDiagnostics);
790}
791
Ben Langmuir97882e72014-02-24 20:56:37 +0000792TEST_F(VFSFromYAMLTest, CaseSensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000793 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000794 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000795 IntrusiveRefCntPtr<vfs::FileSystem> FS =
796 getFromYAMLString("{ 'case-sensitive': 'true',\n"
797 " 'roots': [\n"
798 "{\n"
799 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000800 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000801 " 'contents': [ {\n"
802 " 'type': 'file',\n"
803 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000804 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000805 " }\n"
806 " ]\n"
807 "}]}",
808 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000809 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000810
811 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
812 new vfs::OverlayFileSystem(Lower));
813 O->pushOverlay(FS);
814
Ben Langmuir93853232014-03-05 21:32:20 +0000815 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000816 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000817 SS = O->status("//root/xX");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000818 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000819 SS = O->status("//root/Xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000820 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000821 EXPECT_EQ(0, NumDiagnostics);
822}
823
Ben Langmuir97882e72014-02-24 20:56:37 +0000824TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000825 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
826
827 // invalid YAML at top-level
828 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000829 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000830 // invalid YAML in roots
831 FS = getFromYAMLString("{ 'roots':[}", Lower);
832 // invalid YAML in directory
833 FS = getFromYAMLString(
834 "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
835 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000836 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000837
838 // invalid configuration
839 FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000840 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000841 FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000842 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000843
844 // invalid roots
845 FS = getFromYAMLString("{ 'roots':'' }", 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':{} }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000848 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000849
850 // invalid entries
851 FS = getFromYAMLString(
852 "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000853 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000854 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
855 "'external-contents': 'other' }",
856 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000857 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000858 FS = getFromYAMLString(
859 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
860 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000861 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000862 FS = getFromYAMLString(
863 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
864 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000865 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000866 FS = getFromYAMLString(
867 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
868 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000869 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000870 FS = getFromYAMLString(
871 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
872 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000873 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000874 FS = getFromYAMLString(
875 "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
876 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000877 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000878
879 // missing mandatory fields
880 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000881 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000882 FS = getFromYAMLString(
883 "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000884 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000885 FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000886 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000887
888 // duplicate keys
889 FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000890 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000891 FS = getFromYAMLString(
892 "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
893 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000894 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000895 FS =
896 getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
897 "'external-contents':'blah' } ] }",
898 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000899 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000900
901 // missing version
902 FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000903 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000904
905 // bad version number
906 FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000907 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000908 FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000909 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000910 FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000911 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000912 EXPECT_EQ(24, NumDiagnostics);
913}
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000914
Ben Langmuirb59cf672014-02-27 00:25:12 +0000915TEST_F(VFSFromYAMLTest, UseExternalName) {
916 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000917 Lower->addRegularFile("//root/external/file");
Ben Langmuirb59cf672014-02-27 00:25:12 +0000918
919 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
920 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000921 " { 'type': 'file', 'name': '//root/A',\n"
922 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000923 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000924 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000925 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000926 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000927 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000928 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000929 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000930 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000931 " }\n"
932 "] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000933 ASSERT_TRUE(nullptr != FS.get());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000934
935 // default true
Ben Langmuir93853232014-03-05 21:32:20 +0000936 EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000937 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000938 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
939 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000940
941 // global configuration
942 FS = getFromYAMLString(
943 "{ 'use-external-names': false,\n"
944 " 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000945 " { 'type': 'file', 'name': '//root/A',\n"
946 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000947 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000948 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000949 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000950 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000951 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000952 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000953 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000954 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000955 " }\n"
956 "] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000957 ASSERT_TRUE(nullptr != FS.get());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000958
959 // default
Ben Langmuir93853232014-03-05 21:32:20 +0000960 EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000961 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000962 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
963 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000964}
965
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000966TEST_F(VFSFromYAMLTest, MultiComponentPath) {
967 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000968 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000969
970 // file in roots
971 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
972 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000973 " { 'type': 'file', 'name': '//root/path/to/file',\n"
974 " 'external-contents': '//root/other' }]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000975 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000976 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000977 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
978 EXPECT_FALSE(FS->status("//root/path/to").getError());
979 EXPECT_FALSE(FS->status("//root/path").getError());
980 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000981
982 // at the start
983 FS = getFromYAMLString(
984 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000985 " { 'type': 'directory', 'name': '//root/path/to',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000986 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000987 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000988 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000989 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000990 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
991 EXPECT_FALSE(FS->status("//root/path/to").getError());
992 EXPECT_FALSE(FS->status("//root/path").getError());
993 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000994
995 // at the end
996 FS = getFromYAMLString(
997 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000998 " { 'type': 'directory', 'name': '//root/',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000999 " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +00001000 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001001 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +00001002 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +00001003 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
1004 EXPECT_FALSE(FS->status("//root/path/to").getError());
1005 EXPECT_FALSE(FS->status("//root/path").getError());
1006 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001007}
1008
1009TEST_F(VFSFromYAMLTest, TrailingSlashes) {
1010 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +00001011 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001012
1013 // file in roots
1014 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
1015 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +00001016 " { 'type': 'directory', 'name': '//root/path/to////',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001017 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +00001018 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001019 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +00001020 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +00001021 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
1022 EXPECT_FALSE(FS->status("//root/path/to").getError());
1023 EXPECT_FALSE(FS->status("//root/path").getError());
1024 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001025}
Ben Langmuir740812b2014-06-24 19:37:16 +00001026
1027TEST_F(VFSFromYAMLTest, DirectoryIteration) {
1028 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1029 Lower->addDirectory("//root/");
1030 Lower->addDirectory("//root/foo");
1031 Lower->addDirectory("//root/foo/bar");
1032 Lower->addRegularFile("//root/foo/bar/a");
1033 Lower->addRegularFile("//root/foo/bar/b");
1034 Lower->addRegularFile("//root/file3");
1035 IntrusiveRefCntPtr<vfs::FileSystem> FS =
1036 getFromYAMLString("{ 'use-external-names': false,\n"
1037 " 'roots': [\n"
1038 "{\n"
1039 " 'type': 'directory',\n"
1040 " 'name': '//root/',\n"
1041 " 'contents': [ {\n"
1042 " 'type': 'file',\n"
1043 " 'name': 'file1',\n"
1044 " 'external-contents': '//root/foo/bar/a'\n"
1045 " },\n"
1046 " {\n"
1047 " 'type': 'file',\n"
1048 " 'name': 'file2',\n"
1049 " 'external-contents': '//root/foo/bar/b'\n"
1050 " }\n"
1051 " ]\n"
1052 "}\n"
1053 "]\n"
1054 "}",
1055 Lower);
Hans Wennborgdcfba332015-10-06 23:40:43 +00001056 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuir740812b2014-06-24 19:37:16 +00001057
1058 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1059 new vfs::OverlayFileSystem(Lower));
1060 O->pushOverlay(FS);
1061
1062 std::error_code EC;
Benjamin Kramer2a23e552016-01-10 10:45:19 +00001063 checkContents(O->dir_begin("//root/", EC),
Sean Silva7e61e152016-05-11 04:04:59 +00001064 {"//root/file1", "//root/file2", "//root/file3", "//root/foo"});
Ben Langmuir740812b2014-06-24 19:37:16 +00001065
Benjamin Kramer2a23e552016-01-10 10:45:19 +00001066 checkContents(O->dir_begin("//root/foo/bar", EC),
1067 {"//root/foo/bar/a", "//root/foo/bar/b"});
Ben Langmuir740812b2014-06-24 19:37:16 +00001068}