blob: 231343cd78ba5b4d769ccadd68e7dcd1bdc6bd4c [file] [log] [blame]
Kirill Bobyrev5abe4782018-09-10 08:23:53 +00001//===-- DexTests.cpp ---------------------------------*- C++ -*-----------===//
Kirill Bobyrev5e82f052018-07-25 10:34:57 +00002//
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
Kirill Bobyrev19a94612018-09-06 12:54:43 +000010#include "FuzzyMatch.h"
11#include "TestFS.h"
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000012#include "TestIndex.h"
13#include "index/Index.h"
14#include "index/Merge.h"
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000015#include "index/dex/Dex.h"
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000016#include "index/dex/Iterator.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000017#include "index/dex/Token.h"
18#include "index/dex/Trigram.h"
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000019#include "llvm/Support/ScopedPrinter.h"
20#include "llvm/Support/raw_ostream.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000021#include "gmock/gmock.h"
22#include "gtest/gtest.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000023#include <string>
24#include <vector>
25
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000026using ::testing::ElementsAre;
27using ::testing::UnorderedElementsAre;
Sam McCall9c7624e2018-09-03 14:37:43 +000028using namespace llvm;
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000029
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000030namespace clang {
31namespace clangd {
32namespace dex {
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000033namespace {
Kirill Bobyrevbea258d2018-07-26 10:42:31 +000034
Kirill Bobyrev19a94612018-09-06 12:54:43 +000035std::vector<std::string> URISchemes = {"unittest"};
36
37//===----------------------------------------------------------------------===//
38// Query iterator tests.
39//===----------------------------------------------------------------------===//
40
Kirill Bobyreva98961b2018-08-24 11:25:43 +000041std::vector<DocID> consumeIDs(Iterator &It) {
42 auto IDAndScore = consume(It);
Kirill Bobyrev7413e982018-08-22 13:44:15 +000043 std::vector<DocID> IDs(IDAndScore.size());
44 for (size_t I = 0; I < IDAndScore.size(); ++I)
45 IDs[I] = IDAndScore[I].first;
46 return IDs;
47}
48
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000049TEST(DexIterators, DocumentIterator) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +000050 const PostingList L({4, 7, 8, 20, 42, 100});
51 auto DocIterator = L.iterator();
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000052
53 EXPECT_EQ(DocIterator->peek(), 4U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000054 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000055
56 DocIterator->advance();
57 EXPECT_EQ(DocIterator->peek(), 7U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000058 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000059
60 DocIterator->advanceTo(20);
61 EXPECT_EQ(DocIterator->peek(), 20U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000062 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000063
64 DocIterator->advanceTo(65);
65 EXPECT_EQ(DocIterator->peek(), 100U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000066 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000067
68 DocIterator->advanceTo(420);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000069 EXPECT_TRUE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000070}
71
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000072TEST(DexIterators, AndTwoLists) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +000073 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
74 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000075
Kirill Bobyrev249c5862018-09-13 17:11:03 +000076 auto And = createAnd(L1.iterator(), L0.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000077
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000078 EXPECT_FALSE(And->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +000079 EXPECT_THAT(consumeIDs(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000080
Kirill Bobyrev249c5862018-09-13 17:11:03 +000081 And = createAnd(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000082
83 And->advanceTo(0);
84 EXPECT_EQ(And->peek(), 0U);
85 And->advanceTo(5);
86 EXPECT_EQ(And->peek(), 7U);
87 And->advanceTo(10);
88 EXPECT_EQ(And->peek(), 10U);
89 And->advanceTo(42);
90 EXPECT_EQ(And->peek(), 320U);
91 And->advanceTo(8999);
92 EXPECT_EQ(And->peek(), 9000U);
93 And->advanceTo(9001);
94}
95
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000096TEST(DexIterators, AndThreeLists) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +000097 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
98 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
99 const PostingList L2({1, 4, 7, 11, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000100
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000101 auto And = createAnd(L0.iterator(), L1.iterator(), L2.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000102 EXPECT_EQ(And->peek(), 7U);
103 And->advanceTo(300);
104 EXPECT_EQ(And->peek(), 320U);
105 And->advanceTo(100000);
106
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000107 EXPECT_TRUE(And->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000108}
109
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000110TEST(DexIterators, OrTwoLists) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000111 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
112 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000113
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000114 auto Or = createOr(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000115
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000116 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000117 EXPECT_EQ(Or->peek(), 0U);
118 Or->advance();
119 EXPECT_EQ(Or->peek(), 4U);
120 Or->advance();
121 EXPECT_EQ(Or->peek(), 5U);
122 Or->advance();
123 EXPECT_EQ(Or->peek(), 7U);
124 Or->advance();
125 EXPECT_EQ(Or->peek(), 10U);
126 Or->advance();
127 EXPECT_EQ(Or->peek(), 30U);
128 Or->advanceTo(42);
129 EXPECT_EQ(Or->peek(), 42U);
130 Or->advanceTo(300);
131 EXPECT_EQ(Or->peek(), 320U);
132 Or->advanceTo(9000);
133 EXPECT_EQ(Or->peek(), 9000U);
134 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000135 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000136
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000137 Or = createOr(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000138
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000139 EXPECT_THAT(consumeIDs(*Or),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000140 ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
141}
142
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000143TEST(DexIterators, OrThreeLists) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000144 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
145 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
146 const PostingList L2({1, 4, 7, 11, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000147
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000148 auto Or = createOr(L0.iterator(), L1.iterator(), L2.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000149
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000150 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000151 EXPECT_EQ(Or->peek(), 0U);
152
153 Or->advance();
154 EXPECT_EQ(Or->peek(), 1U);
155
156 Or->advance();
157 EXPECT_EQ(Or->peek(), 4U);
158
159 Or->advanceTo(7);
160
161 Or->advanceTo(59);
162 EXPECT_EQ(Or->peek(), 60U);
163
164 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000165 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000166}
167
168// FIXME(kbobyrev): The testcase below is similar to what is expected in real
169// queries. It should be updated once new iterators (such as boosting, limiting,
170// etc iterators) appear. However, it is not exhaustive and it would be
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000171// beneficial to implement automatic generation (e.g. fuzzing) of query trees
172// for more comprehensive testing.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000173TEST(DexIterators, QueryTree) {
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000174 //
175 // +-----------------+
176 // |And Iterator:1, 5|
177 // +--------+--------+
178 // |
179 // |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000180 // +-------------+----------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000181 // | |
182 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000183 // +----------v----------+ +----------v------------+
184 // |And Iterator: 1, 5, 9| |Or Iterator: 0, 1, 3, 5|
185 // +----------+----------+ +----------+------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000186 // | |
Kirill Bobyrev6c2f5bd2018-09-25 11:54:51 +0000187 // +------+-----+ ------------+
188 // | | | |
189 // +-------v-----+ +----+---+ +---v----+ +----v---+
190 // |1, 3, 5, 8, 9| |Boost: 2| |Boost: 3| |Boost: 4|
191 // +-------------+ +----+---+ +---+----+ +----+---+
192 // | | |
193 // +----v-----+ +-v--+ +---v---+
194 // |1, 5, 7, 9| |1, 5| |0, 3, 5|
195 // +----------+ +----+ +-------+
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000196 //
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000197 const PostingList L0({1, 3, 5, 8, 9});
198 const PostingList L1({1, 5, 7, 9});
Kirill Bobyrev6c2f5bd2018-09-25 11:54:51 +0000199 const PostingList L2({1, 5});
200 const PostingList L3({0, 3, 5});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000201
202 // Root of the query tree: [1, 5]
203 auto Root = createAnd(
204 // Lower And Iterator: [1, 5, 9]
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000205 createAnd(L0.iterator(), createBoost(L1.iterator(), 2U)),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000206 // Lower Or Iterator: [0, 1, 5]
Kirill Bobyrev6c2f5bd2018-09-25 11:54:51 +0000207 createOr(createBoost(L2.iterator(), 3U), createBoost(L3.iterator(), 4U)));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000208
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000209 EXPECT_FALSE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000210 EXPECT_EQ(Root->peek(), 1U);
211 Root->advanceTo(0);
212 // Advance multiple times. Shouldn't do anything.
213 Root->advanceTo(1);
214 Root->advanceTo(0);
215 EXPECT_EQ(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000216 auto ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000217 EXPECT_THAT(ElementBoost, 6);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000218 Root->advance();
219 EXPECT_EQ(Root->peek(), 5U);
220 Root->advanceTo(5);
221 EXPECT_EQ(Root->peek(), 5U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000222 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000223 EXPECT_THAT(ElementBoost, 8);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000224 Root->advanceTo(9000);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000225 EXPECT_TRUE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000226}
227
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000228TEST(DexIterators, StringRepresentation) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000229 const PostingList L0({4, 7, 8, 20, 42, 100});
230 const PostingList L1({1, 3, 5, 8, 9});
231 const PostingList L2({1, 5, 7, 9});
232 const PostingList L3({0, 5});
233 const PostingList L4({0, 1, 5});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000234
Kirill Bobyrev6c2f5bd2018-09-25 11:54:51 +0000235 EXPECT_EQ(llvm::to_string(*(L0.iterator())), "[4 ...]");
236 auto It = L0.iterator();
237 It->advanceTo(19);
238 EXPECT_EQ(llvm::to_string(*It), "[... 20 ...]");
239 It->advanceTo(9000);
240 EXPECT_EQ(llvm::to_string(*It), "[... END]");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000241}
242
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000243TEST(DexIterators, Limit) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000244 const PostingList L0({3, 6, 7, 20, 42, 100});
245 const PostingList L1({1, 3, 5, 6, 7, 30, 100});
246 const PostingList L2({0, 3, 5, 7, 8, 100});
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000247
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000248 auto DocIterator = createLimit(L0.iterator(), 42);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000249 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7, 20, 42, 100));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000250
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000251 DocIterator = createLimit(L0.iterator(), 3);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000252 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000253
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000254 DocIterator = createLimit(L0.iterator(), 0);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000255 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre());
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000256
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000257 auto AndIterator = createAnd(
258 createLimit(createTrue(9000), 343), createLimit(L0.iterator(), 2),
259 createLimit(L1.iterator(), 3), createLimit(L2.iterator(), 42));
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000260 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(3, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000261}
262
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000263TEST(DexIterators, True) {
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000264 auto TrueIterator = createTrue(0U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000265 EXPECT_TRUE(TrueIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000266 EXPECT_THAT(consumeIDs(*TrueIterator), ElementsAre());
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000267
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000268 const PostingList L0({1, 2, 5, 7});
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000269 TrueIterator = createTrue(7U);
270 EXPECT_THAT(TrueIterator->peek(), 0);
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000271 auto AndIterator = createAnd(L0.iterator(), move(TrueIterator));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000272 EXPECT_FALSE(AndIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000273 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(1, 2, 5));
274}
275
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000276TEST(DexIterators, Boost) {
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000277 auto BoostIterator = createBoost(createTrue(5U), 42U);
278 EXPECT_FALSE(BoostIterator->reachedEnd());
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000279 auto ElementBoost = BoostIterator->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000280 EXPECT_THAT(ElementBoost, 42U);
281
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000282 const PostingList L0({2, 4});
283 const PostingList L1({1, 4});
284 auto Root = createOr(createTrue(5U), createBoost(L0.iterator(), 2U),
285 createBoost(L1.iterator(), 3U));
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000286
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000287 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000288 EXPECT_THAT(ElementBoost, Iterator::DEFAULT_BOOST_SCORE);
289 Root->advance();
290 EXPECT_THAT(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000291 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000292 EXPECT_THAT(ElementBoost, 3);
293
294 Root->advance();
295 EXPECT_THAT(Root->peek(), 2U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000296 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000297 EXPECT_THAT(ElementBoost, 2);
298
299 Root->advanceTo(4);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000300 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000301 EXPECT_THAT(ElementBoost, 3);
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000302}
303
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000304//===----------------------------------------------------------------------===//
305// Search token tests.
306//===----------------------------------------------------------------------===//
307
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000308testing::Matcher<std::vector<Token>>
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000309tokensAre(std::initializer_list<std::string> Strings, Token::Kind Kind) {
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000310 std::vector<Token> Tokens;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000311 for (const auto &TokenData : Strings) {
312 Tokens.push_back(Token(Kind, TokenData));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000313 }
314 return testing::UnorderedElementsAreArray(Tokens);
315}
316
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000317testing::Matcher<std::vector<Token>>
318trigramsAre(std::initializer_list<std::string> Trigrams) {
319 return tokensAre(Trigrams, Token::Kind::Trigram);
320}
321
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000322TEST(DexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000323 EXPECT_THAT(generateIdentifierTrigrams("X86"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000324 trigramsAre({"x86", "x$$", "x8$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000325
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000326 EXPECT_THAT(generateIdentifierTrigrams("nl"), trigramsAre({"nl$", "n$$"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000327
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000328 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000329
330 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000331 trigramsAre({"c$$", "cl$", "cla", "lan", "ang", "ngd"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000332
333 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000334 trigramsAre({"a$$", "abc", "abd", "ade", "bcd", "bde", "cde",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000335 "def", "ab$", "ad$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000336
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000337 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
338 trigramsAre({"a$$", "a_$", "a_b", "abc", "abd", "acd", "ace",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000339 "bcd", "bce", "bde", "cde", "ab$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000340
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000341 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
342 trigramsAre({"u$$", "uni", "unp", "upt", "niq", "nip", "npt",
343 "iqu", "iqp", "ipt", "que", "qup", "qpt", "uep",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000344 "ept", "ptr", "un$", "up$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000345
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000346 EXPECT_THAT(
347 generateIdentifierTrigrams("TUDecl"),
348 trigramsAre({"t$$", "tud", "tde", "ude", "dec", "ecl", "tu$", "td$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000349
350 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000351 trigramsAre({"i$$", "iso", "iok", "sok", "is$", "io$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000352
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000353 EXPECT_THAT(
354 generateIdentifierTrigrams("abc_defGhij__klm"),
355 trigramsAre({"a$$", "abc", "abd", "abg", "ade", "adg", "adk", "agh",
356 "agk", "bcd", "bcg", "bde", "bdg", "bdk", "bgh", "bgk",
357 "cde", "cdg", "cdk", "cgh", "cgk", "def", "deg", "dek",
358 "dgh", "dgk", "dkl", "efg", "efk", "egh", "egk", "ekl",
359 "fgh", "fgk", "fkl", "ghi", "ghk", "gkl", "hij", "hik",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000360 "hkl", "ijk", "ikl", "jkl", "klm", "ab$", "ad$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000361}
362
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000363TEST(DexTrigrams, QueryTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000364 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c$$"}));
365 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl$"}));
366 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000367
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000368 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_$$"}));
369 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__$"}));
370 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({"___"}));
371
372 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000373
374 EXPECT_THAT(generateQueryTrigrams("clangd"),
375 trigramsAre({"cla", "lan", "ang", "ngd"}));
376
377 EXPECT_THAT(generateQueryTrigrams("abc_def"),
378 trigramsAre({"abc", "bcd", "cde", "def"}));
379
380 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
381 trigramsAre({"abc", "bcd", "cde"}));
382
383 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
384 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
385
386 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
387 trigramsAre({"tud", "ude", "dec", "ecl"}));
388
389 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
390
391 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
392 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
393 "hij", "ijk", "jkl", "klm"}));
394}
395
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000396TEST(DexSearchTokens, SymbolPath) {
397 EXPECT_THAT(generateProximityURIs(
398 "unittest:///clang-tools-extra/clangd/index/Token.h"),
399 ElementsAre("unittest:///clang-tools-extra/clangd/index/Token.h",
400 "unittest:///clang-tools-extra/clangd/index",
401 "unittest:///clang-tools-extra/clangd",
402 "unittest:///clang-tools-extra", "unittest:///"));
403
404 EXPECT_THAT(generateProximityURIs("unittest:///a/b/c.h"),
405 ElementsAre("unittest:///a/b/c.h", "unittest:///a/b",
406 "unittest:///a", "unittest:///"));
407}
408
409//===----------------------------------------------------------------------===//
410// Index tests.
411//===----------------------------------------------------------------------===//
412
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000413TEST(Dex, Lookup) {
414 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000415 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
416 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000417 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000418 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000419 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000420 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000421}
422
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000423TEST(Dex, FuzzyFind) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000424 auto Index =
425 Dex::build(generateSymbols({"ns::ABC", "ns::BCD", "::ABC",
426 "ns::nested::ABC", "other::ABC", "other::A"}),
427 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000428 FuzzyFindRequest Req;
429 Req.Query = "ABC";
430 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000431 EXPECT_THAT(match(*Index, Req), UnorderedElementsAre("ns::ABC"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000432 Req.Scopes = {"ns::", "ns::nested::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000433 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000434 UnorderedElementsAre("ns::ABC", "ns::nested::ABC"));
435 Req.Query = "A";
436 Req.Scopes = {"other::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000437 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000438 UnorderedElementsAre("other::A", "other::ABC"));
439 Req.Query = "";
440 Req.Scopes = {};
Sam McCall9c7624e2018-09-03 14:37:43 +0000441 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000442 UnorderedElementsAre("ns::ABC", "ns::BCD", "::ABC",
443 "ns::nested::ABC", "other::ABC",
444 "other::A"));
445}
446
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000447// FIXME(kbobyrev): This test is different for Dex and MemIndex: while
448// MemIndex manages response deduplication, Dex simply returns all matched
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000449// symbols which means there might be equivalent symbols in the response.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000450// Before drop-in replacement of MemIndex with Dex happens, FileIndex
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000451// should handle deduplication instead.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000452TEST(DexTest, DexDeduplicate) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000453 std::vector<Symbol> Symbols = {symbol("1"), symbol("2"), symbol("3"),
454 symbol("2") /* duplicate */};
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000455 FuzzyFindRequest Req;
Sam McCall9c7624e2018-09-03 14:37:43 +0000456 Req.Query = "2";
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000457 Dex I(Symbols, URISchemes);
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000458 EXPECT_FALSE(Req.Limit);
Sam McCall9c7624e2018-09-03 14:37:43 +0000459 EXPECT_THAT(match(I, Req), ElementsAre("2", "2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000460}
461
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000462TEST(DexTest, DexLimitedNumMatches) {
463 auto I = Dex::build(generateNumSymbols(0, 100), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000464 FuzzyFindRequest Req;
465 Req.Query = "5";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000466 Req.Limit = 3;
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000467 bool Incomplete;
Sam McCall9c7624e2018-09-03 14:37:43 +0000468 auto Matches = match(*I, Req, &Incomplete);
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000469 EXPECT_TRUE(Req.Limit);
470 EXPECT_EQ(Matches.size(), *Req.Limit);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000471 EXPECT_TRUE(Incomplete);
472}
473
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000474TEST(DexTest, FuzzyMatch) {
475 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000476 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}),
477 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000478 FuzzyFindRequest Req;
479 Req.Query = "lol";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000480 Req.Limit = 2;
Sam McCall9c7624e2018-09-03 14:37:43 +0000481 EXPECT_THAT(match(*I, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000482 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
483}
484
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000485TEST(DexTest, MatchQualifiedNamesWithoutSpecificScope) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000486 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000487 FuzzyFindRequest Req;
488 Req.Query = "y";
Sam McCall9c7624e2018-09-03 14:37:43 +0000489 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000490}
491
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000492TEST(DexTest, MatchQualifiedNamesWithGlobalScope) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000493 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000494 FuzzyFindRequest Req;
495 Req.Query = "y";
496 Req.Scopes = {""};
Sam McCall9c7624e2018-09-03 14:37:43 +0000497 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000498}
499
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000500TEST(DexTest, MatchQualifiedNamesWithOneScope) {
501 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000502 generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000503 FuzzyFindRequest Req;
504 Req.Query = "y";
505 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000506 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000507}
508
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000509TEST(DexTest, MatchQualifiedNamesWithMultipleScopes) {
510 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000511 generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000512 FuzzyFindRequest Req;
513 Req.Query = "y";
514 Req.Scopes = {"a::", "b::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000515 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000516}
517
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000518TEST(DexTest, NoMatchNestedScopes) {
519 auto I = Dex::build(generateSymbols({"a::y1", "a::b::y2"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000520 FuzzyFindRequest Req;
521 Req.Query = "y";
522 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000523 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000524}
525
Eric Liu670c1472018-09-27 18:46:00 +0000526TEST(DexTest, WildcardScope) {
527 auto I =
528 Dex::build(generateSymbols({"a::y1", "a::b::y2", "c::y3"}), URISchemes);
529 FuzzyFindRequest Req;
530 Req.Query = "y";
531 Req.Scopes = {"a::"};
532 Req.AnyScope = true;
533 EXPECT_THAT(match(*I, Req),
534 UnorderedElementsAre("a::y1", "a::b::y2", "c::y3"));
535}
536
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000537TEST(DexTest, IgnoreCases) {
538 auto I = Dex::build(generateSymbols({"ns::ABC", "ns::abc"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000539 FuzzyFindRequest Req;
540 Req.Query = "AB";
541 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000542 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000543}
544
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000545TEST(DexTest, Lookup) {
546 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000547 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
548 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000549 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000550 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000551 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000552 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000553}
554
Kirill Bobyrev94af0612018-09-24 08:45:18 +0000555TEST(DexTest, SymbolIndexOptionsFilter) {
556 auto CodeCompletionSymbol = symbol("Completion");
557 auto NonCodeCompletionSymbol = symbol("NoCompletion");
558 CodeCompletionSymbol.Flags = Symbol::SymbolFlag::IndexedForCodeCompletion;
559 NonCodeCompletionSymbol.Flags = Symbol::SymbolFlag::None;
560 std::vector<Symbol> Symbols{CodeCompletionSymbol, NonCodeCompletionSymbol};
561 Dex I(Symbols, URISchemes);
562 FuzzyFindRequest Req;
563 Req.RestrictForCodeCompletion = false;
564 EXPECT_THAT(match(I, Req), ElementsAre("Completion", "NoCompletion"));
565 Req.RestrictForCodeCompletion = true;
566 EXPECT_THAT(match(I, Req), ElementsAre("Completion"));
567}
568
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000569TEST(DexTest, ProximityPathsBoosting) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000570 auto RootSymbol = symbol("root::abc");
571 RootSymbol.CanonicalDeclaration.FileURI = "unittest:///file.h";
572 auto CloseSymbol = symbol("close::abc");
573 CloseSymbol.CanonicalDeclaration.FileURI = "unittest:///a/b/c/d/e/f/file.h";
574
575 std::vector<Symbol> Symbols{CloseSymbol, RootSymbol};
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000576 Dex I(Symbols, URISchemes);
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000577
578 FuzzyFindRequest Req;
579 Req.Query = "abc";
580 // The best candidate can change depending on the proximity paths.
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000581 Req.Limit = 1;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000582
583 // FuzzyFind request comes from the file which is far from the root: expect
584 // CloseSymbol to come out.
585 Req.ProximityPaths = {testPath("a/b/c/d/e/f/file.h")};
586 EXPECT_THAT(match(I, Req), ElementsAre("close::abc"));
587
588 // FuzzyFind request comes from the file which is close to the root: expect
589 // RootSymbol to come out.
590 Req.ProximityPaths = {testPath("file.h")};
591 EXPECT_THAT(match(I, Req), ElementsAre("root::abc"));
592}
593
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000594} // namespace
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000595} // namespace dex
596} // namespace clangd
597} // namespace clang