1651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===- unittests/Basic/VirtualFileSystem.cpp ---------------- VFS tests ---===//
2651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//
3651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//                     The LLVM Compiler Infrastructure
4651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//
5651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// This file is distributed under the University of Illinois Open Source
6651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// License. See LICENSE.TXT for details.
7651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//
8651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===----------------------------------------------------------------------===//
9651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
10651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Basic/VirtualFileSystem.h"
11c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines#include "llvm/Support/Errc.h"
12651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/MemoryBuffer.h"
13651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/Path.h"
14651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/SourceMgr.h"
15651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "gtest/gtest.h"
16651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <map>
17a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
18651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesusing namespace clang;
19651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesusing namespace llvm;
20651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesusing llvm::sys::fs::UniqueID;
21651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
22651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace {
23a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainarstruct DummyFile : public vfs::File {
24a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  vfs::Status S;
25a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  explicit DummyFile(vfs::Status S) : S(S) {}
26a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  llvm::ErrorOr<vfs::Status> status() override { return S; }
27a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
28a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
29a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar            bool IsVolatile) override {
30a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    llvm_unreachable("unimplemented");
31a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  }
32a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  virtual std::error_code close() override { return std::error_code(); }
33a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar};
34a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
35651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass DummyFileSystem : public vfs::FileSystem {
36651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  int FSID;   // used to produce UniqueIDs
37651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  int FileID; // used to produce UniqueIDs
38651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::map<std::string, vfs::Status> FilesAndDirs;
39651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
40651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  static int getNextFSID() {
41651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    static int Count = 0;
42651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return Count++;
43651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
44651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
45651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic:
46651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
47651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
48176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  ErrorOr<vfs::Status> status(const Twine &Path) override {
49651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    std::map<std::string, vfs::Status>::iterator I =
50651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        FilesAndDirs.find(Path.str());
51651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (I == FilesAndDirs.end())
52c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      return make_error_code(llvm::errc::no_such_file_or_directory);
53651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return I->second;
54651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
55176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  ErrorOr<std::unique_ptr<vfs::File>>
56176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  openFileForRead(const Twine &Path) override {
57a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    auto S = status(Path);
58a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    if (S)
59a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar      return std::unique_ptr<vfs::File>(new DummyFile{*S});
60a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    return S.getError();
61a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  }
62a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
63a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    return std::string();
64a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  }
65a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
66a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    return std::error_code();
67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
69c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
70c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::map<std::string, vfs::Status> &FilesAndDirs;
71c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::map<std::string, vfs::Status>::iterator I;
72c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::string Path;
73c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    bool isInPath(StringRef S) {
74c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (Path.size() < S.size() && S.find(Path) == 0) {
75c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        auto LastSep = S.find_last_of('/');
76c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (LastSep == Path.size() || LastSep == Path.size()-1)
77c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          return true;
78c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
79c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      return false;
80c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
81c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    DirIterImpl(std::map<std::string, vfs::Status> &FilesAndDirs,
82c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                const Twine &_Path)
83c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        : FilesAndDirs(FilesAndDirs), I(FilesAndDirs.begin()),
84c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          Path(_Path.str()) {
85c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      for ( ; I != FilesAndDirs.end(); ++I) {
86c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (isInPath(I->first)) {
87c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          CurrentEntry = I->second;
88c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          break;
89c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        }
90c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
91c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
92c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::error_code increment() override {
93c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      ++I;
94c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      for ( ; I != FilesAndDirs.end(); ++I) {
95c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (isInPath(I->first)) {
96c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          CurrentEntry = I->second;
97c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          break;
98c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        }
99c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
100c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (I == FilesAndDirs.end())
101c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        CurrentEntry = vfs::Status();
102c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      return std::error_code();
103c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
104c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  };
105c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
106c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  vfs::directory_iterator dir_begin(const Twine &Dir,
107c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                    std::error_code &EC) override {
108c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    return vfs::directory_iterator(
109c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        std::make_shared<DirIterImpl>(FilesAndDirs, Dir));
110c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
111c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void addEntry(StringRef Path, const vfs::Status &Status) {
113651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    FilesAndDirs[Path] = Status;
114651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
117a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
118a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar                  1024, sys::fs::file_type::regular_file, Perms);
119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    addEntry(Path, S);
120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
121651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
123a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
124a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar                  0, sys::fs::file_type::directory_file, Perms);
125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    addEntry(Path, S);
126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
128651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void addSymlink(StringRef Path) {
129a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
130a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar                  0, sys::fs::file_type::symlink_file, sys::fs::all_all);
131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    addEntry(Path, S);
132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines};
134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} // end anonymous namespace
135651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
136651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST(VirtualFileSystemTest, StatusQueries) {
137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
138c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ErrorOr<vfs::Status> Status((std::error_code()));
139651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  D->addRegularFile("/foo");
141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status = D->status("/foo");
142c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status.getError());
143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->isStatusKnown());
144651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->isDirectory());
145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->isRegularFile());
146651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->isSymlink());
147651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->isOther());
148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->exists());
149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  D->addDirectory("/bar");
151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status = D->status("/bar");
152c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status.getError());
153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->isStatusKnown());
154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->isDirectory());
155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->isRegularFile());
156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->isSymlink());
157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->isOther());
158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->exists());
159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  D->addSymlink("/baz");
161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status = D->status("/baz");
162c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status.getError());
163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->isStatusKnown());
164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->isDirectory());
165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->isRegularFile());
166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->isSymlink());
167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->isOther());
168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->exists());
169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->equivalent(*Status));
171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ErrorOr<vfs::Status> Status2 = D->status("/foo");
172c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status2.getError());
173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status->equivalent(*Status2));
174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
176651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST(VirtualFileSystemTest, BaseOnlyOverlay) {
177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
178c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ErrorOr<vfs::Status> Status((std::error_code()));
179651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status = D->status("/foo"));
180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status = O->status("/foo"));
183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  D->addRegularFile("/foo");
185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status = D->status("/foo");
186c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(Status.getError());
187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
188c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ErrorOr<vfs::Status> Status2((std::error_code()));
189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status2 = O->status("/foo");
190c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(Status2.getError());
191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status->equivalent(*Status2));
192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
194651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST(VirtualFileSystemTest, OverlayFiles) {
195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new vfs::OverlayFileSystem(Base));
200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  O->pushOverlay(Middle);
201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  O->pushOverlay(Top);
202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
203c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ErrorOr<vfs::Status> Status1((std::error_code())),
204c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Status2((std::error_code())), Status3((std::error_code())),
205c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      StatusB((std::error_code())), StatusM((std::error_code())),
206c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      StatusT((std::error_code()));
207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Base->addRegularFile("/foo");
209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StatusB = Base->status("/foo");
210c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(StatusB.getError());
211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status1 = O->status("/foo");
212c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status1.getError());
213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Middle->addRegularFile("/foo");
214651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StatusM = Middle->status("/foo");
215c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(StatusM.getError());
216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status2 = O->status("/foo");
217c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status2.getError());
218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Top->addRegularFile("/foo");
219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StatusT = Top->status("/foo");
220c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(StatusT.getError());
221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status3 = O->status("/foo");
222c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status3.getError());
223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status1->equivalent(*StatusB));
225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status2->equivalent(*StatusM));
226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status3->equivalent(*StatusT));
227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
228651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status1->equivalent(*Status2));
229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status2->equivalent(*Status3));
230651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_FALSE(Status1->equivalent(*Status3));
231651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
232651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
233651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST(VirtualFileSystemTest, OverlayDirsNonMerged) {
234651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
235651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
236651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
237651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new vfs::OverlayFileSystem(Lower));
238651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  O->pushOverlay(Upper);
239651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
240651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Lower->addDirectory("/lower-only");
241651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Upper->addDirectory("/upper-only");
242651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
243651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // non-merged paths should be the same
244651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
245c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status1.getError());
246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
247c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status2.getError());
248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status1->equivalent(*Status2));
249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
250651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status1 = Upper->status("/upper-only");
251c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status1.getError());
252651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status2 = O->status("/upper-only");
253c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status2.getError());
254651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(Status1->equivalent(*Status2));
255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
257651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST(VirtualFileSystemTest, MergedDirPermissions) {
258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // merged directories get the permissions of the upper dir
259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new vfs::OverlayFileSystem(Lower));
263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  O->pushOverlay(Upper);
264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
265c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ErrorOr<vfs::Status> Status((std::error_code()));
266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Lower->addDirectory("/both", sys::fs::owner_read);
267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status = O->status("/both");
269c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status.getError());
270651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ(0740, Status->getPermissions());
271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
272651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // permissions (as usual) are not recursively applied
273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Lower->addRegularFile("/both/foo", sys::fs::owner_read);
274651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Upper->addRegularFile("/both/bar", sys::fs::owner_write);
275651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status = O->status("/both/foo");
276c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE( Status.getError());
277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ(0400, Status->getPermissions());
278651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Status = O->status("/both/bar");
279c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(Status.getError());
280651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ(0200, Status->getPermissions());
281651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
282651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
283c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesnamespace {
284c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstruct ScopedDir {
285c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  SmallString<128> Path;
286c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir(const Twine &Name, bool Unique=false) {
287c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::error_code EC;
288c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Unique) {
289c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      EC =  llvm::sys::fs::createUniqueDirectory(Name, Path);
290c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    } else {
291c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Path = Name.str();
292c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      EC = llvm::sys::fs::create_directory(Twine(Path));
293c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
294c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (EC)
295c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Path = "";
296c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    EXPECT_FALSE(EC);
297c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
298c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ~ScopedDir() {
299c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (Path != "")
300c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
301c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
302c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  operator StringRef() { return Path.str(); }
303c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines};
304a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar} // end anonymous namespace
305c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
306c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesTEST(VirtualFileSystemTest, BasicRealFSIteration) {
307c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
308c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
309c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
310c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::error_code EC;
311c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC);
312c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(EC);
313c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(vfs::directory_iterator(), I); // empty directory is empty
314c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
315c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir _a(TestDirectory+"/a");
316c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir _ab(TestDirectory+"/a/b");
317c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir _c(TestDirectory+"/c");
318c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir _cd(TestDirectory+"/c/d");
319c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
320c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  I = FS->dir_begin(Twine(TestDirectory), EC);
321c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(EC);
322c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_NE(vfs::directory_iterator(), I);
323c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Check either a or c, since we can't rely on the iteration order.
324c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
325c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  I.increment(EC);
326c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(EC);
327c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_NE(vfs::directory_iterator(), I);
328c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
329c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  I.increment(EC);
330c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(vfs::directory_iterator(), I);
331c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
332c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
333c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesTEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) {
334c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
335c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
336c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
337c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::error_code EC;
338c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  auto I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
339c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(EC);
340c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(vfs::recursive_directory_iterator(), I); // empty directory is empty
341c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
342c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir _a(TestDirectory+"/a");
343c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir _ab(TestDirectory+"/a/b");
344c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir _c(TestDirectory+"/c");
345c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ScopedDir _cd(TestDirectory+"/c/d");
346c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
347c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
348c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(EC);
349c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_NE(vfs::recursive_directory_iterator(), I);
350c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
351c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
352c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<std::string> Contents;
353c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
354c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines       I.increment(EC)) {
355c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Contents.push_back(I->getName());
356c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
357c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
358c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Check contents, which may be in any order
359c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(4U, Contents.size());
360c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  int Counts[4] = { 0, 0, 0, 0 };
361c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (const std::string &Name : Contents) {
362c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ASSERT_FALSE(Name.empty());
363c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    int Index = Name[Name.size()-1] - 'a';
364c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ASSERT_TRUE(Index >= 0 && Index < 4);
365c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Counts[Index]++;
366c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
367c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(1, Counts[0]); // a
368c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(1, Counts[1]); // b
369c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(1, Counts[2]); // c
370c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(1, Counts[3]); // d
371c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
372c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
373c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinestemplate <typename T, size_t N>
374c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstd::vector<StringRef> makeStringRefVector(const T (&Arr)[N]) {
375c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::vector<StringRef> Vec;
376c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (size_t i = 0; i != N; ++i)
377c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    Vec.push_back(Arr[i]);
378c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return Vec;
379c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
380c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
381c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinestemplate <typename DirIter>
382c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesstatic void checkContents(DirIter I, ArrayRef<StringRef> Expected) {
383c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::error_code EC;
384c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  auto ExpectedIter = Expected.begin(), ExpectedEnd = Expected.end();
385c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  for (DirIter E;
386c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines       !EC && I != E && ExpectedIter != ExpectedEnd;
387c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines       I.increment(EC), ++ExpectedIter)
388c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    EXPECT_EQ(*ExpectedIter, I->getName());
389c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
390c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(ExpectedEnd, ExpectedIter);
391c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(DirIter(), I);
392c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
393c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
394c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesTEST(VirtualFileSystemTest, OverlayIteration) {
395c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
396c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
397c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
398c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      new vfs::OverlayFileSystem(Lower));
399c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  O->pushOverlay(Upper);
400c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
401c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::error_code EC;
402c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
403c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
404c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("/file1");
405c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1"));
406c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
407c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addRegularFile("/file2");
408c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
409c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    const char *Contents[] = {"/file2", "/file1"};
410c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
411c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
412c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
413c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addDirectory("/dir1");
414c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("/dir1/foo");
415c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addDirectory("/dir2");
416c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addRegularFile("/dir2/foo");
417c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo"));
418c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
419c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    const char *Contents[] = {"/dir2", "/file2", "/dir1", "/file1"};
420c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
421c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
422c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
423c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
424c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesTEST(VirtualFileSystemTest, OverlayRecursiveIteration) {
425c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
426c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
427c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
428c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
429c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      new vfs::OverlayFileSystem(Lower));
430c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  O->pushOverlay(Middle);
431c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  O->pushOverlay(Upper);
432c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
433c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::error_code EC;
434c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
435c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                ArrayRef<StringRef>());
436c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
437c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("/file1");
438c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
439c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                ArrayRef<StringRef>("/file1"));
440c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
441c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addDirectory("/dir");
442c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addRegularFile("/dir/file2");
443c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
444c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    const char *Contents[] = {"/dir", "/dir/file2", "/file1"};
445c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
446c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                  makeStringRefVector(Contents));
447c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
448c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
449c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addDirectory("/dir1");
450c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("/dir1/foo");
451c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addDirectory("/dir1/a");
452c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("/dir1/a/b");
453c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Middle->addDirectory("/a");
454c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Middle->addDirectory("/a/b");
455c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Middle->addDirectory("/a/b/c");
456c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Middle->addRegularFile("/a/b/c/d");
457c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Middle->addRegularFile("/hiddenByUp");
458c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addDirectory("/dir2");
459c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addRegularFile("/dir2/foo");
460c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addRegularFile("/hiddenByUp");
461c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  checkContents(vfs::recursive_directory_iterator(*O, "/dir2", EC),
462c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                ArrayRef<StringRef>("/dir2/foo"));
463c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
464c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    const char *Contents[] = { "/dir", "/dir/file2", "/dir2", "/dir2/foo",
465c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "/hiddenByUp", "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/dir1", "/dir1/a",
466c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        "/dir1/a/b", "/dir1/foo", "/file1" };
467c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
468c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                  makeStringRefVector(Contents));
469c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
470c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
471c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
472c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesTEST(VirtualFileSystemTest, ThreeLevelIteration) {
473c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
474c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
475c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
476c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
477c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      new vfs::OverlayFileSystem(Lower));
478c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  O->pushOverlay(Middle);
479c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  O->pushOverlay(Upper);
480c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
481c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::error_code EC;
482c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
483c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
484c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Middle->addRegularFile("/file2");
485c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2"));
486c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
487c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("/file1");
488c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addRegularFile("/file3");
489c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
490c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    const char *Contents[] = {"/file3", "/file2", "/file1"};
491c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
492c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
493c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
494c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
495c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesTEST(VirtualFileSystemTest, HiddenInIteration) {
496c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
497c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
498c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
499c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
500c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      new vfs::OverlayFileSystem(Lower));
501c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  O->pushOverlay(Middle);
502c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  O->pushOverlay(Upper);
503c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
504c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::error_code EC;
505c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("/onlyInLow", sys::fs::owner_read);
506c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("/hiddenByMid", sys::fs::owner_read);
507c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("/hiddenByUp", sys::fs::owner_read);
508c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Middle->addRegularFile("/onlyInMid", sys::fs::owner_write);
509c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Middle->addRegularFile("/hiddenByMid", sys::fs::owner_write);
510c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Middle->addRegularFile("/hiddenByUp", sys::fs::owner_write);
511c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addRegularFile("/onlyInUp", sys::fs::owner_all);
512c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Upper->addRegularFile("/hiddenByUp", sys::fs::owner_all);
513c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
514c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    const char *Contents[] = {"/hiddenByUp", "/onlyInUp", "/hiddenByMid",
515c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                              "/onlyInMid", "/onlyInLow"};
516c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    checkContents(O->dir_begin("/", EC), makeStringRefVector(Contents));
517c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
518c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
519c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  // Make sure we get the top-most entry
520c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
521c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::error_code EC;
522c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    vfs::directory_iterator I = O->dir_begin("/", EC), E;
523c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for ( ; !EC && I != E; I.increment(EC))
524c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (I->getName() == "/hiddenByUp")
525c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        break;
526c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ASSERT_NE(E, I);
527c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    EXPECT_EQ(sys::fs::owner_all, I->getPermissions());
528c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
529c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
530c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    std::error_code EC;
531c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    vfs::directory_iterator I = O->dir_begin("/", EC), E;
532c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    for ( ; !EC && I != E; I.increment(EC))
533c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (I->getName() == "/hiddenByMid")
534c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        break;
535c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ASSERT_NE(E, I);
536c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    EXPECT_EQ(sys::fs::owner_write, I->getPermissions());
537c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
538c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
539c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
540a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainarclass InMemoryFileSystemTest : public ::testing::Test {
541a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainarprotected:
542a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  clang::vfs::InMemoryFileSystem FS;
543a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  clang::vfs::InMemoryFileSystem NormalizedFS;
544a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
545a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  InMemoryFileSystemTest()
546a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar      : FS(/*UseNormalizedPaths=*/false),
547a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar        NormalizedFS(/*UseNormalizedPaths=*/true) {}
548a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar};
549a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
550a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga NainarTEST_F(InMemoryFileSystemTest, IsEmpty) {
551a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto Stat = FS.status("/a");
552a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
553a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  Stat = FS.status("/");
554a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
555a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
556a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
557a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga NainarTEST_F(InMemoryFileSystemTest, WindowsPath) {
558a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
559a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto Stat = FS.status("c:");
560a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar#if !defined(_WIN32)
561a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
562a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar#endif
563a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  Stat = FS.status("c:/windows/system128/foo.cpp");
564a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
565a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
566a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  Stat = FS.status("d:/windows/foo.cpp");
567a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
568a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
569a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
570a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga NainarTEST_F(InMemoryFileSystemTest, OverlayFile) {
571a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
572a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
573a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto Stat = FS.status("/");
574a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
575a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  Stat = FS.status("/.");
576a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat);
577a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  Stat = NormalizedFS.status("/.");
578a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
579a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  Stat = FS.status("/a");
580a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
581a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("/a", Stat->getName());
582a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
583a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
584a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga NainarTEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) {
585a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto Buf = MemoryBuffer::getMemBuffer("a");
586a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFileNoOwn("/a", 0, Buf.get());
587a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto Stat = FS.status("/a");
588a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
589a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("/a", Stat->getName());
590a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
591a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
592a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga NainarTEST_F(InMemoryFileSystemTest, OpenFileForRead) {
593a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
594a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
595a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
596a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
597a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
598a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
599a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto File = FS.openFileForRead("/a");
600a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
601a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  File = FS.openFileForRead("/a"); // Open again.
602a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
603a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  File = NormalizedFS.openFileForRead("/././a"); // Open again.
604a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
605a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  File = FS.openFileForRead("/");
606a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString();
607a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  File = FS.openFileForRead("/b");
608a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString();
609a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  File = FS.openFileForRead("./c");
610a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(File);
611a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  File = FS.openFileForRead("e/../d");
612a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(File);
613a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  File = NormalizedFS.openFileForRead("./c");
614a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer());
615a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  File = NormalizedFS.openFileForRead("e/../d");
616a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer());
617a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
618a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
619a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga NainarTEST_F(InMemoryFileSystemTest, DuplicatedFile) {
620a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
621a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a")));
622a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
623a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b")));
624a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
625a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
626a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga NainarTEST_F(InMemoryFileSystemTest, DirectoryIteration) {
627a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""));
628a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer(""));
629a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
630a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  std::error_code EC;
631a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  vfs::directory_iterator I = FS.dir_begin("/", EC);
632a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(EC);
633a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("/a", I->getName());
634a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  I.increment(EC);
635a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(EC);
636a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("/b", I->getName());
637a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  I.increment(EC);
638a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(EC);
639a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ(vfs::directory_iterator(), I);
640a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
641a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  I = FS.dir_begin("/b", EC);
642a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(EC);
643a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("/b/c", I->getName());
644a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  I.increment(EC);
645a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(EC);
646a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ(vfs::directory_iterator(), I);
647a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
648a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
649a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga NainarTEST_F(InMemoryFileSystemTest, WorkingDirectory) {
650a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.setCurrentWorkingDirectory("/b");
651a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  FS.addFile("c", 0, MemoryBuffer::getMemBuffer(""));
652a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
653a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto Stat = FS.status("/b/c");
654a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
655a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("c", Stat->getName());
656a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
657a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
658a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  Stat = FS.status("c");
659a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
660a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
661a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
662651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// NOTE: in the tests below, we use '//root/' as our root directory, since it is
663651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// a legal *absolute* path on Windows as well as *nix.
664651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass VFSFromYAMLTest : public ::testing::Test {
665651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic:
666651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  int NumDiagnostics;
667651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
66858878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar  void SetUp() override { NumDiagnostics = 0; }
669651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
670651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
671651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
672651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ++Test->NumDiagnostics;
673651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
674651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
675651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem>
676651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  getFromYAMLRawString(StringRef Content,
677651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                       IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
678176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content);
679176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, this,
680176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                          ExternalFS);
681651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
682651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
683651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
684651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      StringRef Content,
685651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
686651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    std::string VersionPlusContent("{\n  'version':0,\n");
687651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
688651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return getFromYAMLRawString(VersionPlusContent, ExternalFS);
689651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
690651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines};
691651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
692651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
693651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS;
694651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("");
695c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
696651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("[]");
697c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
698651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("'string'");
699c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
700651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ(3, NumDiagnostics);
701651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
702651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
703651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST_F(VFSFromYAMLTest, MappedFiles) {
704651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
705651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Lower->addRegularFile("//root/foo/bar/a");
706651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS =
707651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      getFromYAMLString("{ 'roots': [\n"
708651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "{\n"
709651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'type': 'directory',\n"
710651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'name': '//root/',\n"
711651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'contents': [ {\n"
712651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'type': 'file',\n"
713651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'name': 'file1',\n"
714651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'external-contents': '//root/foo/bar/a'\n"
715651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                },\n"
716651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                {\n"
717651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'type': 'file',\n"
718651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'name': 'file2',\n"
719651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'external-contents': '//root/foo/b'\n"
720651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                }\n"
721651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "              ]\n"
722651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "}\n"
723651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "]\n"
724651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "}",
725651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        Lower);
726c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_TRUE(FS.get() != nullptr);
727651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
728651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
729651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new vfs::OverlayFileSystem(Lower));
730651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  O->pushOverlay(FS);
731651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
732651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // file
733651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ErrorOr<vfs::Status> S = O->status("//root/file1");
734c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(S.getError());
735651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ("//root/foo/bar/a", S->getName());
736a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  EXPECT_TRUE(S->IsVFSMapped);
737651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
738651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
739651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ("//root/foo/bar/a", SLower->getName());
740651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(S->equivalent(*SLower));
741a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  EXPECT_FALSE(SLower->IsVFSMapped);
742a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
743a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  // file after opening
744a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto OpenedF = O->openFileForRead("//root/file1");
745a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(OpenedF.getError());
746a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  auto OpenedS = (*OpenedF)->status();
747a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_FALSE(OpenedS.getError());
748a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
749a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  EXPECT_TRUE(OpenedS->IsVFSMapped);
750651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
751651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // directory
752651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  S = O->status("//root/");
753c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(S.getError());
754651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(S->isDirectory());
755651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
756651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
757651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // broken mapping
758c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(O->status("//root/file2").getError(),
759c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines            llvm::errc::no_such_file_or_directory);
760651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ(0, NumDiagnostics);
761651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
762651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
763651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST_F(VFSFromYAMLTest, CaseInsensitive) {
764651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
765651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Lower->addRegularFile("//root/foo/bar/a");
766651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS =
767651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      getFromYAMLString("{ 'case-sensitive': 'false',\n"
768651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'roots': [\n"
769651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "{\n"
770651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'type': 'directory',\n"
771651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'name': '//root/',\n"
772651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'contents': [ {\n"
773651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'type': 'file',\n"
774651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'name': 'XX',\n"
775651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'external-contents': '//root/foo/bar/a'\n"
776651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                }\n"
777651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "              ]\n"
778651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "}]}",
779651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        Lower);
780c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_TRUE(FS.get() != nullptr);
781651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
782651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
783651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new vfs::OverlayFileSystem(Lower));
784651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  O->pushOverlay(FS);
785651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
786651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ErrorOr<vfs::Status> S = O->status("//root/XX");
787c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(S.getError());
788651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
789651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ErrorOr<vfs::Status> SS = O->status("//root/xx");
790c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_FALSE(SS.getError());
791651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(S->equivalent(*SS));
792651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SS = O->status("//root/xX");
793651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(S->equivalent(*SS));
794651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SS = O->status("//root/Xx");
795651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_TRUE(S->equivalent(*SS));
796651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ(0, NumDiagnostics);
797651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
798651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
799651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST_F(VFSFromYAMLTest, CaseSensitive) {
800651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
801651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Lower->addRegularFile("//root/foo/bar/a");
802651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS =
803651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      getFromYAMLString("{ 'case-sensitive': 'true',\n"
804651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'roots': [\n"
805651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "{\n"
806651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'type': 'directory',\n"
807651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'name': '//root/',\n"
808651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "  'contents': [ {\n"
809651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'type': 'file',\n"
810651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'name': 'XX',\n"
811651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                  'external-contents': '//root/foo/bar/a'\n"
812651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "                }\n"
813651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "              ]\n"
814651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "}]}",
815651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        Lower);
816c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_TRUE(FS.get() != nullptr);
817651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
818651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
819651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new vfs::OverlayFileSystem(Lower));
820651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  O->pushOverlay(FS);
821651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
822651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  ErrorOr<vfs::Status> SS = O->status("//root/xx");
823c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
824651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SS = O->status("//root/xX");
825c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
826651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SS = O->status("//root/Xx");
827c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
828651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ(0, NumDiagnostics);
829651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
830651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
831651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST_F(VFSFromYAMLTest, IllegalVFSFile) {
832651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
833651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
834651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // invalid YAML at top-level
835651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
836c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
837651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // invalid YAML in roots
838651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("{ 'roots':[}", Lower);
839651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // invalid YAML in directory
840651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
841651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
842651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Lower);
843c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
844651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
845651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // invalid configuration
846651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
847c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
848651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
849c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
850651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
851651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // invalid roots
852651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("{ 'roots':'' }", Lower);
853c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
854651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("{ 'roots':{} }", Lower);
855c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
856651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
857651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // invalid entries
858651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
859651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
860c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
861651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
862651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         "'external-contents': 'other' }",
863651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         Lower);
864c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
865651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
866651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
867651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Lower);
868c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
869651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
870651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
871651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Lower);
872c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
873651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
874651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
875651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Lower);
876c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
877651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
878651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
879651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Lower);
880c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
881651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
882651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
883651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Lower);
884c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
885651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
886651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // missing mandatory fields
887651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
888c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
889651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
891c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
892651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
893c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
894651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
895651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // duplicate keys
896651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
897c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
898651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
899651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
900651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Lower);
901c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
902651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS =
903651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
904651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        "'external-contents':'blah' } ] }",
905651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        Lower);
906c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
907651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
908651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // missing version
909651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
910c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
911651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
912651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // bad version number
913651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
914c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
915651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
916c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
917651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
918c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_EQ(nullptr, FS.get());
919651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ(24, NumDiagnostics);
920651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
921651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
922651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST_F(VFSFromYAMLTest, UseExternalName) {
923651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
924651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Lower->addRegularFile("//root/external/file");
925651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
926651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
927651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots': [\n"
928651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'file', 'name': '//root/A',\n"
929651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'external-contents': '//root/external/file'\n"
930651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  },\n"
931651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'file', 'name': '//root/B',\n"
932651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'use-external-name': true,\n"
933651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'external-contents': '//root/external/file'\n"
934651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  },\n"
935651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'file', 'name': '//root/C',\n"
936651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'use-external-name': false,\n"
937651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'external-contents': '//root/external/file'\n"
938651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  }\n"
939651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "] }", Lower);
940c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_TRUE(nullptr != FS.get());
941651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
942651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // default true
943651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
944651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // explicit
945651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
946651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
947651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
948651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // global configuration
949651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
950651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'use-external-names': false,\n"
951651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  'roots': [\n"
952651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'file', 'name': '//root/A',\n"
953651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'external-contents': '//root/external/file'\n"
954651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  },\n"
955651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'file', 'name': '//root/B',\n"
956651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'use-external-name': true,\n"
957651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'external-contents': '//root/external/file'\n"
958651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  },\n"
959651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'file', 'name': '//root/C',\n"
960651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'use-external-name': false,\n"
961651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'external-contents': '//root/external/file'\n"
962651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  }\n"
963651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "] }", Lower);
964c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_TRUE(nullptr != FS.get());
965651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
966651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // default
967651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
968651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // explicit
969651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
970651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
971651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
972651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
973651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST_F(VFSFromYAMLTest, MultiComponentPath) {
974651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
975651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Lower->addRegularFile("//root/other");
976651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
977651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // file in roots
978651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
979651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots': [\n"
980651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'file', 'name': '//root/path/to/file',\n"
981651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'external-contents': '//root/other' }]\n"
982651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "}", Lower);
983c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_TRUE(nullptr != FS.get());
984c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path/to/file").getError());
985c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path/to").getError());
986c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path").getError());
987c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/").getError());
988651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
989651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // at the start
990651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
991651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots': [\n"
992651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'directory', 'name': '//root/path/to',\n"
993651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'contents': [ { 'type': 'file', 'name': 'file',\n"
994651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "                    'external-contents': '//root/other' }]}]\n"
995651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "}", Lower);
996c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_TRUE(nullptr != FS.get());
997c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path/to/file").getError());
998c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path/to").getError());
999c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path").getError());
1000c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/").getError());
1001651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1002651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // at the end
1003651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FS = getFromYAMLString(
1004651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots': [\n"
1005651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'directory', 'name': '//root/',\n"
1006651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
1007651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "                    'external-contents': '//root/other' }]}]\n"
1008651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "}", Lower);
1009c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_TRUE(nullptr != FS.get());
1010c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path/to/file").getError());
1011c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path/to").getError());
1012c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path").getError());
1013c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/").getError());
1014651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
1015651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1016651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesTEST_F(VFSFromYAMLTest, TrailingSlashes) {
1017651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1018651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Lower->addRegularFile("//root/other");
1019651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1020651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // file in roots
1021651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
1022651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "{ 'roots': [\n"
1023651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "  { 'type': 'directory', 'name': '//root/path/to////',\n"
1024651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "    'contents': [ { 'type': 'file', 'name': 'file',\n"
1025651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "                    'external-contents': '//root/other' }]}]\n"
1026651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      "}", Lower);
1027c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  ASSERT_TRUE(nullptr != FS.get());
1028c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path/to/file").getError());
1029c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path/to").getError());
1030c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/path").getError());
1031c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  EXPECT_FALSE(FS->status("//root/").getError());
1032c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
1033c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1034c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen HinesTEST_F(VFSFromYAMLTest, DirectoryIteration) {
1035c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
1036c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addDirectory("//root/");
1037c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addDirectory("//root/foo");
1038c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addDirectory("//root/foo/bar");
1039c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("//root/foo/bar/a");
1040c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("//root/foo/bar/b");
1041c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  Lower->addRegularFile("//root/file3");
1042c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<vfs::FileSystem> FS =
1043c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  getFromYAMLString("{ 'use-external-names': false,\n"
1044c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "  'roots': [\n"
1045c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "{\n"
1046c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "  'type': 'directory',\n"
1047c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "  'name': '//root/',\n"
1048c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "  'contents': [ {\n"
1049c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "                  'type': 'file',\n"
1050c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "                  'name': 'file1',\n"
1051c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "                  'external-contents': '//root/foo/bar/a'\n"
1052c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "                },\n"
1053c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "                {\n"
1054c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "                  'type': 'file',\n"
1055c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "                  'name': 'file2',\n"
1056c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "                  'external-contents': '//root/foo/bar/b'\n"
1057c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "                }\n"
1058c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "              ]\n"
1059c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "}\n"
1060c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "]\n"
1061c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    "}",
1062c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    Lower);
1063a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar  ASSERT_TRUE(FS.get() != nullptr);
1064c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1065c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
1066c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      new vfs::OverlayFileSystem(Lower));
1067c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  O->pushOverlay(FS);
1068c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1069c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  std::error_code EC;
1070c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
1071c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    const char *Contents[] = {"//root/file1", "//root/file2", "//root/file3",
1072c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                              "//root/foo"};
1073c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    checkContents(O->dir_begin("//root/", EC), makeStringRefVector(Contents));
1074c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1075c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
1076c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  {
1077c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    const char *Contents[] = {"//root/foo/bar/a", "//root/foo/bar/b"};
1078c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    checkContents(O->dir_begin("//root/foo/bar", EC),
1079c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                  makeStringRefVector(Contents));
1080c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
1081651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
1082