diff options
Diffstat (limited to 'unittests/Basic')
-rw-r--r-- | unittests/Basic/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittests/Basic/FileManagerTest.cpp | 52 | ||||
-rw-r--r-- | unittests/Basic/MemoryBufferCacheTest.cpp | 94 | ||||
-rw-r--r-- | unittests/Basic/SourceManagerTest.cpp | 10 | ||||
-rw-r--r-- | unittests/Basic/VirtualFileSystemTest.cpp | 102 |
5 files changed, 254 insertions, 5 deletions
diff --git a/unittests/Basic/CMakeLists.txt b/unittests/Basic/CMakeLists.txt index 3cb3cb8d3c80..3a9f34f3d275 100644 --- a/unittests/Basic/CMakeLists.txt +++ b/unittests/Basic/CMakeLists.txt @@ -6,6 +6,7 @@ add_clang_unittest(BasicTests CharInfoTest.cpp DiagnosticTest.cpp FileManagerTest.cpp + MemoryBufferCacheTest.cpp SourceManagerTest.cpp VirtualFileSystemTest.cpp ) diff --git a/unittests/Basic/FileManagerTest.cpp b/unittests/Basic/FileManagerTest.cpp index 4cf21cd8459a..a19535e1047c 100644 --- a/unittests/Basic/FileManagerTest.cpp +++ b/unittests/Basic/FileManagerTest.cpp @@ -12,6 +12,7 @@ #include "clang/Basic/FileSystemStatCache.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Support/Path.h" #include "gtest/gtest.h" using namespace llvm; @@ -29,6 +30,12 @@ private: llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls; void InjectFileOrDirectory(const char *Path, ino_t INode, bool IsFile) { +#ifndef LLVM_ON_WIN32 + SmallString<128> NormalizedPath(Path); + llvm::sys::path::native(NormalizedPath); + Path = NormalizedPath.c_str(); +#endif + FileData Data; Data.Name = Path; Data.Size = 0; @@ -55,6 +62,12 @@ public: LookupResult getStat(StringRef Path, FileData &Data, bool isFile, std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) override { +#ifndef LLVM_ON_WIN32 + SmallString<128> NormalizedPath(Path); + llvm::sys::path::native(NormalizedPath); + Path = NormalizedPath.c_str(); +#endif + if (StatCalls.count(Path) != 0) { Data = StatCalls[Path]; return CacheExists; @@ -140,6 +153,7 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) { const FileEntry *file = manager.getFile("/tmp/test"); ASSERT_TRUE(file != nullptr); + ASSERT_TRUE(file->isValid()); EXPECT_EQ("/tmp/test", file->getName()); const DirectoryEntry *dir = file->getDir(); @@ -164,6 +178,7 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingVirtualFile) { manager.getVirtualFile("virtual/dir/bar.h", 100, 0); const FileEntry *file = manager.getFile("virtual/dir/bar.h"); ASSERT_TRUE(file != nullptr); + ASSERT_TRUE(file->isValid()); EXPECT_EQ("virtual/dir/bar.h", file->getName()); const DirectoryEntry *dir = file->getDir(); @@ -185,7 +200,9 @@ TEST_F(FileManagerTest, getFileReturnsDifferentFileEntriesForDifferentFiles) { const FileEntry *fileFoo = manager.getFile("foo.cpp"); const FileEntry *fileBar = manager.getFile("bar.cpp"); ASSERT_TRUE(fileFoo != nullptr); + ASSERT_TRUE(fileFoo->isValid()); ASSERT_TRUE(fileBar != nullptr); + ASSERT_TRUE(fileBar->isValid()); EXPECT_NE(fileFoo, fileBar); } @@ -231,8 +248,8 @@ TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedVirtualFiles) { statCache->InjectFile("abc/bar.cpp", 42); manager.addStatCache(std::move(statCache)); - manager.getVirtualFile("abc/foo.cpp", 100, 0); - manager.getVirtualFile("abc/bar.cpp", 200, 0); + ASSERT_TRUE(manager.getVirtualFile("abc/foo.cpp", 100, 0)->isValid()); + ASSERT_TRUE(manager.getVirtualFile("abc/bar.cpp", 200, 0)->isValid()); EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp")); } @@ -246,6 +263,37 @@ TEST_F(FileManagerTest, addRemoveStatCache) { manager.removeStatCache(statCache); } +// 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 checkng the size. +TEST_F(FileManagerTest, getVirtualFileWithDifferentName) { + // Inject fake files into the file system. + auto statCache = llvm::make_unique<FakeStatCache>(); + statCache->InjectDirectory("c:\\tmp", 42); + statCache->InjectFile("c:\\tmp\\test", 43); + + manager.addStatCache(std::move(statCache)); + + // Inject the virtual file: + const FileEntry *file1 = manager.getVirtualFile("c:\\tmp\\test", 123, 1); + ASSERT_TRUE(file1 != nullptr); + ASSERT_TRUE(file1->isValid()); + EXPECT_EQ(43U, file1->getUniqueID().getFile()); + EXPECT_EQ(123, file1->getSize()); + + // Lookup the virtual file with a different name: + const FileEntry *file2 = manager.getFile("c:/tmp/test", 100, 1); + ASSERT_TRUE(file2 != nullptr); + ASSERT_TRUE(file2->isValid()); + // 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 // !LLVM_ON_WIN32 } // anonymous namespace diff --git a/unittests/Basic/MemoryBufferCacheTest.cpp b/unittests/Basic/MemoryBufferCacheTest.cpp new file mode 100644 index 000000000000..99178f8150cc --- /dev/null +++ b/unittests/Basic/MemoryBufferCacheTest.cpp @@ -0,0 +1,94 @@ +//===- MemoryBufferCacheTest.cpp - MemoryBufferCache tests ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/MemoryBufferCache.h" +#include "llvm/Support/MemoryBuffer.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace clang; + +namespace { + +std::unique_ptr<MemoryBuffer> getBuffer(int I) { + SmallVector<char, 8> Bytes; + raw_svector_ostream(Bytes) << "data:" << I; + return MemoryBuffer::getMemBuffer(StringRef(Bytes.data(), Bytes.size()), "", + /* RequiresNullTerminator = */ false); +} + +TEST(MemoryBufferCacheTest, addBuffer) { + auto B1 = getBuffer(1); + auto B2 = getBuffer(2); + auto B3 = getBuffer(3); + auto *RawB1 = B1.get(); + auto *RawB2 = B2.get(); + auto *RawB3 = B3.get(); + + // Add a few buffers. + MemoryBufferCache Cache; + EXPECT_EQ(RawB1, &Cache.addBuffer("1", std::move(B1))); + EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2))); + EXPECT_EQ(RawB3, &Cache.addBuffer("3", std::move(B3))); + EXPECT_EQ(RawB1, Cache.lookupBuffer("1")); + EXPECT_EQ(RawB2, Cache.lookupBuffer("2")); + EXPECT_EQ(RawB3, Cache.lookupBuffer("3")); + EXPECT_FALSE(Cache.isBufferFinal("1")); + EXPECT_FALSE(Cache.isBufferFinal("2")); + EXPECT_FALSE(Cache.isBufferFinal("3")); + + // Remove the middle buffer. + EXPECT_FALSE(Cache.tryToRemoveBuffer("2")); + EXPECT_EQ(nullptr, Cache.lookupBuffer("2")); + EXPECT_FALSE(Cache.isBufferFinal("2")); + + // Replace the middle buffer. + B2 = getBuffer(2); + RawB2 = B2.get(); + EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2))); + + // Check that nothing is final. + EXPECT_FALSE(Cache.isBufferFinal("1")); + EXPECT_FALSE(Cache.isBufferFinal("2")); + EXPECT_FALSE(Cache.isBufferFinal("3")); +} + +TEST(MemoryBufferCacheTest, finalizeCurrentBuffers) { + // Add a buffer. + MemoryBufferCache Cache; + auto B1 = getBuffer(1); + auto *RawB1 = B1.get(); + Cache.addBuffer("1", std::move(B1)); + ASSERT_FALSE(Cache.isBufferFinal("1")); + + // Finalize it. + Cache.finalizeCurrentBuffers(); + EXPECT_TRUE(Cache.isBufferFinal("1")); + EXPECT_TRUE(Cache.tryToRemoveBuffer("1")); + EXPECT_EQ(RawB1, Cache.lookupBuffer("1")); + EXPECT_TRUE(Cache.isBufferFinal("1")); + + // Repeat. + auto B2 = getBuffer(2); + auto *RawB2 = B2.get(); + Cache.addBuffer("2", std::move(B2)); + EXPECT_FALSE(Cache.isBufferFinal("2")); + + Cache.finalizeCurrentBuffers(); + EXPECT_TRUE(Cache.isBufferFinal("1")); + EXPECT_TRUE(Cache.isBufferFinal("2")); + EXPECT_TRUE(Cache.tryToRemoveBuffer("1")); + EXPECT_TRUE(Cache.tryToRemoveBuffer("2")); + EXPECT_EQ(RawB1, Cache.lookupBuffer("1")); + EXPECT_EQ(RawB2, Cache.lookupBuffer("2")); + EXPECT_TRUE(Cache.isBufferFinal("1")); + EXPECT_TRUE(Cache.isBufferFinal("2")); +} + +} // namespace diff --git a/unittests/Basic/SourceManagerTest.cpp b/unittests/Basic/SourceManagerTest.cpp index a967b0ec7c21..dddc3f98662d 100644 --- a/unittests/Basic/SourceManagerTest.cpp +++ b/unittests/Basic/SourceManagerTest.cpp @@ -12,6 +12,7 @@ #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/MemoryBufferCache.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Lex/HeaderSearch.h" @@ -78,10 +79,11 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnit) { SourceMgr.setMainFileID(mainFileID); VoidModuleLoader ModLoader; + MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, Diags, LangOpts, &*Target); Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, - SourceMgr, HeaderInfo, ModLoader, + SourceMgr, PCMCache, HeaderInfo, ModLoader, /*IILookup =*/nullptr, /*OwnsHeaderSearch =*/false); PP.Initialize(*Target); @@ -198,10 +200,11 @@ TEST_F(SourceManagerTest, getMacroArgExpandedLocation) { SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf)); VoidModuleLoader ModLoader; + MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, Diags, LangOpts, &*Target); Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, - SourceMgr, HeaderInfo, ModLoader, + SourceMgr, PCMCache, HeaderInfo, ModLoader, /*IILookup =*/nullptr, /*OwnsHeaderSearch =*/false); PP.Initialize(*Target); @@ -298,10 +301,11 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) { SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf)); VoidModuleLoader ModLoader; + MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, Diags, LangOpts, &*Target); Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, - SourceMgr, HeaderInfo, ModLoader, + SourceMgr, PCMCache, HeaderInfo, ModLoader, /*IILookup =*/nullptr, /*OwnsHeaderSearch =*/false); PP.Initialize(*Target); diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp index 580343d93ea1..0856b17791fa 100644 --- a/unittests/Basic/VirtualFileSystemTest.cpp +++ b/unittests/Basic/VirtualFileSystemTest.cpp @@ -305,6 +305,22 @@ struct ScopedDir { } operator StringRef() { return Path.str(); } }; + +struct ScopedLink { + SmallString<128> Path; + ScopedLink(const Twine &To, const Twine &From) { + Path = From.str(); + std::error_code EC = sys::fs::create_link(To, From); + if (EC) + Path = ""; + EXPECT_FALSE(EC); + } + ~ScopedLink() { + if (Path != "") + EXPECT_FALSE(llvm::sys::fs::remove(Path.str())); + } + operator StringRef() { return Path.str(); } +}; } // end anonymous namespace TEST(VirtualFileSystemTest, BasicRealFSIteration) { @@ -334,6 +350,42 @@ TEST(VirtualFileSystemTest, BasicRealFSIteration) { EXPECT_EQ(vfs::directory_iterator(), I); } +#ifdef LLVM_ON_UNIX +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + + std::error_code EC; + for (vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC), E; + I != E; I.increment(EC)) { + // Skip broken symlinks. + auto EC2 = std::make_error_code(std::errc::no_such_file_or_directory); + if (EC == EC2) { + EC.clear(); + continue; + } + // For bot debugging. + if (EC) { + outs() << "Error code found:\n" + << "EC value: " << EC.value() << "\n" + << "EC category: " << EC.category().name() + << "EC message: " << EC.message() << "\n"; + + outs() << "Error code tested for:\n" + << "EC value: " << EC2.value() << "\n" + << "EC category: " << EC2.category().name() + << "EC message: " << EC2.message() << "\n"; + } + ASSERT_FALSE(EC); + EXPECT_TRUE(I->getName() == _b); + } +} +#endif + TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) { ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true); IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); @@ -373,6 +425,56 @@ TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) { EXPECT_EQ(1, Counts[3]); // d } +#ifdef LLVM_ON_UNIX +TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) { + ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true); + IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(); + + ScopedLink _a("no_such_file", TestDirectory + "/a"); + ScopedDir _b(TestDirectory + "/b"); + ScopedLink _ba("no_such_file", TestDirectory + "/b/a"); + ScopedDir _bb(TestDirectory + "/b/b"); + ScopedLink _bc("no_such_file", TestDirectory + "/b/c"); + ScopedLink _c("no_such_file", TestDirectory + "/c"); + ScopedDir _d(TestDirectory + "/d"); + ScopedDir _dd(TestDirectory + "/d/d"); + ScopedDir _ddd(TestDirectory + "/d/d/d"); + ScopedLink _e("no_such_file", TestDirectory + "/e"); + std::vector<StringRef> Expected = {_b, _bb, _d, _dd, _ddd}; + + std::vector<std::string> Contents; + std::error_code EC; + for (vfs::recursive_directory_iterator I(*FS, Twine(TestDirectory), EC), E; + I != E; I.increment(EC)) { + // Skip broken symlinks. + auto EC2 = std::make_error_code(std::errc::no_such_file_or_directory); + if (EC == EC2) { + EC.clear(); + continue; + } + // For bot debugging. + if (EC) { + outs() << "Error code found:\n" + << "EC value: " << EC.value() << "\n" + << "EC category: " << EC.category().name() + << "EC message: " << EC.message() << "\n"; + + outs() << "Error code tested for:\n" + << "EC value: " << EC2.value() << "\n" + << "EC category: " << EC2.category().name() + << "EC message: " << EC2.message() << "\n"; + } + ASSERT_FALSE(EC); + Contents.push_back(I->getName()); + } + + // Check sorted contents. + std::sort(Contents.begin(), Contents.end()); + EXPECT_EQ(Expected.size(), Contents.size()); + EXPECT_TRUE(std::equal(Contents.begin(), Contents.end(), Expected.begin())); +} +#endif + template <typename DirIter> static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) { std::error_code EC; |