brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · 6d728ce Raw
162 lines · cpp
1//===-- QueryEngineTest.cpp - clang-query test ----------------------------===//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 "Query.h"10#include "QueryParser.h"11#include "QuerySession.h"12#include "clang/ASTMatchers/ASTMatchers.h"13#include "clang/ASTMatchers/Dynamic/VariantValue.h"14#include "clang/Frontend/ASTUnit.h"15#include "clang/Tooling/Tooling.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/Support/raw_ostream.h"18#include "gtest/gtest.h"19#include <string>20 21using namespace clang;22using namespace clang::ast_matchers;23using namespace clang::ast_matchers::dynamic;24using namespace clang::query;25using namespace clang::tooling;26 27class QueryEngineTest : public ::testing::Test {28  ArrayRef<std::unique_ptr<ASTUnit>> mkASTUnit2(std::unique_ptr<ASTUnit> a,29                                                std::unique_ptr<ASTUnit> b) {30    ASTs[0] = std::move(a);31    ASTs[1] = std::move(b);32    return ArrayRef<std::unique_ptr<ASTUnit>>(ASTs);33  }34 35protected:36  QueryEngineTest()37      : S(mkASTUnit2(buildASTFromCode("void foo1(void) {}\nvoid foo2(void) {}",38                                      "foo.cc"),39                     buildASTFromCode("void bar1(void) {}\nvoid bar2(void) {}",40                                      "bar.cc"))),41        OS(Str) {}42 43  std::unique_ptr<ASTUnit> ASTs[2];44  QuerySession S;45 46  std::string Str;47  llvm::raw_string_ostream OS;48};49 50TEST_F(QueryEngineTest, Basic) {51  DynTypedMatcher FnMatcher = functionDecl();52  DynTypedMatcher FooMatcher = functionDecl(hasName("foo1"));53 54  std::string FooMatcherString = "functionDecl(hasName(\"foo1\"))";55 56  EXPECT_TRUE(NoOpQuery().run(OS, S));57 58  EXPECT_EQ("", OS.str());59 60  Str.clear();61 62  EXPECT_FALSE(InvalidQuery("Parse error").run(OS, S));63 64  EXPECT_EQ("Parse error\n", OS.str());65 66  Str.clear();67 68  EXPECT_TRUE(HelpQuery().run(OS, S));69 70  EXPECT_TRUE(OS.str().find("Available commands:") != std::string::npos);71 72  Str.clear();73 74  EXPECT_TRUE(MatchQuery("functionDecl()", FnMatcher).run(OS, S));75 76  EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=77              std::string::npos);78  EXPECT_TRUE(OS.str().find("foo.cc:2:1: note: \"root\" binds here") !=79              std::string::npos);80  EXPECT_TRUE(OS.str().find("bar.cc:1:1: note: \"root\" binds here") !=81              std::string::npos);82  EXPECT_TRUE(OS.str().find("bar.cc:2:1: note: \"root\" binds here") !=83              std::string::npos);84  EXPECT_TRUE(OS.str().find("4 matches.") != std::string::npos);85 86  Str.clear();87 88  EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));89 90  EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=91              std::string::npos);92  EXPECT_TRUE(OS.str().find("1 match.") != std::string::npos);93 94  Str.clear();95 96  EXPECT_TRUE(97      SetExclusiveOutputQuery(&QuerySession::PrintOutput).run(OS, S));98  EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));99 100  EXPECT_TRUE(OS.str().find("Binding for \"root\":\nvoid foo1()") !=101              std::string::npos);102 103  Str.clear();104 105  EXPECT_TRUE(106      SetExclusiveOutputQuery(&QuerySession::DetailedASTOutput).run(OS, S));107  EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));108 109  EXPECT_TRUE(OS.str().find("FunctionDecl") != std::string::npos);110 111  Str.clear();112 113  EXPECT_TRUE(EnableOutputQuery(&QuerySession::DiagOutput).run(OS, S));114  EXPECT_TRUE(EnableOutputQuery(&QuerySession::DetailedASTOutput).run(OS, S));115  EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));116 117  {118    auto Output = OS.str();119    EXPECT_TRUE(Output.find("FunctionDecl") != std::string::npos);120    EXPECT_TRUE(Output.find("foo.cc:1:1: note: \"root\" binds here") !=121                std::string::npos);122  }123 124  Str.clear();125 126  EXPECT_TRUE(SetQuery<bool>(&QuerySession::BindRoot, false).run(OS, S));127  EXPECT_TRUE(MatchQuery(FooMatcherString, FooMatcher).run(OS, S));128 129  EXPECT_TRUE(OS.str().find("No bindings.") != std::string::npos);130 131  Str.clear();132 133  EXPECT_FALSE(MatchQuery("isMain()", isMain()).run(OS, S));134 135  EXPECT_EQ("Not a valid top-level matcher.\n", OS.str());136}137 138TEST_F(QueryEngineTest, LetAndMatch) {139  EXPECT_TRUE(QueryParser::parse("let x \"foo1\"", S)->run(OS, S));140  EXPECT_EQ("", OS.str());141  Str.clear();142 143  EXPECT_TRUE(QueryParser::parse("let y hasName(x)", S)->run(OS, S));144  EXPECT_EQ("", OS.str());145  Str.clear();146 147  EXPECT_TRUE(QueryParser::parse("match functionDecl(y)", S)->run(OS, S));148  EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") !=149              std::string::npos);150  EXPECT_TRUE(OS.str().find("1 match.") != std::string::npos);151  Str.clear();152 153  EXPECT_TRUE(QueryParser::parse("unlet x", S)->run(OS, S));154  EXPECT_EQ("", OS.str());155  Str.clear();156 157  EXPECT_FALSE(QueryParser::parse("let y hasName(x)", S)->run(OS, S));158  EXPECT_EQ("1:2: Error parsing argument 1 for matcher hasName.\n"159            "1:10: Value not found: x\n", OS.str());160  Str.clear();161}162