blob: 63e9c42047f0b2aa7cba15dd01641f7cdfd4e693 [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
35 ErrorOr<vfs::Status> status(const Twine &Path) {
36 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 }
Rafael Espindola8e650d72014-06-12 20:37:59 +000042 std::error_code openFileForRead(const Twine &Path,
43 std::unique_ptr<vfs::File> &Result) {
Ben Langmuirc8130a72014-02-20 21:59:23 +000044 llvm_unreachable("unimplemented");
45 }
Rafael Espindola8e650d72014-06-12 20:37:59 +000046 std::error_code getBufferForFile(const Twine &Name,
47 std::unique_ptr<MemoryBuffer> &Result,
48 int64_t FileSize = -1,
49 bool RequiresNullTerminator = true) {
Ben Langmuirc8130a72014-02-20 21:59:23 +000050 llvm_unreachable("unimplemented");
51 }
52
Ben Langmuir740812b2014-06-24 19:37:16 +000053 struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
54 std::map<std::string, vfs::Status> &FilesAndDirs;
55 std::map<std::string, vfs::Status>::iterator I;
56 std::string Path;
57 DirIterImpl(std::map<std::string, vfs::Status> &FilesAndDirs,
58 const Twine &_Path)
59 : FilesAndDirs(FilesAndDirs), I(FilesAndDirs.begin()),
60 Path(_Path.str()) {
61 for ( ; I != FilesAndDirs.end(); ++I) {
62 if (Path.size() < I->first.size() && I->first.find(Path) == 0 && I->first.find_last_of('/') <= Path.size()) {
63 CurrentEntry = I->second;
64 break;
65 }
66 }
67 }
68 std::error_code increment() override {
69 ++I;
70 for ( ; I != FilesAndDirs.end(); ++I) {
71 if (Path.size() < I->first.size() && I->first.find(Path) == 0 && I->first.find_last_of('/') <= Path.size()) {
72 CurrentEntry = I->second;
73 break;
74 }
75 }
76 if (I == FilesAndDirs.end())
77 CurrentEntry = vfs::Status();
78 return std::error_code();
79 }
80 };
81
82 vfs::directory_iterator dir_begin(const Twine &Dir,
83 std::error_code &EC) override {
84 return vfs::directory_iterator(
85 std::make_shared<DirIterImpl>(FilesAndDirs, Dir));
86 }
87
Ben Langmuirc8130a72014-02-20 21:59:23 +000088 void addEntry(StringRef Path, const vfs::Status &Status) {
89 FilesAndDirs[Path] = Status;
90 }
91
Ben Langmuird51ba0b2014-02-21 23:39:37 +000092 void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
Ben Langmuirc8130a72014-02-20 21:59:23 +000093 vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
94 0, 0, 1024, sys::fs::file_type::regular_file, Perms);
95 addEntry(Path, S);
96 }
97
Ben Langmuird51ba0b2014-02-21 23:39:37 +000098 void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
Ben Langmuirc8130a72014-02-20 21:59:23 +000099 vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
100 0, 0, 0, sys::fs::file_type::directory_file, Perms);
101 addEntry(Path, S);
102 }
103
104 void addSymlink(StringRef Path) {
105 vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
106 0, 0, 0, sys::fs::file_type::symlink_file, sys::fs::all_all);
107 addEntry(Path, S);
108 }
109};
110} // end anonymous namespace
111
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000112TEST(VirtualFileSystemTest, StatusQueries) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000113 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
Rafael Espindola8e650d72014-06-12 20:37:59 +0000114 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000115
116 D->addRegularFile("/foo");
117 Status = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000118 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000119 EXPECT_TRUE(Status->isStatusKnown());
120 EXPECT_FALSE(Status->isDirectory());
121 EXPECT_TRUE(Status->isRegularFile());
122 EXPECT_FALSE(Status->isSymlink());
123 EXPECT_FALSE(Status->isOther());
124 EXPECT_TRUE(Status->exists());
125
126 D->addDirectory("/bar");
127 Status = D->status("/bar");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000128 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000129 EXPECT_TRUE(Status->isStatusKnown());
130 EXPECT_TRUE(Status->isDirectory());
131 EXPECT_FALSE(Status->isRegularFile());
132 EXPECT_FALSE(Status->isSymlink());
133 EXPECT_FALSE(Status->isOther());
134 EXPECT_TRUE(Status->exists());
135
136 D->addSymlink("/baz");
137 Status = D->status("/baz");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000138 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000139 EXPECT_TRUE(Status->isStatusKnown());
140 EXPECT_FALSE(Status->isDirectory());
141 EXPECT_FALSE(Status->isRegularFile());
142 EXPECT_TRUE(Status->isSymlink());
143 EXPECT_FALSE(Status->isOther());
144 EXPECT_TRUE(Status->exists());
145
146 EXPECT_TRUE(Status->equivalent(*Status));
147 ErrorOr<vfs::Status> Status2 = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000148 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000149 EXPECT_FALSE(Status->equivalent(*Status2));
150}
151
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000152TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000153 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
Rafael Espindola8e650d72014-06-12 20:37:59 +0000154 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000155 EXPECT_FALSE(Status = D->status("/foo"));
156
157 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
158 EXPECT_FALSE(Status = O->status("/foo"));
159
160 D->addRegularFile("/foo");
161 Status = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000162 EXPECT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000163
Rafael Espindola8e650d72014-06-12 20:37:59 +0000164 ErrorOr<vfs::Status> Status2((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000165 Status2 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000166 EXPECT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000167 EXPECT_TRUE(Status->equivalent(*Status2));
168}
169
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000170TEST(VirtualFileSystemTest, OverlayFiles) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000171 IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
172 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
173 IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000174 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
175 new vfs::OverlayFileSystem(Base));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000176 O->pushOverlay(Middle);
177 O->pushOverlay(Top);
178
Rafael Espindola8e650d72014-06-12 20:37:59 +0000179 ErrorOr<vfs::Status> Status1((std::error_code())),
180 Status2((std::error_code())), Status3((std::error_code())),
181 StatusB((std::error_code())), StatusM((std::error_code())),
182 StatusT((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000183
184 Base->addRegularFile("/foo");
185 StatusB = Base->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000186 ASSERT_FALSE(StatusB.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000187 Status1 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000188 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000189 Middle->addRegularFile("/foo");
190 StatusM = Middle->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000191 ASSERT_FALSE(StatusM.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000192 Status2 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000193 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000194 Top->addRegularFile("/foo");
195 StatusT = Top->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000196 ASSERT_FALSE(StatusT.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000197 Status3 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000198 ASSERT_FALSE(Status3.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000199
200 EXPECT_TRUE(Status1->equivalent(*StatusB));
201 EXPECT_TRUE(Status2->equivalent(*StatusM));
202 EXPECT_TRUE(Status3->equivalent(*StatusT));
203
204 EXPECT_FALSE(Status1->equivalent(*Status2));
205 EXPECT_FALSE(Status2->equivalent(*Status3));
206 EXPECT_FALSE(Status1->equivalent(*Status3));
207}
208
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000209TEST(VirtualFileSystemTest, OverlayDirsNonMerged) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000210 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
211 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000212 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
213 new vfs::OverlayFileSystem(Lower));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000214 O->pushOverlay(Upper);
215
216 Lower->addDirectory("/lower-only");
217 Upper->addDirectory("/upper-only");
218
219 // non-merged paths should be the same
220 ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000221 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000222 ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000223 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000224 EXPECT_TRUE(Status1->equivalent(*Status2));
225
226 Status1 = Upper->status("/upper-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000227 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000228 Status2 = O->status("/upper-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000229 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000230 EXPECT_TRUE(Status1->equivalent(*Status2));
231}
232
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000233TEST(VirtualFileSystemTest, MergedDirPermissions) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000234 // merged directories get the permissions of the upper dir
235 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
236 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000237 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
238 new vfs::OverlayFileSystem(Lower));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000239 O->pushOverlay(Upper);
240
Rafael Espindola8e650d72014-06-12 20:37:59 +0000241 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000242 Lower->addDirectory("/both", sys::fs::owner_read);
243 Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
244 Status = O->status("/both");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000245 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000246 EXPECT_EQ(0740, Status->getPermissions());
247
248 // permissions (as usual) are not recursively applied
249 Lower->addRegularFile("/both/foo", sys::fs::owner_read);
250 Upper->addRegularFile("/both/bar", sys::fs::owner_write);
251 Status = O->status("/both/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000252 ASSERT_FALSE( Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000253 EXPECT_EQ(0400, Status->getPermissions());
254 Status = O->status("/both/bar");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000255 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000256 EXPECT_EQ(0200, Status->getPermissions());
257}
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000258
Ben Langmuir740812b2014-06-24 19:37:16 +0000259namespace {
260struct ScopedDir {
261 SmallString<128> Path;
262 ScopedDir(const Twine &Name, bool Unique=false) {
263 std::error_code EC;
264 if (Unique) {
265 EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
266 } else {
267 Path = Name.str();
268 EC = llvm::sys::fs::create_directory(Twine(Path));
269 }
270 if (EC)
271 Path = "";
272 EXPECT_FALSE(EC);
273 }
274 ~ScopedDir() {
275 if (Path != "")
276 EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
277 }
278 operator StringRef() { return Path.str(); }
279};
280}
281
282TEST(VirtualFileSystemTest, BasicRealFSIteration) {
283 ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
284 IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
285
286 std::error_code EC;
287 vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC);
288 ASSERT_FALSE(EC);
289 EXPECT_EQ(vfs::directory_iterator(), I); // empty directory is empty
290
291 ScopedDir _a(TestDirectory+"/a");
292 ScopedDir _ab(TestDirectory+"/a/b");
293 ScopedDir _c(TestDirectory+"/c");
294 ScopedDir _cd(TestDirectory+"/c/d");
295
296 I = FS->dir_begin(Twine(TestDirectory), EC);
297 ASSERT_FALSE(EC);
298 ASSERT_NE(vfs::directory_iterator(), I);
299 EXPECT_TRUE(I->getName().endswith("a"));
300 I.increment(EC);
301 ASSERT_FALSE(EC);
302 ASSERT_NE(vfs::directory_iterator(), I);
303 EXPECT_TRUE(I->getName().endswith("c"));
304 I.increment(EC);
305 EXPECT_EQ(vfs::directory_iterator(), I);
306}
307
308static void checkContents(vfs::directory_iterator I,
309 ArrayRef<std::string> Expected) {
310 std::error_code EC;
311 auto ExpectedIter = Expected.begin(), ExpectedEnd = Expected.end();
312 for (vfs::directory_iterator E;
313 !EC && I != E && ExpectedIter != ExpectedEnd;
314 I.increment(EC), ++ExpectedIter)
315 EXPECT_EQ(*ExpectedIter, I->getName());
316
317 EXPECT_EQ(ExpectedEnd, ExpectedIter);
318 EXPECT_EQ(vfs::directory_iterator(), I);
319}
320
321TEST(VirtualFileSystemTest, OverlayIteration) {
322 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
323 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
324 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
325 new vfs::OverlayFileSystem(Lower));
326 O->pushOverlay(Upper);
327
328 std::error_code EC;
329 checkContents(O->dir_begin("/", EC), ArrayRef<std::string>());
330
331 Lower->addRegularFile("/file1");
332 checkContents(O->dir_begin("/", EC), ArrayRef<std::string>("/file1"));
333
334 Upper->addRegularFile("/file2");
335 {
336 std::vector<std::string> Contents = { "/file2", "/file1" };
337 checkContents(O->dir_begin("/", EC), Contents);
338 }
339
340 Lower->addDirectory("/dir1");
341 Lower->addRegularFile("/dir1/foo");
342 Upper->addDirectory("/dir2");
343 Upper->addRegularFile("/dir2/foo");
344 checkContents(O->dir_begin("/dir2", EC), ArrayRef<std::string>("/dir2/foo"));
345 {
346 std::vector<std::string> Contents = { "/dir2", "/file2", "/dir1", "/file1" };
347 checkContents(O->dir_begin("/", EC), Contents);
348 }
349}
350
351TEST(VirtualFileSystemTest, ThreeLevelIteration) {
352 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
353 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
354 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
355 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
356 new vfs::OverlayFileSystem(Lower));
357 O->pushOverlay(Middle);
358 O->pushOverlay(Upper);
359
360 std::error_code EC;
361 checkContents(O->dir_begin("/", EC), ArrayRef<std::string>());
362
363 Middle->addRegularFile("/file2");
364 checkContents(O->dir_begin("/", EC), ArrayRef<std::string>("/file2"));
365
366 Lower->addRegularFile("/file1");
367 Upper->addRegularFile("/file3");
368 {
369 std::vector<std::string> Contents = { "/file3", "/file2", "/file1" };
370 checkContents(O->dir_begin("/", EC), Contents);
371 }
372}
373
374TEST(VirtualFileSystemTest, HiddenInIteration) {
375 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
376 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
377 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
378 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
379 new vfs::OverlayFileSystem(Lower));
380 O->pushOverlay(Middle);
381 O->pushOverlay(Upper);
382
383 std::error_code EC;
384 Lower->addRegularFile("/onlyInLow", sys::fs::owner_read);
385 Lower->addRegularFile("/hiddenByMid", sys::fs::owner_read);
386 Lower->addRegularFile("/hiddenByUp", sys::fs::owner_read);
387 Middle->addRegularFile("/onlyInMid", sys::fs::owner_write);
388 Middle->addRegularFile("/hiddenByMid", sys::fs::owner_write);
389 Middle->addRegularFile("/hiddenByUp", sys::fs::owner_write);
390 Upper->addRegularFile("/onlyInUp", sys::fs::owner_all);
391 Upper->addRegularFile("/hiddenByUp", sys::fs::owner_all);
392 {
393 std::vector<std::string> Contents = { "/hiddenByUp", "/onlyInUp",
394 "/hiddenByMid", "/onlyInMid", "/onlyInLow" };
395 checkContents(O->dir_begin("/", EC), Contents);
396 }
397
Ben Langmuirc6326a42014-06-24 20:00:30 +0000398 // FIXME: broke gcc build
Ben Langmuir740812b2014-06-24 19:37:16 +0000399 // Make sure we get the top-most entry
Ben Langmuirc6326a42014-06-24 20:00:30 +0000400 // vfs::directory_iterator E;
401 // {
402 // auto I = std::find_if(O->dir_begin("/", EC), E, [](vfs::Status S){
403 // return S.getName() == "/hiddenByUp";
404 // });
405 // ASSERT_NE(E, I);
406 // EXPECT_EQ(sys::fs::owner_all, I->getPermissions());
407 // }
408 // {
409 // auto I = std::find_if(O->dir_begin("/", EC), E, [](vfs::Status S){
410 // return S.getName() == "/hiddenByMid";
411 // });
412 // ASSERT_NE(E, I);
413 // EXPECT_EQ(sys::fs::owner_write, I->getPermissions());
414 // }
Ben Langmuir740812b2014-06-24 19:37:16 +0000415}
416
Ben Langmuir93853232014-03-05 21:32:20 +0000417// NOTE: in the tests below, we use '//root/' as our root directory, since it is
418// a legal *absolute* path on Windows as well as *nix.
Ben Langmuir97882e72014-02-24 20:56:37 +0000419class VFSFromYAMLTest : public ::testing::Test {
420public:
421 int NumDiagnostics;
Ben Langmuir93853232014-03-05 21:32:20 +0000422
Ben Langmuir97882e72014-02-24 20:56:37 +0000423 void SetUp() {
424 NumDiagnostics = 0;
425 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000426
Ben Langmuir97882e72014-02-24 20:56:37 +0000427 static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
428 VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
429 ++Test->NumDiagnostics;
430 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000431
Ben Langmuir97882e72014-02-24 20:56:37 +0000432 IntrusiveRefCntPtr<vfs::FileSystem>
433 getFromYAMLRawString(StringRef Content,
434 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
435 MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Content);
436 return getVFSFromYAML(Buffer, CountingDiagHandler, this, ExternalFS);
437 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000438
Ben Langmuir97882e72014-02-24 20:56:37 +0000439 IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
440 StringRef Content,
441 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
442 std::string VersionPlusContent("{\n 'version':0,\n");
443 VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
444 return getFromYAMLRawString(VersionPlusContent, ExternalFS);
445 }
Ben Langmuir97882e72014-02-24 20:56:37 +0000446};
447
448TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000449 IntrusiveRefCntPtr<vfs::FileSystem> FS;
450 FS = getFromYAMLString("");
Craig Topper416fa342014-06-08 08:38:12 +0000451 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000452 FS = getFromYAMLString("[]");
Craig Topper416fa342014-06-08 08:38:12 +0000453 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000454 FS = getFromYAMLString("'string'");
Craig Topper416fa342014-06-08 08:38:12 +0000455 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000456 EXPECT_EQ(3, NumDiagnostics);
457}
458
Ben Langmuir97882e72014-02-24 20:56:37 +0000459TEST_F(VFSFromYAMLTest, MappedFiles) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000460 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000461 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000462 IntrusiveRefCntPtr<vfs::FileSystem> FS =
463 getFromYAMLString("{ 'roots': [\n"
464 "{\n"
465 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000466 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000467 " 'contents': [ {\n"
468 " 'type': 'file',\n"
469 " 'name': 'file1',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000470 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000471 " },\n"
472 " {\n"
473 " 'type': 'file',\n"
474 " 'name': 'file2',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000475 " 'external-contents': '//root/foo/b'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000476 " }\n"
477 " ]\n"
478 "}\n"
479 "]\n"
480 "}",
481 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000482 ASSERT_TRUE(FS.getPtr() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000483
484 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
485 new vfs::OverlayFileSystem(Lower));
486 O->pushOverlay(FS);
487
488 // file
Ben Langmuir93853232014-03-05 21:32:20 +0000489 ErrorOr<vfs::Status> S = O->status("//root/file1");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000490 ASSERT_FALSE(S.getError());
Ben Langmuir93853232014-03-05 21:32:20 +0000491 EXPECT_EQ("//root/foo/bar/a", S->getName());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000492
Ben Langmuir93853232014-03-05 21:32:20 +0000493 ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
494 EXPECT_EQ("//root/foo/bar/a", SLower->getName());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000495 EXPECT_TRUE(S->equivalent(*SLower));
496
497 // directory
Ben Langmuir93853232014-03-05 21:32:20 +0000498 S = O->status("//root/");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000499 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000500 EXPECT_TRUE(S->isDirectory());
Ben Langmuir93853232014-03-05 21:32:20 +0000501 EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000502
503 // broken mapping
Rafael Espindola71de0b62014-06-13 17:20:50 +0000504 EXPECT_EQ(O->status("//root/file2").getError(),
505 llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000506 EXPECT_EQ(0, NumDiagnostics);
507}
508
Ben Langmuir97882e72014-02-24 20:56:37 +0000509TEST_F(VFSFromYAMLTest, CaseInsensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000510 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000511 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000512 IntrusiveRefCntPtr<vfs::FileSystem> FS =
513 getFromYAMLString("{ 'case-sensitive': 'false',\n"
514 " 'roots': [\n"
515 "{\n"
516 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000517 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000518 " 'contents': [ {\n"
519 " 'type': 'file',\n"
520 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000521 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000522 " }\n"
523 " ]\n"
524 "}]}",
525 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000526 ASSERT_TRUE(FS.getPtr() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000527
528 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
529 new vfs::OverlayFileSystem(Lower));
530 O->pushOverlay(FS);
531
Ben Langmuir93853232014-03-05 21:32:20 +0000532 ErrorOr<vfs::Status> S = O->status("//root/XX");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000533 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000534
Ben Langmuir93853232014-03-05 21:32:20 +0000535 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000536 ASSERT_FALSE(SS.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000537 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000538 SS = O->status("//root/xX");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000539 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000540 SS = O->status("//root/Xx");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000541 EXPECT_TRUE(S->equivalent(*SS));
542 EXPECT_EQ(0, NumDiagnostics);
543}
544
Ben Langmuir97882e72014-02-24 20:56:37 +0000545TEST_F(VFSFromYAMLTest, CaseSensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000546 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000547 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000548 IntrusiveRefCntPtr<vfs::FileSystem> FS =
549 getFromYAMLString("{ 'case-sensitive': 'true',\n"
550 " 'roots': [\n"
551 "{\n"
552 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000553 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000554 " 'contents': [ {\n"
555 " 'type': 'file',\n"
556 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000557 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000558 " }\n"
559 " ]\n"
560 "}]}",
561 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000562 ASSERT_TRUE(FS.getPtr() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000563
564 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
565 new vfs::OverlayFileSystem(Lower));
566 O->pushOverlay(FS);
567
Ben Langmuir93853232014-03-05 21:32:20 +0000568 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000569 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000570 SS = O->status("//root/xX");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000571 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000572 SS = O->status("//root/Xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000573 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000574 EXPECT_EQ(0, NumDiagnostics);
575}
576
Ben Langmuir97882e72014-02-24 20:56:37 +0000577TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000578 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
579
580 // invalid YAML at top-level
581 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000582 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000583 // invalid YAML in roots
584 FS = getFromYAMLString("{ 'roots':[}", Lower);
585 // invalid YAML in directory
586 FS = getFromYAMLString(
587 "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
588 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000589 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000590
591 // invalid configuration
592 FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000593 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000594 FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000595 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000596
597 // invalid roots
598 FS = getFromYAMLString("{ 'roots':'' }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000599 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000600 FS = getFromYAMLString("{ 'roots':{} }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000601 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000602
603 // invalid entries
604 FS = getFromYAMLString(
605 "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000606 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000607 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
608 "'external-contents': 'other' }",
609 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000610 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000611 FS = getFromYAMLString(
612 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
613 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000614 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000615 FS = getFromYAMLString(
616 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
617 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000618 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000619 FS = getFromYAMLString(
620 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
621 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000622 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000623 FS = getFromYAMLString(
624 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
625 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000626 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000627 FS = getFromYAMLString(
628 "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
629 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000630 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000631
632 // missing mandatory fields
633 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000634 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000635 FS = getFromYAMLString(
636 "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000637 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000638 FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000639 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000640
641 // duplicate keys
642 FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000643 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000644 FS = getFromYAMLString(
645 "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
646 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000647 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000648 FS =
649 getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
650 "'external-contents':'blah' } ] }",
651 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000652 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000653
654 // missing version
655 FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000656 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000657
658 // bad version number
659 FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000660 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000661 FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000662 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000663 FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000664 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000665 EXPECT_EQ(24, NumDiagnostics);
666}
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000667
Ben Langmuirb59cf672014-02-27 00:25:12 +0000668TEST_F(VFSFromYAMLTest, UseExternalName) {
669 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000670 Lower->addRegularFile("//root/external/file");
Ben Langmuirb59cf672014-02-27 00:25:12 +0000671
672 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
673 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000674 " { 'type': 'file', 'name': '//root/A',\n"
675 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000676 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000677 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000678 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000679 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000680 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000681 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000682 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000683 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000684 " }\n"
685 "] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000686 ASSERT_TRUE(nullptr != FS.getPtr());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000687
688 // default true
Ben Langmuir93853232014-03-05 21:32:20 +0000689 EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000690 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000691 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
692 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000693
694 // global configuration
695 FS = getFromYAMLString(
696 "{ 'use-external-names': false,\n"
697 " 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000698 " { 'type': 'file', 'name': '//root/A',\n"
699 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000700 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000701 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000702 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000703 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000704 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000705 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000706 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000707 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000708 " }\n"
709 "] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000710 ASSERT_TRUE(nullptr != FS.getPtr());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000711
712 // default
Ben Langmuir93853232014-03-05 21:32:20 +0000713 EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000714 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000715 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
716 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000717}
718
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000719TEST_F(VFSFromYAMLTest, MultiComponentPath) {
720 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000721 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000722
723 // file in roots
724 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
725 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000726 " { 'type': 'file', 'name': '//root/path/to/file',\n"
727 " 'external-contents': '//root/other' }]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000728 "}", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000729 ASSERT_TRUE(nullptr != FS.getPtr());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000730 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
731 EXPECT_FALSE(FS->status("//root/path/to").getError());
732 EXPECT_FALSE(FS->status("//root/path").getError());
733 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000734
735 // at the start
736 FS = getFromYAMLString(
737 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000738 " { 'type': 'directory', 'name': '//root/path/to',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000739 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000740 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000741 "}", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000742 ASSERT_TRUE(nullptr != FS.getPtr());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000743 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
744 EXPECT_FALSE(FS->status("//root/path/to").getError());
745 EXPECT_FALSE(FS->status("//root/path").getError());
746 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000747
748 // at the end
749 FS = getFromYAMLString(
750 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000751 " { 'type': 'directory', 'name': '//root/',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000752 " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000753 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000754 "}", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000755 ASSERT_TRUE(nullptr != FS.getPtr());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000756 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
757 EXPECT_FALSE(FS->status("//root/path/to").getError());
758 EXPECT_FALSE(FS->status("//root/path").getError());
759 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000760}
761
762TEST_F(VFSFromYAMLTest, TrailingSlashes) {
763 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000764 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000765
766 // file in roots
767 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
768 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000769 " { 'type': 'directory', 'name': '//root/path/to////',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000770 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000771 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000772 "}", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000773 ASSERT_TRUE(nullptr != FS.getPtr());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000774 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
775 EXPECT_FALSE(FS->status("//root/path/to").getError());
776 EXPECT_FALSE(FS->status("//root/path").getError());
777 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000778}
Ben Langmuir740812b2014-06-24 19:37:16 +0000779
780TEST_F(VFSFromYAMLTest, DirectoryIteration) {
781 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
782 Lower->addDirectory("//root/");
783 Lower->addDirectory("//root/foo");
784 Lower->addDirectory("//root/foo/bar");
785 Lower->addRegularFile("//root/foo/bar/a");
786 Lower->addRegularFile("//root/foo/bar/b");
787 Lower->addRegularFile("//root/file3");
788 IntrusiveRefCntPtr<vfs::FileSystem> FS =
789 getFromYAMLString("{ 'use-external-names': false,\n"
790 " 'roots': [\n"
791 "{\n"
792 " 'type': 'directory',\n"
793 " 'name': '//root/',\n"
794 " 'contents': [ {\n"
795 " 'type': 'file',\n"
796 " 'name': 'file1',\n"
797 " 'external-contents': '//root/foo/bar/a'\n"
798 " },\n"
799 " {\n"
800 " 'type': 'file',\n"
801 " 'name': 'file2',\n"
802 " 'external-contents': '//root/foo/bar/b'\n"
803 " }\n"
804 " ]\n"
805 "}\n"
806 "]\n"
807 "}",
808 Lower);
809 ASSERT_TRUE(FS.getPtr() != NULL);
810
811 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
812 new vfs::OverlayFileSystem(Lower));
813 O->pushOverlay(FS);
814
815 std::error_code EC;
816 {
817 std::vector<std::string> Contents = { "//root/file1", "//root/file2",
818 "//root/file3", "//root/foo" };
819 checkContents(O->dir_begin("//root/", EC), Contents);
820 }
821
822 {
823 std::vector<std::string> Contents = {
824 "//root/foo/bar/a", "//root/foo/bar/b" };
825 checkContents(O->dir_begin("//root/foo/bar", EC), Contents);
826 }
827}
828