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 protected: 30 QueryEngineTest() {} 31 32 std::unique_ptr<ASTUnit> FooAST{ 33 buildASTFromCode("void foo1(void) {}\nvoid foo2(void) {}", "foo.cc")}; 34 std::unique_ptr<ASTUnit> BarAST{ 35 buildASTFromCode("void bar1(void) {}\nvoid bar2(void) {}", "bar.cc")}; 36 ASTUnit *ASTs[2]{FooAST.get(), BarAST.get()}; 37 QuerySession S{ASTs}; 38 39 std::string Str; 40 llvm::raw_string_ostream OS{Str}; 41 }; 42 43 TEST_F(QueryEngineTest, Basic) { 44 DynTypedMatcher FnMatcher = functionDecl(); 45 DynTypedMatcher FooMatcher = functionDecl(hasName("foo1")); 46 47 EXPECT_TRUE(NoOpQuery().run(OS, S)); 48 49 EXPECT_EQ("", OS.str()); 50 51 Str.clear(); 52 53 EXPECT_FALSE(InvalidQuery("Parse error").run(OS, S)); 54 55 EXPECT_EQ("Parse error\n", OS.str()); 56 57 Str.clear(); 58 59 EXPECT_TRUE(HelpQuery().run(OS, S)); 60 61 EXPECT_TRUE(OS.str().find("Available commands:") != std::string::npos); 62 63 Str.clear(); 64 65 EXPECT_TRUE(MatchQuery(FnMatcher).run(OS, S)); 66 67 EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") != 68 std::string::npos); 69 EXPECT_TRUE(OS.str().find("foo.cc:2:1: note: \"root\" binds here") != 70 std::string::npos); 71 EXPECT_TRUE(OS.str().find("bar.cc:1:1: note: \"root\" binds here") != 72 std::string::npos); 73 EXPECT_TRUE(OS.str().find("bar.cc:2:1: note: \"root\" binds here") != 74 std::string::npos); 75 EXPECT_TRUE(OS.str().find("4 matches.") != std::string::npos); 76 77 Str.clear(); 78 79 EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S)); 80 81 EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") != 82 std::string::npos); 83 EXPECT_TRUE(OS.str().find("1 match.") != std::string::npos); 84 85 Str.clear(); 86 87 EXPECT_TRUE( 88 SetQuery<OutputKind>(&QuerySession::OutKind, OK_Print).run(OS, S)); 89 EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S)); 90 91 EXPECT_TRUE(OS.str().find("Binding for \"root\":\nvoid foo1()") != 92 std::string::npos); 93 94 Str.clear(); 95 96 EXPECT_TRUE(SetQuery<OutputKind>(&QuerySession::OutKind, OK_Dump).run(OS, S)); 97 EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S)); 98 99 EXPECT_TRUE(OS.str().find("FunctionDecl") != std::string::npos); 100 101 Str.clear(); 102 103 EXPECT_TRUE(SetQuery<bool>(&QuerySession::BindRoot, false).run(OS, S)); 104 EXPECT_TRUE(MatchQuery(FooMatcher).run(OS, S)); 105 106 EXPECT_TRUE(OS.str().find("No bindings.") != std::string::npos); 107 108 Str.clear(); 109 110 EXPECT_FALSE(MatchQuery(isArrow()).run(OS, S)); 111 112 EXPECT_EQ("Not a valid top-level matcher.\n", OS.str()); 113 } 114 115 TEST_F(QueryEngineTest, LetAndMatch) { 116 EXPECT_TRUE(QueryParser::parse("let x \"foo1\"", S)->run(OS, S)); 117 EXPECT_EQ("", OS.str()); 118 Str.clear(); 119 120 EXPECT_TRUE(QueryParser::parse("let y hasName(x)", S)->run(OS, S)); 121 EXPECT_EQ("", OS.str()); 122 Str.clear(); 123 124 EXPECT_TRUE(QueryParser::parse("match functionDecl(y)", S)->run(OS, S)); 125 EXPECT_TRUE(OS.str().find("foo.cc:1:1: note: \"root\" binds here") != 126 std::string::npos); 127 EXPECT_TRUE(OS.str().find("1 match.") != std::string::npos); 128 Str.clear(); 129 130 EXPECT_TRUE(QueryParser::parse("unlet x", S)->run(OS, S)); 131 EXPECT_EQ("", OS.str()); 132 Str.clear(); 133 134 EXPECT_FALSE(QueryParser::parse("let y hasName(x)", S)->run(OS, S)); 135 EXPECT_EQ("1:2: Error parsing argument 1 for matcher hasName.\n" 136 "1:10: Value not found: x\n", OS.str()); 137 Str.clear(); 138 } 139