blob: 631a53ebb0ed8fb4cd3b211407efc3db5dd4ff80 [file] [log] [blame]
Peter Collingbourne8b1265b2013-11-08 00:08:23 +00001//===---- 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"
Samuel Benzaquen1f6066c2014-04-23 14:04:52 +000011#include "QueryParser.h"
Peter Collingbourne8b1265b2013-11-08 00:08:23 +000012#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
22using namespace clang;
23using namespace clang::ast_matchers;
24using namespace clang::ast_matchers::dynamic;
25using namespace clang::query;
26using namespace clang::tooling;
27
Samuel Benzaquen1f6066c2014-04-23 14:04:52 +000028class QueryEngineTest : public ::testing::Test {
David Blaikie35013fa2014-04-25 15:21:43 +000029 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);
NAKAMURA Takumibe6b63b2014-04-24 10:58:17 +000034 }
Peter Collingbourne8b1265b2013-11-08 00:08:23 +000035
NAKAMURA Takumibe6b63b2014-04-24 10:58:17 +000036protected:
37 QueryEngineTest()
David Blaikie25286a52014-04-25 17:03:20 +000038 : S(mkASTUnit2(buildASTFromCode("void foo1(void) {}\nvoid foo2(void) {}",
39 "foo.cc"),
40 buildASTFromCode("void bar1(void) {}\nvoid bar2(void) {}",
41 "bar.cc"))),
David Blaikie35013fa2014-04-25 15:21:43 +000042 OS(Str) {}
NAKAMURA Takumibe6b63b2014-04-24 10:58:17 +000043
David Blaikie35013fa2014-04-25 15:21:43 +000044 std::unique_ptr<ASTUnit> ASTs[2];
NAKAMURA Takumibe6b63b2014-04-24 10:58:17 +000045 QuerySession S;
Peter Collingbourne8b1265b2013-11-08 00:08:23 +000046
47 std::string Str;
NAKAMURA Takumibe6b63b2014-04-24 10:58:17 +000048 llvm::raw_string_ostream OS;
Samuel Benzaquen1f6066c2014-04-23 14:04:52 +000049};
Peter Collingbourne8b1265b2013-11-08 00:08:23 +000050
Samuel Benzaquen1f6066c2014-04-23 14:04:52 +000051TEST_F(QueryEngineTest, Basic) {
Peter Collingbourne8b1265b2013-11-08 00:08:23 +000052 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(isArrow()).run(OS, S));
119
120 EXPECT_EQ("Not a valid top-level matcher.\n", OS.str());
121}
Samuel Benzaquen1f6066c2014-04-23 14:04:52 +0000122
123TEST_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}