brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · cdb0ce2 Raw
300 lines · cpp
1//===- DependencyScanningFilesystemTest.cpp -------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h"10#include "llvm/ADT/SmallString.h"11#include "llvm/Support/VirtualFileSystem.h"12#include "gtest/gtest.h"13 14using namespace clang::tooling::dependencies;15 16TEST(DependencyScanningFilesystem, OpenFileAndGetBufferRepeatedly) {17  auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();18  InMemoryFS->setCurrentWorkingDirectory("/");19  InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer("content"));20 21  DependencyScanningFilesystemSharedCache SharedCache;22  DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS);23 24  auto FileOrErr1 = DepFS.openFileForRead("foo");25  auto FileOrErr2 = DepFS.openFileForRead("foo");26  ASSERT_EQ(FileOrErr1.getError(), std::error_code{});27  ASSERT_EQ(FileOrErr1.getError(), std::error_code{});28  std::unique_ptr<llvm::vfs::File> File1 = std::move(*FileOrErr1);29  std::unique_ptr<llvm::vfs::File> File2 = std::move(*FileOrErr2);30  ASSERT_NE(File1, nullptr);31  ASSERT_NE(File2, nullptr);32  auto BufOrErr11 = File1->getBuffer("buf11");33  auto BufOrErr12 = File1->getBuffer("buf12");34  auto BufOrErr21 = File1->getBuffer("buf21");35  ASSERT_EQ(BufOrErr11.getError(), std::error_code{});36  ASSERT_EQ(BufOrErr12.getError(), std::error_code{});37  ASSERT_EQ(BufOrErr21.getError(), std::error_code{});38  std::unique_ptr<llvm::MemoryBuffer> Buf11 = std::move(*BufOrErr11);39  std::unique_ptr<llvm::MemoryBuffer> Buf12 = std::move(*BufOrErr12);40  std::unique_ptr<llvm::MemoryBuffer> Buf21 = std::move(*BufOrErr21);41  ASSERT_NE(Buf11, nullptr);42  ASSERT_NE(Buf12, nullptr);43  ASSERT_NE(Buf21, nullptr);44  ASSERT_EQ(Buf11->getBuffer().data(), Buf12->getBuffer().data());45  ASSERT_EQ(Buf11->getBuffer().data(), Buf21->getBuffer().data());46  EXPECT_EQ(Buf11->getBuffer(), "content");47}48 49TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) {50  auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();51 52  auto InstrumentingFS =53      llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);54 55  DependencyScanningFilesystemSharedCache SharedCache;56  DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);57  DependencyScanningWorkerFilesystem DepFS2(SharedCache, InstrumentingFS);58 59  DepFS.status("/foo.c");60  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u);61 62  DepFS.status("/foo.c");63  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u); // Cached, no increase.64 65  DepFS.status("/bar.c");66  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);67 68  DepFS2.status("/foo.c");69  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); // Shared cache.70}71 72TEST(DependencyScanningFilesystem, CacheGetRealPath) {73  auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();74  InMemoryFS->setCurrentWorkingDirectory("/");75  InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer(""));76  InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer(""));77 78  auto InstrumentingFS =79      llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);80 81  DependencyScanningFilesystemSharedCache SharedCache;82  DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);83  DependencyScanningWorkerFilesystem DepFS2(SharedCache, InstrumentingFS);84 85  {86    llvm::SmallString<128> Result;87    DepFS.getRealPath("/foo", Result);88    EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 1u);89  }90 91  {92    llvm::SmallString<128> Result;93    DepFS.getRealPath("/foo", Result);94    EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 1u); // Cached, no increase.95  }96 97  {98    llvm::SmallString<128> Result;99    DepFS.getRealPath("/bar", Result);100    EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 2u);101  }102 103  {104    llvm::SmallString<128> Result;105    DepFS2.getRealPath("/foo", Result);106    EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 2u); // Shared cache.107  }108}109 110TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) {111  auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();112  InMemoryFS->setCurrentWorkingDirectory("/");113  InMemoryFS->addFile("/foo.c", 0, llvm::MemoryBuffer::getMemBuffer(""));114  InMemoryFS->addFile("/bar.c", 0, llvm::MemoryBuffer::getMemBuffer(""));115 116  DependencyScanningFilesystemSharedCache SharedCache;117  DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS);118 119  // Success.120  {121    DepFS.status("/foo.c");122 123    llvm::SmallString<128> Result;124    DepFS.getRealPath("/foo.c", Result);125  }126  {127    llvm::SmallString<128> Result;128    DepFS.getRealPath("/bar.c", Result);129 130    DepFS.status("/bar.c");131  }132 133  // Failure.134  {135    DepFS.status("/foo.m");136 137    llvm::SmallString<128> Result;138    DepFS.getRealPath("/foo.m", Result);139  }140  {141    llvm::SmallString<128> Result;142    DepFS.getRealPath("/bar.m", Result);143 144    DepFS.status("/bar.m");145  }146 147  // Failure without caching.148  {149    DepFS.status("/foo");150 151    llvm::SmallString<128> Result;152    DepFS.getRealPath("/foo", Result);153  }154  {155    llvm::SmallString<128> Result;156    DepFS.getRealPath("/bar", Result);157 158    DepFS.status("/bar");159  }160}161 162TEST(DependencyScanningFilesystem, CacheStatOnExists) {163  auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();164  auto InstrumentingFS =165      llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);166  InMemoryFS->setCurrentWorkingDirectory("/");167  InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer(""));168  InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer(""));169  DependencyScanningFilesystemSharedCache SharedCache;170  DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);171 172  DepFS.status("/foo");173  DepFS.status("/foo");174  DepFS.status("/bar");175  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);176 177  DepFS.exists("/foo");178  DepFS.exists("/bar");179  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);180  EXPECT_EQ(InstrumentingFS->NumExistsCalls, 0u);181}182 183TEST(DependencyScanningFilesystem, CacheStatFailures) {184  auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();185  InMemoryFS->setCurrentWorkingDirectory("/");186  InMemoryFS->addFile("/dir/vector", 0, llvm::MemoryBuffer::getMemBuffer(""));187  InMemoryFS->addFile("/cache/a.pcm", 0, llvm::MemoryBuffer::getMemBuffer(""));188 189  auto InstrumentingFS =190      llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);191 192  DependencyScanningFilesystemSharedCache SharedCache;193  DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);194 195  DepFS.status("/dir");196  DepFS.status("/dir");197  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u);198 199  DepFS.status("/dir/vector");200  DepFS.status("/dir/vector");201  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);202 203  DepFS.setBypassedPathPrefix("/cache");204  DepFS.exists("/cache/a.pcm");205  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 3u);206  DepFS.exists("/cache/a.pcm");207  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 4u);208 209  DepFS.resetBypassedPathPrefix();210  DepFS.exists("/cache/a.pcm");211  DepFS.exists("/cache/a.pcm");212  EXPECT_EQ(InstrumentingFS->NumStatusCalls, 5u);213}214 215TEST(DependencyScanningFilesystem, DiagnoseStaleStatFailures) {216  auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();217  InMemoryFS->setCurrentWorkingDirectory("/");218 219  DependencyScanningFilesystemSharedCache SharedCache;220  DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS);221 222  bool Path1Exists = DepFS.exists("/path1.suffix");223  ASSERT_EQ(Path1Exists, false);224 225  // Adding a file that has been stat-ed,226  InMemoryFS->addFile("/path1.suffix", 0, llvm::MemoryBuffer::getMemBuffer(""));227  Path1Exists = DepFS.exists("/path1.suffix");228  // Due to caching in SharedCache, path1 should not exist in229  // DepFS's eyes.230  ASSERT_EQ(Path1Exists, false);231 232  auto InvalidEntries = SharedCache.getOutOfDateEntries(*InMemoryFS);233 234  EXPECT_EQ(InvalidEntries.size(), 1u);235  ASSERT_STREQ("/path1.suffix", InvalidEntries[0].Path);236}237 238TEST(DependencyScanningFilesystem, DiagnoseCachedFileSizeChange) {239  auto InMemoryFS1 = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();240  auto InMemoryFS2 = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();241  InMemoryFS1->setCurrentWorkingDirectory("/");242  InMemoryFS2->setCurrentWorkingDirectory("/");243 244  DependencyScanningFilesystemSharedCache SharedCache;245  DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS1);246 247  InMemoryFS1->addFile("/path1.suffix", 0,248                       llvm::MemoryBuffer::getMemBuffer(""));249  bool Path1Exists = DepFS.exists("/path1.suffix");250  ASSERT_EQ(Path1Exists, true);251 252  // Add a file to a new FS that has the same path but different content.253  InMemoryFS2->addFile("/path1.suffix", 1,254                       llvm::MemoryBuffer::getMemBuffer("        "));255 256  // Check against the new file system. InMemoryFS2 could be the underlying257  // physical system in the real world.258  auto InvalidEntries = SharedCache.getOutOfDateEntries(*InMemoryFS2);259 260  ASSERT_EQ(InvalidEntries.size(), 1u);261  ASSERT_STREQ("/path1.suffix", InvalidEntries[0].Path);262  auto SizeInfo = std::get_if<263      DependencyScanningFilesystemSharedCache::OutOfDateEntry::SizeChangedInfo>(264      &InvalidEntries[0].Info);265  ASSERT_TRUE(SizeInfo);266  ASSERT_EQ(SizeInfo->CachedSize, 0u);267  ASSERT_EQ(SizeInfo->ActualSize, 8u);268}269 270TEST(DependencyScanningFilesystem, DoNotDiagnoseDirSizeChange) {271  llvm::SmallString<128> Dir;272  ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory("tmp", Dir));273 274  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =275      llvm::vfs::createPhysicalFileSystem();276 277  DependencyScanningFilesystemSharedCache SharedCache;278  DependencyScanningWorkerFilesystem DepFS(SharedCache, FS);279 280  // Trigger the file system cache.281  ASSERT_EQ(DepFS.exists(Dir), true);282 283  // Add a file to the FS to change its size.284  // It seems that directory sizes reported are not meaningful,285  // and should not be used to check for size changes.286  // This test is setup only to trigger a size change so that we287  // know we are excluding directories from reporting.288  llvm::SmallString<128> FilePath = Dir;289  llvm::sys::path::append(FilePath, "file.h");290  {291    std::error_code EC;292    llvm::raw_fd_ostream TempFile(FilePath, EC);293    ASSERT_FALSE(EC);294  }295 296  // We do not report directory size changes.297  auto InvalidEntries = SharedCache.getOutOfDateEntries(*FS);298  EXPECT_EQ(InvalidEntries.size(), 0u);299}300