summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/clang/unittests/Tooling/ExecutionTest.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 14:31:31 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 14:31:31 +0000
commite5dd70708596ae51455a0ffa086a00c5b29f8583 (patch)
tree5d676f27b570bacf71e786c3b5cff3e6f6679b59 /gnu/llvm/clang/unittests/Tooling/ExecutionTest.cpp
parentImport LLVM 10.0.0 release including clang, lld and lldb. (diff)
downloadwireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.tar.xz
wireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.zip
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom tested by plenty
Diffstat (limited to 'gnu/llvm/clang/unittests/Tooling/ExecutionTest.cpp')
-rw-r--r--gnu/llvm/clang/unittests/Tooling/ExecutionTest.cpp297
1 files changed, 297 insertions, 0 deletions
diff --git a/gnu/llvm/clang/unittests/Tooling/ExecutionTest.cpp b/gnu/llvm/clang/unittests/Tooling/ExecutionTest.cpp
new file mode 100644
index 00000000000..16455fb2fd7
--- /dev/null
+++ b/gnu/llvm/clang/unittests/Tooling/ExecutionTest.cpp
@@ -0,0 +1,297 @@
+//===- unittest/Tooling/ExecutionTest.cpp - Tool execution tests. --------===//
+//
+// 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/Tooling/Execution.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/AllTUsExecution.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/StandaloneExecution.h"
+#include "clang/Tooling/ToolExecutorPluginRegistry.h"
+#include "clang/Tooling/Tooling.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <string>
+
+namespace clang {
+namespace tooling {
+
+namespace {
+
+// This traverses the AST and outputs function name as key and "1" as value for
+// each function declaration.
+class ASTConsumerWithResult
+ : public ASTConsumer,
+ public RecursiveASTVisitor<ASTConsumerWithResult> {
+public:
+ using ASTVisitor = RecursiveASTVisitor<ASTConsumerWithResult>;
+
+ explicit ASTConsumerWithResult(ExecutionContext *Context) : Context(Context) {
+ assert(Context != nullptr);
+ }
+
+ void HandleTranslationUnit(clang::ASTContext &Context) override {
+ TraverseDecl(Context.getTranslationUnitDecl());
+ }
+
+ bool TraverseFunctionDecl(clang::FunctionDecl *Decl) {
+ Context->reportResult(Decl->getNameAsString(),
+ Context->getRevision() + ":" + Context->getCorpus() +
+ ":" + Context->getCurrentCompilationUnit() +
+ "/1");
+ return ASTVisitor::TraverseFunctionDecl(Decl);
+ }
+
+private:
+ ExecutionContext *const Context;
+};
+
+class ReportResultAction : public ASTFrontendAction {
+public:
+ explicit ReportResultAction(ExecutionContext *Context) : Context(Context) {
+ assert(Context != nullptr);
+ }
+
+protected:
+ std::unique_ptr<clang::ASTConsumer>
+ CreateASTConsumer(clang::CompilerInstance &compiler,
+ StringRef /* dummy */) override {
+ std::unique_ptr<clang::ASTConsumer> ast_consumer{
+ new ASTConsumerWithResult(Context)};
+ return ast_consumer;
+ }
+
+private:
+ ExecutionContext *const Context;
+};
+
+class ReportResultActionFactory : public FrontendActionFactory {
+public:
+ ReportResultActionFactory(ExecutionContext *Context) : Context(Context) {}
+ std::unique_ptr<FrontendAction> create() override {
+ return std::make_unique<ReportResultAction>(Context);
+ }
+
+private:
+ ExecutionContext *const Context;
+};
+
+} // namespace
+
+class TestToolExecutor : public ToolExecutor {
+public:
+ static const char *ExecutorName;
+
+ TestToolExecutor(CommonOptionsParser Options)
+ : OptionsParser(std::move(Options)) {}
+
+ StringRef getExecutorName() const override { return ExecutorName; }
+
+ llvm::Error
+ execute(llvm::ArrayRef<std::pair<std::unique_ptr<FrontendActionFactory>,
+ ArgumentsAdjuster>>) override {
+ return llvm::Error::success();
+ }
+
+ ExecutionContext *getExecutionContext() override { return nullptr; };
+
+ ToolResults *getToolResults() override { return nullptr; }
+
+ llvm::ArrayRef<std::string> getSourcePaths() const {
+ return OptionsParser.getSourcePathList();
+ }
+
+ void mapVirtualFile(StringRef FilePath, StringRef Content) override {
+ VFS[FilePath] = Content;
+ }
+
+private:
+ CommonOptionsParser OptionsParser;
+ std::string SourcePaths;
+ std::map<std::string, std::string> VFS;
+};
+
+const char *TestToolExecutor::ExecutorName = "test-executor";
+
+class TestToolExecutorPlugin : public ToolExecutorPlugin {
+public:
+ llvm::Expected<std::unique_ptr<ToolExecutor>>
+ create(CommonOptionsParser &OptionsParser) override {
+ return std::make_unique<TestToolExecutor>(std::move(OptionsParser));
+ }
+};
+
+static ToolExecutorPluginRegistry::Add<TestToolExecutorPlugin>
+ X("test-executor", "Plugin for TestToolExecutor.");
+
+llvm::cl::OptionCategory TestCategory("execution-test options");
+
+TEST(CreateToolExecutorTest, FailedCreateExecutorUndefinedFlag) {
+ std::vector<const char *> argv = {"prog", "--fake_flag_no_no_no", "f"};
+ int argc = argv.size();
+ auto Executor = internal::createExecutorFromCommandLineArgsImpl(
+ argc, &argv[0], TestCategory);
+ ASSERT_FALSE((bool)Executor);
+ llvm::consumeError(Executor.takeError());
+}
+
+TEST(CreateToolExecutorTest, RegisterFlagsBeforeReset) {
+ llvm::cl::opt<std::string> BeforeReset(
+ "before_reset", llvm::cl::desc("Defined before reset."),
+ llvm::cl::init(""));
+
+ llvm::cl::ResetAllOptionOccurrences();
+
+ std::vector<const char *> argv = {"prog", "--before_reset=set", "f"};
+ int argc = argv.size();
+ auto Executor = internal::createExecutorFromCommandLineArgsImpl(
+ argc, &argv[0], TestCategory);
+ ASSERT_TRUE((bool)Executor);
+ EXPECT_EQ(BeforeReset, "set");
+ BeforeReset.removeArgument();
+}
+
+TEST(CreateToolExecutorTest, CreateStandaloneToolExecutor) {
+ std::vector<const char *> argv = {"prog", "standalone.cpp"};
+ int argc = argv.size();
+ auto Executor = internal::createExecutorFromCommandLineArgsImpl(
+ argc, &argv[0], TestCategory);
+ ASSERT_TRUE((bool)Executor);
+ EXPECT_EQ(Executor->get()->getExecutorName(),
+ StandaloneToolExecutor::ExecutorName);
+}
+
+TEST(CreateToolExecutorTest, CreateTestToolExecutor) {
+ std::vector<const char *> argv = {"prog", "test.cpp",
+ "--executor=test-executor"};
+ int argc = argv.size();
+ auto Executor = internal::createExecutorFromCommandLineArgsImpl(
+ argc, &argv[0], TestCategory);
+ ASSERT_TRUE((bool)Executor);
+ EXPECT_EQ(Executor->get()->getExecutorName(), TestToolExecutor::ExecutorName);
+}
+
+TEST(StandaloneToolTest, SynctaxOnlyActionOnSimpleCode) {
+ FixedCompilationDatabase Compilations(".", std::vector<std::string>());
+ StandaloneToolExecutor Executor(Compilations,
+ std::vector<std::string>(1, "a.cc"));
+ Executor.mapVirtualFile("a.cc", "int x = 0;");
+
+ auto Err = Executor.execute(newFrontendActionFactory<SyntaxOnlyAction>(),
+ getClangSyntaxOnlyAdjuster());
+ ASSERT_TRUE(!Err);
+}
+
+TEST(StandaloneToolTest, SimpleAction) {
+ FixedCompilationDatabase Compilations(".", std::vector<std::string>());
+ StandaloneToolExecutor Executor(Compilations,
+ std::vector<std::string>(1, "a.cc"));
+ Executor.mapVirtualFile("a.cc", "int x = 0;");
+
+ auto Err = Executor.execute(std::unique_ptr<FrontendActionFactory>(
+ new ReportResultActionFactory(Executor.getExecutionContext())));
+ ASSERT_TRUE(!Err);
+ auto KVs = Executor.getToolResults()->AllKVResults();
+ ASSERT_EQ(KVs.size(), 0u);
+}
+
+TEST(StandaloneToolTest, SimpleActionWithResult) {
+ FixedCompilationDatabase Compilations(".", std::vector<std::string>());
+ StandaloneToolExecutor Executor(Compilations,
+ std::vector<std::string>(1, "a.cc"));
+ Executor.mapVirtualFile("a.cc", "int x = 0; void f() {}");
+
+ auto Err = Executor.execute(std::unique_ptr<FrontendActionFactory>(
+ new ReportResultActionFactory(Executor.getExecutionContext())));
+ ASSERT_TRUE(!Err);
+ auto KVs = Executor.getToolResults()->AllKVResults();
+ ASSERT_EQ(KVs.size(), 1u);
+ EXPECT_EQ("f", KVs[0].first);
+ // Currently the standlone executor returns empty corpus, revision, and
+ // compilation unit.
+ EXPECT_EQ("::/1", KVs[0].second);
+
+ Executor.getToolResults()->forEachResult(
+ [](StringRef, StringRef Value) { EXPECT_EQ("::/1", Value); });
+}
+
+class FixedCompilationDatabaseWithFiles : public CompilationDatabase {
+public:
+ FixedCompilationDatabaseWithFiles(Twine Directory,
+ ArrayRef<std::string> Files,
+ ArrayRef<std::string> CommandLine)
+ : FixedCompilations(Directory, CommandLine), Files(Files) {}
+
+ std::vector<CompileCommand>
+ getCompileCommands(StringRef FilePath) const override {
+ return FixedCompilations.getCompileCommands(FilePath);
+ }
+
+ std::vector<std::string> getAllFiles() const override { return Files; }
+
+private:
+ FixedCompilationDatabase FixedCompilations;
+ std::vector<std::string> Files;
+};
+
+MATCHER_P(Named, Name, "") { return arg.first == Name; }
+
+TEST(AllTUsToolTest, AFewFiles) {
+ FixedCompilationDatabaseWithFiles Compilations(
+ ".", {"a.cc", "b.cc", "c.cc", "ignore.cc"}, std::vector<std::string>());
+ AllTUsToolExecutor Executor(Compilations, /*ThreadCount=*/0);
+ Filter.setValue("[a-c].cc");
+ Executor.mapVirtualFile("a.cc", "void x() {}");
+ Executor.mapVirtualFile("b.cc", "void y() {}");
+ Executor.mapVirtualFile("c.cc", "void z() {}");
+ Executor.mapVirtualFile("ignore.cc", "void d() {}");
+
+ auto Err = Executor.execute(std::unique_ptr<FrontendActionFactory>(
+ new ReportResultActionFactory(Executor.getExecutionContext())));
+ ASSERT_TRUE(!Err);
+ EXPECT_THAT(
+ Executor.getToolResults()->AllKVResults(),
+ ::testing::UnorderedElementsAre(Named("x"), Named("y"), Named("z")));
+ Filter.setValue(".*"); // reset to default value.
+}
+
+TEST(AllTUsToolTest, ManyFiles) {
+ unsigned NumFiles = 100;
+ std::vector<std::string> Files;
+ std::map<std::string, std::string> FileToContent;
+ std::vector<std::string> ExpectedSymbols;
+ for (unsigned i = 1; i <= NumFiles; ++i) {
+ std::string File = "f" + std::to_string(i) + ".cc";
+ std::string Symbol = "looong_function_name_" + std::to_string(i);
+ Files.push_back(File);
+ FileToContent[File] = "void " + Symbol + "() {}";
+ ExpectedSymbols.push_back(Symbol);
+ }
+ FixedCompilationDatabaseWithFiles Compilations(".", Files,
+ std::vector<std::string>());
+ AllTUsToolExecutor Executor(Compilations, /*ThreadCount=*/0);
+ for (const auto &FileAndContent : FileToContent) {
+ Executor.mapVirtualFile(FileAndContent.first, FileAndContent.second);
+ }
+
+ auto Err = Executor.execute(std::unique_ptr<FrontendActionFactory>(
+ new ReportResultActionFactory(Executor.getExecutionContext())));
+ ASSERT_TRUE(!Err);
+ std::vector<std::string> Results;
+ Executor.getToolResults()->forEachResult(
+ [&](StringRef Name, StringRef) { Results.push_back(Name); });
+ EXPECT_THAT(ExpectedSymbols, ::testing::UnorderedElementsAreArray(Results));
+}
+
+} // end namespace tooling
+} // end namespace clang