CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
337 lines
12 KiB
C++
337 lines
12 KiB
C++
//===- DependencyScanningFilesystemTest.cpp -------------------------------===//
|
|
//
|
|
// 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/DependencyScanning/DependencyScanningFilesystem.h"
|
|
#include "clang/DependencyScanning/DependencyScanningService.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/Support/VirtualFileSystem.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace clang::dependencies;
|
|
|
|
TEST(DependencyScanningFilesystem, OpenFileAndGetBufferRepeatedly) {
|
|
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
InMemoryFS->setCurrentWorkingDirectory("/");
|
|
InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer("content"));
|
|
|
|
DependencyScanningService Service({});
|
|
DependencyScanningWorkerFilesystem DepFS(Service, InMemoryFS);
|
|
|
|
auto FileOrErr1 = DepFS.openFileForRead("foo");
|
|
auto FileOrErr2 = DepFS.openFileForRead("foo");
|
|
ASSERT_EQ(FileOrErr1.getError(), std::error_code{});
|
|
ASSERT_EQ(FileOrErr1.getError(), std::error_code{});
|
|
std::unique_ptr<llvm::vfs::File> File1 = std::move(*FileOrErr1);
|
|
std::unique_ptr<llvm::vfs::File> File2 = std::move(*FileOrErr2);
|
|
ASSERT_NE(File1, nullptr);
|
|
ASSERT_NE(File2, nullptr);
|
|
auto BufOrErr11 = File1->getBuffer("buf11");
|
|
auto BufOrErr12 = File1->getBuffer("buf12");
|
|
auto BufOrErr21 = File1->getBuffer("buf21");
|
|
ASSERT_EQ(BufOrErr11.getError(), std::error_code{});
|
|
ASSERT_EQ(BufOrErr12.getError(), std::error_code{});
|
|
ASSERT_EQ(BufOrErr21.getError(), std::error_code{});
|
|
std::unique_ptr<llvm::MemoryBuffer> Buf11 = std::move(*BufOrErr11);
|
|
std::unique_ptr<llvm::MemoryBuffer> Buf12 = std::move(*BufOrErr12);
|
|
std::unique_ptr<llvm::MemoryBuffer> Buf21 = std::move(*BufOrErr21);
|
|
ASSERT_NE(Buf11, nullptr);
|
|
ASSERT_NE(Buf12, nullptr);
|
|
ASSERT_NE(Buf21, nullptr);
|
|
ASSERT_EQ(Buf11->getBuffer().data(), Buf12->getBuffer().data());
|
|
ASSERT_EQ(Buf11->getBuffer().data(), Buf21->getBuffer().data());
|
|
EXPECT_EQ(Buf11->getBuffer(), "content");
|
|
}
|
|
|
|
TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) {
|
|
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
|
|
auto InstrumentingFS =
|
|
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
|
|
|
|
DependencyScanningServiceOptions Opts;
|
|
Opts.CacheNegativeStats = true;
|
|
DependencyScanningService Service(std::move(Opts));
|
|
DependencyScanningWorkerFilesystem DepFS(Service, InstrumentingFS);
|
|
DependencyScanningWorkerFilesystem DepFS2(Service, InstrumentingFS);
|
|
|
|
DepFS.status("/foo.c");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u);
|
|
|
|
DepFS.status("/foo.c");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u); // Cached, no increase.
|
|
|
|
DepFS.status("/bar.c");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
|
|
|
|
DepFS2.status("/foo.c");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); // Shared cache.
|
|
}
|
|
|
|
TEST(DependencyScanningFilesystem, CacheGetRealPath) {
|
|
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
InMemoryFS->setCurrentWorkingDirectory("/");
|
|
InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer(""));
|
|
InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer(""));
|
|
|
|
auto InstrumentingFS =
|
|
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
|
|
|
|
DependencyScanningService Service({});
|
|
DependencyScanningWorkerFilesystem DepFS(Service, InstrumentingFS);
|
|
DependencyScanningWorkerFilesystem DepFS2(Service, InstrumentingFS);
|
|
|
|
{
|
|
llvm::SmallString<128> Result;
|
|
DepFS.getRealPath("/foo", Result);
|
|
EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 1u);
|
|
}
|
|
|
|
{
|
|
llvm::SmallString<128> Result;
|
|
DepFS.getRealPath("/foo", Result);
|
|
EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 1u); // Cached, no increase.
|
|
}
|
|
|
|
{
|
|
llvm::SmallString<128> Result;
|
|
DepFS.getRealPath("/bar", Result);
|
|
EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 2u);
|
|
}
|
|
|
|
{
|
|
llvm::SmallString<128> Result;
|
|
DepFS2.getRealPath("/foo", Result);
|
|
EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 2u); // Shared cache.
|
|
}
|
|
}
|
|
|
|
TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) {
|
|
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
InMemoryFS->setCurrentWorkingDirectory("/");
|
|
InMemoryFS->addFile("/foo.c", 0, llvm::MemoryBuffer::getMemBuffer(""));
|
|
InMemoryFS->addFile("/bar.c", 0, llvm::MemoryBuffer::getMemBuffer(""));
|
|
|
|
DependencyScanningService Service({});
|
|
DependencyScanningWorkerFilesystem DepFS(Service, InMemoryFS);
|
|
|
|
// Success.
|
|
{
|
|
DepFS.status("/foo.c");
|
|
|
|
llvm::SmallString<128> Result;
|
|
DepFS.getRealPath("/foo.c", Result);
|
|
}
|
|
{
|
|
llvm::SmallString<128> Result;
|
|
DepFS.getRealPath("/bar.c", Result);
|
|
|
|
DepFS.status("/bar.c");
|
|
}
|
|
|
|
// Failure.
|
|
{
|
|
DepFS.status("/foo.m");
|
|
|
|
llvm::SmallString<128> Result;
|
|
DepFS.getRealPath("/foo.m", Result);
|
|
}
|
|
{
|
|
llvm::SmallString<128> Result;
|
|
DepFS.getRealPath("/bar.m", Result);
|
|
|
|
DepFS.status("/bar.m");
|
|
}
|
|
|
|
// Failure without caching.
|
|
{
|
|
DepFS.status("/foo");
|
|
|
|
llvm::SmallString<128> Result;
|
|
DepFS.getRealPath("/foo", Result);
|
|
}
|
|
{
|
|
llvm::SmallString<128> Result;
|
|
DepFS.getRealPath("/bar", Result);
|
|
|
|
DepFS.status("/bar");
|
|
}
|
|
}
|
|
|
|
TEST(DependencyScanningFilesystem, CacheStatOnExists) {
|
|
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
auto InstrumentingFS =
|
|
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
|
|
InMemoryFS->setCurrentWorkingDirectory("/");
|
|
InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer(""));
|
|
InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer(""));
|
|
DependencyScanningService Service({});
|
|
DependencyScanningWorkerFilesystem DepFS(Service, InstrumentingFS);
|
|
|
|
DepFS.status("/foo");
|
|
DepFS.status("/foo");
|
|
DepFS.status("/bar");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
|
|
|
|
DepFS.exists("/foo");
|
|
DepFS.exists("/bar");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
|
|
EXPECT_EQ(InstrumentingFS->NumExistsCalls, 0u);
|
|
}
|
|
|
|
TEST(DependencyScanningFilesystem, CacheStatFailures) {
|
|
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
InMemoryFS->setCurrentWorkingDirectory("/");
|
|
InMemoryFS->addFile("/dir/present.h", 0,
|
|
llvm::MemoryBuffer::getMemBuffer(""));
|
|
|
|
auto InstrumentingFS =
|
|
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
|
|
|
|
DependencyScanningServiceOptions Opts;
|
|
Opts.CacheNegativeStats = true;
|
|
DependencyScanningService Service(std::move(Opts));
|
|
DependencyScanningWorkerFilesystem DepFS(Service, InstrumentingFS);
|
|
|
|
DepFS.status("/dir");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u);
|
|
DepFS.status("/dir");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u);
|
|
|
|
DepFS.status("/dir/present.h");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
|
|
DepFS.status("/dir/present.h");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
|
|
|
|
DepFS.status("/dir/missing.h");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 3u);
|
|
DepFS.status("/dir/missing.h");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 3u);
|
|
}
|
|
|
|
TEST(DependencyScanningFilesystem, NoNegativeCache) {
|
|
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
InMemoryFS->setCurrentWorkingDirectory("/");
|
|
InMemoryFS->addFile("/dir/present.h", 0,
|
|
llvm::MemoryBuffer::getMemBuffer(""));
|
|
|
|
auto InstrumentingFS =
|
|
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
|
|
|
|
DependencyScanningServiceOptions Opts;
|
|
Opts.CacheNegativeStats = false;
|
|
DependencyScanningService Service(std::move(Opts));
|
|
DependencyScanningWorkerFilesystem DepFS(Service, InstrumentingFS);
|
|
|
|
DepFS.status("/dir");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u);
|
|
DepFS.status("/dir");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u);
|
|
|
|
DepFS.status("/dir/present.h");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
|
|
DepFS.status("/dir/present.h");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
|
|
|
|
DepFS.status("/dir/missing.h");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 3u);
|
|
DepFS.status("/dir/missing.h");
|
|
EXPECT_EQ(InstrumentingFS->NumStatusCalls, 4u);
|
|
}
|
|
|
|
TEST(DependencyScanningFilesystem, DiagnoseStaleStatFailures) {
|
|
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
InMemoryFS->setCurrentWorkingDirectory("/");
|
|
|
|
DependencyScanningServiceOptions Opts;
|
|
Opts.CacheNegativeStats = true;
|
|
DependencyScanningService Service(std::move(Opts));
|
|
DependencyScanningWorkerFilesystem DepFS(Service, InMemoryFS);
|
|
|
|
bool Path1Exists = DepFS.exists("/path1.suffix");
|
|
ASSERT_EQ(Path1Exists, false);
|
|
|
|
// Adding a file that has been stat-ed,
|
|
InMemoryFS->addFile("/path1.suffix", 0, llvm::MemoryBuffer::getMemBuffer(""));
|
|
Path1Exists = DepFS.exists("/path1.suffix");
|
|
// Due to caching in SharedCache, path1 should not exist in
|
|
// DepFS's eyes.
|
|
ASSERT_EQ(Path1Exists, false);
|
|
|
|
auto InvalidEntries =
|
|
Service.getSharedCache().getOutOfDateEntries(*InMemoryFS);
|
|
|
|
EXPECT_EQ(InvalidEntries.size(), 1u);
|
|
ASSERT_STREQ("/path1.suffix", InvalidEntries[0].Path);
|
|
}
|
|
|
|
TEST(DependencyScanningFilesystem, DiagnoseCachedFileSizeChange) {
|
|
auto InMemoryFS1 = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
auto InMemoryFS2 = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
|
|
InMemoryFS1->setCurrentWorkingDirectory("/");
|
|
InMemoryFS2->setCurrentWorkingDirectory("/");
|
|
|
|
DependencyScanningServiceOptions Opts;
|
|
Opts.CacheNegativeStats = true;
|
|
DependencyScanningService Service(std::move(Opts));
|
|
DependencyScanningWorkerFilesystem DepFS(Service, InMemoryFS1);
|
|
|
|
InMemoryFS1->addFile("/path1.suffix", 0,
|
|
llvm::MemoryBuffer::getMemBuffer(""));
|
|
bool Path1Exists = DepFS.exists("/path1.suffix");
|
|
ASSERT_EQ(Path1Exists, true);
|
|
|
|
// Add a file to a new FS that has the same path but different content.
|
|
InMemoryFS2->addFile("/path1.suffix", 1,
|
|
llvm::MemoryBuffer::getMemBuffer(" "));
|
|
|
|
// Check against the new file system. InMemoryFS2 could be the underlying
|
|
// physical system in the real world.
|
|
auto InvalidEntries =
|
|
Service.getSharedCache().getOutOfDateEntries(*InMemoryFS2);
|
|
|
|
ASSERT_EQ(InvalidEntries.size(), 1u);
|
|
ASSERT_STREQ("/path1.suffix", InvalidEntries[0].Path);
|
|
auto SizeInfo = std::get_if<
|
|
DependencyScanningFilesystemSharedCache::OutOfDateEntry::SizeChangedInfo>(
|
|
&InvalidEntries[0].Info);
|
|
ASSERT_TRUE(SizeInfo);
|
|
ASSERT_EQ(SizeInfo->CachedSize, 0u);
|
|
ASSERT_EQ(SizeInfo->ActualSize, 8u);
|
|
}
|
|
|
|
TEST(DependencyScanningFilesystem, DoNotDiagnoseDirSizeChange) {
|
|
llvm::SmallString<128> Dir;
|
|
ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory("tmp", Dir));
|
|
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
|
|
llvm::vfs::createPhysicalFileSystem();
|
|
|
|
DependencyScanningService Service({});
|
|
DependencyScanningWorkerFilesystem DepFS(Service, FS);
|
|
|
|
// Trigger the file system cache.
|
|
ASSERT_EQ(DepFS.exists(Dir), true);
|
|
|
|
// Add a file to the FS to change its size.
|
|
// It seems that directory sizes reported are not meaningful,
|
|
// and should not be used to check for size changes.
|
|
// This test is setup only to trigger a size change so that we
|
|
// know we are excluding directories from reporting.
|
|
llvm::SmallString<128> FilePath = Dir;
|
|
llvm::sys::path::append(FilePath, "file.h");
|
|
{
|
|
std::error_code EC;
|
|
llvm::raw_fd_ostream TempFile(FilePath, EC);
|
|
ASSERT_FALSE(EC);
|
|
}
|
|
|
|
// We do not report directory size changes.
|
|
auto InvalidEntries = Service.getSharedCache().getOutOfDateEntries(*FS);
|
|
EXPECT_EQ(InvalidEntries.size(), 0u);
|
|
}
|