blob: 67beb923d9764a9de6d01074b8caf99122a17996 [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>
17using namespace clang;
18using namespace llvm;
19using llvm::sys::fs::UniqueID;
20
21namespace {
22class DummyFileSystem : public vfs::FileSystem {
23 int FSID; // used to produce UniqueIDs
24 int FileID; // used to produce UniqueIDs
25 std::map<std::string, vfs::Status> FilesAndDirs;
26
27 static int getNextFSID() {
28 static int Count = 0;
29 return Count++;
30 }
31
32public:
33 DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
34
Fariborz Jahanian5afc8692014-10-01 16:56:40 +000035 ErrorOr<vfs::Status> status(const Twine &Path) override {
Ben Langmuirc8130a72014-02-20 21:59:23 +000036 std::map<std::string, vfs::Status>::iterator I =
Ben Langmuird51ba0b2014-02-21 23:39:37 +000037 FilesAndDirs.find(Path.str());
Ben Langmuirc8130a72014-02-20 21:59:23 +000038 if (I == FilesAndDirs.end())
Rafael Espindola71de0b62014-06-13 17:20:50 +000039 return make_error_code(llvm::errc::no_such_file_or_directory);
Ben Langmuirc8130a72014-02-20 21:59:23 +000040 return I->second;
41 }
Benjamin Kramera8857962014-10-26 22:44:13 +000042 ErrorOr<std::unique_ptr<vfs::File>>
43 openFileForRead(const Twine &Path) override {
Ben Langmuirc8130a72014-02-20 21:59:23 +000044 llvm_unreachable("unimplemented");
45 }
46
Ben Langmuir740812b2014-06-24 19:37:16 +000047 struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
48 std::map<std::string, vfs::Status> &FilesAndDirs;
49 std::map<std::string, vfs::Status>::iterator I;
50 std::string Path;
Ben Langmuir7c9f6c82014-06-25 20:25:40 +000051 bool isInPath(StringRef S) {
52 if (Path.size() < S.size() && S.find(Path) == 0) {
53 auto LastSep = S.find_last_of('/');
54 if (LastSep == Path.size() || LastSep == Path.size()-1)
55 return true;
56 }
57 return false;
58 }
Ben Langmuir740812b2014-06-24 19:37:16 +000059 DirIterImpl(std::map<std::string, vfs::Status> &FilesAndDirs,
60 const Twine &_Path)
61 : FilesAndDirs(FilesAndDirs), I(FilesAndDirs.begin()),
62 Path(_Path.str()) {
63 for ( ; I != FilesAndDirs.end(); ++I) {
Ben Langmuir7c9f6c82014-06-25 20:25:40 +000064 if (isInPath(I->first)) {
Ben Langmuir740812b2014-06-24 19:37:16 +000065 CurrentEntry = I->second;
66 break;
67 }
68 }
69 }
70 std::error_code increment() override {
71 ++I;
72 for ( ; I != FilesAndDirs.end(); ++I) {
Ben Langmuir7c9f6c82014-06-25 20:25:40 +000073 if (isInPath(I->first)) {
Ben Langmuir740812b2014-06-24 19:37:16 +000074 CurrentEntry = I->second;
75 break;
76 }
77 }
78 if (I == FilesAndDirs.end())
79 CurrentEntry = vfs::Status();
80 return std::error_code();
81 }
82 };
83
84 vfs::directory_iterator dir_begin(const Twine &Dir,
85 std::error_code &EC) override {
86 return vfs::directory_iterator(
87 std::make_shared<DirIterImpl>(FilesAndDirs, Dir));
88 }
89
Ben Langmuirc8130a72014-02-20 21:59:23 +000090 void addEntry(StringRef Path, const vfs::Status &Status) {
91 FilesAndDirs[Path] = Status;
92 }
93
Ben Langmuird51ba0b2014-02-21 23:39:37 +000094 void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
Ben Langmuirc8130a72014-02-20 21:59:23 +000095 vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
96 0, 0, 1024, sys::fs::file_type::regular_file, Perms);
97 addEntry(Path, S);
98 }
99
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000100 void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000101 vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
102 0, 0, 0, sys::fs::file_type::directory_file, Perms);
103 addEntry(Path, S);
104 }
105
106 void addSymlink(StringRef Path) {
107 vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
108 0, 0, 0, sys::fs::file_type::symlink_file, sys::fs::all_all);
109 addEntry(Path, S);
110 }
111};
112} // end anonymous namespace
113
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000114TEST(VirtualFileSystemTest, StatusQueries) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000115 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
Rafael Espindola8e650d72014-06-12 20:37:59 +0000116 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000117
118 D->addRegularFile("/foo");
119 Status = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000120 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000121 EXPECT_TRUE(Status->isStatusKnown());
122 EXPECT_FALSE(Status->isDirectory());
123 EXPECT_TRUE(Status->isRegularFile());
124 EXPECT_FALSE(Status->isSymlink());
125 EXPECT_FALSE(Status->isOther());
126 EXPECT_TRUE(Status->exists());
127
128 D->addDirectory("/bar");
129 Status = D->status("/bar");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000130 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000131 EXPECT_TRUE(Status->isStatusKnown());
132 EXPECT_TRUE(Status->isDirectory());
133 EXPECT_FALSE(Status->isRegularFile());
134 EXPECT_FALSE(Status->isSymlink());
135 EXPECT_FALSE(Status->isOther());
136 EXPECT_TRUE(Status->exists());
137
138 D->addSymlink("/baz");
139 Status = D->status("/baz");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000140 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000141 EXPECT_TRUE(Status->isStatusKnown());
142 EXPECT_FALSE(Status->isDirectory());
143 EXPECT_FALSE(Status->isRegularFile());
144 EXPECT_TRUE(Status->isSymlink());
145 EXPECT_FALSE(Status->isOther());
146 EXPECT_TRUE(Status->exists());
147
148 EXPECT_TRUE(Status->equivalent(*Status));
149 ErrorOr<vfs::Status> Status2 = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000150 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000151 EXPECT_FALSE(Status->equivalent(*Status2));
152}
153
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000154TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000155 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
Rafael Espindola8e650d72014-06-12 20:37:59 +0000156 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000157 EXPECT_FALSE(Status = D->status("/foo"));
158
159 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
160 EXPECT_FALSE(Status = O->status("/foo"));
161
162 D->addRegularFile("/foo");
163 Status = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000164 EXPECT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000165
Rafael Espindola8e650d72014-06-12 20:37:59 +0000166 ErrorOr<vfs::Status> Status2((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000167 Status2 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000168 EXPECT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000169 EXPECT_TRUE(Status->equivalent(*Status2));
170}
171
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000172TEST(VirtualFileSystemTest, OverlayFiles) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000173 IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
174 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
175 IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000176 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
177 new vfs::OverlayFileSystem(Base));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000178 O->pushOverlay(Middle);
179 O->pushOverlay(Top);
180
Rafael Espindola8e650d72014-06-12 20:37:59 +0000181 ErrorOr<vfs::Status> Status1((std::error_code())),
182 Status2((std::error_code())), Status3((std::error_code())),
183 StatusB((std::error_code())), StatusM((std::error_code())),
184 StatusT((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000185
186 Base->addRegularFile("/foo");
187 StatusB = Base->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000188 ASSERT_FALSE(StatusB.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000189 Status1 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000190 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000191 Middle->addRegularFile("/foo");
192 StatusM = Middle->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000193 ASSERT_FALSE(StatusM.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000194 Status2 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000195 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000196 Top->addRegularFile("/foo");
197 StatusT = Top->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000198 ASSERT_FALSE(StatusT.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000199 Status3 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000200 ASSERT_FALSE(Status3.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000201
202 EXPECT_TRUE(Status1->equivalent(*StatusB));
203 EXPECT_TRUE(Status2->equivalent(*StatusM));
204 EXPECT_TRUE(Status3->equivalent(*StatusT));
205
206 EXPECT_FALSE(Status1->equivalent(*Status2));
207 EXPECT_FALSE(Status2->equivalent(*Status3));
208 EXPECT_FALSE(Status1->equivalent(*Status3));
209}
210
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000211TEST(VirtualFileSystemTest, OverlayDirsNonMerged) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000212 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
213 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000214 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
215 new vfs::OverlayFileSystem(Lower));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000216 O->pushOverlay(Upper);
217
218 Lower->addDirectory("/lower-only");
219 Upper->addDirectory("/upper-only");
220
221 // non-merged paths should be the same
222 ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000223 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000224 ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000225 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000226 EXPECT_TRUE(Status1->equivalent(*Status2));
227
228 Status1 = Upper->status("/upper-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000229 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000230 Status2 = O->status("/upper-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000231 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000232 EXPECT_TRUE(Status1->equivalent(*Status2));
233}
234
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000235TEST(VirtualFileSystemTest, MergedDirPermissions) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000236 // merged directories get the permissions of the upper dir
237 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
238 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000239 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
240 new vfs::OverlayFileSystem(Lower));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000241 O->pushOverlay(Upper);
242
Rafael Espindola8e650d72014-06-12 20:37:59 +0000243 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000244 Lower->addDirectory("/both", sys::fs::owner_read);
245 Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
246 Status = O->status("/both");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000247 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000248 EXPECT_EQ(0740, Status->getPermissions());
249
250 // permissions (as usual) are not recursively applied
251 Lower->addRegularFile("/both/foo", sys::fs::owner_read);
252 Upper->addRegularFile("/both/bar", sys::fs::owner_write);
253 Status = O->status("/both/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000254 ASSERT_FALSE( Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000255 EXPECT_EQ(0400, Status->getPermissions());
256 Status = O->status("/both/bar");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000257 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000258 EXPECT_EQ(0200, Status->getPermissions());
259}
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000260
Ben Langmuir740812b2014-06-24 19:37:16 +0000261namespace {
262struct ScopedDir {
263 SmallString<128> Path;
264 ScopedDir(const Twine &Name, bool Unique=false) {
265 std::error_code EC;
266 if (Unique) {
267 EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
268 } else {
269 Path = Name.str();
270 EC = llvm::sys::fs::create_directory(Twine(Path));
271 }
272 if (EC)
273 Path = "";
274 EXPECT_FALSE(EC);
275 }
276 ~ScopedDir() {
277 if (Path != "")
278 EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
279 }
280 operator StringRef() { return Path.str(); }
281};
282}
283
284TEST(VirtualFileSystemTest, BasicRealFSIteration) {
285 ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
286 IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
287
288 std::error_code EC;
289 vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC);
290 ASSERT_FALSE(EC);
291 EXPECT_EQ(vfs::directory_iterator(), I); // empty directory is empty
292
293 ScopedDir _a(TestDirectory+"/a");
294 ScopedDir _ab(TestDirectory+"/a/b");
295 ScopedDir _c(TestDirectory+"/c");
296 ScopedDir _cd(TestDirectory+"/c/d");
297
298 I = FS->dir_begin(Twine(TestDirectory), EC);
299 ASSERT_FALSE(EC);
300 ASSERT_NE(vfs::directory_iterator(), I);
Ben Langmuirefb8b602014-06-24 21:08:13 +0000301 // Check either a or c, since we can't rely on the iteration order.
302 EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000303 I.increment(EC);
304 ASSERT_FALSE(EC);
305 ASSERT_NE(vfs::directory_iterator(), I);
Ben Langmuirefb8b602014-06-24 21:08:13 +0000306 EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000307 I.increment(EC);
308 EXPECT_EQ(vfs::directory_iterator(), I);
309}
310
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000311TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) {
312 ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
313 IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
314
315 std::error_code EC;
316 auto I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
317 ASSERT_FALSE(EC);
318 EXPECT_EQ(vfs::recursive_directory_iterator(), I); // empty directory is empty
319
320 ScopedDir _a(TestDirectory+"/a");
321 ScopedDir _ab(TestDirectory+"/a/b");
322 ScopedDir _c(TestDirectory+"/c");
323 ScopedDir _cd(TestDirectory+"/c/d");
324
325 I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
326 ASSERT_FALSE(EC);
327 ASSERT_NE(vfs::recursive_directory_iterator(), I);
328
329
330 std::vector<std::string> Contents;
331 for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
332 I.increment(EC)) {
333 Contents.push_back(I->getName());
334 }
335
336 // Check contents, which may be in any order
337 EXPECT_EQ(4U, Contents.size());
338 int Counts[4] = { 0, 0, 0, 0 };
339 for (const std::string &Name : Contents) {
340 ASSERT_FALSE(Name.empty());
341 int Index = Name[Name.size()-1] - 'a';
342 ASSERT_TRUE(Index >= 0 && Index < 4);
343 Counts[Index]++;
344 }
345 EXPECT_EQ(1, Counts[0]); // a
346 EXPECT_EQ(1, Counts[1]); // b
347 EXPECT_EQ(1, Counts[2]); // c
348 EXPECT_EQ(1, Counts[3]); // d
349}
350
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000351template <typename T, size_t N>
352std::vector<StringRef> makeStringRefVector(const T (&Arr)[N]) {
353 std::vector<StringRef> Vec;
354 for (size_t i = 0; i != N; ++i)
355 Vec.push_back(Arr[i]);
356 return Vec;
357}
358
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000359template <typename DirIter>
360static void checkContents(DirIter I, ArrayRef<StringRef> Expected) {
Ben Langmuir740812b2014-06-24 19:37:16 +0000361 std::error_code EC;
362 auto ExpectedIter = Expected.begin(), ExpectedEnd = Expected.end();
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000363 for (DirIter E;
Ben Langmuir740812b2014-06-24 19:37:16 +0000364 !EC && I != E && ExpectedIter != ExpectedEnd;
365 I.increment(EC), ++ExpectedIter)
366 EXPECT_EQ(*ExpectedIter, I->getName());
367
368 EXPECT_EQ(ExpectedEnd, ExpectedIter);
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000369 EXPECT_EQ(DirIter(), I);
Ben Langmuir740812b2014-06-24 19:37:16 +0000370}
371
372TEST(VirtualFileSystemTest, OverlayIteration) {
373 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
374 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
375 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
376 new vfs::OverlayFileSystem(Lower));
377 O->pushOverlay(Upper);
378
379 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000380 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000381
382 Lower->addRegularFile("/file1");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000383 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000384
385 Upper->addRegularFile("/file2");
386 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000387 const char *Contents[] = {"/file2", "/file1"};
388 checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000389 }
390
391 Lower->addDirectory("/dir1");
392 Lower->addRegularFile("/dir1/foo");
393 Upper->addDirectory("/dir2");
394 Upper->addRegularFile("/dir2/foo");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000395 checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000396 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000397 const char *Contents[] = {"/dir2", "/file2", "/dir1", "/file1"};
398 checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000399 }
400}
401
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000402TEST(VirtualFileSystemTest, OverlayRecursiveIteration) {
403 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
404 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
405 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
406 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
407 new vfs::OverlayFileSystem(Lower));
408 O->pushOverlay(Middle);
409 O->pushOverlay(Upper);
410
411 std::error_code EC;
412 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
413 ArrayRef<StringRef>());
414
415 Lower->addRegularFile("/file1");
416 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
417 ArrayRef<StringRef>("/file1"));
418
419 Upper->addDirectory("/dir");
420 Upper->addRegularFile("/dir/file2");
421 {
422 const char *Contents[] = {"/dir", "/dir/file2", "/file1"};
423 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
424 makeStringRefVector(Contents));
425 }
426
427 Lower->addDirectory("/dir1");
428 Lower->addRegularFile("/dir1/foo");
429 Lower->addDirectory("/dir1/a");
430 Lower->addRegularFile("/dir1/a/b");
431 Middle->addDirectory("/a");
432 Middle->addDirectory("/a/b");
433 Middle->addDirectory("/a/b/c");
434 Middle->addRegularFile("/a/b/c/d");
435 Middle->addRegularFile("/hiddenByUp");
436 Upper->addDirectory("/dir2");
437 Upper->addRegularFile("/dir2/foo");
438 Upper->addRegularFile("/hiddenByUp");
439 checkContents(vfs::recursive_directory_iterator(*O, "/dir2", EC),
440 ArrayRef<StringRef>("/dir2/foo"));
441 {
442 const char *Contents[] = { "/dir", "/dir/file2", "/dir2", "/dir2/foo",
443 "/hiddenByUp", "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/dir1", "/dir1/a",
444 "/dir1/a/b", "/dir1/foo", "/file1" };
445 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
446 makeStringRefVector(Contents));
447 }
448}
449
Ben Langmuir740812b2014-06-24 19:37:16 +0000450TEST(VirtualFileSystemTest, ThreeLevelIteration) {
451 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
452 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
453 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
454 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
455 new vfs::OverlayFileSystem(Lower));
456 O->pushOverlay(Middle);
457 O->pushOverlay(Upper);
458
459 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000460 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000461
462 Middle->addRegularFile("/file2");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000463 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000464
465 Lower->addRegularFile("/file1");
466 Upper->addRegularFile("/file3");
467 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000468 const char *Contents[] = {"/file3", "/file2", "/file1"};
469 checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000470 }
471}
472
473TEST(VirtualFileSystemTest, HiddenInIteration) {
474 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
475 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
476 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
477 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
478 new vfs::OverlayFileSystem(Lower));
479 O->pushOverlay(Middle);
480 O->pushOverlay(Upper);
481
482 std::error_code EC;
483 Lower->addRegularFile("/onlyInLow", sys::fs::owner_read);
484 Lower->addRegularFile("/hiddenByMid", sys::fs::owner_read);
485 Lower->addRegularFile("/hiddenByUp", sys::fs::owner_read);
486 Middle->addRegularFile("/onlyInMid", sys::fs::owner_write);
487 Middle->addRegularFile("/hiddenByMid", sys::fs::owner_write);
488 Middle->addRegularFile("/hiddenByUp", sys::fs::owner_write);
489 Upper->addRegularFile("/onlyInUp", sys::fs::owner_all);
490 Upper->addRegularFile("/hiddenByUp", sys::fs::owner_all);
491 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000492 const char *Contents[] = {"/hiddenByUp", "/onlyInUp", "/hiddenByMid",
493 "/onlyInMid", "/onlyInLow"};
494 checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000495 }
496
497 // Make sure we get the top-most entry
Ben Langmuirefb8b602014-06-24 21:08:13 +0000498 {
499 std::error_code EC;
500 vfs::directory_iterator I = O->dir_begin("/", EC), E;
501 for ( ; !EC && I != E; I.increment(EC))
502 if (I->getName() == "/hiddenByUp")
503 break;
504 ASSERT_NE(E, I);
505 EXPECT_EQ(sys::fs::owner_all, I->getPermissions());
506 }
507 {
508 std::error_code EC;
509 vfs::directory_iterator I = O->dir_begin("/", EC), E;
510 for ( ; !EC && I != E; I.increment(EC))
511 if (I->getName() == "/hiddenByMid")
512 break;
513 ASSERT_NE(E, I);
514 EXPECT_EQ(sys::fs::owner_write, I->getPermissions());
515 }
Ben Langmuir740812b2014-06-24 19:37:16 +0000516}
517
Ben Langmuir93853232014-03-05 21:32:20 +0000518// NOTE: in the tests below, we use '//root/' as our root directory, since it is
519// a legal *absolute* path on Windows as well as *nix.
Ben Langmuir97882e72014-02-24 20:56:37 +0000520class VFSFromYAMLTest : public ::testing::Test {
521public:
522 int NumDiagnostics;
Ben Langmuir93853232014-03-05 21:32:20 +0000523
Ben Langmuir97882e72014-02-24 20:56:37 +0000524 void SetUp() {
525 NumDiagnostics = 0;
526 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000527
Ben Langmuir97882e72014-02-24 20:56:37 +0000528 static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
529 VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
530 ++Test->NumDiagnostics;
531 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000532
Ben Langmuir97882e72014-02-24 20:56:37 +0000533 IntrusiveRefCntPtr<vfs::FileSystem>
534 getFromYAMLRawString(StringRef Content,
535 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
Rafael Espindolad87f8d72014-08-27 20:03:29 +0000536 std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content);
Rafael Espindola91ac8df2014-08-17 23:27:13 +0000537 return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, this,
538 ExternalFS);
Ben Langmuir97882e72014-02-24 20:56:37 +0000539 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000540
Ben Langmuir97882e72014-02-24 20:56:37 +0000541 IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
542 StringRef Content,
543 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
544 std::string VersionPlusContent("{\n 'version':0,\n");
545 VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
546 return getFromYAMLRawString(VersionPlusContent, ExternalFS);
547 }
Ben Langmuir97882e72014-02-24 20:56:37 +0000548};
549
550TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000551 IntrusiveRefCntPtr<vfs::FileSystem> FS;
552 FS = getFromYAMLString("");
Alp Tokerf994cef2014-07-05 03:08:06 +0000553 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000554 FS = getFromYAMLString("[]");
Alp Tokerf994cef2014-07-05 03:08:06 +0000555 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000556 FS = getFromYAMLString("'string'");
Alp Tokerf994cef2014-07-05 03:08:06 +0000557 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000558 EXPECT_EQ(3, NumDiagnostics);
559}
560
Ben Langmuir97882e72014-02-24 20:56:37 +0000561TEST_F(VFSFromYAMLTest, MappedFiles) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000562 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000563 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000564 IntrusiveRefCntPtr<vfs::FileSystem> FS =
565 getFromYAMLString("{ 'roots': [\n"
566 "{\n"
567 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000568 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000569 " 'contents': [ {\n"
570 " 'type': 'file',\n"
571 " 'name': 'file1',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000572 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000573 " },\n"
574 " {\n"
575 " 'type': 'file',\n"
576 " 'name': 'file2',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000577 " 'external-contents': '//root/foo/b'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000578 " }\n"
579 " ]\n"
580 "}\n"
581 "]\n"
582 "}",
583 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000584 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000585
586 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
587 new vfs::OverlayFileSystem(Lower));
588 O->pushOverlay(FS);
589
590 // file
Ben Langmuir93853232014-03-05 21:32:20 +0000591 ErrorOr<vfs::Status> S = O->status("//root/file1");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000592 ASSERT_FALSE(S.getError());
Ben Langmuir93853232014-03-05 21:32:20 +0000593 EXPECT_EQ("//root/foo/bar/a", S->getName());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000594
Ben Langmuir93853232014-03-05 21:32:20 +0000595 ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
596 EXPECT_EQ("//root/foo/bar/a", SLower->getName());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000597 EXPECT_TRUE(S->equivalent(*SLower));
598
599 // directory
Ben Langmuir93853232014-03-05 21:32:20 +0000600 S = O->status("//root/");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000601 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000602 EXPECT_TRUE(S->isDirectory());
Ben Langmuir93853232014-03-05 21:32:20 +0000603 EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000604
605 // broken mapping
Rafael Espindola71de0b62014-06-13 17:20:50 +0000606 EXPECT_EQ(O->status("//root/file2").getError(),
607 llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000608 EXPECT_EQ(0, NumDiagnostics);
609}
610
Ben Langmuir97882e72014-02-24 20:56:37 +0000611TEST_F(VFSFromYAMLTest, CaseInsensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000612 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000613 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000614 IntrusiveRefCntPtr<vfs::FileSystem> FS =
615 getFromYAMLString("{ 'case-sensitive': 'false',\n"
616 " 'roots': [\n"
617 "{\n"
618 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000619 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000620 " 'contents': [ {\n"
621 " 'type': 'file',\n"
622 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000623 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000624 " }\n"
625 " ]\n"
626 "}]}",
627 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000628 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000629
630 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
631 new vfs::OverlayFileSystem(Lower));
632 O->pushOverlay(FS);
633
Ben Langmuir93853232014-03-05 21:32:20 +0000634 ErrorOr<vfs::Status> S = O->status("//root/XX");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000635 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000636
Ben Langmuir93853232014-03-05 21:32:20 +0000637 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000638 ASSERT_FALSE(SS.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000639 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000640 SS = O->status("//root/xX");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000641 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000642 SS = O->status("//root/Xx");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000643 EXPECT_TRUE(S->equivalent(*SS));
644 EXPECT_EQ(0, NumDiagnostics);
645}
646
Ben Langmuir97882e72014-02-24 20:56:37 +0000647TEST_F(VFSFromYAMLTest, CaseSensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000648 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000649 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000650 IntrusiveRefCntPtr<vfs::FileSystem> FS =
651 getFromYAMLString("{ 'case-sensitive': 'true',\n"
652 " 'roots': [\n"
653 "{\n"
654 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000655 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000656 " 'contents': [ {\n"
657 " 'type': 'file',\n"
658 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000659 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000660 " }\n"
661 " ]\n"
662 "}]}",
663 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000664 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000665
666 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
667 new vfs::OverlayFileSystem(Lower));
668 O->pushOverlay(FS);
669
Ben Langmuir93853232014-03-05 21:32:20 +0000670 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000671 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000672 SS = O->status("//root/xX");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000673 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000674 SS = O->status("//root/Xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000675 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000676 EXPECT_EQ(0, NumDiagnostics);
677}
678
Ben Langmuir97882e72014-02-24 20:56:37 +0000679TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000680 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
681
682 // invalid YAML at top-level
683 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000684 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000685 // invalid YAML in roots
686 FS = getFromYAMLString("{ 'roots':[}", Lower);
687 // invalid YAML in directory
688 FS = getFromYAMLString(
689 "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
690 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000691 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000692
693 // invalid configuration
694 FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000695 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000696 FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000697 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000698
699 // invalid roots
700 FS = getFromYAMLString("{ 'roots':'' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000701 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000702 FS = getFromYAMLString("{ 'roots':{} }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000703 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000704
705 // invalid entries
706 FS = getFromYAMLString(
707 "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000708 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000709 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
710 "'external-contents': 'other' }",
711 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000712 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000713 FS = getFromYAMLString(
714 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
715 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000716 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000717 FS = getFromYAMLString(
718 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
719 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000720 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000721 FS = getFromYAMLString(
722 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
723 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000724 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000725 FS = getFromYAMLString(
726 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
727 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000728 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000729 FS = getFromYAMLString(
730 "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
731 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000732 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000733
734 // missing mandatory fields
735 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000736 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000737 FS = getFromYAMLString(
738 "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000739 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000740 FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000741 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000742
743 // duplicate keys
744 FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000745 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000746 FS = getFromYAMLString(
747 "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
748 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000749 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000750 FS =
751 getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
752 "'external-contents':'blah' } ] }",
753 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000754 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000755
756 // missing version
757 FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000758 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000759
760 // bad version number
761 FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000762 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000763 FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000764 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000765 FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000766 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000767 EXPECT_EQ(24, NumDiagnostics);
768}
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000769
Ben Langmuirb59cf672014-02-27 00:25:12 +0000770TEST_F(VFSFromYAMLTest, UseExternalName) {
771 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000772 Lower->addRegularFile("//root/external/file");
Ben Langmuirb59cf672014-02-27 00:25:12 +0000773
774 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
775 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000776 " { 'type': 'file', 'name': '//root/A',\n"
777 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000778 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000779 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000780 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000781 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000782 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000783 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000784 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000785 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000786 " }\n"
787 "] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000788 ASSERT_TRUE(nullptr != FS.get());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000789
790 // default true
Ben Langmuir93853232014-03-05 21:32:20 +0000791 EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000792 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000793 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
794 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000795
796 // global configuration
797 FS = getFromYAMLString(
798 "{ 'use-external-names': false,\n"
799 " 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000800 " { 'type': 'file', 'name': '//root/A',\n"
801 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000802 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000803 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000804 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000805 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000806 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000807 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000808 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000809 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000810 " }\n"
811 "] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000812 ASSERT_TRUE(nullptr != FS.get());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000813
814 // default
Ben Langmuir93853232014-03-05 21:32:20 +0000815 EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000816 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000817 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
818 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000819}
820
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000821TEST_F(VFSFromYAMLTest, MultiComponentPath) {
822 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000823 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000824
825 // file in roots
826 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
827 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000828 " { 'type': 'file', 'name': '//root/path/to/file',\n"
829 " 'external-contents': '//root/other' }]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000830 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000831 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000832 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
833 EXPECT_FALSE(FS->status("//root/path/to").getError());
834 EXPECT_FALSE(FS->status("//root/path").getError());
835 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000836
837 // at the start
838 FS = getFromYAMLString(
839 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000840 " { 'type': 'directory', 'name': '//root/path/to',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000841 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000842 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000843 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000844 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000845 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
846 EXPECT_FALSE(FS->status("//root/path/to").getError());
847 EXPECT_FALSE(FS->status("//root/path").getError());
848 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000849
850 // at the end
851 FS = getFromYAMLString(
852 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000853 " { 'type': 'directory', 'name': '//root/',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000854 " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000855 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000856 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000857 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000858 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
859 EXPECT_FALSE(FS->status("//root/path/to").getError());
860 EXPECT_FALSE(FS->status("//root/path").getError());
861 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000862}
863
864TEST_F(VFSFromYAMLTest, TrailingSlashes) {
865 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000866 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000867
868 // file in roots
869 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
870 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000871 " { 'type': 'directory', 'name': '//root/path/to////',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000872 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000873 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000874 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000875 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000876 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
877 EXPECT_FALSE(FS->status("//root/path/to").getError());
878 EXPECT_FALSE(FS->status("//root/path").getError());
879 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000880}
Ben Langmuir740812b2014-06-24 19:37:16 +0000881
882TEST_F(VFSFromYAMLTest, DirectoryIteration) {
883 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
884 Lower->addDirectory("//root/");
885 Lower->addDirectory("//root/foo");
886 Lower->addDirectory("//root/foo/bar");
887 Lower->addRegularFile("//root/foo/bar/a");
888 Lower->addRegularFile("//root/foo/bar/b");
889 Lower->addRegularFile("//root/file3");
890 IntrusiveRefCntPtr<vfs::FileSystem> FS =
891 getFromYAMLString("{ 'use-external-names': false,\n"
892 " 'roots': [\n"
893 "{\n"
894 " 'type': 'directory',\n"
895 " 'name': '//root/',\n"
896 " 'contents': [ {\n"
897 " 'type': 'file',\n"
898 " 'name': 'file1',\n"
899 " 'external-contents': '//root/foo/bar/a'\n"
900 " },\n"
901 " {\n"
902 " 'type': 'file',\n"
903 " 'name': 'file2',\n"
904 " 'external-contents': '//root/foo/bar/b'\n"
905 " }\n"
906 " ]\n"
907 "}\n"
908 "]\n"
909 "}",
910 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000911 ASSERT_TRUE(FS.get() != NULL);
Ben Langmuir740812b2014-06-24 19:37:16 +0000912
913 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
914 new vfs::OverlayFileSystem(Lower));
915 O->pushOverlay(FS);
916
917 std::error_code EC;
918 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000919 const char *Contents[] = {"//root/file1", "//root/file2", "//root/file3",
920 "//root/foo"};
921 checkContents(O->dir_begin("//root/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000922 }
923
924 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000925 const char *Contents[] = {"//root/foo/bar/a", "//root/foo/bar/b"};
926 checkContents(O->dir_begin("//root/foo/bar", EC),
927 makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000928 }
929}