blob: ca20e5a8b235f3b42d8254b7289f20b734a26976 [file] [log] [blame]
Kirill Bobyrev5e82f052018-07-25 10:34:57 +00001//===-- DexIndexTests.cpp ----------------------------*- C++ -*-----------===//
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
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000010#include "TestIndex.h"
11#include "index/Index.h"
12#include "index/Merge.h"
13#include "index/dex/DexIndex.h"
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000014#include "index/dex/Iterator.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000015#include "index/dex/Token.h"
16#include "index/dex/Trigram.h"
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000017#include "llvm/Support/ScopedPrinter.h"
18#include "llvm/Support/raw_ostream.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000019#include "gmock/gmock.h"
20#include "gtest/gtest.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000021#include <string>
22#include <vector>
23
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000024using ::testing::ElementsAre;
25using ::testing::UnorderedElementsAre;
26
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000027namespace clang {
28namespace clangd {
29namespace dex {
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000030namespace {
Kirill Bobyrevbea258d2018-07-26 10:42:31 +000031
Kirill Bobyrev7413e982018-08-22 13:44:15 +000032std::vector<DocID>
33consumeIDs(Iterator &It, size_t Limit = std::numeric_limits<size_t>::max()) {
34 auto IDAndScore = consume(It, Limit);
35 std::vector<DocID> IDs(IDAndScore.size());
36 for (size_t I = 0; I < IDAndScore.size(); ++I)
37 IDs[I] = IDAndScore[I].first;
38 return IDs;
39}
40
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000041TEST(DexIndexIterators, DocumentIterator) {
42 const PostingList L = {4, 7, 8, 20, 42, 100};
43 auto DocIterator = create(L);
44
45 EXPECT_EQ(DocIterator->peek(), 4U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000046 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000047
48 DocIterator->advance();
49 EXPECT_EQ(DocIterator->peek(), 7U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000050 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000051
52 DocIterator->advanceTo(20);
53 EXPECT_EQ(DocIterator->peek(), 20U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000054 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000055
56 DocIterator->advanceTo(65);
57 EXPECT_EQ(DocIterator->peek(), 100U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000058 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000059
60 DocIterator->advanceTo(420);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000061 EXPECT_TRUE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000062}
63
64TEST(DexIndexIterators, AndWithEmpty) {
65 const PostingList L0;
66 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
67
68 auto AndEmpty = createAnd(create(L0));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000069 EXPECT_TRUE(AndEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000070
71 auto AndWithEmpty = createAnd(create(L0), create(L1));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000072 EXPECT_TRUE(AndWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000073
Kirill Bobyrev7413e982018-08-22 13:44:15 +000074 EXPECT_THAT(consumeIDs(*AndWithEmpty), ElementsAre());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000075}
76
77TEST(DexIndexIterators, AndTwoLists) {
78 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
79 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
80
81 auto And = createAnd(create(L1), create(L0));
82
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000083 EXPECT_FALSE(And->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +000084 EXPECT_THAT(consumeIDs(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000085
86 And = createAnd(create(L0), create(L1));
87
88 And->advanceTo(0);
89 EXPECT_EQ(And->peek(), 0U);
90 And->advanceTo(5);
91 EXPECT_EQ(And->peek(), 7U);
92 And->advanceTo(10);
93 EXPECT_EQ(And->peek(), 10U);
94 And->advanceTo(42);
95 EXPECT_EQ(And->peek(), 320U);
96 And->advanceTo(8999);
97 EXPECT_EQ(And->peek(), 9000U);
98 And->advanceTo(9001);
99}
100
101TEST(DexIndexIterators, AndThreeLists) {
102 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
103 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
104 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
105
106 auto And = createAnd(create(L0), create(L1), create(L2));
107 EXPECT_EQ(And->peek(), 7U);
108 And->advanceTo(300);
109 EXPECT_EQ(And->peek(), 320U);
110 And->advanceTo(100000);
111
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000112 EXPECT_TRUE(And->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000113}
114
115TEST(DexIndexIterators, OrWithEmpty) {
116 const PostingList L0;
117 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
118
119 auto OrEmpty = createOr(create(L0));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000120 EXPECT_TRUE(OrEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000121
122 auto OrWithEmpty = createOr(create(L0), create(L1));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000123 EXPECT_FALSE(OrWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000124
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000125 EXPECT_THAT(consumeIDs(*OrWithEmpty),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000126 ElementsAre(0U, 5U, 7U, 10U, 42U, 320U, 9000U));
127}
128
129TEST(DexIndexIterators, OrTwoLists) {
130 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
131 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
132
133 auto Or = createOr(create(L0), create(L1));
134
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000135 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000136 EXPECT_EQ(Or->peek(), 0U);
137 Or->advance();
138 EXPECT_EQ(Or->peek(), 4U);
139 Or->advance();
140 EXPECT_EQ(Or->peek(), 5U);
141 Or->advance();
142 EXPECT_EQ(Or->peek(), 7U);
143 Or->advance();
144 EXPECT_EQ(Or->peek(), 10U);
145 Or->advance();
146 EXPECT_EQ(Or->peek(), 30U);
147 Or->advanceTo(42);
148 EXPECT_EQ(Or->peek(), 42U);
149 Or->advanceTo(300);
150 EXPECT_EQ(Or->peek(), 320U);
151 Or->advanceTo(9000);
152 EXPECT_EQ(Or->peek(), 9000U);
153 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000154 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000155
156 Or = createOr(create(L0), create(L1));
157
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000158 EXPECT_THAT(consumeIDs(*Or),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000159 ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
160}
161
162TEST(DexIndexIterators, OrThreeLists) {
163 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
164 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
165 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
166
167 auto Or = createOr(create(L0), create(L1), create(L2));
168
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000169 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000170 EXPECT_EQ(Or->peek(), 0U);
171
172 Or->advance();
173 EXPECT_EQ(Or->peek(), 1U);
174
175 Or->advance();
176 EXPECT_EQ(Or->peek(), 4U);
177
178 Or->advanceTo(7);
179
180 Or->advanceTo(59);
181 EXPECT_EQ(Or->peek(), 60U);
182
183 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000184 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000185}
186
187// FIXME(kbobyrev): The testcase below is similar to what is expected in real
188// queries. It should be updated once new iterators (such as boosting, limiting,
189// etc iterators) appear. However, it is not exhaustive and it would be
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000190// beneficial to implement automatic generation (e.g. fuzzing) of query trees
191// for more comprehensive testing.
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000192TEST(DexIndexIterators, QueryTree) {
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000193 //
194 // +-----------------+
195 // |And Iterator:1, 5|
196 // +--------+--------+
197 // |
198 // |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000199 // +-------------+----------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000200 // | |
201 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000202 // +----------v----------+ +----------v------------+
203 // |And Iterator: 1, 5, 9| |Or Iterator: 0, 1, 3, 5|
204 // +----------+----------+ +----------+------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000205 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000206 // +------+-----+ +---------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000207 // | | | | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000208 // +-------v-----+ +----+---+ +--v--+ +---v----+ +----v---+
209 // |1, 3, 5, 8, 9| |Boost: 2| |Empty| |Boost: 3| |Boost: 4|
210 // +-------------+ +----+---+ +-----+ +---+----+ +----+---+
211 // | | |
212 // +----v-----+ +-v--+ +---v---+
213 // |1, 5, 7, 9| |1, 5| |0, 3, 5|
214 // +----------+ +----+ +-------+
215 //
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000216 const PostingList L0 = {1, 3, 5, 8, 9};
217 const PostingList L1 = {1, 5, 7, 9};
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000218 const PostingList L3;
219 const PostingList L4 = {1, 5};
220 const PostingList L5 = {0, 3, 5};
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000221
222 // Root of the query tree: [1, 5]
223 auto Root = createAnd(
224 // Lower And Iterator: [1, 5, 9]
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000225 createAnd(create(L0), createBoost(create(L1), 2U)),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000226 // Lower Or Iterator: [0, 1, 5]
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000227 createOr(create(L3), createBoost(create(L4), 3U),
228 createBoost(create(L5), 4U)));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000229
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000230 EXPECT_FALSE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000231 EXPECT_EQ(Root->peek(), 1U);
232 Root->advanceTo(0);
233 // Advance multiple times. Shouldn't do anything.
234 Root->advanceTo(1);
235 Root->advanceTo(0);
236 EXPECT_EQ(Root->peek(), 1U);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000237 auto ElementBoost = Root->consume(Root->peek());
238 EXPECT_THAT(ElementBoost, 6);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000239 Root->advance();
240 EXPECT_EQ(Root->peek(), 5U);
241 Root->advanceTo(5);
242 EXPECT_EQ(Root->peek(), 5U);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000243 ElementBoost = Root->consume(Root->peek());
244 EXPECT_THAT(ElementBoost, 8);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000245 Root->advanceTo(9000);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000246 EXPECT_TRUE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000247}
248
249TEST(DexIndexIterators, StringRepresentation) {
250 const PostingList L0 = {4, 7, 8, 20, 42, 100};
251 const PostingList L1 = {1, 3, 5, 8, 9};
252 const PostingList L2 = {1, 5, 7, 9};
253 const PostingList L3 = {0, 5};
254 const PostingList L4 = {0, 1, 5};
255 const PostingList L5;
256
Kirill Bobyrev51534ab2018-08-16 13:19:43 +0000257 EXPECT_EQ(llvm::to_string(*(create(L0))), "[{4}, 7, 8, 20, 42, 100, END]");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000258
259 auto Nested = createAnd(createAnd(create(L1), create(L2)),
260 createOr(create(L3), create(L4), create(L5)));
261
262 EXPECT_EQ(llvm::to_string(*Nested),
Kirill Bobyrev51534ab2018-08-16 13:19:43 +0000263 "(& (& [{1}, 3, 5, 8, 9, END] [{1}, 5, 7, 9, END]) (| [0, {5}, "
264 "END] [0, {1}, 5, END] [{END}]))");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000265}
266
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000267TEST(DexIndexIterators, Limit) {
268 const PostingList L0 = {4, 7, 8, 20, 42, 100};
269 const PostingList L1 = {1, 3, 5, 8, 9};
270 const PostingList L2 = {1, 5, 7, 9};
271 const PostingList L3 = {0, 5};
272 const PostingList L4 = {0, 1, 5};
273 const PostingList L5;
274
275 auto DocIterator = create(L0);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000276 EXPECT_THAT(consumeIDs(*DocIterator, 42), ElementsAre(4, 7, 8, 20, 42, 100));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000277
278 DocIterator = create(L0);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000279 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(4, 7, 8, 20, 42, 100));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000280
281 DocIterator = create(L0);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000282 EXPECT_THAT(consumeIDs(*DocIterator, 3), ElementsAre(4, 7, 8));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000283
284 DocIterator = create(L0);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000285 EXPECT_THAT(consumeIDs(*DocIterator, 0), ElementsAre());
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000286}
287
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000288TEST(DexIndexIterators, True) {
289 auto TrueIterator = createTrue(0U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000290 EXPECT_TRUE(TrueIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000291 EXPECT_THAT(consumeIDs(*TrueIterator), ElementsAre());
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000292
293 PostingList L0 = {1, 2, 5, 7};
294 TrueIterator = createTrue(7U);
295 EXPECT_THAT(TrueIterator->peek(), 0);
296 auto AndIterator = createAnd(create(L0), move(TrueIterator));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000297 EXPECT_FALSE(AndIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000298 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(1, 2, 5));
299}
300
301TEST(DexIndexIterators, Boost) {
302 auto BoostIterator = createBoost(createTrue(5U), 42U);
303 EXPECT_FALSE(BoostIterator->reachedEnd());
304 auto ElementBoost = BoostIterator->consume(BoostIterator->peek());
305 EXPECT_THAT(ElementBoost, 42U);
306
307 const PostingList L0 = {2, 4};
308 const PostingList L1 = {1, 4};
309 auto Root = createOr(createTrue(5U), createBoost(create(L0), 2U),
310 createBoost(create(L1), 3U));
311
312 ElementBoost = Root->consume(Root->peek());
313 EXPECT_THAT(ElementBoost, Iterator::DEFAULT_BOOST_SCORE);
314 Root->advance();
315 EXPECT_THAT(Root->peek(), 1U);
316 ElementBoost = Root->consume(Root->peek());
317 EXPECT_THAT(ElementBoost, 3);
318
319 Root->advance();
320 EXPECT_THAT(Root->peek(), 2U);
321 ElementBoost = Root->consume(Root->peek());
322 EXPECT_THAT(ElementBoost, 2);
323
324 Root->advanceTo(4);
325 ElementBoost = Root->consume(Root->peek());
326 EXPECT_THAT(ElementBoost, 3);
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000327}
328
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000329testing::Matcher<std::vector<Token>>
330trigramsAre(std::initializer_list<std::string> Trigrams) {
331 std::vector<Token> Tokens;
332 for (const auto &Symbols : Trigrams) {
333 Tokens.push_back(Token(Token::Kind::Trigram, Symbols));
334 }
335 return testing::UnorderedElementsAreArray(Tokens);
336}
337
338TEST(DexIndexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000339 EXPECT_THAT(generateIdentifierTrigrams("X86"),
340 trigramsAre({"x86", "x$$", "x8$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000341
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000342 EXPECT_THAT(generateIdentifierTrigrams("nl"),
343 trigramsAre({"nl$", "n$$", "$$$"}));
344
345 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n$$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000346
347 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000348 trigramsAre({"c$$", "cl$", "cla", "lan", "ang", "ngd", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000349
350 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000351 trigramsAre({"a$$", "abc", "abd", "ade", "bcd", "bde", "cde",
352 "def", "ab$", "ad$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000353
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000354 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
355 trigramsAre({"a$$", "a_$", "a_b", "abc", "abd", "acd", "ace",
356 "bcd", "bce", "bde", "cde", "ab$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000357
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000358 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
359 trigramsAre({"u$$", "uni", "unp", "upt", "niq", "nip", "npt",
360 "iqu", "iqp", "ipt", "que", "qup", "qpt", "uep",
361 "ept", "ptr", "un$", "up$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000362
363 EXPECT_THAT(generateIdentifierTrigrams("TUDecl"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000364 trigramsAre({"t$$", "tud", "tde", "ude", "dec", "ecl", "tu$",
365 "td$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000366
367 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000368 trigramsAre({"i$$", "iso", "iok", "sok", "is$", "io$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000369
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000370 EXPECT_THAT(
371 generateIdentifierTrigrams("abc_defGhij__klm"),
372 trigramsAre({"a$$", "abc", "abd", "abg", "ade", "adg", "adk", "agh",
373 "agk", "bcd", "bcg", "bde", "bdg", "bdk", "bgh", "bgk",
374 "cde", "cdg", "cdk", "cgh", "cgk", "def", "deg", "dek",
375 "dgh", "dgk", "dkl", "efg", "efk", "egh", "egk", "ekl",
376 "fgh", "fgk", "fkl", "ghi", "ghk", "gkl", "hij", "hik",
377 "hkl", "ijk", "ikl", "jkl", "klm", "ab$", "ad$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000378}
379
380TEST(DexIndexTrigrams, QueryTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000381 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c$$"}));
382 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl$"}));
383 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000384
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000385 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_$$"}));
386 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__$"}));
387 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({"___"}));
388
389 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000390
391 EXPECT_THAT(generateQueryTrigrams("clangd"),
392 trigramsAre({"cla", "lan", "ang", "ngd"}));
393
394 EXPECT_THAT(generateQueryTrigrams("abc_def"),
395 trigramsAre({"abc", "bcd", "cde", "def"}));
396
397 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
398 trigramsAre({"abc", "bcd", "cde"}));
399
400 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
401 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
402
403 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
404 trigramsAre({"tud", "ude", "dec", "ecl"}));
405
406 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
407
408 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
409 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
410 "hij", "ijk", "jkl", "klm"}));
411}
412
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000413TEST(DexIndex, Lookup) {
414 DexIndex I;
415 I.build(generateSymbols({"ns::abc", "ns::xyz"}));
416 EXPECT_THAT(lookup(I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
417 EXPECT_THAT(lookup(I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
418 UnorderedElementsAre("ns::abc", "ns::xyz"));
419 EXPECT_THAT(lookup(I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
420 UnorderedElementsAre("ns::xyz"));
421 EXPECT_THAT(lookup(I, SymbolID("ns::nonono")), UnorderedElementsAre());
422}
423
424TEST(DexIndex, FuzzyFind) {
425 DexIndex Index;
426 Index.build(generateSymbols({"ns::ABC", "ns::BCD", "::ABC", "ns::nested::ABC",
427 "other::ABC", "other::A"}));
428 FuzzyFindRequest Req;
429 Req.Query = "ABC";
430 Req.Scopes = {"ns::"};
431 EXPECT_THAT(match(Index, Req), UnorderedElementsAre("ns::ABC"));
432 Req.Scopes = {"ns::", "ns::nested::"};
433 EXPECT_THAT(match(Index, Req),
434 UnorderedElementsAre("ns::ABC", "ns::nested::ABC"));
435 Req.Query = "A";
436 Req.Scopes = {"other::"};
437 EXPECT_THAT(match(Index, Req),
438 UnorderedElementsAre("other::A", "other::ABC"));
439 Req.Query = "";
440 Req.Scopes = {};
441 EXPECT_THAT(match(Index, Req),
442 UnorderedElementsAre("ns::ABC", "ns::BCD", "::ABC",
443 "ns::nested::ABC", "other::ABC",
444 "other::A"));
445}
446
447TEST(DexIndexTest, FuzzyMatchQ) {
448 DexIndex I;
449 I.build(
450 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}));
451 FuzzyFindRequest Req;
452 Req.Query = "lol";
453 Req.MaxCandidateCount = 2;
454 EXPECT_THAT(match(I, Req),
455 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
456}
457
458TEST(DexIndexTest, DexIndexSymbolsRecycled) {
459 DexIndex I;
460 std::weak_ptr<SlabAndPointers> Symbols;
461 I.build(generateNumSymbols(0, 10, &Symbols));
462 FuzzyFindRequest Req;
463 Req.Query = "7";
464 EXPECT_THAT(match(I, Req), UnorderedElementsAre("7"));
465
466 EXPECT_FALSE(Symbols.expired());
467 // Release old symbols.
468 I.build(generateNumSymbols(0, 0));
469 EXPECT_TRUE(Symbols.expired());
470}
471
472// FIXME(kbobyrev): This test is different for DexIndex and MemIndex: while
473// MemIndex manages response deduplication, DexIndex simply returns all matched
474// symbols which means there might be equivalent symbols in the response.
475// Before drop-in replacement of MemIndex with DexIndex happens, FileIndex
476// should handle deduplication instead.
477TEST(DexIndexTest, DexIndexDeduplicate) {
478 auto Symbols = generateNumSymbols(0, 10);
479
480 // Inject duplicates.
481 auto Sym = symbol("7");
482 Symbols->push_back(&Sym);
483 Symbols->push_back(&Sym);
484 Symbols->push_back(&Sym);
485
486 FuzzyFindRequest Req;
487 Req.Query = "7";
488 DexIndex I;
489 I.build(std::move(Symbols));
490 auto Matches = match(I, Req);
491 EXPECT_EQ(Matches.size(), 4u);
492}
493
494TEST(DexIndexTest, DexIndexLimitedNumMatches) {
495 DexIndex I;
496 I.build(generateNumSymbols(0, 100));
497 FuzzyFindRequest Req;
498 Req.Query = "5";
499 Req.MaxCandidateCount = 3;
500 bool Incomplete;
501 auto Matches = match(I, Req, &Incomplete);
502 EXPECT_EQ(Matches.size(), Req.MaxCandidateCount);
503 EXPECT_TRUE(Incomplete);
504}
505
506TEST(DexIndexTest, FuzzyMatch) {
507 DexIndex I;
508 I.build(
509 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}));
510 FuzzyFindRequest Req;
511 Req.Query = "lol";
512 Req.MaxCandidateCount = 2;
513 EXPECT_THAT(match(I, Req),
514 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
515}
516
517TEST(DexIndexTest, MatchQualifiedNamesWithoutSpecificScope) {
518 DexIndex I;
519 I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
520 FuzzyFindRequest Req;
521 Req.Query = "y";
522 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
523}
524
525TEST(DexIndexTest, MatchQualifiedNamesWithGlobalScope) {
526 DexIndex I;
527 I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
528 FuzzyFindRequest Req;
529 Req.Query = "y";
530 Req.Scopes = {""};
531 EXPECT_THAT(match(I, Req), UnorderedElementsAre("y3"));
532}
533
534TEST(DexIndexTest, MatchQualifiedNamesWithOneScope) {
535 DexIndex I;
536 I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}));
537 FuzzyFindRequest Req;
538 Req.Query = "y";
539 Req.Scopes = {"a::"};
540 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2"));
541}
542
543TEST(DexIndexTest, MatchQualifiedNamesWithMultipleScopes) {
544 DexIndex I;
545 I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}));
546 FuzzyFindRequest Req;
547 Req.Query = "y";
548 Req.Scopes = {"a::", "b::"};
549 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
550}
551
552TEST(DexIndexTest, NoMatchNestedScopes) {
553 DexIndex I;
554 I.build(generateSymbols({"a::y1", "a::b::y2"}));
555 FuzzyFindRequest Req;
556 Req.Query = "y";
557 Req.Scopes = {"a::"};
558 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1"));
559}
560
561TEST(DexIndexTest, IgnoreCases) {
562 DexIndex I;
563 I.build(generateSymbols({"ns::ABC", "ns::abc"}));
564 FuzzyFindRequest Req;
565 Req.Query = "AB";
566 Req.Scopes = {"ns::"};
567 EXPECT_THAT(match(I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
568}
569
570TEST(DexIndexTest, Lookup) {
571 DexIndex I;
572 I.build(generateSymbols({"ns::abc", "ns::xyz"}));
573 EXPECT_THAT(lookup(I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
574 EXPECT_THAT(lookup(I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
575 UnorderedElementsAre("ns::abc", "ns::xyz"));
576 EXPECT_THAT(lookup(I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
577 UnorderedElementsAre("ns::xyz"));
578 EXPECT_THAT(lookup(I, SymbolID("ns::nonono")), UnorderedElementsAre());
579}
580
581} // namespace
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000582} // namespace dex
583} // namespace clangd
584} // namespace clang