blob: c416aa6c49417e9754d30b37db59489e9fc6b5a5 [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);
Ben Langmuirefb8b602014-06-24 21:08:13 +0000299 // Check either a or c, since we can't rely on the iteration order.
300 EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000301 I.increment(EC);
302 ASSERT_FALSE(EC);
303 ASSERT_NE(vfs::directory_iterator(), I);
Ben Langmuirefb8b602014-06-24 21:08:13 +0000304 EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000305 I.increment(EC);
306 EXPECT_EQ(vfs::directory_iterator(), I);
307}
308
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000309template <typename T, size_t N>
310std::vector<StringRef> makeStringRefVector(const T (&Arr)[N]) {
311 std::vector<StringRef> Vec;
312 for (size_t i = 0; i != N; ++i)
313 Vec.push_back(Arr[i]);
314 return Vec;
315}
316
Ben Langmuir740812b2014-06-24 19:37:16 +0000317static void checkContents(vfs::directory_iterator I,
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000318 ArrayRef<StringRef> Expected) {
Ben Langmuir740812b2014-06-24 19:37:16 +0000319 std::error_code EC;
320 auto ExpectedIter = Expected.begin(), ExpectedEnd = Expected.end();
321 for (vfs::directory_iterator E;
322 !EC && I != E && ExpectedIter != ExpectedEnd;
323 I.increment(EC), ++ExpectedIter)
324 EXPECT_EQ(*ExpectedIter, I->getName());
325
326 EXPECT_EQ(ExpectedEnd, ExpectedIter);
327 EXPECT_EQ(vfs::directory_iterator(), I);
328}
329
330TEST(VirtualFileSystemTest, OverlayIteration) {
331 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
332 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
333 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
334 new vfs::OverlayFileSystem(Lower));
335 O->pushOverlay(Upper);
336
337 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000338 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000339
340 Lower->addRegularFile("/file1");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000341 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000342
343 Upper->addRegularFile("/file2");
344 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000345 const char *Contents[] = {"/file2", "/file1"};
346 checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000347 }
348
349 Lower->addDirectory("/dir1");
350 Lower->addRegularFile("/dir1/foo");
351 Upper->addDirectory("/dir2");
352 Upper->addRegularFile("/dir2/foo");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000353 checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000354 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000355 const char *Contents[] = {"/dir2", "/file2", "/dir1", "/file1"};
356 checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000357 }
358}
359
360TEST(VirtualFileSystemTest, ThreeLevelIteration) {
361 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
362 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
363 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
364 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
365 new vfs::OverlayFileSystem(Lower));
366 O->pushOverlay(Middle);
367 O->pushOverlay(Upper);
368
369 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000370 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000371
372 Middle->addRegularFile("/file2");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000373 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000374
375 Lower->addRegularFile("/file1");
376 Upper->addRegularFile("/file3");
377 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000378 const char *Contents[] = {"/file3", "/file2", "/file1"};
379 checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000380 }
381}
382
383TEST(VirtualFileSystemTest, HiddenInIteration) {
384 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
385 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
386 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
387 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
388 new vfs::OverlayFileSystem(Lower));
389 O->pushOverlay(Middle);
390 O->pushOverlay(Upper);
391
392 std::error_code EC;
393 Lower->addRegularFile("/onlyInLow", sys::fs::owner_read);
394 Lower->addRegularFile("/hiddenByMid", sys::fs::owner_read);
395 Lower->addRegularFile("/hiddenByUp", sys::fs::owner_read);
396 Middle->addRegularFile("/onlyInMid", sys::fs::owner_write);
397 Middle->addRegularFile("/hiddenByMid", sys::fs::owner_write);
398 Middle->addRegularFile("/hiddenByUp", sys::fs::owner_write);
399 Upper->addRegularFile("/onlyInUp", sys::fs::owner_all);
400 Upper->addRegularFile("/hiddenByUp", sys::fs::owner_all);
401 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000402 const char *Contents[] = {"/hiddenByUp", "/onlyInUp", "/hiddenByMid",
403 "/onlyInMid", "/onlyInLow"};
404 checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000405 }
406
407 // Make sure we get the top-most entry
Ben Langmuirefb8b602014-06-24 21:08:13 +0000408 {
409 std::error_code EC;
410 vfs::directory_iterator I = O->dir_begin("/", EC), E;
411 for ( ; !EC && I != E; I.increment(EC))
412 if (I->getName() == "/hiddenByUp")
413 break;
414 ASSERT_NE(E, I);
415 EXPECT_EQ(sys::fs::owner_all, I->getPermissions());
416 }
417 {
418 std::error_code EC;
419 vfs::directory_iterator I = O->dir_begin("/", EC), E;
420 for ( ; !EC && I != E; I.increment(EC))
421 if (I->getName() == "/hiddenByMid")
422 break;
423 ASSERT_NE(E, I);
424 EXPECT_EQ(sys::fs::owner_write, I->getPermissions());
425 }
Ben Langmuir740812b2014-06-24 19:37:16 +0000426}
427
Ben Langmuir93853232014-03-05 21:32:20 +0000428// NOTE: in the tests below, we use '//root/' as our root directory, since it is
429// a legal *absolute* path on Windows as well as *nix.
Ben Langmuir97882e72014-02-24 20:56:37 +0000430class VFSFromYAMLTest : public ::testing::Test {
431public:
432 int NumDiagnostics;
Ben Langmuir93853232014-03-05 21:32:20 +0000433
Ben Langmuir97882e72014-02-24 20:56:37 +0000434 void SetUp() {
435 NumDiagnostics = 0;
436 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000437
Ben Langmuir97882e72014-02-24 20:56:37 +0000438 static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
439 VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
440 ++Test->NumDiagnostics;
441 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000442
Ben Langmuir97882e72014-02-24 20:56:37 +0000443 IntrusiveRefCntPtr<vfs::FileSystem>
444 getFromYAMLRawString(StringRef Content,
445 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
446 MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Content);
447 return getVFSFromYAML(Buffer, CountingDiagHandler, this, ExternalFS);
448 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000449
Ben Langmuir97882e72014-02-24 20:56:37 +0000450 IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
451 StringRef Content,
452 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
453 std::string VersionPlusContent("{\n 'version':0,\n");
454 VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
455 return getFromYAMLRawString(VersionPlusContent, ExternalFS);
456 }
Ben Langmuir97882e72014-02-24 20:56:37 +0000457};
458
459TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000460 IntrusiveRefCntPtr<vfs::FileSystem> FS;
461 FS = getFromYAMLString("");
Craig Topper416fa342014-06-08 08:38:12 +0000462 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000463 FS = getFromYAMLString("[]");
Craig Topper416fa342014-06-08 08:38:12 +0000464 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000465 FS = getFromYAMLString("'string'");
Craig Topper416fa342014-06-08 08:38:12 +0000466 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000467 EXPECT_EQ(3, NumDiagnostics);
468}
469
Ben Langmuir97882e72014-02-24 20:56:37 +0000470TEST_F(VFSFromYAMLTest, MappedFiles) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000471 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000472 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000473 IntrusiveRefCntPtr<vfs::FileSystem> FS =
474 getFromYAMLString("{ 'roots': [\n"
475 "{\n"
476 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000477 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000478 " 'contents': [ {\n"
479 " 'type': 'file',\n"
480 " 'name': 'file1',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000481 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000482 " },\n"
483 " {\n"
484 " 'type': 'file',\n"
485 " 'name': 'file2',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000486 " 'external-contents': '//root/foo/b'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000487 " }\n"
488 " ]\n"
489 "}\n"
490 "]\n"
491 "}",
492 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000493 ASSERT_TRUE(FS.getPtr() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000494
495 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
496 new vfs::OverlayFileSystem(Lower));
497 O->pushOverlay(FS);
498
499 // file
Ben Langmuir93853232014-03-05 21:32:20 +0000500 ErrorOr<vfs::Status> S = O->status("//root/file1");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000501 ASSERT_FALSE(S.getError());
Ben Langmuir93853232014-03-05 21:32:20 +0000502 EXPECT_EQ("//root/foo/bar/a", S->getName());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000503
Ben Langmuir93853232014-03-05 21:32:20 +0000504 ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
505 EXPECT_EQ("//root/foo/bar/a", SLower->getName());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000506 EXPECT_TRUE(S->equivalent(*SLower));
507
508 // directory
Ben Langmuir93853232014-03-05 21:32:20 +0000509 S = O->status("//root/");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000510 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000511 EXPECT_TRUE(S->isDirectory());
Ben Langmuir93853232014-03-05 21:32:20 +0000512 EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000513
514 // broken mapping
Rafael Espindola71de0b62014-06-13 17:20:50 +0000515 EXPECT_EQ(O->status("//root/file2").getError(),
516 llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000517 EXPECT_EQ(0, NumDiagnostics);
518}
519
Ben Langmuir97882e72014-02-24 20:56:37 +0000520TEST_F(VFSFromYAMLTest, CaseInsensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000521 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000522 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000523 IntrusiveRefCntPtr<vfs::FileSystem> FS =
524 getFromYAMLString("{ 'case-sensitive': 'false',\n"
525 " 'roots': [\n"
526 "{\n"
527 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000528 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000529 " 'contents': [ {\n"
530 " 'type': 'file',\n"
531 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000532 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000533 " }\n"
534 " ]\n"
535 "}]}",
536 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000537 ASSERT_TRUE(FS.getPtr() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000538
539 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
540 new vfs::OverlayFileSystem(Lower));
541 O->pushOverlay(FS);
542
Ben Langmuir93853232014-03-05 21:32:20 +0000543 ErrorOr<vfs::Status> S = O->status("//root/XX");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000544 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000545
Ben Langmuir93853232014-03-05 21:32:20 +0000546 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000547 ASSERT_FALSE(SS.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000548 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000549 SS = O->status("//root/xX");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000550 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000551 SS = O->status("//root/Xx");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000552 EXPECT_TRUE(S->equivalent(*SS));
553 EXPECT_EQ(0, NumDiagnostics);
554}
555
Ben Langmuir97882e72014-02-24 20:56:37 +0000556TEST_F(VFSFromYAMLTest, CaseSensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000557 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000558 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000559 IntrusiveRefCntPtr<vfs::FileSystem> FS =
560 getFromYAMLString("{ 'case-sensitive': 'true',\n"
561 " 'roots': [\n"
562 "{\n"
563 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000564 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000565 " 'contents': [ {\n"
566 " 'type': 'file',\n"
567 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000568 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000569 " }\n"
570 " ]\n"
571 "}]}",
572 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000573 ASSERT_TRUE(FS.getPtr() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000574
575 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
576 new vfs::OverlayFileSystem(Lower));
577 O->pushOverlay(FS);
578
Ben Langmuir93853232014-03-05 21:32:20 +0000579 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000580 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000581 SS = O->status("//root/xX");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000582 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000583 SS = O->status("//root/Xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000584 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000585 EXPECT_EQ(0, NumDiagnostics);
586}
587
Ben Langmuir97882e72014-02-24 20:56:37 +0000588TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000589 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
590
591 // invalid YAML at top-level
592 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000593 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000594 // invalid YAML in roots
595 FS = getFromYAMLString("{ 'roots':[}", Lower);
596 // invalid YAML in directory
597 FS = getFromYAMLString(
598 "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
599 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000600 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000601
602 // invalid configuration
603 FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000604 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000605 FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000606 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000607
608 // invalid roots
609 FS = getFromYAMLString("{ 'roots':'' }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000610 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000611 FS = getFromYAMLString("{ 'roots':{} }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000612 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000613
614 // invalid entries
615 FS = getFromYAMLString(
616 "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000617 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000618 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
619 "'external-contents': 'other' }",
620 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000621 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000622 FS = getFromYAMLString(
623 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
624 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000625 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000626 FS = getFromYAMLString(
627 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
628 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000629 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000630 FS = getFromYAMLString(
631 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
632 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000633 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000634 FS = getFromYAMLString(
635 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
636 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000637 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000638 FS = getFromYAMLString(
639 "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
640 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000641 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000642
643 // missing mandatory fields
644 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000645 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000646 FS = getFromYAMLString(
647 "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000648 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000649 FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000650 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000651
652 // duplicate keys
653 FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000654 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000655 FS = getFromYAMLString(
656 "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
657 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000658 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000659 FS =
660 getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
661 "'external-contents':'blah' } ] }",
662 Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000663 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000664
665 // missing version
666 FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000667 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000668
669 // bad version number
670 FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000671 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000672 FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000673 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000674 FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000675 EXPECT_EQ(nullptr, FS.getPtr());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000676 EXPECT_EQ(24, NumDiagnostics);
677}
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000678
Ben Langmuirb59cf672014-02-27 00:25:12 +0000679TEST_F(VFSFromYAMLTest, UseExternalName) {
680 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000681 Lower->addRegularFile("//root/external/file");
Ben Langmuirb59cf672014-02-27 00:25:12 +0000682
683 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
684 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000685 " { 'type': 'file', 'name': '//root/A',\n"
686 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000687 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000688 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000689 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000690 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000691 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000692 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000693 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000694 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000695 " }\n"
696 "] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000697 ASSERT_TRUE(nullptr != FS.getPtr());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000698
699 // default true
Ben Langmuir93853232014-03-05 21:32:20 +0000700 EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000701 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000702 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
703 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000704
705 // global configuration
706 FS = getFromYAMLString(
707 "{ 'use-external-names': false,\n"
708 " 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000709 " { 'type': 'file', 'name': '//root/A',\n"
710 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000711 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000712 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000713 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000714 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000715 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000716 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000717 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000718 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000719 " }\n"
720 "] }", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000721 ASSERT_TRUE(nullptr != FS.getPtr());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000722
723 // default
Ben Langmuir93853232014-03-05 21:32:20 +0000724 EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000725 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000726 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
727 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000728}
729
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000730TEST_F(VFSFromYAMLTest, MultiComponentPath) {
731 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000732 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000733
734 // file in roots
735 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
736 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000737 " { 'type': 'file', 'name': '//root/path/to/file',\n"
738 " 'external-contents': '//root/other' }]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000739 "}", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000740 ASSERT_TRUE(nullptr != FS.getPtr());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000741 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
742 EXPECT_FALSE(FS->status("//root/path/to").getError());
743 EXPECT_FALSE(FS->status("//root/path").getError());
744 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000745
746 // at the start
747 FS = getFromYAMLString(
748 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000749 " { 'type': 'directory', 'name': '//root/path/to',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000750 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000751 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000752 "}", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000753 ASSERT_TRUE(nullptr != FS.getPtr());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000754 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
755 EXPECT_FALSE(FS->status("//root/path/to").getError());
756 EXPECT_FALSE(FS->status("//root/path").getError());
757 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000758
759 // at the end
760 FS = getFromYAMLString(
761 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000762 " { 'type': 'directory', 'name': '//root/',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000763 " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000764 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000765 "}", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000766 ASSERT_TRUE(nullptr != FS.getPtr());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000767 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
768 EXPECT_FALSE(FS->status("//root/path/to").getError());
769 EXPECT_FALSE(FS->status("//root/path").getError());
770 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000771}
772
773TEST_F(VFSFromYAMLTest, TrailingSlashes) {
774 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000775 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000776
777 // file in roots
778 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
779 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000780 " { 'type': 'directory', 'name': '//root/path/to////',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000781 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000782 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000783 "}", Lower);
Craig Topper416fa342014-06-08 08:38:12 +0000784 ASSERT_TRUE(nullptr != FS.getPtr());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000785 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
786 EXPECT_FALSE(FS->status("//root/path/to").getError());
787 EXPECT_FALSE(FS->status("//root/path").getError());
788 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000789}
Ben Langmuir740812b2014-06-24 19:37:16 +0000790
791TEST_F(VFSFromYAMLTest, DirectoryIteration) {
792 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
793 Lower->addDirectory("//root/");
794 Lower->addDirectory("//root/foo");
795 Lower->addDirectory("//root/foo/bar");
796 Lower->addRegularFile("//root/foo/bar/a");
797 Lower->addRegularFile("//root/foo/bar/b");
798 Lower->addRegularFile("//root/file3");
799 IntrusiveRefCntPtr<vfs::FileSystem> FS =
800 getFromYAMLString("{ 'use-external-names': false,\n"
801 " 'roots': [\n"
802 "{\n"
803 " 'type': 'directory',\n"
804 " 'name': '//root/',\n"
805 " 'contents': [ {\n"
806 " 'type': 'file',\n"
807 " 'name': 'file1',\n"
808 " 'external-contents': '//root/foo/bar/a'\n"
809 " },\n"
810 " {\n"
811 " 'type': 'file',\n"
812 " 'name': 'file2',\n"
813 " 'external-contents': '//root/foo/bar/b'\n"
814 " }\n"
815 " ]\n"
816 "}\n"
817 "]\n"
818 "}",
819 Lower);
820 ASSERT_TRUE(FS.getPtr() != NULL);
821
822 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
823 new vfs::OverlayFileSystem(Lower));
824 O->pushOverlay(FS);
825
826 std::error_code EC;
827 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000828 const char *Contents[] = {"//root/file1", "//root/file2", "//root/file3",
829 "//root/foo"};
830 checkContents(O->dir_begin("//root/", EC), makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000831 }
832
833 {
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000834 const char *Contents[] = {"//root/foo/bar/a", "//root/foo/bar/b"};
835 checkContents(O->dir_begin("//root/foo/bar", EC),
836 makeStringRefVector(Contents));
Ben Langmuir740812b2014-06-24 19:37:16 +0000837 }
838}