1 //===---- QueryParserTest.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 "QueryParser.h" 11 #include "Query.h" 12 #include "QuerySession.h" 13 #include "llvm/LineEditor/LineEditor.h" 14 #include "gtest/gtest.h" 15 16 using namespace clang; 17 using namespace clang::query; 18 19 class QueryParserTest : public ::testing::Test { 20 protected: 21 QueryParserTest() : QS(llvm::ArrayRef<std::unique_ptr<ASTUnit>>()) {} 22 QueryRef parse(StringRef Code) { return QueryParser::parse(Code, QS); } 23 24 QuerySession QS; 25 }; 26 27 TEST_F(QueryParserTest, NoOp) { 28 QueryRef Q = parse(""); 29 EXPECT_TRUE(isa<NoOpQuery>(Q)); 30 31 Q = parse("\n"); 32 EXPECT_TRUE(isa<NoOpQuery>(Q)); 33 } 34 35 TEST_F(QueryParserTest, Invalid) { 36 QueryRef Q = parse("foo"); 37 ASSERT_TRUE(isa<InvalidQuery>(Q)); 38 EXPECT_EQ("unknown command: foo", cast<InvalidQuery>(Q)->ErrStr); 39 } 40 41 TEST_F(QueryParserTest, Help) { 42 QueryRef Q = parse("help"); 43 ASSERT_TRUE(isa<HelpQuery>(Q)); 44 45 Q = parse("help me"); 46 ASSERT_TRUE(isa<InvalidQuery>(Q)); 47 EXPECT_EQ("unexpected extra input: ' me'", cast<InvalidQuery>(Q)->ErrStr); 48 } 49 50 TEST_F(QueryParserTest, Quit) { 51 QueryRef Q = parse("quit"); 52 ASSERT_TRUE(isa<QuitQuery>(Q)); 53 54 Q = parse("q"); 55 ASSERT_TRUE(isa<QuitQuery>(Q)); 56 57 Q = parse("quit me"); 58 ASSERT_TRUE(isa<InvalidQuery>(Q)); 59 EXPECT_EQ("unexpected extra input: ' me'", cast<InvalidQuery>(Q)->ErrStr); 60 } 61 62 TEST_F(QueryParserTest, Set) { 63 QueryRef Q = parse("set"); 64 ASSERT_TRUE(isa<InvalidQuery>(Q)); 65 EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr); 66 67 Q = parse("set foo bar"); 68 ASSERT_TRUE(isa<InvalidQuery>(Q)); 69 EXPECT_EQ("unknown variable: 'foo'", cast<InvalidQuery>(Q)->ErrStr); 70 71 Q = parse("set output"); 72 ASSERT_TRUE(isa<InvalidQuery>(Q)); 73 EXPECT_EQ("expected 'diag', 'print' or 'dump', got ''", 74 cast<InvalidQuery>(Q)->ErrStr); 75 76 Q = parse("set bind-root true foo"); 77 ASSERT_TRUE(isa<InvalidQuery>(Q)); 78 EXPECT_EQ("unexpected extra input: ' foo'", cast<InvalidQuery>(Q)->ErrStr); 79 80 Q = parse("set output foo"); 81 ASSERT_TRUE(isa<InvalidQuery>(Q)); 82 EXPECT_EQ("expected 'diag', 'print' or 'dump', got 'foo'", 83 cast<InvalidQuery>(Q)->ErrStr); 84 85 Q = parse("set output dump"); 86 ASSERT_TRUE(isa<SetQuery<OutputKind> >(Q)); 87 EXPECT_EQ(&QuerySession::OutKind, cast<SetQuery<OutputKind> >(Q)->Var); 88 EXPECT_EQ(OK_Dump, cast<SetQuery<OutputKind> >(Q)->Value); 89 90 Q = parse("set bind-root foo"); 91 ASSERT_TRUE(isa<InvalidQuery>(Q)); 92 EXPECT_EQ("expected 'true' or 'false', got 'foo'", 93 cast<InvalidQuery>(Q)->ErrStr); 94 95 Q = parse("set bind-root true"); 96 ASSERT_TRUE(isa<SetQuery<bool> >(Q)); 97 EXPECT_EQ(&QuerySession::BindRoot, cast<SetQuery<bool> >(Q)->Var); 98 EXPECT_EQ(true, cast<SetQuery<bool> >(Q)->Value); 99 } 100 101 TEST_F(QueryParserTest, Match) { 102 QueryRef Q = parse("match decl()"); 103 ASSERT_TRUE(isa<MatchQuery>(Q)); 104 EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Decl>()); 105 106 Q = parse("m stmt()"); 107 ASSERT_TRUE(isa<MatchQuery>(Q)); 108 EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Stmt>()); 109 } 110 111 TEST_F(QueryParserTest, LetUnlet) { 112 QueryRef Q = parse("let foo decl()"); 113 ASSERT_TRUE(isa<LetQuery>(Q)); 114 EXPECT_EQ("foo", cast<LetQuery>(Q)->Name); 115 EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher()); 116 EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>()); 117 118 Q = parse("l foo decl()"); 119 ASSERT_TRUE(isa<LetQuery>(Q)); 120 EXPECT_EQ("foo", cast<LetQuery>(Q)->Name); 121 EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher()); 122 EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>()); 123 124 Q = parse("let bar \"str\""); 125 ASSERT_TRUE(isa<LetQuery>(Q)); 126 EXPECT_EQ("bar", cast<LetQuery>(Q)->Name); 127 EXPECT_TRUE(cast<LetQuery>(Q)->Value.isString()); 128 EXPECT_EQ("str", cast<LetQuery>(Q)->Value.getString()); 129 130 Q = parse("let"); 131 ASSERT_TRUE(isa<InvalidQuery>(Q)); 132 EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr); 133 134 Q = parse("unlet x"); 135 ASSERT_TRUE(isa<LetQuery>(Q)); 136 EXPECT_EQ("x", cast<LetQuery>(Q)->Name); 137 EXPECT_FALSE(cast<LetQuery>(Q)->Value.hasValue()); 138 139 Q = parse("unlet"); 140 ASSERT_TRUE(isa<InvalidQuery>(Q)); 141 EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr); 142 143 Q = parse("unlet x bad_data"); 144 ASSERT_TRUE(isa<InvalidQuery>(Q)); 145 EXPECT_EQ("unexpected extra input: ' bad_data'", 146 cast<InvalidQuery>(Q)->ErrStr); 147 } 148 149 TEST_F(QueryParserTest, Comment) { 150 QueryRef Q = parse("# let foo decl()"); 151 ASSERT_TRUE(isa<NoOpQuery>(Q)); 152 153 Q = parse("let foo decl() # creates a decl() matcher called foo"); 154 ASSERT_TRUE(isa<LetQuery>(Q)); 155 156 Q = parse("set bind-root false # reduce noise"); 157 ASSERT_TRUE(isa<SetQuery<bool>>(Q)); 158 } 159 160 TEST_F(QueryParserTest, Complete) { 161 std::vector<llvm::LineEditor::Completion> Comps = 162 QueryParser::complete("", 0, QS); 163 ASSERT_EQ(6u, Comps.size()); 164 EXPECT_EQ("help ", Comps[0].TypedText); 165 EXPECT_EQ("help", Comps[0].DisplayText); 166 EXPECT_EQ("let ", Comps[1].TypedText); 167 EXPECT_EQ("let", Comps[1].DisplayText); 168 EXPECT_EQ("match ", Comps[2].TypedText); 169 EXPECT_EQ("match", Comps[2].DisplayText); 170 EXPECT_EQ("quit ", Comps[3].TypedText); 171 EXPECT_EQ("quit", Comps[3].DisplayText); 172 EXPECT_EQ("set ", Comps[4].TypedText); 173 EXPECT_EQ("set", Comps[4].DisplayText); 174 EXPECT_EQ("unlet ", Comps[5].TypedText); 175 EXPECT_EQ("unlet", Comps[5].DisplayText); 176 177 Comps = QueryParser::complete("set o", 5, QS); 178 ASSERT_EQ(1u, Comps.size()); 179 EXPECT_EQ("utput ", Comps[0].TypedText); 180 EXPECT_EQ("output", Comps[0].DisplayText); 181 182 Comps = QueryParser::complete("match while", 11, QS); 183 ASSERT_EQ(1u, Comps.size()); 184 EXPECT_EQ("Stmt(", Comps[0].TypedText); 185 EXPECT_EQ("Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)", 186 Comps[0].DisplayText); 187 188 Comps = QueryParser::complete("m", 1, QS); 189 ASSERT_EQ(1u, Comps.size()); 190 EXPECT_EQ("atch ", Comps[0].TypedText); 191 EXPECT_EQ("match", Comps[0].DisplayText); 192 193 Comps = QueryParser::complete("l", 1, QS); 194 ASSERT_EQ(1u, Comps.size()); 195 EXPECT_EQ("et ", Comps[0].TypedText); 196 EXPECT_EQ("let", Comps[0].DisplayText); 197 } 198