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