blob: 40d2f168cdf38ac89490dba6bad71e1cb4d68ef2 [file] [log] [blame]
Stephen Hines651f13c2014-04-23 16:59:28 -07001//===- 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"
11#include "llvm/Support/MemoryBuffer.h"
12#include "llvm/Support/Path.h"
13#include "llvm/Support/SourceMgr.h"
14#include "gtest/gtest.h"
15#include <map>
16using namespace clang;
17using namespace llvm;
18using llvm::sys::fs::UniqueID;
19
20namespace {
21class DummyFileSystem : public vfs::FileSystem {
22 int FSID; // used to produce UniqueIDs
23 int FileID; // used to produce UniqueIDs
24 std::map<std::string, vfs::Status> FilesAndDirs;
25
26 static int getNextFSID() {
27 static int Count = 0;
28 return Count++;
29 }
30
31public:
32 DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
33
34 ErrorOr<vfs::Status> status(const Twine &Path) {
35 std::map<std::string, vfs::Status>::iterator I =
36 FilesAndDirs.find(Path.str());
37 if (I == FilesAndDirs.end())
38 return error_code(errc::no_such_file_or_directory, posix_category());
39 return I->second;
40 }
41 error_code openFileForRead(const Twine &Path,
42 std::unique_ptr<vfs::File> &Result) {
43 llvm_unreachable("unimplemented");
44 }
45 error_code getBufferForFile(const Twine &Name,
46 std::unique_ptr<MemoryBuffer> &Result,
47 int64_t FileSize = -1,
48 bool RequiresNullTerminator = true) {
49 llvm_unreachable("unimplemented");
50 }
51
52 void addEntry(StringRef Path, const vfs::Status &Status) {
53 FilesAndDirs[Path] = Status;
54 }
55
56 void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
57 vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
58 0, 0, 1024, sys::fs::file_type::regular_file, Perms);
59 addEntry(Path, S);
60 }
61
62 void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
63 vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
64 0, 0, 0, sys::fs::file_type::directory_file, Perms);
65 addEntry(Path, S);
66 }
67
68 void addSymlink(StringRef Path) {
69 vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
70 0, 0, 0, sys::fs::file_type::symlink_file, sys::fs::all_all);
71 addEntry(Path, S);
72 }
73};
74} // end anonymous namespace
75
76TEST(VirtualFileSystemTest, StatusQueries) {
77 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
78 ErrorOr<vfs::Status> Status((error_code()));
79
80 D->addRegularFile("/foo");
81 Status = D->status("/foo");
82 ASSERT_EQ(errc::success, Status.getError());
83 EXPECT_TRUE(Status->isStatusKnown());
84 EXPECT_FALSE(Status->isDirectory());
85 EXPECT_TRUE(Status->isRegularFile());
86 EXPECT_FALSE(Status->isSymlink());
87 EXPECT_FALSE(Status->isOther());
88 EXPECT_TRUE(Status->exists());
89
90 D->addDirectory("/bar");
91 Status = D->status("/bar");
92 ASSERT_EQ(errc::success, Status.getError());
93 EXPECT_TRUE(Status->isStatusKnown());
94 EXPECT_TRUE(Status->isDirectory());
95 EXPECT_FALSE(Status->isRegularFile());
96 EXPECT_FALSE(Status->isSymlink());
97 EXPECT_FALSE(Status->isOther());
98 EXPECT_TRUE(Status->exists());
99
100 D->addSymlink("/baz");
101 Status = D->status("/baz");
102 ASSERT_EQ(errc::success, Status.getError());
103 EXPECT_TRUE(Status->isStatusKnown());
104 EXPECT_FALSE(Status->isDirectory());
105 EXPECT_FALSE(Status->isRegularFile());
106 EXPECT_TRUE(Status->isSymlink());
107 EXPECT_FALSE(Status->isOther());
108 EXPECT_TRUE(Status->exists());
109
110 EXPECT_TRUE(Status->equivalent(*Status));
111 ErrorOr<vfs::Status> Status2 = D->status("/foo");
112 ASSERT_EQ(errc::success, Status2.getError());
113 EXPECT_FALSE(Status->equivalent(*Status2));
114}
115
116TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
117 IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
118 ErrorOr<vfs::Status> Status((error_code()));
119 EXPECT_FALSE(Status = D->status("/foo"));
120
121 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
122 EXPECT_FALSE(Status = O->status("/foo"));
123
124 D->addRegularFile("/foo");
125 Status = D->status("/foo");
126 EXPECT_EQ(errc::success, Status.getError());
127
128 ErrorOr<vfs::Status> Status2((error_code()));
129 Status2 = O->status("/foo");
130 EXPECT_EQ(errc::success, Status2.getError());
131 EXPECT_TRUE(Status->equivalent(*Status2));
132}
133
134TEST(VirtualFileSystemTest, OverlayFiles) {
135 IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
136 IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
137 IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
138 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
139 new vfs::OverlayFileSystem(Base));
140 O->pushOverlay(Middle);
141 O->pushOverlay(Top);
142
143 ErrorOr<vfs::Status> Status1((error_code())), Status2((error_code())),
144 Status3((error_code())), StatusB((error_code())), StatusM((error_code())),
145 StatusT((error_code()));
146
147 Base->addRegularFile("/foo");
148 StatusB = Base->status("/foo");
149 ASSERT_EQ(errc::success, StatusB.getError());
150 Status1 = O->status("/foo");
151 ASSERT_EQ(errc::success, Status1.getError());
152 Middle->addRegularFile("/foo");
153 StatusM = Middle->status("/foo");
154 ASSERT_EQ(errc::success, StatusM.getError());
155 Status2 = O->status("/foo");
156 ASSERT_EQ(errc::success, Status2.getError());
157 Top->addRegularFile("/foo");
158 StatusT = Top->status("/foo");
159 ASSERT_EQ(errc::success, StatusT.getError());
160 Status3 = O->status("/foo");
161 ASSERT_EQ(errc::success, Status3.getError());
162
163 EXPECT_TRUE(Status1->equivalent(*StatusB));
164 EXPECT_TRUE(Status2->equivalent(*StatusM));
165 EXPECT_TRUE(Status3->equivalent(*StatusT));
166
167 EXPECT_FALSE(Status1->equivalent(*Status2));
168 EXPECT_FALSE(Status2->equivalent(*Status3));
169 EXPECT_FALSE(Status1->equivalent(*Status3));
170}
171
172TEST(VirtualFileSystemTest, OverlayDirsNonMerged) {
173 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
174 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
175 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
176 new vfs::OverlayFileSystem(Lower));
177 O->pushOverlay(Upper);
178
179 Lower->addDirectory("/lower-only");
180 Upper->addDirectory("/upper-only");
181
182 // non-merged paths should be the same
183 ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
184 ASSERT_EQ(errc::success, Status1.getError());
185 ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
186 ASSERT_EQ(errc::success, Status2.getError());
187 EXPECT_TRUE(Status1->equivalent(*Status2));
188
189 Status1 = Upper->status("/upper-only");
190 ASSERT_EQ(errc::success, Status1.getError());
191 Status2 = O->status("/upper-only");
192 ASSERT_EQ(errc::success, Status2.getError());
193 EXPECT_TRUE(Status1->equivalent(*Status2));
194}
195
196TEST(VirtualFileSystemTest, MergedDirPermissions) {
197 // merged directories get the permissions of the upper dir
198 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
199 IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
200 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
201 new vfs::OverlayFileSystem(Lower));
202 O->pushOverlay(Upper);
203
204 ErrorOr<vfs::Status> Status((error_code()));
205 Lower->addDirectory("/both", sys::fs::owner_read);
206 Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
207 Status = O->status("/both");
208 ASSERT_EQ(errc::success, Status.getError());
209 EXPECT_EQ(0740, Status->getPermissions());
210
211 // permissions (as usual) are not recursively applied
212 Lower->addRegularFile("/both/foo", sys::fs::owner_read);
213 Upper->addRegularFile("/both/bar", sys::fs::owner_write);
214 Status = O->status("/both/foo");
215 ASSERT_EQ(errc::success, Status.getError());
216 EXPECT_EQ(0400, Status->getPermissions());
217 Status = O->status("/both/bar");
218 ASSERT_EQ(errc::success, Status.getError());
219 EXPECT_EQ(0200, Status->getPermissions());
220}
221
222// NOTE: in the tests below, we use '//root/' as our root directory, since it is
223// a legal *absolute* path on Windows as well as *nix.
224class VFSFromYAMLTest : public ::testing::Test {
225public:
226 int NumDiagnostics;
227
228 void SetUp() {
229 NumDiagnostics = 0;
230 }
231
232 static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
233 VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
234 ++Test->NumDiagnostics;
235 }
236
237 IntrusiveRefCntPtr<vfs::FileSystem>
238 getFromYAMLRawString(StringRef Content,
239 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
240 MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Content);
241 return getVFSFromYAML(Buffer, CountingDiagHandler, this, ExternalFS);
242 }
243
244 IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
245 StringRef Content,
246 IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
247 std::string VersionPlusContent("{\n 'version':0,\n");
248 VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
249 return getFromYAMLRawString(VersionPlusContent, ExternalFS);
250 }
251};
252
253TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
254 IntrusiveRefCntPtr<vfs::FileSystem> FS;
255 FS = getFromYAMLString("");
256 EXPECT_EQ(NULL, FS.getPtr());
257 FS = getFromYAMLString("[]");
258 EXPECT_EQ(NULL, FS.getPtr());
259 FS = getFromYAMLString("'string'");
260 EXPECT_EQ(NULL, FS.getPtr());
261 EXPECT_EQ(3, NumDiagnostics);
262}
263
264TEST_F(VFSFromYAMLTest, MappedFiles) {
265 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
266 Lower->addRegularFile("//root/foo/bar/a");
267 IntrusiveRefCntPtr<vfs::FileSystem> FS =
268 getFromYAMLString("{ 'roots': [\n"
269 "{\n"
270 " 'type': 'directory',\n"
271 " 'name': '//root/',\n"
272 " 'contents': [ {\n"
273 " 'type': 'file',\n"
274 " 'name': 'file1',\n"
275 " 'external-contents': '//root/foo/bar/a'\n"
276 " },\n"
277 " {\n"
278 " 'type': 'file',\n"
279 " 'name': 'file2',\n"
280 " 'external-contents': '//root/foo/b'\n"
281 " }\n"
282 " ]\n"
283 "}\n"
284 "]\n"
285 "}",
286 Lower);
287 ASSERT_TRUE(FS.getPtr() != NULL);
288
289 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
290 new vfs::OverlayFileSystem(Lower));
291 O->pushOverlay(FS);
292
293 // file
294 ErrorOr<vfs::Status> S = O->status("//root/file1");
295 ASSERT_EQ(errc::success, S.getError());
296 EXPECT_EQ("//root/foo/bar/a", S->getName());
297
298 ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
299 EXPECT_EQ("//root/foo/bar/a", SLower->getName());
300 EXPECT_TRUE(S->equivalent(*SLower));
301
302 // directory
303 S = O->status("//root/");
304 ASSERT_EQ(errc::success, S.getError());
305 EXPECT_TRUE(S->isDirectory());
306 EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
307
308 // broken mapping
309 EXPECT_EQ(errc::no_such_file_or_directory, O->status("//root/file2").getError());
310 EXPECT_EQ(0, NumDiagnostics);
311}
312
313TEST_F(VFSFromYAMLTest, CaseInsensitive) {
314 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
315 Lower->addRegularFile("//root/foo/bar/a");
316 IntrusiveRefCntPtr<vfs::FileSystem> FS =
317 getFromYAMLString("{ 'case-sensitive': 'false',\n"
318 " 'roots': [\n"
319 "{\n"
320 " 'type': 'directory',\n"
321 " 'name': '//root/',\n"
322 " 'contents': [ {\n"
323 " 'type': 'file',\n"
324 " 'name': 'XX',\n"
325 " 'external-contents': '//root/foo/bar/a'\n"
326 " }\n"
327 " ]\n"
328 "}]}",
329 Lower);
330 ASSERT_TRUE(FS.getPtr() != NULL);
331
332 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
333 new vfs::OverlayFileSystem(Lower));
334 O->pushOverlay(FS);
335
336 ErrorOr<vfs::Status> S = O->status("//root/XX");
337 ASSERT_EQ(errc::success, S.getError());
338
339 ErrorOr<vfs::Status> SS = O->status("//root/xx");
340 ASSERT_EQ(errc::success, SS.getError());
341 EXPECT_TRUE(S->equivalent(*SS));
342 SS = O->status("//root/xX");
343 EXPECT_TRUE(S->equivalent(*SS));
344 SS = O->status("//root/Xx");
345 EXPECT_TRUE(S->equivalent(*SS));
346 EXPECT_EQ(0, NumDiagnostics);
347}
348
349TEST_F(VFSFromYAMLTest, CaseSensitive) {
350 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
351 Lower->addRegularFile("//root/foo/bar/a");
352 IntrusiveRefCntPtr<vfs::FileSystem> FS =
353 getFromYAMLString("{ 'case-sensitive': 'true',\n"
354 " 'roots': [\n"
355 "{\n"
356 " 'type': 'directory',\n"
357 " 'name': '//root/',\n"
358 " 'contents': [ {\n"
359 " 'type': 'file',\n"
360 " 'name': 'XX',\n"
361 " 'external-contents': '//root/foo/bar/a'\n"
362 " }\n"
363 " ]\n"
364 "}]}",
365 Lower);
366 ASSERT_TRUE(FS.getPtr() != NULL);
367
368 IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
369 new vfs::OverlayFileSystem(Lower));
370 O->pushOverlay(FS);
371
372 ErrorOr<vfs::Status> SS = O->status("//root/xx");
373 EXPECT_EQ(errc::no_such_file_or_directory, SS.getError());
374 SS = O->status("//root/xX");
375 EXPECT_EQ(errc::no_such_file_or_directory, SS.getError());
376 SS = O->status("//root/Xx");
377 EXPECT_EQ(errc::no_such_file_or_directory, SS.getError());
378 EXPECT_EQ(0, NumDiagnostics);
379}
380
381TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
382 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
383
384 // invalid YAML at top-level
385 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
386 EXPECT_EQ(NULL, FS.getPtr());
387 // invalid YAML in roots
388 FS = getFromYAMLString("{ 'roots':[}", Lower);
389 // invalid YAML in directory
390 FS = getFromYAMLString(
391 "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
392 Lower);
393 EXPECT_EQ(NULL, FS.getPtr());
394
395 // invalid configuration
396 FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
397 EXPECT_EQ(NULL, FS.getPtr());
398 FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
399 EXPECT_EQ(NULL, FS.getPtr());
400
401 // invalid roots
402 FS = getFromYAMLString("{ 'roots':'' }", Lower);
403 EXPECT_EQ(NULL, FS.getPtr());
404 FS = getFromYAMLString("{ 'roots':{} }", Lower);
405 EXPECT_EQ(NULL, FS.getPtr());
406
407 // invalid entries
408 FS = getFromYAMLString(
409 "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
410 EXPECT_EQ(NULL, FS.getPtr());
411 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
412 "'external-contents': 'other' }",
413 Lower);
414 EXPECT_EQ(NULL, FS.getPtr());
415 FS = getFromYAMLString(
416 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
417 Lower);
418 EXPECT_EQ(NULL, FS.getPtr());
419 FS = getFromYAMLString(
420 "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
421 Lower);
422 EXPECT_EQ(NULL, FS.getPtr());
423 FS = getFromYAMLString(
424 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
425 Lower);
426 EXPECT_EQ(NULL, FS.getPtr());
427 FS = getFromYAMLString(
428 "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
429 Lower);
430 EXPECT_EQ(NULL, FS.getPtr());
431 FS = getFromYAMLString(
432 "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
433 Lower);
434 EXPECT_EQ(NULL, FS.getPtr());
435
436 // missing mandatory fields
437 FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
438 EXPECT_EQ(NULL, FS.getPtr());
439 FS = getFromYAMLString(
440 "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
441 EXPECT_EQ(NULL, FS.getPtr());
442 FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
443 EXPECT_EQ(NULL, FS.getPtr());
444
445 // duplicate keys
446 FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
447 EXPECT_EQ(NULL, FS.getPtr());
448 FS = getFromYAMLString(
449 "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
450 Lower);
451 EXPECT_EQ(NULL, FS.getPtr());
452 FS =
453 getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
454 "'external-contents':'blah' } ] }",
455 Lower);
456 EXPECT_EQ(NULL, FS.getPtr());
457
458 // missing version
459 FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
460 EXPECT_EQ(NULL, FS.getPtr());
461
462 // bad version number
463 FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
464 EXPECT_EQ(NULL, FS.getPtr());
465 FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
466 EXPECT_EQ(NULL, FS.getPtr());
467 FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
468 EXPECT_EQ(NULL, FS.getPtr());
469 EXPECT_EQ(24, NumDiagnostics);
470}
471
472TEST_F(VFSFromYAMLTest, UseExternalName) {
473 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
474 Lower->addRegularFile("//root/external/file");
475
476 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
477 "{ 'roots': [\n"
478 " { 'type': 'file', 'name': '//root/A',\n"
479 " 'external-contents': '//root/external/file'\n"
480 " },\n"
481 " { 'type': 'file', 'name': '//root/B',\n"
482 " 'use-external-name': true,\n"
483 " 'external-contents': '//root/external/file'\n"
484 " },\n"
485 " { 'type': 'file', 'name': '//root/C',\n"
486 " 'use-external-name': false,\n"
487 " 'external-contents': '//root/external/file'\n"
488 " }\n"
489 "] }", Lower);
490 ASSERT_TRUE(NULL != FS.getPtr());
491
492 // default true
493 EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
494 // explicit
495 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
496 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
497
498 // global configuration
499 FS = getFromYAMLString(
500 "{ 'use-external-names': false,\n"
501 " 'roots': [\n"
502 " { 'type': 'file', 'name': '//root/A',\n"
503 " 'external-contents': '//root/external/file'\n"
504 " },\n"
505 " { 'type': 'file', 'name': '//root/B',\n"
506 " 'use-external-name': true,\n"
507 " 'external-contents': '//root/external/file'\n"
508 " },\n"
509 " { 'type': 'file', 'name': '//root/C',\n"
510 " 'use-external-name': false,\n"
511 " 'external-contents': '//root/external/file'\n"
512 " }\n"
513 "] }", Lower);
514 ASSERT_TRUE(NULL != FS.getPtr());
515
516 // default
517 EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
518 // explicit
519 EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
520 EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
521}
522
523TEST_F(VFSFromYAMLTest, MultiComponentPath) {
524 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
525 Lower->addRegularFile("//root/other");
526
527 // file in roots
528 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
529 "{ 'roots': [\n"
530 " { 'type': 'file', 'name': '//root/path/to/file',\n"
531 " 'external-contents': '//root/other' }]\n"
532 "}", Lower);
533 ASSERT_TRUE(NULL != FS.getPtr());
534 EXPECT_EQ(errc::success, FS->status("//root/path/to/file").getError());
535 EXPECT_EQ(errc::success, FS->status("//root/path/to").getError());
536 EXPECT_EQ(errc::success, FS->status("//root/path").getError());
537 EXPECT_EQ(errc::success, FS->status("//root/").getError());
538
539 // at the start
540 FS = getFromYAMLString(
541 "{ 'roots': [\n"
542 " { 'type': 'directory', 'name': '//root/path/to',\n"
543 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
544 " 'external-contents': '//root/other' }]}]\n"
545 "}", Lower);
546 ASSERT_TRUE(NULL != FS.getPtr());
547 EXPECT_EQ(errc::success, FS->status("//root/path/to/file").getError());
548 EXPECT_EQ(errc::success, FS->status("//root/path/to").getError());
549 EXPECT_EQ(errc::success, FS->status("//root/path").getError());
550 EXPECT_EQ(errc::success, FS->status("//root/").getError());
551
552 // at the end
553 FS = getFromYAMLString(
554 "{ 'roots': [\n"
555 " { 'type': 'directory', 'name': '//root/',\n"
556 " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
557 " 'external-contents': '//root/other' }]}]\n"
558 "}", Lower);
559 ASSERT_TRUE(NULL != FS.getPtr());
560 EXPECT_EQ(errc::success, FS->status("//root/path/to/file").getError());
561 EXPECT_EQ(errc::success, FS->status("//root/path/to").getError());
562 EXPECT_EQ(errc::success, FS->status("//root/path").getError());
563 EXPECT_EQ(errc::success, FS->status("//root/").getError());
564}
565
566TEST_F(VFSFromYAMLTest, TrailingSlashes) {
567 IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
568 Lower->addRegularFile("//root/other");
569
570 // file in roots
571 IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
572 "{ 'roots': [\n"
573 " { 'type': 'directory', 'name': '//root/path/to////',\n"
574 " 'contents': [ { 'type': 'file', 'name': 'file',\n"
575 " 'external-contents': '//root/other' }]}]\n"
576 "}", Lower);
577 ASSERT_TRUE(NULL != FS.getPtr());
578 EXPECT_EQ(errc::success, FS->status("//root/path/to/file").getError());
579 EXPECT_EQ(errc::success, FS->status("//root/path/to").getError());
580 EXPECT_EQ(errc::success, FS->status("//root/path").getError());
581 EXPECT_EQ(errc::success, FS->status("//root/").getError());
582}