blob: 547cba159be5f183dbc494fa0ca35a135a7ffac5 [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"
Bruno Cardoso Lopesf6a0a722016-05-12 19:13:07 +000011#include "llvm/ADT/Triple.h"
Rafael Espindola71de0b62014-06-13 17:20:50 +000012#include "llvm/Support/Errc.h"
Bruno Cardoso Lopesf6a0a722016-05-12 19:13:07 +000013#include "llvm/Support/Host.h"
Ben Langmuird51ba0b2014-02-21 23:39:37 +000014#include "llvm/Support/MemoryBuffer.h"
Ben Langmuird51ba0b2014-02-21 23:39:37 +000015#include "llvm/Support/SourceMgr.h"
Ben Langmuirc8130a72014-02-20 21:59:23 +000016#include "gtest/gtest.h"
17#include <map>
Hans Wennborgdcfba332015-10-06 23:40:43 +000018
Ben Langmuirc8130a72014-02-20 21:59:23 +000019using namespace clang;
20using namespace llvm;
21using llvm::sys::fs::UniqueID;
22
23namespace {
Ben Langmuirf13302e2015-12-10 23:41:39 +000024struct DummyFile : public vfs::File {
25 vfs::Status S;
26 explicit DummyFile(vfs::Status S) : S(S) {}
27 llvm::ErrorOr<vfs::Status> status() override { return S; }
28 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
29 getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
30 bool IsVolatile) override {
31 llvm_unreachable("unimplemented");
32 }
Eugene Zelenko1660a5d2016-01-26 19:01:06 +000033 std::error_code close() override { return std::error_code(); }
Ben Langmuirf13302e2015-12-10 23:41:39 +000034};
35
Ben Langmuirc8130a72014-02-20 21:59:23 +000036class DummyFileSystem : public vfs::FileSystem {
37 int FSID; // used to produce UniqueIDs
38 int FileID; // used to produce UniqueIDs
39 std::map<std::string, vfs::Status> FilesAndDirs;
40
41 static int getNextFSID() {
42 static int Count = 0;
43 return Count++;
44 }
45
46public:
47 DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
48
Fariborz Jahanian5afc8692014-10-01 16:56:40 +000049 ErrorOr<vfs::Status> status(const Twine &Path) override {
Ben Langmuirc8130a72014-02-20 21:59:23 +000050 std::map<std::string, vfs::Status>::iterator I =
Ben Langmuird51ba0b2014-02-21 23:39:37 +000051 FilesAndDirs.find(Path.str());
Ben Langmuirc8130a72014-02-20 21:59:23 +000052 if (I == FilesAndDirs.end())
Rafael Espindola71de0b62014-06-13 17:20:50 +000053 return make_error_code(llvm::errc::no_such_file_or_directory);
Ben Langmuirc8130a72014-02-20 21:59:23 +000054 return I->second;
55 }
Benjamin Kramera8857962014-10-26 22:44:13 +000056 ErrorOr<std::unique_ptr<vfs::File>>
57 openFileForRead(const Twine &Path) override {
Ben Langmuirf13302e2015-12-10 23:41:39 +000058 auto S = status(Path);
59 if (S)
60 return std::unique_ptr<vfs::File>(new DummyFile{*S});
61 return S.getError();
Ben Langmuirc8130a72014-02-20 21:59:23 +000062 }
Benjamin Kramer7708b2a2015-10-05 13:55:20 +000063 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
64 return std::string();
65 }
66 std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
67 return std::error_code();
68 }
Ben Langmuirc8130a72014-02-20 21:59:23 +000069
Ben Langmuir740812b2014-06-24 19:37:16 +000070 struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
71 std::map<std::string, vfs::Status> &FilesAndDirs;
72 std::map<std::string, vfs::Status>::iterator I;
73 std::string Path;
Ben Langmuir7c9f6c82014-06-25 20:25:40 +000074 bool isInPath(StringRef S) {
75 if (Path.size() < S.size() && S.find(Path) == 0) {
76 auto LastSep = S.find_last_of('/');
77 if (LastSep == Path.size() || LastSep == Path.size()-1)
78 return true;
79 }
80 return false;
81 }
Ben Langmuir740812b2014-06-24 19:37:16 +000082 DirIterImpl(std::map<std::string, vfs::Status> &FilesAndDirs,
83 const Twine &_Path)
84 : FilesAndDirs(FilesAndDirs), I(FilesAndDirs.begin()),
85 Path(_Path.str()) {
86 for ( ; I != FilesAndDirs.end(); ++I) {
Ben Langmuir7c9f6c82014-06-25 20:25:40 +000087 if (isInPath(I->first)) {
Ben Langmuir740812b2014-06-24 19:37:16 +000088 CurrentEntry = I->second;
89 break;
90 }
91 }
92 }
93 std::error_code increment() override {
94 ++I;
95 for ( ; I != FilesAndDirs.end(); ++I) {
Ben Langmuir7c9f6c82014-06-25 20:25:40 +000096 if (isInPath(I->first)) {
Ben Langmuir740812b2014-06-24 19:37:16 +000097 CurrentEntry = I->second;
98 break;
99 }
100 }
101 if (I == FilesAndDirs.end())
102 CurrentEntry = vfs::Status();
103 return std::error_code();
104 }
105 };
106
107 vfs::directory_iterator dir_begin(const Twine &Dir,
108 std::error_code &EC) override {
109 return vfs::directory_iterator(
110 std::make_shared<DirIterImpl>(FilesAndDirs, Dir));
111 }
112
Ben Langmuirc8130a72014-02-20 21:59:23 +0000113 void addEntry(StringRef Path, const vfs::Status &Status) {
114 FilesAndDirs[Path] = Status;
115 }
116
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000117 void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
Benjamin Kramer268b51a2015-10-05 13:15:33 +0000118 vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
119 1024, sys::fs::file_type::regular_file, Perms);
Ben Langmuirc8130a72014-02-20 21:59:23 +0000120 addEntry(Path, S);
121 }
122
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000123 void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
Benjamin Kramer268b51a2015-10-05 13:15:33 +0000124 vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
125 0, sys::fs::file_type::directory_file, Perms);
Ben Langmuirc8130a72014-02-20 21:59:23 +0000126 addEntry(Path, S);
127 }
128
129 void addSymlink(StringRef Path) {
Benjamin Kramer268b51a2015-10-05 13:15:33 +0000130 vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
131 0, sys::fs::file_type::symlink_file, sys::fs::all_all);
Ben Langmuirc8130a72014-02-20 21:59:23 +0000132 addEntry(Path, S);
133 }
134};
135} // end anonymous namespace
136
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000137TEST(VirtualFileSystemTest, StatusQueries) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000138 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
Rafael Espindola8e650d72014-06-12 20:37:59 +0000139 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000140
141 D->addRegularFile("/foo");
142 Status = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000143 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000144 EXPECT_TRUE(Status->isStatusKnown());
145 EXPECT_FALSE(Status->isDirectory());
146 EXPECT_TRUE(Status->isRegularFile());
147 EXPECT_FALSE(Status->isSymlink());
148 EXPECT_FALSE(Status->isOther());
149 EXPECT_TRUE(Status->exists());
150
151 D->addDirectory("/bar");
152 Status = D->status("/bar");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000153 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000154 EXPECT_TRUE(Status->isStatusKnown());
155 EXPECT_TRUE(Status->isDirectory());
156 EXPECT_FALSE(Status->isRegularFile());
157 EXPECT_FALSE(Status->isSymlink());
158 EXPECT_FALSE(Status->isOther());
159 EXPECT_TRUE(Status->exists());
160
161 D->addSymlink("/baz");
162 Status = D->status("/baz");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000163 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000164 EXPECT_TRUE(Status->isStatusKnown());
165 EXPECT_FALSE(Status->isDirectory());
166 EXPECT_FALSE(Status->isRegularFile());
167 EXPECT_TRUE(Status->isSymlink());
168 EXPECT_FALSE(Status->isOther());
169 EXPECT_TRUE(Status->exists());
170
171 EXPECT_TRUE(Status->equivalent(*Status));
172 ErrorOr<vfs::Status> Status2 = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000173 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000174 EXPECT_FALSE(Status->equivalent(*Status2));
175}
176
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000177TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000178 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
Rafael Espindola8e650d72014-06-12 20:37:59 +0000179 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000180 EXPECT_FALSE(Status = D->status("/foo"));
181
182 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
183 EXPECT_FALSE(Status = O->status("/foo"));
184
185 D->addRegularFile("/foo");
186 Status = D->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000187 EXPECT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000188
Rafael Espindola8e650d72014-06-12 20:37:59 +0000189 ErrorOr<vfs::Status> Status2((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000190 Status2 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000191 EXPECT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000192 EXPECT_TRUE(Status->equivalent(*Status2));
193}
194
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000195TEST(VirtualFileSystemTest, OverlayFiles) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000196 IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
197 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
198 IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000199 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
200 new vfs::OverlayFileSystem(Base));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000201 O->pushOverlay(Middle);
202 O->pushOverlay(Top);
203
Rafael Espindola8e650d72014-06-12 20:37:59 +0000204 ErrorOr<vfs::Status> Status1((std::error_code())),
205 Status2((std::error_code())), Status3((std::error_code())),
206 StatusB((std::error_code())), StatusM((std::error_code())),
207 StatusT((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000208
209 Base->addRegularFile("/foo");
210 StatusB = Base->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000211 ASSERT_FALSE(StatusB.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000212 Status1 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000213 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000214 Middle->addRegularFile("/foo");
215 StatusM = Middle->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000216 ASSERT_FALSE(StatusM.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000217 Status2 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000218 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000219 Top->addRegularFile("/foo");
220 StatusT = Top->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000221 ASSERT_FALSE(StatusT.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000222 Status3 = O->status("/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000223 ASSERT_FALSE(Status3.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000224
225 EXPECT_TRUE(Status1->equivalent(*StatusB));
226 EXPECT_TRUE(Status2->equivalent(*StatusM));
227 EXPECT_TRUE(Status3->equivalent(*StatusT));
228
229 EXPECT_FALSE(Status1->equivalent(*Status2));
230 EXPECT_FALSE(Status2->equivalent(*Status3));
231 EXPECT_FALSE(Status1->equivalent(*Status3));
232}
233
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000234TEST(VirtualFileSystemTest, OverlayDirsNonMerged) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000235 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
241 Lower->addDirectory("/lower-only");
242 Upper->addDirectory("/upper-only");
243
244 // non-merged paths should be the same
245 ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000246 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000247 ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000248 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000249 EXPECT_TRUE(Status1->equivalent(*Status2));
250
251 Status1 = Upper->status("/upper-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000252 ASSERT_FALSE(Status1.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000253 Status2 = O->status("/upper-only");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000254 ASSERT_FALSE(Status2.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000255 EXPECT_TRUE(Status1->equivalent(*Status2));
256}
257
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000258TEST(VirtualFileSystemTest, MergedDirPermissions) {
Ben Langmuirc8130a72014-02-20 21:59:23 +0000259 // merged directories get the permissions of the upper dir
260 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
261 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000262 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
263 new vfs::OverlayFileSystem(Lower));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000264 O->pushOverlay(Upper);
265
Rafael Espindola8e650d72014-06-12 20:37:59 +0000266 ErrorOr<vfs::Status> Status((std::error_code()));
Ben Langmuirc8130a72014-02-20 21:59:23 +0000267 Lower->addDirectory("/both", sys::fs::owner_read);
268 Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
269 Status = O->status("/both");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000270 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000271 EXPECT_EQ(0740, Status->getPermissions());
272
273 // permissions (as usual) are not recursively applied
274 Lower->addRegularFile("/both/foo", sys::fs::owner_read);
275 Upper->addRegularFile("/both/bar", sys::fs::owner_write);
276 Status = O->status("/both/foo");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000277 ASSERT_FALSE( Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000278 EXPECT_EQ(0400, Status->getPermissions());
279 Status = O->status("/both/bar");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000280 ASSERT_FALSE(Status.getError());
Ben Langmuirc8130a72014-02-20 21:59:23 +0000281 EXPECT_EQ(0200, Status->getPermissions());
282}
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000283
Ben Langmuir740812b2014-06-24 19:37:16 +0000284namespace {
285struct ScopedDir {
286 SmallString<128> Path;
287 ScopedDir(const Twine &Name, bool Unique=false) {
288 std::error_code EC;
289 if (Unique) {
290 EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
291 } else {
292 Path = Name.str();
293 EC = llvm::sys::fs::create_directory(Twine(Path));
294 }
295 if (EC)
296 Path = "";
297 EXPECT_FALSE(EC);
298 }
299 ~ScopedDir() {
300 if (Path != "")
301 EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
302 }
303 operator StringRef() { return Path.str(); }
304};
Hans Wennborgdcfba332015-10-06 23:40:43 +0000305} // end anonymous namespace
Ben Langmuir740812b2014-06-24 19:37:16 +0000306
307TEST(VirtualFileSystemTest, BasicRealFSIteration) {
308 ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
309 IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
310
311 std::error_code EC;
312 vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC);
313 ASSERT_FALSE(EC);
314 EXPECT_EQ(vfs::directory_iterator(), I); // empty directory is empty
315
316 ScopedDir _a(TestDirectory+"/a");
317 ScopedDir _ab(TestDirectory+"/a/b");
318 ScopedDir _c(TestDirectory+"/c");
319 ScopedDir _cd(TestDirectory+"/c/d");
320
321 I = FS->dir_begin(Twine(TestDirectory), EC);
322 ASSERT_FALSE(EC);
323 ASSERT_NE(vfs::directory_iterator(), I);
Ben Langmuirefb8b602014-06-24 21:08:13 +0000324 // Check either a or c, since we can't rely on the iteration order.
325 EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000326 I.increment(EC);
327 ASSERT_FALSE(EC);
328 ASSERT_NE(vfs::directory_iterator(), I);
Ben Langmuirefb8b602014-06-24 21:08:13 +0000329 EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000330 I.increment(EC);
331 EXPECT_EQ(vfs::directory_iterator(), I);
332}
333
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000334TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) {
335 ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
336 IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
337
338 std::error_code EC;
339 auto I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
340 ASSERT_FALSE(EC);
341 EXPECT_EQ(vfs::recursive_directory_iterator(), I); // empty directory is empty
342
343 ScopedDir _a(TestDirectory+"/a");
344 ScopedDir _ab(TestDirectory+"/a/b");
345 ScopedDir _c(TestDirectory+"/c");
346 ScopedDir _cd(TestDirectory+"/c/d");
347
348 I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
349 ASSERT_FALSE(EC);
350 ASSERT_NE(vfs::recursive_directory_iterator(), I);
351
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000352 std::vector<std::string> Contents;
353 for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
354 I.increment(EC)) {
355 Contents.push_back(I->getName());
356 }
357
358 // Check contents, which may be in any order
359 EXPECT_EQ(4U, Contents.size());
360 int Counts[4] = { 0, 0, 0, 0 };
361 for (const std::string &Name : Contents) {
362 ASSERT_FALSE(Name.empty());
363 int Index = Name[Name.size()-1] - 'a';
364 ASSERT_TRUE(Index >= 0 && Index < 4);
365 Counts[Index]++;
366 }
367 EXPECT_EQ(1, Counts[0]); // a
368 EXPECT_EQ(1, Counts[1]); // b
369 EXPECT_EQ(1, Counts[2]); // c
370 EXPECT_EQ(1, Counts[3]); // d
371}
372
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000373template <typename DirIter>
Bruno Cardoso Lopes29ebd492016-05-11 20:58:47 +0000374static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) {
Ben Langmuir740812b2014-06-24 19:37:16 +0000375 std::error_code EC;
Bruno Cardoso Lopes29ebd492016-05-11 20:58:47 +0000376 SmallVector<StringRef, 4> Expected(ExpectedOut.begin(), ExpectedOut.end());
377 SmallVector<std::string, 4> InputToCheck;
Ben Langmuir740812b2014-06-24 19:37:16 +0000378
Bruno Cardoso Lopes29ebd492016-05-11 20:58:47 +0000379 // Do not rely on iteration order to check for contents, sort both
380 // content vectors before comparison.
381 for (DirIter E; !EC && I != E; I.increment(EC))
382 InputToCheck.push_back(I->getName());
383
384 std::sort(InputToCheck.begin(), InputToCheck.end());
385 std::sort(Expected.begin(), Expected.end());
386 EXPECT_EQ(InputToCheck.size(), Expected.size());
387
388 unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
389 for (unsigned Idx = 0; Idx != LastElt; ++Idx)
Bruno Cardoso Lopes2835c5c2016-05-12 19:13:04 +0000390 EXPECT_EQ(StringRef(InputToCheck[Idx]), Expected[Idx]);
Ben Langmuir740812b2014-06-24 19:37:16 +0000391}
392
393TEST(VirtualFileSystemTest, OverlayIteration) {
394 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
395 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
396 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
397 new vfs::OverlayFileSystem(Lower));
398 O->pushOverlay(Upper);
399
400 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000401 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000402
403 Lower->addRegularFile("/file1");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000404 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000405
406 Upper->addRegularFile("/file2");
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000407 checkContents(O->dir_begin("/", EC), {"/file2", "/file1"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000408
409 Lower->addDirectory("/dir1");
410 Lower->addRegularFile("/dir1/foo");
411 Upper->addDirectory("/dir2");
412 Upper->addRegularFile("/dir2/foo");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000413 checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo"));
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000414 checkContents(O->dir_begin("/", EC), {"/dir2", "/file2", "/dir1", "/file1"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000415}
416
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000417TEST(VirtualFileSystemTest, OverlayRecursiveIteration) {
418 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
419 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
420 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
421 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
422 new vfs::OverlayFileSystem(Lower));
423 O->pushOverlay(Middle);
424 O->pushOverlay(Upper);
425
426 std::error_code EC;
427 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
428 ArrayRef<StringRef>());
429
430 Lower->addRegularFile("/file1");
431 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
432 ArrayRef<StringRef>("/file1"));
433
434 Upper->addDirectory("/dir");
435 Upper->addRegularFile("/dir/file2");
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000436 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
437 {"/dir", "/dir/file2", "/file1"});
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000438
439 Lower->addDirectory("/dir1");
440 Lower->addRegularFile("/dir1/foo");
441 Lower->addDirectory("/dir1/a");
442 Lower->addRegularFile("/dir1/a/b");
443 Middle->addDirectory("/a");
444 Middle->addDirectory("/a/b");
445 Middle->addDirectory("/a/b/c");
446 Middle->addRegularFile("/a/b/c/d");
447 Middle->addRegularFile("/hiddenByUp");
448 Upper->addDirectory("/dir2");
449 Upper->addRegularFile("/dir2/foo");
450 Upper->addRegularFile("/hiddenByUp");
451 checkContents(vfs::recursive_directory_iterator(*O, "/dir2", EC),
452 ArrayRef<StringRef>("/dir2/foo"));
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000453 checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
454 {"/dir", "/dir/file2", "/dir2", "/dir2/foo", "/hiddenByUp",
455 "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/dir1", "/dir1/a",
456 "/dir1/a/b", "/dir1/foo", "/file1"});
Ben Langmuir7c9f6c82014-06-25 20:25:40 +0000457}
458
Ben Langmuir740812b2014-06-24 19:37:16 +0000459TEST(VirtualFileSystemTest, ThreeLevelIteration) {
460 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
461 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
462 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
463 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
464 new vfs::OverlayFileSystem(Lower));
465 O->pushOverlay(Middle);
466 O->pushOverlay(Upper);
467
468 std::error_code EC;
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000469 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
Ben Langmuir740812b2014-06-24 19:37:16 +0000470
471 Middle->addRegularFile("/file2");
NAKAMURA Takumi4669bd42014-06-25 04:34:10 +0000472 checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2"));
Ben Langmuir740812b2014-06-24 19:37:16 +0000473
474 Lower->addRegularFile("/file1");
475 Upper->addRegularFile("/file3");
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000476 checkContents(O->dir_begin("/", EC), {"/file3", "/file2", "/file1"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000477}
478
479TEST(VirtualFileSystemTest, HiddenInIteration) {
480 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
481 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
482 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
483 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
484 new vfs::OverlayFileSystem(Lower));
485 O->pushOverlay(Middle);
486 O->pushOverlay(Upper);
487
488 std::error_code EC;
489 Lower->addRegularFile("/onlyInLow", sys::fs::owner_read);
490 Lower->addRegularFile("/hiddenByMid", sys::fs::owner_read);
491 Lower->addRegularFile("/hiddenByUp", sys::fs::owner_read);
492 Middle->addRegularFile("/onlyInMid", sys::fs::owner_write);
493 Middle->addRegularFile("/hiddenByMid", sys::fs::owner_write);
494 Middle->addRegularFile("/hiddenByUp", sys::fs::owner_write);
495 Upper->addRegularFile("/onlyInUp", sys::fs::owner_all);
496 Upper->addRegularFile("/hiddenByUp", sys::fs::owner_all);
Benjamin Kramer2a23e552016-01-10 10:45:19 +0000497 checkContents(
498 O->dir_begin("/", EC),
499 {"/hiddenByUp", "/onlyInUp", "/hiddenByMid", "/onlyInMid", "/onlyInLow"});
Ben Langmuir740812b2014-06-24 19:37:16 +0000500
501 // Make sure we get the top-most entry
Ben Langmuirefb8b602014-06-24 21:08:13 +0000502 {
503 std::error_code EC;
504 vfs::directory_iterator I = O->dir_begin("/", EC), E;
505 for ( ; !EC && I != E; I.increment(EC))
506 if (I->getName() == "/hiddenByUp")
507 break;
508 ASSERT_NE(E, I);
509 EXPECT_EQ(sys::fs::owner_all, I->getPermissions());
510 }
511 {
512 std::error_code EC;
513 vfs::directory_iterator I = O->dir_begin("/", EC), E;
514 for ( ; !EC && I != E; I.increment(EC))
515 if (I->getName() == "/hiddenByMid")
516 break;
517 ASSERT_NE(E, I);
518 EXPECT_EQ(sys::fs::owner_write, I->getPermissions());
519 }
Ben Langmuir740812b2014-06-24 19:37:16 +0000520}
521
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000522class InMemoryFileSystemTest : public ::testing::Test {
523protected:
524 clang::vfs::InMemoryFileSystem FS;
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000525 clang::vfs::InMemoryFileSystem NormalizedFS;
526
527 InMemoryFileSystemTest()
528 : FS(/*UseNormalizedPaths=*/false),
529 NormalizedFS(/*UseNormalizedPaths=*/true) {}
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000530};
531
532TEST_F(InMemoryFileSystemTest, IsEmpty) {
533 auto Stat = FS.status("/a");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000534 ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000535 Stat = FS.status("/");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000536 ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000537}
538
539TEST_F(InMemoryFileSystemTest, WindowsPath) {
540 FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
541 auto Stat = FS.status("c:");
NAKAMURA Takumi4c33a1a2015-10-06 12:16:27 +0000542#if !defined(_WIN32)
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000543 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
NAKAMURA Takumi4c33a1a2015-10-06 12:16:27 +0000544#endif
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000545 Stat = FS.status("c:/windows/system128/foo.cpp");
546 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
547 FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
548 Stat = FS.status("d:/windows/foo.cpp");
549 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
550}
551
552TEST_F(InMemoryFileSystemTest, OverlayFile) {
553 FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000554 NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000555 auto Stat = FS.status("/");
556 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000557 Stat = FS.status("/.");
558 ASSERT_FALSE(Stat);
559 Stat = NormalizedFS.status("/.");
560 ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000561 Stat = FS.status("/a");
562 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
563 ASSERT_EQ("/a", Stat->getName());
564}
565
Benjamin Kramer2e2351a2015-10-06 10:04:08 +0000566TEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) {
567 auto Buf = MemoryBuffer::getMemBuffer("a");
568 FS.addFileNoOwn("/a", 0, Buf.get());
569 auto Stat = FS.status("/a");
570 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
571 ASSERT_EQ("/a", Stat->getName());
572}
573
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000574TEST_F(InMemoryFileSystemTest, OpenFileForRead) {
575 FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000576 FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
577 FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
578 NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
579 NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
580 NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000581 auto File = FS.openFileForRead("/a");
582 ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
583 File = FS.openFileForRead("/a"); // Open again.
584 ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000585 File = NormalizedFS.openFileForRead("/././a"); // Open again.
586 ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000587 File = FS.openFileForRead("/");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000588 ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString();
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000589 File = FS.openFileForRead("/b");
Rafael Espindolab7ab1872015-10-05 20:20:50 +0000590 ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString();
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000591 File = FS.openFileForRead("./c");
592 ASSERT_FALSE(File);
593 File = FS.openFileForRead("e/../d");
594 ASSERT_FALSE(File);
595 File = NormalizedFS.openFileForRead("./c");
Benjamin Kramerd5e0b582015-10-07 08:32:50 +0000596 ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer());
Benjamin Kramer71ce3762015-10-12 16:16:39 +0000597 File = NormalizedFS.openFileForRead("e/../d");
598 ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer());
599}
600
601TEST_F(InMemoryFileSystemTest, DuplicatedFile) {
602 ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
603 ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a")));
604 ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
605 ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b")));
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000606}
607
608TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
609 FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""));
610 FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer(""));
611
612 std::error_code EC;
613 vfs::directory_iterator I = FS.dir_begin("/", EC);
614 ASSERT_FALSE(EC);
615 ASSERT_EQ("/a", I->getName());
616 I.increment(EC);
617 ASSERT_FALSE(EC);
618 ASSERT_EQ("/b", I->getName());
619 I.increment(EC);
620 ASSERT_FALSE(EC);
621 ASSERT_EQ(vfs::directory_iterator(), I);
622
623 I = FS.dir_begin("/b", EC);
624 ASSERT_FALSE(EC);
625 ASSERT_EQ("/b/c", I->getName());
626 I.increment(EC);
627 ASSERT_FALSE(EC);
628 ASSERT_EQ(vfs::directory_iterator(), I);
629}
630
Benjamin Kramer1b8dbe32015-10-06 14:45:16 +0000631TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
632 FS.setCurrentWorkingDirectory("/b");
633 FS.addFile("c", 0, MemoryBuffer::getMemBuffer(""));
634
635 auto Stat = FS.status("/b/c");
636 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
637 ASSERT_EQ("c", Stat->getName());
638 ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
639
640 Stat = FS.status("c");
641 ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
Benjamin Kramere9e76072016-01-09 16:33:16 +0000642
Benjamin Kramer730338b2016-01-10 10:36:59 +0000643 auto ReplaceBackslashes = [](std::string S) {
644 std::replace(S.begin(), S.end(), '\\', '/');
645 return S;
646 };
Benjamin Kramere9e76072016-01-09 16:33:16 +0000647 NormalizedFS.setCurrentWorkingDirectory("/b/c");
648 NormalizedFS.setCurrentWorkingDirectory(".");
Benjamin Kramer730338b2016-01-10 10:36:59 +0000649 ASSERT_EQ("/b/c", ReplaceBackslashes(
650 NormalizedFS.getCurrentWorkingDirectory().get()));
Benjamin Kramere9e76072016-01-09 16:33:16 +0000651 NormalizedFS.setCurrentWorkingDirectory("..");
Benjamin Kramer730338b2016-01-10 10:36:59 +0000652 ASSERT_EQ("/b", ReplaceBackslashes(
653 NormalizedFS.getCurrentWorkingDirectory().get()));
Benjamin Kramer1b8dbe32015-10-06 14:45:16 +0000654}
655
Ben Langmuir93853232014-03-05 21:32:20 +0000656// NOTE: in the tests below, we use '//root/' as our root directory, since it is
657// a legal *absolute* path on Windows as well as *nix.
Ben Langmuir97882e72014-02-24 20:56:37 +0000658class VFSFromYAMLTest : public ::testing::Test {
659public:
660 int NumDiagnostics;
Ben Langmuir93853232014-03-05 21:32:20 +0000661
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000662 void SetUp() override { NumDiagnostics = 0; }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000663
Ben Langmuir97882e72014-02-24 20:56:37 +0000664 static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
665 VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
666 ++Test->NumDiagnostics;
667 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000668
Ben Langmuir97882e72014-02-24 20:56:37 +0000669 IntrusiveRefCntPtr<vfs::FileSystem>
670 getFromYAMLRawString(StringRef Content,
671 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
Rafael Espindolad87f8d72014-08-27 20:03:29 +0000672 std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content);
Bruno Cardoso Lopesd878e282016-03-20 02:08:48 +0000673 return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, "", this,
Rafael Espindola91ac8df2014-08-17 23:27:13 +0000674 ExternalFS);
Ben Langmuir97882e72014-02-24 20:56:37 +0000675 }
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000676
Ben Langmuir97882e72014-02-24 20:56:37 +0000677 IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
678 StringRef Content,
679 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
680 std::string VersionPlusContent("{\n 'version':0,\n");
681 VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
682 return getFromYAMLRawString(VersionPlusContent, ExternalFS);
683 }
Bruno Cardoso Lopesf6a0a722016-05-12 19:13:07 +0000684
685 // This is intended as a "XFAIL" for windows hosts.
686 bool supportsSameDirMultipleYAMLEntries() {
687 Triple Host(Triple::normalize(sys::getProcessTriple()));
688 return !Host.isOSWindows();
689 }
Ben Langmuir97882e72014-02-24 20:56:37 +0000690};
691
692TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000693 IntrusiveRefCntPtr<vfs::FileSystem> FS;
694 FS = getFromYAMLString("");
Alp Tokerf994cef2014-07-05 03:08:06 +0000695 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000696 FS = getFromYAMLString("[]");
Alp Tokerf994cef2014-07-05 03:08:06 +0000697 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000698 FS = getFromYAMLString("'string'");
Alp Tokerf994cef2014-07-05 03:08:06 +0000699 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000700 EXPECT_EQ(3, NumDiagnostics);
701}
702
Ben Langmuir97882e72014-02-24 20:56:37 +0000703TEST_F(VFSFromYAMLTest, MappedFiles) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000704 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000705 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000706 IntrusiveRefCntPtr<vfs::FileSystem> FS =
707 getFromYAMLString("{ 'roots': [\n"
708 "{\n"
709 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000710 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000711 " 'contents': [ {\n"
712 " 'type': 'file',\n"
713 " 'name': 'file1',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000714 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000715 " },\n"
716 " {\n"
717 " 'type': 'file',\n"
718 " 'name': 'file2',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000719 " 'external-contents': '//root/foo/b'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000720 " }\n"
721 " ]\n"
722 "}\n"
723 "]\n"
724 "}",
725 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000726 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000727
728 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
729 new vfs::OverlayFileSystem(Lower));
730 O->pushOverlay(FS);
731
732 // file
Ben Langmuir93853232014-03-05 21:32:20 +0000733 ErrorOr<vfs::Status> S = O->status("//root/file1");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000734 ASSERT_FALSE(S.getError());
Ben Langmuir93853232014-03-05 21:32:20 +0000735 EXPECT_EQ("//root/foo/bar/a", S->getName());
Ben Langmuirf13302e2015-12-10 23:41:39 +0000736 EXPECT_TRUE(S->IsVFSMapped);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000737
Ben Langmuir93853232014-03-05 21:32:20 +0000738 ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
739 EXPECT_EQ("//root/foo/bar/a", SLower->getName());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000740 EXPECT_TRUE(S->equivalent(*SLower));
Ben Langmuirf13302e2015-12-10 23:41:39 +0000741 EXPECT_FALSE(SLower->IsVFSMapped);
742
743 // file after opening
744 auto OpenedF = O->openFileForRead("//root/file1");
745 ASSERT_FALSE(OpenedF.getError());
746 auto OpenedS = (*OpenedF)->status();
747 ASSERT_FALSE(OpenedS.getError());
748 EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
749 EXPECT_TRUE(OpenedS->IsVFSMapped);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000750
751 // directory
Ben Langmuir93853232014-03-05 21:32:20 +0000752 S = O->status("//root/");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000753 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000754 EXPECT_TRUE(S->isDirectory());
Ben Langmuir93853232014-03-05 21:32:20 +0000755 EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000756
757 // broken mapping
Rafael Espindola71de0b62014-06-13 17:20:50 +0000758 EXPECT_EQ(O->status("//root/file2").getError(),
759 llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000760 EXPECT_EQ(0, NumDiagnostics);
761}
762
Ben Langmuir97882e72014-02-24 20:56:37 +0000763TEST_F(VFSFromYAMLTest, CaseInsensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000764 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000765 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000766 IntrusiveRefCntPtr<vfs::FileSystem> FS =
767 getFromYAMLString("{ 'case-sensitive': 'false',\n"
768 " 'roots': [\n"
769 "{\n"
770 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000771 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000772 " 'contents': [ {\n"
773 " 'type': 'file',\n"
774 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000775 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000776 " }\n"
777 " ]\n"
778 "}]}",
779 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000780 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000781
782 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
783 new vfs::OverlayFileSystem(Lower));
784 O->pushOverlay(FS);
785
Ben Langmuir93853232014-03-05 21:32:20 +0000786 ErrorOr<vfs::Status> S = O->status("//root/XX");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000787 ASSERT_FALSE(S.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000788
Ben Langmuir93853232014-03-05 21:32:20 +0000789 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola3ae06202014-05-31 03:20:52 +0000790 ASSERT_FALSE(SS.getError());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000791 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000792 SS = O->status("//root/xX");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000793 EXPECT_TRUE(S->equivalent(*SS));
Ben Langmuir93853232014-03-05 21:32:20 +0000794 SS = O->status("//root/Xx");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000795 EXPECT_TRUE(S->equivalent(*SS));
796 EXPECT_EQ(0, NumDiagnostics);
797}
798
Ben Langmuir97882e72014-02-24 20:56:37 +0000799TEST_F(VFSFromYAMLTest, CaseSensitive) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000800 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000801 Lower->addRegularFile("//root/foo/bar/a");
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000802 IntrusiveRefCntPtr<vfs::FileSystem> FS =
803 getFromYAMLString("{ 'case-sensitive': 'true',\n"
804 " 'roots': [\n"
805 "{\n"
806 " 'type': 'directory',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000807 " 'name': '//root/',\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000808 " 'contents': [ {\n"
809 " 'type': 'file',\n"
810 " 'name': 'XX',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000811 " 'external-contents': '//root/foo/bar/a'\n"
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000812 " }\n"
813 " ]\n"
814 "}]}",
815 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000816 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000817
818 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
819 new vfs::OverlayFileSystem(Lower));
820 O->pushOverlay(FS);
821
Ben Langmuir93853232014-03-05 21:32:20 +0000822 ErrorOr<vfs::Status> SS = O->status("//root/xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000823 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000824 SS = O->status("//root/xX");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000825 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuir93853232014-03-05 21:32:20 +0000826 SS = O->status("//root/Xx");
Rafael Espindola71de0b62014-06-13 17:20:50 +0000827 EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000828 EXPECT_EQ(0, NumDiagnostics);
829}
830
Ben Langmuir97882e72014-02-24 20:56:37 +0000831TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000832 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
833
834 // invalid YAML at top-level
835 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000836 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000837 // invalid YAML in roots
838 FS = getFromYAMLString("{ 'roots':[}", Lower);
839 // invalid YAML in directory
840 FS = getFromYAMLString(
841 "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
842 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000843 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000844
845 // invalid configuration
846 FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000847 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000848 FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000849 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000850
851 // invalid roots
852 FS = getFromYAMLString("{ 'roots':'' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000853 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000854 FS = getFromYAMLString("{ 'roots':{} }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000855 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000856
857 // invalid entries
858 FS = getFromYAMLString(
859 "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000860 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000861 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
862 "'external-contents': 'other' }",
863 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000864 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000865 FS = getFromYAMLString(
866 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
867 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000868 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000869 FS = getFromYAMLString(
870 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
871 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000872 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000873 FS = getFromYAMLString(
874 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
875 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000876 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000877 FS = getFromYAMLString(
878 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
879 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000880 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000881 FS = getFromYAMLString(
882 "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
883 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000884 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000885
886 // missing mandatory fields
887 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000888 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000889 FS = getFromYAMLString(
890 "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000891 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000892 FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000893 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000894
895 // duplicate keys
896 FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000897 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000898 FS = getFromYAMLString(
899 "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
900 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000901 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000902 FS =
903 getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
904 "'external-contents':'blah' } ] }",
905 Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000906 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000907
908 // missing version
909 FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000910 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000911
912 // bad version number
913 FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000914 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000915 FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000916 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000917 FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000918 EXPECT_EQ(nullptr, FS.get());
Ben Langmuird51ba0b2014-02-21 23:39:37 +0000919 EXPECT_EQ(24, NumDiagnostics);
920}
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000921
Ben Langmuirb59cf672014-02-27 00:25:12 +0000922TEST_F(VFSFromYAMLTest, UseExternalName) {
923 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000924 Lower->addRegularFile("//root/external/file");
Ben Langmuirb59cf672014-02-27 00:25:12 +0000925
926 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
927 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000928 " { 'type': 'file', 'name': '//root/A',\n"
929 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000930 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000931 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000932 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000933 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000934 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000935 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000936 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000937 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000938 " }\n"
939 "] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000940 ASSERT_TRUE(nullptr != FS.get());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000941
942 // default true
Ben Langmuir93853232014-03-05 21:32:20 +0000943 EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000944 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000945 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
946 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000947
948 // global configuration
949 FS = getFromYAMLString(
950 "{ 'use-external-names': false,\n"
951 " 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000952 " { 'type': 'file', 'name': '//root/A',\n"
953 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000954 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000955 " { 'type': 'file', 'name': '//root/B',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000956 " 'use-external-name': true,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000957 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000958 " },\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000959 " { 'type': 'file', 'name': '//root/C',\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000960 " 'use-external-name': false,\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000961 " 'external-contents': '//root/external/file'\n"
Ben Langmuirb59cf672014-02-27 00:25:12 +0000962 " }\n"
963 "] }", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000964 ASSERT_TRUE(nullptr != FS.get());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000965
966 // default
Ben Langmuir93853232014-03-05 21:32:20 +0000967 EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000968 // explicit
Ben Langmuir93853232014-03-05 21:32:20 +0000969 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
970 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
Ben Langmuirb59cf672014-02-27 00:25:12 +0000971}
972
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000973TEST_F(VFSFromYAMLTest, MultiComponentPath) {
974 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +0000975 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000976
977 // file in roots
978 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
979 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000980 " { 'type': 'file', 'name': '//root/path/to/file',\n"
981 " 'external-contents': '//root/other' }]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000982 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000983 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000984 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
985 EXPECT_FALSE(FS->status("//root/path/to").getError());
986 EXPECT_FALSE(FS->status("//root/path").getError());
987 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000988
989 // at the start
990 FS = getFromYAMLString(
991 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000992 " { 'type': 'directory', 'name': '//root/path/to',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000993 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +0000994 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +0000995 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +0000996 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +0000997 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
998 EXPECT_FALSE(FS->status("//root/path/to").getError());
999 EXPECT_FALSE(FS->status("//root/path").getError());
1000 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001001
1002 // at the end
1003 FS = getFromYAMLString(
1004 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +00001005 " { 'type': 'directory', 'name': '//root/',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001006 " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +00001007 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001008 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +00001009 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +00001010 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
1011 EXPECT_FALSE(FS->status("//root/path/to").getError());
1012 EXPECT_FALSE(FS->status("//root/path").getError());
1013 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001014}
1015
1016TEST_F(VFSFromYAMLTest, TrailingSlashes) {
1017 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Ben Langmuir93853232014-03-05 21:32:20 +00001018 Lower->addRegularFile("//root/other");
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001019
1020 // file in roots
1021 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
1022 "{ 'roots': [\n"
Ben Langmuir93853232014-03-05 21:32:20 +00001023 " { 'type': 'directory', 'name': '//root/path/to////',\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001024 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
Ben Langmuir93853232014-03-05 21:32:20 +00001025 " 'external-contents': '//root/other' }]}]\n"
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001026 "}", Lower);
Alp Tokerf994cef2014-07-05 03:08:06 +00001027 ASSERT_TRUE(nullptr != FS.get());
Rafael Espindola3ae06202014-05-31 03:20:52 +00001028 EXPECT_FALSE(FS->status("//root/path/to/file").getError());
1029 EXPECT_FALSE(FS->status("//root/path/to").getError());
1030 EXPECT_FALSE(FS->status("//root/path").getError());
1031 EXPECT_FALSE(FS->status("//root/").getError());
Ben Langmuir47ff9ab2014-02-25 04:34:14 +00001032}
Ben Langmuir740812b2014-06-24 19:37:16 +00001033
1034TEST_F(VFSFromYAMLTest, DirectoryIteration) {
1035 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1036 Lower->addDirectory("//root/");
1037 Lower->addDirectory("//root/foo");
1038 Lower->addDirectory("//root/foo/bar");
1039 Lower->addRegularFile("//root/foo/bar/a");
1040 Lower->addRegularFile("//root/foo/bar/b");
1041 Lower->addRegularFile("//root/file3");
1042 IntrusiveRefCntPtr<vfs::FileSystem> FS =
1043 getFromYAMLString("{ 'use-external-names': false,\n"
1044 " 'roots': [\n"
1045 "{\n"
1046 " 'type': 'directory',\n"
1047 " 'name': '//root/',\n"
1048 " 'contents': [ {\n"
1049 " 'type': 'file',\n"
1050 " 'name': 'file1',\n"
1051 " 'external-contents': '//root/foo/bar/a'\n"
1052 " },\n"
1053 " {\n"
1054 " 'type': 'file',\n"
1055 " 'name': 'file2',\n"
1056 " 'external-contents': '//root/foo/bar/b'\n"
1057 " }\n"
1058 " ]\n"
1059 "}\n"
1060 "]\n"
1061 "}",
1062 Lower);
Hans Wennborgdcfba332015-10-06 23:40:43 +00001063 ASSERT_TRUE(FS.get() != nullptr);
Ben Langmuir740812b2014-06-24 19:37:16 +00001064
1065 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1066 new vfs::OverlayFileSystem(Lower));
1067 O->pushOverlay(FS);
1068
1069 std::error_code EC;
Benjamin Kramer2a23e552016-01-10 10:45:19 +00001070 checkContents(O->dir_begin("//root/", EC),
Bruno Cardoso Lopes26092b22016-05-12 04:43:27 +00001071 {"//root/file1", "//root/file2", "//root/file3", "//root/foo"});
Ben Langmuir740812b2014-06-24 19:37:16 +00001072
Benjamin Kramer2a23e552016-01-10 10:45:19 +00001073 checkContents(O->dir_begin("//root/foo/bar", EC),
1074 {"//root/foo/bar/a", "//root/foo/bar/b"});
Ben Langmuir740812b2014-06-24 19:37:16 +00001075}
Bruno Cardoso Lopesf6a0a722016-05-12 19:13:07 +00001076
1077TEST_F(VFSFromYAMLTest, DirectoryIterationSameDirMultipleEntries) {
1078 // https://llvm.org/bugs/show_bug.cgi?id=27725
1079 if (!supportsSameDirMultipleYAMLEntries())
1080 return;
1081
1082 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1083 Lower->addDirectory("//root/zab");
1084 Lower->addDirectory("//root/baz");
1085 Lower->addRegularFile("//root/zab/a");
1086 Lower->addRegularFile("//root/zab/b");
1087 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
1088 "{ 'use-external-names': false,\n"
1089 " 'roots': [\n"
1090 "{\n"
1091 " 'type': 'directory',\n"
1092 " 'name': '//root/baz/',\n"
1093 " 'contents': [ {\n"
1094 " 'type': 'file',\n"
1095 " 'name': 'x',\n"
1096 " 'external-contents': '//root/zab/a'\n"
1097 " }\n"
1098 " ]\n"
1099 "},\n"
1100 "{\n"
1101 " 'type': 'directory',\n"
1102 " 'name': '//root/baz/',\n"
1103 " 'contents': [ {\n"
1104 " 'type': 'file',\n"
1105 " 'name': 'y',\n"
1106 " 'external-contents': '//root/zab/b'\n"
1107 " }\n"
1108 " ]\n"
1109 "}\n"
1110 "]\n"
1111 "}",
1112 Lower);
1113 ASSERT_TRUE(FS.get() != nullptr);
1114
1115 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1116 new vfs::OverlayFileSystem(Lower));
1117 O->pushOverlay(FS);
1118
1119 std::error_code EC;
1120
1121 checkContents(O->dir_begin("//root/baz/", EC),
1122 {"//root/baz/x", "//root/baz/y"});
1123}
Bruno Cardoso Lopes32b28972016-05-14 00:00:18 +00001124
1125TEST_F(VFSFromYAMLTest, RecursiveDirectoryIterationLevel) {
1126
1127 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1128 Lower->addDirectory("//root/a");
1129 Lower->addDirectory("//root/a/b");
1130 Lower->addDirectory("//root/a/b/c");
1131 Lower->addRegularFile("//root/a/b/c/file");
1132 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
1133 "{ 'use-external-names': false,\n"
1134 " 'roots': [\n"
1135 "{\n"
1136 " 'type': 'directory',\n"
1137 " 'name': '//root/a/b/c/',\n"
1138 " 'contents': [ {\n"
1139 " 'type': 'file',\n"
1140 " 'name': 'file',\n"
1141 " 'external-contents': '//root/a/b/c/file'\n"
1142 " }\n"
1143 " ]\n"
1144 "},\n"
1145 "]\n"
1146 "}",
1147 Lower);
1148 ASSERT_TRUE(FS.get() != nullptr);
1149
1150 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1151 new vfs::OverlayFileSystem(Lower));
1152 O->pushOverlay(FS);
1153
1154 std::error_code EC;
1155
1156 // Test recursive_directory_iterator level()
1157 vfs::recursive_directory_iterator I = vfs::recursive_directory_iterator(
1158 *O, "//root", EC), E;
1159 ASSERT_FALSE(EC);
1160 for (int l = 0; I != E; I.increment(EC), ++l) {
1161 ASSERT_FALSE(EC);
1162 EXPECT_EQ(I.level(), l);
1163 }
1164 EXPECT_EQ(I, E);
1165}