
All uses of `FileEntry::getName()` were removed in favor of `FileEntryRef::getName()`. This patch finally formally deprecates that function. The plan is to remove it entirely in the main branch after we cut the release branch for LLVM 18.
585 lines
21 KiB
C++
585 lines
21 KiB
C++
//===- unittests/Basic/FileMangerTest.cpp ------------ FileManger tests ---===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Basic/FileManager.h"
|
|
#include "clang/Basic/FileSystemOptions.h"
|
|
#include "clang/Basic/FileSystemStatCache.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/VirtualFileSystem.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
using namespace clang;
|
|
|
|
namespace {
|
|
|
|
// Used to create a fake file system for running the tests with such
|
|
// that the tests are not affected by the structure/contents of the
|
|
// file system on the machine running the tests.
|
|
class FakeStatCache : public FileSystemStatCache {
|
|
private:
|
|
// Maps a file/directory path to its desired stat result. Anything
|
|
// not in this map is considered to not exist in the file system.
|
|
llvm::StringMap<llvm::vfs::Status, llvm::BumpPtrAllocator> StatCalls;
|
|
|
|
void InjectFileOrDirectory(const char *Path, ino_t INode, bool IsFile,
|
|
const char *StatPath) {
|
|
SmallString<128> NormalizedPath(Path);
|
|
SmallString<128> NormalizedStatPath;
|
|
if (is_style_posix(llvm::sys::path::Style::native)) {
|
|
llvm::sys::path::native(NormalizedPath);
|
|
Path = NormalizedPath.c_str();
|
|
|
|
if (StatPath) {
|
|
NormalizedStatPath = StatPath;
|
|
llvm::sys::path::native(NormalizedStatPath);
|
|
StatPath = NormalizedStatPath.c_str();
|
|
}
|
|
}
|
|
|
|
auto fileType = IsFile ?
|
|
llvm::sys::fs::file_type::regular_file :
|
|
llvm::sys::fs::file_type::directory_file;
|
|
llvm::vfs::Status Status(StatPath ? StatPath : Path,
|
|
llvm::sys::fs::UniqueID(1, INode),
|
|
/*MTime*/{}, /*User*/0, /*Group*/0,
|
|
/*Size*/0, fileType,
|
|
llvm::sys::fs::perms::all_all);
|
|
if (StatPath)
|
|
Status.ExposesExternalVFSPath = true;
|
|
StatCalls[Path] = Status;
|
|
}
|
|
|
|
public:
|
|
// Inject a file with the given inode value to the fake file system.
|
|
void InjectFile(const char *Path, ino_t INode,
|
|
const char *StatPath = nullptr) {
|
|
InjectFileOrDirectory(Path, INode, /*IsFile=*/true, StatPath);
|
|
}
|
|
|
|
// Inject a directory with the given inode value to the fake file system.
|
|
void InjectDirectory(const char *Path, ino_t INode) {
|
|
InjectFileOrDirectory(Path, INode, /*IsFile=*/false, nullptr);
|
|
}
|
|
|
|
// Implement FileSystemStatCache::getStat().
|
|
std::error_code getStat(StringRef Path, llvm::vfs::Status &Status,
|
|
bool isFile,
|
|
std::unique_ptr<llvm::vfs::File> *F,
|
|
llvm::vfs::FileSystem &FS) override {
|
|
SmallString<128> NormalizedPath(Path);
|
|
if (is_style_posix(llvm::sys::path::Style::native)) {
|
|
llvm::sys::path::native(NormalizedPath);
|
|
Path = NormalizedPath.c_str();
|
|
}
|
|
|
|
if (StatCalls.count(Path) != 0) {
|
|
Status = StatCalls[Path];
|
|
return std::error_code();
|
|
}
|
|
|
|
return std::make_error_code(std::errc::no_such_file_or_directory);
|
|
}
|
|
};
|
|
|
|
// The test fixture.
|
|
class FileManagerTest : public ::testing::Test {
|
|
protected:
|
|
FileManagerTest() : manager(options) {
|
|
}
|
|
|
|
FileSystemOptions options;
|
|
FileManager manager;
|
|
};
|
|
|
|
// When a virtual file is added, its getDir() field has correct name.
|
|
TEST_F(FileManagerTest, getVirtualFileSetsTheDirFieldCorrectly) {
|
|
FileEntryRef file = manager.getVirtualFileRef("foo.cpp", 42, 0);
|
|
EXPECT_EQ(".", file.getDir().getName());
|
|
|
|
file = manager.getVirtualFileRef("x/y/z.cpp", 42, 0);
|
|
EXPECT_EQ("x/y", file.getDir().getName());
|
|
}
|
|
|
|
// Before any virtual file is added, no virtual directory exists.
|
|
TEST_F(FileManagerTest, NoVirtualDirectoryExistsBeforeAVirtualFileIsAdded) {
|
|
// An empty FakeStatCache causes all stat calls made by the
|
|
// FileManager to report "file/directory doesn't exist". This
|
|
// avoids the possibility of the result of this test being affected
|
|
// by what's in the real file system.
|
|
manager.setStatCache(std::make_unique<FakeStatCache>());
|
|
|
|
ASSERT_FALSE(manager.getDirectory("virtual/dir/foo"));
|
|
ASSERT_FALSE(manager.getDirectory("virtual/dir"));
|
|
ASSERT_FALSE(manager.getDirectory("virtual"));
|
|
}
|
|
|
|
// When a virtual file is added, all of its ancestors should be created.
|
|
TEST_F(FileManagerTest, getVirtualFileCreatesDirectoryEntriesForAncestors) {
|
|
// Fake an empty real file system.
|
|
manager.setStatCache(std::make_unique<FakeStatCache>());
|
|
|
|
manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
|
|
ASSERT_FALSE(manager.getDirectory("virtual/dir/foo"));
|
|
|
|
auto dir = manager.getDirectoryRef("virtual/dir");
|
|
ASSERT_THAT_EXPECTED(dir, llvm::Succeeded());
|
|
EXPECT_EQ("virtual/dir", dir->getName());
|
|
|
|
dir = manager.getDirectoryRef("virtual");
|
|
ASSERT_THAT_EXPECTED(dir, llvm::Succeeded());
|
|
EXPECT_EQ("virtual", dir->getName());
|
|
}
|
|
|
|
// getFileRef() succeeds if a real file exists at the given path.
|
|
TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
|
|
// Inject fake files into the file system.
|
|
auto statCache = std::make_unique<FakeStatCache>();
|
|
statCache->InjectDirectory("/tmp", 42);
|
|
statCache->InjectFile("/tmp/test", 43);
|
|
|
|
#ifdef _WIN32
|
|
const char *DirName = "C:.";
|
|
const char *FileName = "C:test";
|
|
statCache->InjectDirectory(DirName, 44);
|
|
statCache->InjectFile(FileName, 45);
|
|
#endif
|
|
|
|
manager.setStatCache(std::move(statCache));
|
|
|
|
auto file = manager.getFileRef("/tmp/test");
|
|
ASSERT_THAT_EXPECTED(file, llvm::Succeeded());
|
|
EXPECT_EQ("/tmp/test", file->getName());
|
|
|
|
EXPECT_EQ("/tmp", file->getDir().getName());
|
|
|
|
#ifdef _WIN32
|
|
file = manager.getFileRef(FileName);
|
|
ASSERT_THAT_EXPECTED(file, llvm::Succeeded());
|
|
EXPECT_EQ(DirName, file->getDir().getName());
|
|
#endif
|
|
}
|
|
|
|
// getFileRef() succeeds if a virtual file exists at the given path.
|
|
TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingVirtualFile) {
|
|
// Fake an empty real file system.
|
|
manager.setStatCache(std::make_unique<FakeStatCache>());
|
|
|
|
manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
|
|
auto file = manager.getFileRef("virtual/dir/bar.h");
|
|
ASSERT_THAT_EXPECTED(file, llvm::Succeeded());
|
|
EXPECT_EQ("virtual/dir/bar.h", file->getName());
|
|
EXPECT_EQ("virtual/dir", file->getDir().getName());
|
|
}
|
|
|
|
// getFile() returns different FileEntries for different paths when
|
|
// there's no aliasing.
|
|
TEST_F(FileManagerTest, getFileReturnsDifferentFileEntriesForDifferentFiles) {
|
|
// Inject two fake files into the file system. Different inodes
|
|
// mean the files are not symlinked together.
|
|
auto statCache = std::make_unique<FakeStatCache>();
|
|
statCache->InjectDirectory(".", 41);
|
|
statCache->InjectFile("foo.cpp", 42);
|
|
statCache->InjectFile("bar.cpp", 43);
|
|
manager.setStatCache(std::move(statCache));
|
|
|
|
auto fileFoo = manager.getFile("foo.cpp");
|
|
auto fileBar = manager.getFile("bar.cpp");
|
|
ASSERT_TRUE(fileFoo);
|
|
ASSERT_TRUE(fileBar);
|
|
EXPECT_NE(*fileFoo, *fileBar);
|
|
}
|
|
|
|
// getFile() returns an error if neither a real file nor a virtual file
|
|
// exists at the given path.
|
|
TEST_F(FileManagerTest, getFileReturnsErrorForNonexistentFile) {
|
|
// Inject a fake foo.cpp into the file system.
|
|
auto statCache = std::make_unique<FakeStatCache>();
|
|
statCache->InjectDirectory(".", 41);
|
|
statCache->InjectFile("foo.cpp", 42);
|
|
statCache->InjectDirectory("MyDirectory", 49);
|
|
manager.setStatCache(std::move(statCache));
|
|
|
|
// Create a virtual bar.cpp file.
|
|
manager.getVirtualFile("bar.cpp", 200, 0);
|
|
|
|
auto file = manager.getFile("xyz.txt");
|
|
ASSERT_FALSE(file);
|
|
ASSERT_EQ(file.getError(), std::errc::no_such_file_or_directory);
|
|
|
|
auto readingDirAsFile = manager.getFile("MyDirectory");
|
|
ASSERT_FALSE(readingDirAsFile);
|
|
ASSERT_EQ(readingDirAsFile.getError(), std::errc::is_a_directory);
|
|
|
|
auto readingFileAsDir = manager.getDirectory("foo.cpp");
|
|
ASSERT_FALSE(readingFileAsDir);
|
|
ASSERT_EQ(readingFileAsDir.getError(), std::errc::not_a_directory);
|
|
}
|
|
|
|
// The following tests apply to Unix-like system only.
|
|
|
|
#ifndef _WIN32
|
|
|
|
// getFile() returns the same FileEntry for real files that are aliases.
|
|
TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedRealFiles) {
|
|
// Inject two real files with the same inode.
|
|
auto statCache = std::make_unique<FakeStatCache>();
|
|
statCache->InjectDirectory("abc", 41);
|
|
statCache->InjectFile("abc/foo.cpp", 42);
|
|
statCache->InjectFile("abc/bar.cpp", 42);
|
|
manager.setStatCache(std::move(statCache));
|
|
|
|
auto f1 = manager.getFile("abc/foo.cpp");
|
|
auto f2 = manager.getFile("abc/bar.cpp");
|
|
|
|
EXPECT_EQ(f1 ? *f1 : nullptr,
|
|
f2 ? *f2 : nullptr);
|
|
|
|
// Check that getFileRef also does the right thing.
|
|
auto r1 = manager.getFileRef("abc/foo.cpp");
|
|
auto r2 = manager.getFileRef("abc/bar.cpp");
|
|
ASSERT_FALSE(!r1);
|
|
ASSERT_FALSE(!r2);
|
|
|
|
EXPECT_EQ("abc/foo.cpp", r1->getName());
|
|
EXPECT_EQ("abc/bar.cpp", r2->getName());
|
|
EXPECT_EQ((f1 ? *f1 : nullptr), &r1->getFileEntry());
|
|
EXPECT_EQ((f2 ? *f2 : nullptr), &r2->getFileEntry());
|
|
}
|
|
|
|
TEST_F(FileManagerTest, getFileRefReturnsCorrectNameForDifferentStatPath) {
|
|
// Inject files with the same inode, but where some files have a stat that
|
|
// gives a different name. This is adding coverage for stat behaviour
|
|
// triggered by the RedirectingFileSystem for 'use-external-name' that
|
|
// FileManager::getFileRef has special logic for.
|
|
auto StatCache = std::make_unique<FakeStatCache>();
|
|
StatCache->InjectDirectory("dir", 40);
|
|
StatCache->InjectFile("dir/f1.cpp", 41);
|
|
StatCache->InjectFile("dir/f1-alias.cpp", 41, "dir/f1.cpp");
|
|
StatCache->InjectFile("dir/f2.cpp", 42);
|
|
StatCache->InjectFile("dir/f2-alias.cpp", 42, "dir/f2.cpp");
|
|
|
|
// This unintuitive rename-the-file-on-stat behaviour supports how the
|
|
// RedirectingFileSystem VFS layer responds to stats. However, even if you
|
|
// have two layers, you should only get a single filename back. As such the
|
|
// following stat cache behaviour is not supported (the correct stat entry
|
|
// for a double-redirection would be "dir/f1.cpp") and the getFileRef below
|
|
// should assert.
|
|
StatCache->InjectFile("dir/f1-alias-alias.cpp", 41, "dir/f1-alias.cpp");
|
|
|
|
manager.setStatCache(std::move(StatCache));
|
|
|
|
// With F1, test accessing the non-redirected name first.
|
|
auto F1 = manager.getFileRef("dir/f1.cpp");
|
|
auto F1Alias = manager.getFileRef("dir/f1-alias.cpp");
|
|
auto F1Alias2 = manager.getFileRef("dir/f1-alias.cpp");
|
|
ASSERT_FALSE(!F1);
|
|
ASSERT_FALSE(!F1Alias);
|
|
ASSERT_FALSE(!F1Alias2);
|
|
EXPECT_EQ("dir/f1.cpp", F1->getName());
|
|
LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH
|
|
EXPECT_EQ("dir/f1.cpp", F1->getFileEntry().getName());
|
|
LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP
|
|
EXPECT_EQ("dir/f1.cpp", F1Alias->getName());
|
|
EXPECT_EQ("dir/f1.cpp", F1Alias2->getName());
|
|
EXPECT_EQ(&F1->getFileEntry(), &F1Alias->getFileEntry());
|
|
EXPECT_EQ(&F1->getFileEntry(), &F1Alias2->getFileEntry());
|
|
|
|
#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
|
|
EXPECT_DEATH((void)manager.getFileRef("dir/f1-alias-alias.cpp"),
|
|
"filename redirected to a non-canonical filename?");
|
|
#endif
|
|
|
|
// With F2, test accessing the redirected name first.
|
|
auto F2Alias = manager.getFileRef("dir/f2-alias.cpp");
|
|
auto F2 = manager.getFileRef("dir/f2.cpp");
|
|
auto F2Alias2 = manager.getFileRef("dir/f2-alias.cpp");
|
|
ASSERT_FALSE(!F2);
|
|
ASSERT_FALSE(!F2Alias);
|
|
ASSERT_FALSE(!F2Alias2);
|
|
EXPECT_EQ("dir/f2.cpp", F2->getName());
|
|
LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH
|
|
EXPECT_EQ("dir/f2.cpp", F2->getFileEntry().getName());
|
|
LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP
|
|
EXPECT_EQ("dir/f2.cpp", F2Alias->getName());
|
|
EXPECT_EQ("dir/f2.cpp", F2Alias2->getName());
|
|
EXPECT_EQ(&F2->getFileEntry(), &F2Alias->getFileEntry());
|
|
EXPECT_EQ(&F2->getFileEntry(), &F2Alias2->getFileEntry());
|
|
}
|
|
|
|
TEST_F(FileManagerTest, getFileRefReturnsCorrectDirNameForDifferentStatPath) {
|
|
// Inject files with the same inode into distinct directories (name & inode).
|
|
auto StatCache = std::make_unique<FakeStatCache>();
|
|
StatCache->InjectDirectory("dir1", 40);
|
|
StatCache->InjectDirectory("dir2", 41);
|
|
StatCache->InjectFile("dir1/f.cpp", 42);
|
|
StatCache->InjectFile("dir2/f.cpp", 42, "dir1/f.cpp");
|
|
|
|
manager.setStatCache(std::move(StatCache));
|
|
auto Dir1F = manager.getFileRef("dir1/f.cpp");
|
|
auto Dir2F = manager.getFileRef("dir2/f.cpp");
|
|
|
|
ASSERT_FALSE(!Dir1F);
|
|
ASSERT_FALSE(!Dir2F);
|
|
EXPECT_EQ("dir1", Dir1F->getDir().getName());
|
|
EXPECT_EQ("dir2", Dir2F->getDir().getName());
|
|
EXPECT_EQ("dir1/f.cpp", Dir1F->getNameAsRequested());
|
|
EXPECT_EQ("dir2/f.cpp", Dir2F->getNameAsRequested());
|
|
}
|
|
|
|
// getFile() returns the same FileEntry for virtual files that have
|
|
// corresponding real files that are aliases.
|
|
TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedVirtualFiles) {
|
|
// Inject two real files with the same inode.
|
|
auto statCache = std::make_unique<FakeStatCache>();
|
|
statCache->InjectDirectory("abc", 41);
|
|
statCache->InjectFile("abc/foo.cpp", 42);
|
|
statCache->InjectFile("abc/bar.cpp", 42);
|
|
manager.setStatCache(std::move(statCache));
|
|
|
|
auto f1 = manager.getFile("abc/foo.cpp");
|
|
auto f2 = manager.getFile("abc/bar.cpp");
|
|
|
|
EXPECT_EQ(f1 ? *f1 : nullptr,
|
|
f2 ? *f2 : nullptr);
|
|
}
|
|
|
|
TEST_F(FileManagerTest, getFileRefEquality) {
|
|
auto StatCache = std::make_unique<FakeStatCache>();
|
|
StatCache->InjectDirectory("dir", 40);
|
|
StatCache->InjectFile("dir/f1.cpp", 41);
|
|
StatCache->InjectFile("dir/f1-also.cpp", 41);
|
|
StatCache->InjectFile("dir/f1-redirect.cpp", 41, "dir/f1.cpp");
|
|
StatCache->InjectFile("dir/f2.cpp", 42);
|
|
manager.setStatCache(std::move(StatCache));
|
|
|
|
auto F1 = manager.getFileRef("dir/f1.cpp");
|
|
auto F1Again = manager.getFileRef("dir/f1.cpp");
|
|
auto F1Also = manager.getFileRef("dir/f1-also.cpp");
|
|
auto F1Redirect = manager.getFileRef("dir/f1-redirect.cpp");
|
|
auto F1RedirectAgain = manager.getFileRef("dir/f1-redirect.cpp");
|
|
auto F2 = manager.getFileRef("dir/f2.cpp");
|
|
|
|
// Check Expected<FileEntryRef> for error.
|
|
ASSERT_FALSE(!F1);
|
|
ASSERT_FALSE(!F1Also);
|
|
ASSERT_FALSE(!F1Again);
|
|
ASSERT_FALSE(!F1Redirect);
|
|
ASSERT_FALSE(!F1RedirectAgain);
|
|
ASSERT_FALSE(!F2);
|
|
|
|
// Check names.
|
|
EXPECT_EQ("dir/f1.cpp", F1->getName());
|
|
EXPECT_EQ("dir/f1.cpp", F1Again->getName());
|
|
EXPECT_EQ("dir/f1-also.cpp", F1Also->getName());
|
|
EXPECT_EQ("dir/f1.cpp", F1Redirect->getName());
|
|
EXPECT_EQ("dir/f1.cpp", F1RedirectAgain->getName());
|
|
EXPECT_EQ("dir/f2.cpp", F2->getName());
|
|
|
|
EXPECT_EQ("dir/f1.cpp", F1->getNameAsRequested());
|
|
EXPECT_EQ("dir/f1-redirect.cpp", F1Redirect->getNameAsRequested());
|
|
|
|
// Compare against FileEntry*.
|
|
EXPECT_EQ(&F1->getFileEntry(), *F1);
|
|
EXPECT_EQ(*F1, &F1->getFileEntry());
|
|
EXPECT_EQ(&F1->getFileEntry(), &F1Redirect->getFileEntry());
|
|
EXPECT_EQ(&F1->getFileEntry(), &F1RedirectAgain->getFileEntry());
|
|
EXPECT_NE(&F2->getFileEntry(), *F1);
|
|
EXPECT_NE(*F1, &F2->getFileEntry());
|
|
|
|
// Compare using ==.
|
|
EXPECT_EQ(*F1, *F1Also);
|
|
EXPECT_EQ(*F1, *F1Again);
|
|
EXPECT_EQ(*F1, *F1Redirect);
|
|
EXPECT_EQ(*F1Also, *F1Redirect);
|
|
EXPECT_EQ(*F1, *F1RedirectAgain);
|
|
EXPECT_NE(*F2, *F1);
|
|
EXPECT_NE(*F2, *F1Also);
|
|
EXPECT_NE(*F2, *F1Again);
|
|
EXPECT_NE(*F2, *F1Redirect);
|
|
|
|
// Compare using isSameRef.
|
|
EXPECT_TRUE(F1->isSameRef(*F1Again));
|
|
EXPECT_FALSE(F1->isSameRef(*F1Redirect));
|
|
EXPECT_FALSE(F1->isSameRef(*F1Also));
|
|
EXPECT_FALSE(F1->isSameRef(*F2));
|
|
EXPECT_TRUE(F1Redirect->isSameRef(*F1RedirectAgain));
|
|
}
|
|
|
|
// getFile() Should return the same entry as getVirtualFile if the file actually
|
|
// is a virtual file, even if the name is not exactly the same (but is after
|
|
// normalisation done by the file system, like on Windows). This can be checked
|
|
// here by checking the size.
|
|
TEST_F(FileManagerTest, getVirtualFileWithDifferentName) {
|
|
// Inject fake files into the file system.
|
|
auto statCache = std::make_unique<FakeStatCache>();
|
|
statCache->InjectDirectory("c:\\tmp", 42);
|
|
statCache->InjectFile("c:\\tmp\\test", 43);
|
|
|
|
manager.setStatCache(std::move(statCache));
|
|
|
|
// Inject the virtual file:
|
|
const FileEntry *file1 = manager.getVirtualFile("c:\\tmp\\test", 123, 1);
|
|
ASSERT_TRUE(file1 != nullptr);
|
|
EXPECT_EQ(43U, file1->getUniqueID().getFile());
|
|
EXPECT_EQ(123, file1->getSize());
|
|
|
|
// Lookup the virtual file with a different name:
|
|
auto file2 = manager.getFile("c:/tmp/test", 100, 1);
|
|
ASSERT_TRUE(file2);
|
|
// Check that it's the same UFE:
|
|
EXPECT_EQ(file1, *file2);
|
|
EXPECT_EQ(43U, (*file2)->getUniqueID().getFile());
|
|
// Check that the contents of the UFE are not overwritten by the entry in the
|
|
// filesystem:
|
|
EXPECT_EQ(123, (*file2)->getSize());
|
|
}
|
|
|
|
#endif // !_WIN32
|
|
|
|
static StringRef getSystemRoot() {
|
|
return is_style_windows(llvm::sys::path::Style::native) ? "C:\\" : "/";
|
|
}
|
|
|
|
TEST_F(FileManagerTest, makeAbsoluteUsesVFS) {
|
|
// FIXME: Should this be using a root path / call getSystemRoot()? For now,
|
|
// avoiding that and leaving the test as-is.
|
|
SmallString<64> CustomWorkingDir =
|
|
is_style_windows(llvm::sys::path::Style::native) ? StringRef("C:")
|
|
: StringRef("/");
|
|
llvm::sys::path::append(CustomWorkingDir, "some", "weird", "path");
|
|
|
|
auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>(
|
|
new llvm::vfs::InMemoryFileSystem);
|
|
// setCurrentworkingdirectory must finish without error.
|
|
ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
|
|
|
|
FileSystemOptions Opts;
|
|
FileManager Manager(Opts, FS);
|
|
|
|
SmallString<64> Path("a/foo.cpp");
|
|
|
|
SmallString<64> ExpectedResult(CustomWorkingDir);
|
|
llvm::sys::path::append(ExpectedResult, Path);
|
|
|
|
ASSERT_TRUE(Manager.makeAbsolutePath(Path));
|
|
EXPECT_EQ(Path, ExpectedResult);
|
|
}
|
|
|
|
// getVirtualFile should always fill the real path.
|
|
TEST_F(FileManagerTest, getVirtualFileFillsRealPathName) {
|
|
SmallString<64> CustomWorkingDir = getSystemRoot();
|
|
|
|
auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>(
|
|
new llvm::vfs::InMemoryFileSystem);
|
|
// setCurrentworkingdirectory must finish without error.
|
|
ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
|
|
|
|
FileSystemOptions Opts;
|
|
FileManager Manager(Opts, FS);
|
|
|
|
// Inject fake files into the file system.
|
|
auto statCache = std::make_unique<FakeStatCache>();
|
|
statCache->InjectDirectory("/tmp", 42);
|
|
statCache->InjectFile("/tmp/test", 43);
|
|
|
|
Manager.setStatCache(std::move(statCache));
|
|
|
|
// Check for real path.
|
|
const FileEntry *file = Manager.getVirtualFile("/tmp/test", 123, 1);
|
|
ASSERT_TRUE(file != nullptr);
|
|
SmallString<64> ExpectedResult = CustomWorkingDir;
|
|
|
|
llvm::sys::path::append(ExpectedResult, "tmp", "test");
|
|
EXPECT_EQ(file->tryGetRealPathName(), ExpectedResult);
|
|
}
|
|
|
|
TEST_F(FileManagerTest, getFileDontOpenRealPath) {
|
|
SmallString<64> CustomWorkingDir = getSystemRoot();
|
|
|
|
auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>(
|
|
new llvm::vfs::InMemoryFileSystem);
|
|
// setCurrentworkingdirectory must finish without error.
|
|
ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
|
|
|
|
FileSystemOptions Opts;
|
|
FileManager Manager(Opts, FS);
|
|
|
|
// Inject fake files into the file system.
|
|
auto statCache = std::make_unique<FakeStatCache>();
|
|
statCache->InjectDirectory("/tmp", 42);
|
|
statCache->InjectFile("/tmp/test", 43);
|
|
|
|
Manager.setStatCache(std::move(statCache));
|
|
|
|
// Check for real path.
|
|
auto file = Manager.getFile("/tmp/test", /*OpenFile=*/false);
|
|
ASSERT_TRUE(file);
|
|
SmallString<64> ExpectedResult = CustomWorkingDir;
|
|
|
|
llvm::sys::path::append(ExpectedResult, "tmp", "test");
|
|
EXPECT_EQ((*file)->tryGetRealPathName(), ExpectedResult);
|
|
}
|
|
|
|
TEST_F(FileManagerTest, getBypassFile) {
|
|
SmallString<64> CustomWorkingDir;
|
|
#ifdef _WIN32
|
|
CustomWorkingDir = "C:/";
|
|
#else
|
|
CustomWorkingDir = "/";
|
|
#endif
|
|
|
|
auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>(
|
|
new llvm::vfs::InMemoryFileSystem);
|
|
// setCurrentworkingdirectory must finish without error.
|
|
ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
|
|
|
|
FileSystemOptions Opts;
|
|
FileManager Manager(Opts, FS);
|
|
|
|
// Inject fake files into the file system.
|
|
auto Cache = std::make_unique<FakeStatCache>();
|
|
Cache->InjectDirectory("/tmp", 42);
|
|
Cache->InjectFile("/tmp/test", 43);
|
|
Manager.setStatCache(std::move(Cache));
|
|
|
|
// Set up a virtual file with a different size than FakeStatCache uses.
|
|
FileEntryRef File = Manager.getVirtualFileRef("/tmp/test", /*Size=*/10, 0);
|
|
ASSERT_TRUE(File);
|
|
const FileEntry &FE = *File;
|
|
EXPECT_EQ(FE.getSize(), 10);
|
|
|
|
// Calling a second time should not affect the UID or size.
|
|
unsigned VirtualUID = FE.getUID();
|
|
OptionalFileEntryRef SearchRef;
|
|
ASSERT_THAT_ERROR(Manager.getFileRef("/tmp/test").moveInto(SearchRef),
|
|
Succeeded());
|
|
EXPECT_EQ(&FE, &SearchRef->getFileEntry());
|
|
EXPECT_EQ(FE.getUID(), VirtualUID);
|
|
EXPECT_EQ(FE.getSize(), 10);
|
|
|
|
// Bypass the file.
|
|
OptionalFileEntryRef BypassRef = Manager.getBypassFile(File);
|
|
ASSERT_TRUE(BypassRef);
|
|
EXPECT_EQ("/tmp/test", BypassRef->getName());
|
|
|
|
// Check that it's different in the right ways.
|
|
EXPECT_NE(&BypassRef->getFileEntry(), File);
|
|
EXPECT_NE(BypassRef->getUID(), VirtualUID);
|
|
EXPECT_NE(BypassRef->getSize(), FE.getSize());
|
|
|
|
// The virtual file should still be returned when searching.
|
|
ASSERT_THAT_ERROR(Manager.getFileRef("/tmp/test").moveInto(SearchRef),
|
|
Succeeded());
|
|
EXPECT_EQ(&FE, &SearchRef->getFileEntry());
|
|
}
|
|
|
|
} // anonymous namespace
|