forked from OSchip/llvm-project
[clangd] Add a TestWorkspace utility
TestWorkspace allows easily writing tests involving multiple files that can have inclusion relationships between them. BackgroundIndexTest.RelationsMultiFile is refactored to use TestWorkspace, and moved to FileIndexTest as it no longer depends on BackgroundIndex. Differential Revision: https://reviews.llvm.org/D89297
This commit is contained in:
parent
c039e83a2c
commit
aaa8b44d19
|
@ -230,49 +230,6 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) {
|
|||
FileURI("unittest:///root/B.cc")}));
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, RelationsMultiFile) {
|
||||
MockFS FS;
|
||||
FS.Files[testPath("root/Base.h")] = "class Base {};";
|
||||
FS.Files[testPath("root/A.cc")] = R"cpp(
|
||||
#include "Base.h"
|
||||
class A : public Base {};
|
||||
)cpp";
|
||||
FS.Files[testPath("root/B.cc")] = R"cpp(
|
||||
#include "Base.h"
|
||||
class B : public Base {};
|
||||
)cpp";
|
||||
|
||||
llvm::StringMap<std::string> Storage;
|
||||
size_t CacheHits = 0;
|
||||
MemoryShardStorage MSS(Storage, CacheHits);
|
||||
OverlayCDB CDB(/*Base=*/nullptr);
|
||||
BackgroundIndex Index(FS, CDB, [&](llvm::StringRef) { return &MSS; },
|
||||
/*Opts=*/{});
|
||||
|
||||
tooling::CompileCommand Cmd;
|
||||
Cmd.Filename = testPath("root/A.cc");
|
||||
Cmd.Directory = testPath("root");
|
||||
Cmd.CommandLine = {"clang++", Cmd.Filename};
|
||||
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
||||
ASSERT_TRUE(Index.blockUntilIdleForTest());
|
||||
|
||||
Cmd.Filename = testPath("root/B.cc");
|
||||
Cmd.CommandLine = {"clang++", Cmd.Filename};
|
||||
CDB.setCompileCommand(testPath("root/B.cc"), Cmd);
|
||||
ASSERT_TRUE(Index.blockUntilIdleForTest());
|
||||
|
||||
auto HeaderShard = MSS.loadShard(testPath("root/Base.h"));
|
||||
EXPECT_NE(HeaderShard, nullptr);
|
||||
SymbolID Base = findSymbol(*HeaderShard->Symbols, "Base").ID;
|
||||
|
||||
RelationsRequest Req;
|
||||
Req.Subjects.insert(Base);
|
||||
Req.Predicate = RelationKind::BaseOf;
|
||||
uint32_t Results = 0;
|
||||
Index.relations(Req, [&](const SymbolID &, const Symbol &) { ++Results; });
|
||||
EXPECT_EQ(Results, 2u);
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, MainFileRefs) {
|
||||
MockFS FS;
|
||||
FS.Files[testPath("root/A.h")] = R"cpp(
|
||||
|
|
|
@ -88,6 +88,7 @@ add_unittest(ClangdUnitTests ClangdTests
|
|||
TestFS.cpp
|
||||
TestIndex.cpp
|
||||
TestTU.cpp
|
||||
TestWorkspace.cpp
|
||||
TypeHierarchyTests.cpp
|
||||
TweakTests.cpp
|
||||
TweakTesting.cpp
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "SyncAPI.h"
|
||||
#include "TestFS.h"
|
||||
#include "TestTU.h"
|
||||
#include "TestWorkspace.h"
|
||||
#include "URI.h"
|
||||
#include "index/CanonicalIncludes.h"
|
||||
#include "index/FileIndex.h"
|
||||
|
@ -426,6 +427,33 @@ TEST(FileIndexTest, Relations) {
|
|||
EXPECT_EQ(Results, 1u);
|
||||
}
|
||||
|
||||
TEST(FileIndexTest, RelationsMultiFile) {
|
||||
TestWorkspace Workspace;
|
||||
Workspace.addSource("Base.h", "class Base {};");
|
||||
Workspace.addMainFile("A.cpp", R"cpp(
|
||||
#include "Base.h"
|
||||
class A : public Base {};
|
||||
)cpp");
|
||||
Workspace.addMainFile("B.cpp", R"cpp(
|
||||
#include "Base.h"
|
||||
class B : public Base {};
|
||||
)cpp");
|
||||
|
||||
auto Index = Workspace.index();
|
||||
FuzzyFindRequest FFReq;
|
||||
FFReq.Query = "Base";
|
||||
FFReq.AnyScope = true;
|
||||
SymbolID Base;
|
||||
Index->fuzzyFind(FFReq, [&](const Symbol &S) { Base = S.ID; });
|
||||
|
||||
RelationsRequest Req;
|
||||
Req.Subjects.insert(Base);
|
||||
Req.Predicate = RelationKind::BaseOf;
|
||||
uint32_t Results = 0;
|
||||
Index->relations(Req, [&](const SymbolID &, const Symbol &) { ++Results; });
|
||||
EXPECT_EQ(Results, 2u);
|
||||
}
|
||||
|
||||
TEST(FileIndexTest, ReferencesInMainFileWithPreamble) {
|
||||
TestTU TU;
|
||||
TU.HeaderCode = "class Foo{};";
|
||||
|
|
|
@ -80,7 +80,8 @@ void deleteModuleCache(const std::string ModuleCachePath) {
|
|||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<const PreambleData> TestTU::preamble() const {
|
||||
std::shared_ptr<const PreambleData>
|
||||
TestTU::preamble(PreambleParsedCallback PreambleCallback) const {
|
||||
MockFS FS;
|
||||
auto Inputs = inputs(FS);
|
||||
IgnoreDiagnostics Diags;
|
||||
|
@ -91,8 +92,7 @@ std::shared_ptr<const PreambleData> TestTU::preamble() const {
|
|||
auto ModuleCacheDeleter = llvm::make_scope_exit(
|
||||
std::bind(deleteModuleCache, CI->getHeaderSearchOpts().ModuleCachePath));
|
||||
return clang::clangd::buildPreamble(testPath(Filename), *CI, Inputs,
|
||||
/*StoreInMemory=*/true,
|
||||
/*PreambleCallback=*/nullptr);
|
||||
/*StoreInMemory=*/true, PreambleCallback);
|
||||
}
|
||||
|
||||
ParsedAST TestTU::build() const {
|
||||
|
|
|
@ -79,7 +79,8 @@ struct TestTU {
|
|||
// By default, build() will report Error diagnostics as GTest errors.
|
||||
// Suppress this behavior by adding an 'error-ok' comment to the code.
|
||||
ParsedAST build() const;
|
||||
std::shared_ptr<const PreambleData> preamble() const;
|
||||
std::shared_ptr<const PreambleData>
|
||||
preamble(PreambleParsedCallback PreambleCallback = nullptr) const;
|
||||
ParseInputs inputs(MockFS &FS) const;
|
||||
SymbolSlab headerSymbols() const;
|
||||
RefSlab headerRefs() const;
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
//===--- TestWorkspace.cpp - Utility for writing multi-file tests -*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "TestWorkspace.h"
|
||||
|
||||
namespace clang {
|
||||
namespace clangd {
|
||||
|
||||
std::unique_ptr<SymbolIndex> TestWorkspace::index() {
|
||||
auto Index = std::make_unique<FileIndex>();
|
||||
for (const auto &Input : Inputs) {
|
||||
if (!Input.second.IsMainFile)
|
||||
continue;
|
||||
TU.Code = Input.second.Code;
|
||||
TU.Filename = Input.first().str();
|
||||
TU.preamble([&](ASTContext &Ctx, std::shared_ptr<clang::Preprocessor> PP,
|
||||
const CanonicalIncludes &CanonIncludes) {
|
||||
Index->updatePreamble(testPath(Input.first()), "null", Ctx, PP,
|
||||
CanonIncludes);
|
||||
});
|
||||
ParsedAST MainAST = TU.build();
|
||||
Index->updateMain(testPath(Input.first()), MainAST);
|
||||
}
|
||||
return Index;
|
||||
}
|
||||
|
||||
Optional<ParsedAST> TestWorkspace::openFile(llvm::StringRef Filename) {
|
||||
auto It = Inputs.find(Filename);
|
||||
if (It == Inputs.end()) {
|
||||
ADD_FAILURE() << "Accessing non-existing file: " << Filename;
|
||||
return llvm::None;
|
||||
}
|
||||
TU.Code = It->second.Code;
|
||||
TU.Filename = It->first().str();
|
||||
return TU.build();
|
||||
}
|
||||
|
||||
void TestWorkspace::addInput(llvm::StringRef Filename,
|
||||
const SourceFile &Input) {
|
||||
Inputs.insert(std::make_pair(Filename, Input));
|
||||
TU.AdditionalFiles.insert(std::make_pair(Filename, Input.Code));
|
||||
}
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
|
@ -0,0 +1,59 @@
|
|||
//===--- TestWorkspace.h - Utility for writing multi-file tests --*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// TestWorkspace builds on TestTU to provide a way to write tests involving
|
||||
// several related files with inclusion relationships between them.
|
||||
//
|
||||
// The tests can exercise both index and AST based operations.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTWORKSPACE_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTWORKSPACE_H
|
||||
|
||||
#include "TestFS.h"
|
||||
#include "TestTU.h"
|
||||
#include "index/FileIndex.h"
|
||||
#include "index/Index.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
namespace clangd {
|
||||
|
||||
class TestWorkspace {
|
||||
public:
|
||||
// The difference between addSource() and addMainFile() is that only main
|
||||
// files will be indexed.
|
||||
void addSource(llvm::StringRef Filename, llvm::StringRef Code) {
|
||||
addInput(Filename.str(), {Code.str(), /*IsMainFile=*/false});
|
||||
}
|
||||
void addMainFile(llvm::StringRef Filename, llvm::StringRef Code) {
|
||||
addInput(Filename.str(), {Code.str(), /*IsMainFile=*/true});
|
||||
}
|
||||
|
||||
std::unique_ptr<SymbolIndex> index();
|
||||
|
||||
Optional<ParsedAST> openFile(llvm::StringRef Filename);
|
||||
|
||||
private:
|
||||
struct SourceFile {
|
||||
std::string Code;
|
||||
bool IsMainFile = false;
|
||||
};
|
||||
llvm::StringMap<SourceFile> Inputs;
|
||||
TestTU TU;
|
||||
|
||||
void addInput(llvm::StringRef Filename, const SourceFile &Input);
|
||||
};
|
||||
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTWORKSPACE_H
|
|
@ -96,6 +96,7 @@ unittest("ClangdTests") {
|
|||
"TestFS.cpp",
|
||||
"TestIndex.cpp",
|
||||
"TestTU.cpp",
|
||||
"TestWorkspace.cpp",
|
||||
"TweakTesting.cpp",
|
||||
"TweakTests.cpp",
|
||||
"TypeHierarchyTests.cpp",
|
||||
|
|
Loading…
Reference in New Issue