================ @@ -0,0 +1,355 @@ +//===--------------- PrerequisiteModulesTests.cpp -------------------*- C++ +//-*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +/// FIXME: Skip testing on windows temporarily due to the different escaping +/// code mode. +#ifndef _WIN32 + +#include "ModulesBuilder.h" +#include "ScanningProjectModules.h" + +#include "Annotations.h" +#include "CodeComplete.h" +#include "Compiler.h" +#include "TestTU.h" +#include "support/ThreadsafeFS.h" + +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang::clangd { +namespace { + +class MockDirectoryCompilationDatabase : public MockCompilationDatabase { +public: + MockDirectoryCompilationDatabase(StringRef TestDir, const ThreadsafeFS &TFS) + : MockCompilationDatabase(TestDir), + MockedCDBPtr(std::make_shared<MockClangCompilationDatabase>(*this)), + TFS(TFS) { + this->ExtraClangFlags.push_back("-std=c++20"); + this->ExtraClangFlags.push_back("-c"); + } + + void addFile(llvm::StringRef Path, llvm::StringRef Contents); + + std::unique_ptr<ProjectModules> getProjectModules(PathRef) const override { + return scanningProjectModules(MockedCDBPtr, TFS); + } + +private: + class MockClangCompilationDatabase : public tooling::CompilationDatabase { + public: + MockClangCompilationDatabase(MockDirectoryCompilationDatabase &MCDB) + : MCDB(MCDB) {} + + std::vector<tooling::CompileCommand> + getCompileCommands(StringRef FilePath) const override { + std::optional<tooling::CompileCommand> Cmd = + MCDB.getCompileCommand(FilePath); + EXPECT_TRUE(Cmd); + return {*Cmd}; + } + + std::vector<std::string> getAllFiles() const override { return Files; } + + void AddFile(StringRef File) { Files.push_back(File.str()); } + + private: + MockDirectoryCompilationDatabase &MCDB; + std::vector<std::string> Files; + }; + + std::shared_ptr<MockClangCompilationDatabase> MockedCDBPtr; + const ThreadsafeFS &TFS; +}; + +// Add files to the working testing directory and the compilation database. +void MockDirectoryCompilationDatabase::addFile(llvm::StringRef Path, + llvm::StringRef Contents) { + ASSERT_FALSE(llvm::sys::path::is_absolute(Path)); + + SmallString<256> AbsPath(Directory); + llvm::sys::path::append(AbsPath, Path); + + ASSERT_FALSE( + llvm::sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath))); + + std::error_code EC; + llvm::raw_fd_ostream OS(AbsPath, EC); + ASSERT_FALSE(EC); + OS << Contents; + + MockedCDBPtr->AddFile(Path); +} + +class PrerequisiteModulesTests : public ::testing::Test { +protected: + void SetUp() override { + ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory("modules-test", TestDir)); + } + + void TearDown() override { + ASSERT_FALSE(llvm::sys::fs::remove_directories(TestDir)); + } + +public: + // Get the absolute path for file specified by Path under testing working + // directory. + std::string getFullPath(llvm::StringRef Path) { + SmallString<128> Result(TestDir); + llvm::sys::path::append(Result, Path); + EXPECT_TRUE(llvm::sys::fs::exists(Result.str())); + return Result.str().str(); + } + + std::unique_ptr<GlobalCompilationDatabase> getGlobalCompilationDatabase() { + // The compilation flags with modules are much complex so it looks better + // to use DirectoryBasedGlobalCompilationDatabase than a mocked compilation + // database. + DirectoryBasedGlobalCompilationDatabase::Options Opts(TFS); + return std::make_unique<DirectoryBasedGlobalCompilationDatabase>(Opts); + } + + ParseInputs getInputs(llvm::StringRef FileName, + const GlobalCompilationDatabase &CDB) { + std::string FullPathName = getFullPath(FileName); + + ParseInputs Inputs; + std::optional<tooling::CompileCommand> Cmd = + CDB.getCompileCommand(FullPathName); + EXPECT_TRUE(Cmd); + Inputs.CompileCommand = std::move(*Cmd); + Inputs.TFS = &TFS; + + if (auto Contents = TFS.view(TestDir)->getBufferForFile(FullPathName)) + Inputs.Contents = Contents->get()->getBuffer().str(); + + return Inputs; + } + + SmallString<256> TestDir; + // Noticed MockFS but its member variable 'OverlayRealFileSystemForModules' + // implies that it will better to use RealThreadsafeFS directly. ---------------- kadircet wrote:
not sure i follow the reasoning here, isn't it precisely better to use MockFS because of that? e.g. we can put all the sources needed by tests into virtual-fs and let pcms be written/read from realfs. this gets rid of both unnecessary real io for tests and makes sure we don't leave artifacts behind when something goes wrong. https://github.com/llvm/llvm-project/pull/66462 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits