blob: e2cdc34388a2360bc15510dc9fb9005c686bff35 [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 Bobyreva522c1c2018-07-27 09:54:27 +000032TEST(DexIndexIterators, DocumentIterator) {
33 const PostingList L = {4, 7, 8, 20, 42, 100};
34 auto DocIterator = create(L);
35
36 EXPECT_EQ(DocIterator->peek(), 4U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000037 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000038
39 DocIterator->advance();
40 EXPECT_EQ(DocIterator->peek(), 7U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000041 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000042
43 DocIterator->advanceTo(20);
44 EXPECT_EQ(DocIterator->peek(), 20U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000045 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000046
47 DocIterator->advanceTo(65);
48 EXPECT_EQ(DocIterator->peek(), 100U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000049 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000050
51 DocIterator->advanceTo(420);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000052 EXPECT_TRUE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000053}
54
55TEST(DexIndexIterators, AndWithEmpty) {
56 const PostingList L0;
57 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
58
59 auto AndEmpty = createAnd(create(L0));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000060 EXPECT_TRUE(AndEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000061
62 auto AndWithEmpty = createAnd(create(L0), create(L1));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000063 EXPECT_TRUE(AndWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000064
65 EXPECT_THAT(consume(*AndWithEmpty), ElementsAre());
66}
67
68TEST(DexIndexIterators, AndTwoLists) {
69 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
70 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
71
72 auto And = createAnd(create(L1), create(L0));
73
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000074 EXPECT_FALSE(And->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000075 EXPECT_THAT(consume(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
76
77 And = createAnd(create(L0), create(L1));
78
79 And->advanceTo(0);
80 EXPECT_EQ(And->peek(), 0U);
81 And->advanceTo(5);
82 EXPECT_EQ(And->peek(), 7U);
83 And->advanceTo(10);
84 EXPECT_EQ(And->peek(), 10U);
85 And->advanceTo(42);
86 EXPECT_EQ(And->peek(), 320U);
87 And->advanceTo(8999);
88 EXPECT_EQ(And->peek(), 9000U);
89 And->advanceTo(9001);
90}
91
92TEST(DexIndexIterators, AndThreeLists) {
93 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
94 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
95 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
96
97 auto And = createAnd(create(L0), create(L1), create(L2));
98 EXPECT_EQ(And->peek(), 7U);
99 And->advanceTo(300);
100 EXPECT_EQ(And->peek(), 320U);
101 And->advanceTo(100000);
102
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000103 EXPECT_TRUE(And->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000104}
105
106TEST(DexIndexIterators, OrWithEmpty) {
107 const PostingList L0;
108 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
109
110 auto OrEmpty = createOr(create(L0));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000111 EXPECT_TRUE(OrEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000112
113 auto OrWithEmpty = createOr(create(L0), create(L1));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000114 EXPECT_FALSE(OrWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000115
116 EXPECT_THAT(consume(*OrWithEmpty),
117 ElementsAre(0U, 5U, 7U, 10U, 42U, 320U, 9000U));
118}
119
120TEST(DexIndexIterators, OrTwoLists) {
121 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
122 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
123
124 auto Or = createOr(create(L0), create(L1));
125
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000126 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000127 EXPECT_EQ(Or->peek(), 0U);
128 Or->advance();
129 EXPECT_EQ(Or->peek(), 4U);
130 Or->advance();
131 EXPECT_EQ(Or->peek(), 5U);
132 Or->advance();
133 EXPECT_EQ(Or->peek(), 7U);
134 Or->advance();
135 EXPECT_EQ(Or->peek(), 10U);
136 Or->advance();
137 EXPECT_EQ(Or->peek(), 30U);
138 Or->advanceTo(42);
139 EXPECT_EQ(Or->peek(), 42U);
140 Or->advanceTo(300);
141 EXPECT_EQ(Or->peek(), 320U);
142 Or->advanceTo(9000);
143 EXPECT_EQ(Or->peek(), 9000U);
144 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000145 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000146
147 Or = createOr(create(L0), create(L1));
148
149 EXPECT_THAT(consume(*Or),
150 ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
151}
152
153TEST(DexIndexIterators, OrThreeLists) {
154 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
155 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
156 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
157
158 auto Or = createOr(create(L0), create(L1), create(L2));
159
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000160 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000161 EXPECT_EQ(Or->peek(), 0U);
162
163 Or->advance();
164 EXPECT_EQ(Or->peek(), 1U);
165
166 Or->advance();
167 EXPECT_EQ(Or->peek(), 4U);
168
169 Or->advanceTo(7);
170
171 Or->advanceTo(59);
172 EXPECT_EQ(Or->peek(), 60U);
173
174 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000175 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000176}
177
178// FIXME(kbobyrev): The testcase below is similar to what is expected in real
179// queries. It should be updated once new iterators (such as boosting, limiting,
180// etc iterators) appear. However, it is not exhaustive and it would be
181// beneficial to implement automatic generation of query trees for more
182// comprehensive testing.
183TEST(DexIndexIterators, QueryTree) {
184 // An example of more complicated query
185 //
186 // +-----------------+
187 // |And Iterator:1, 5|
188 // +--------+--------+
189 // |
190 // |
191 // +------------------------------------+
192 // | |
193 // | |
194 // +----------v----------+ +----------v---------+
195 // |And Iterator: 1, 5, 9| |Or Iterator: 0, 1, 5|
196 // +----------+----------+ +----------+---------+
197 // | |
198 // +------+-----+ +---------+-----------+
199 // | | | | |
200 // +-------v-----+ +----v-----+ +--v--+ +-V--+ +---v---+
201 // |1, 3, 5, 8, 9| |1, 5, 7, 9| |Empty| |0, 5| |0, 1, 5|
202 // +-------------+ +----------+ +-----+ +----+ +-------+
203
204 const PostingList L0 = {1, 3, 5, 8, 9};
205 const PostingList L1 = {1, 5, 7, 9};
206 const PostingList L2 = {0, 5};
207 const PostingList L3 = {0, 1, 5};
208 const PostingList L4;
209
210 // Root of the query tree: [1, 5]
211 auto Root = createAnd(
212 // Lower And Iterator: [1, 5, 9]
213 createAnd(create(L0), create(L1)),
214 // Lower Or Iterator: [0, 1, 5]
215 createOr(create(L2), create(L3), create(L4)));
216
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000217 EXPECT_FALSE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000218 EXPECT_EQ(Root->peek(), 1U);
219 Root->advanceTo(0);
220 // Advance multiple times. Shouldn't do anything.
221 Root->advanceTo(1);
222 Root->advanceTo(0);
223 EXPECT_EQ(Root->peek(), 1U);
224 Root->advance();
225 EXPECT_EQ(Root->peek(), 5U);
226 Root->advanceTo(5);
227 EXPECT_EQ(Root->peek(), 5U);
228 Root->advanceTo(9000);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000229 EXPECT_TRUE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000230}
231
232TEST(DexIndexIterators, StringRepresentation) {
233 const PostingList L0 = {4, 7, 8, 20, 42, 100};
234 const PostingList L1 = {1, 3, 5, 8, 9};
235 const PostingList L2 = {1, 5, 7, 9};
236 const PostingList L3 = {0, 5};
237 const PostingList L4 = {0, 1, 5};
238 const PostingList L5;
239
Kirill Bobyrev51534ab2018-08-16 13:19:43 +0000240 EXPECT_EQ(llvm::to_string(*(create(L0))), "[{4}, 7, 8, 20, 42, 100, END]");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000241
242 auto Nested = createAnd(createAnd(create(L1), create(L2)),
243 createOr(create(L3), create(L4), create(L5)));
244
245 EXPECT_EQ(llvm::to_string(*Nested),
Kirill Bobyrev51534ab2018-08-16 13:19:43 +0000246 "(& (& [{1}, 3, 5, 8, 9, END] [{1}, 5, 7, 9, END]) (| [0, {5}, "
247 "END] [0, {1}, 5, END] [{END}]))");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000248}
249
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000250TEST(DexIndexIterators, Limit) {
251 const PostingList L0 = {4, 7, 8, 20, 42, 100};
252 const PostingList L1 = {1, 3, 5, 8, 9};
253 const PostingList L2 = {1, 5, 7, 9};
254 const PostingList L3 = {0, 5};
255 const PostingList L4 = {0, 1, 5};
256 const PostingList L5;
257
258 auto DocIterator = create(L0);
259 EXPECT_THAT(consume(*DocIterator, 42), ElementsAre(4, 7, 8, 20, 42, 100));
260
261 DocIterator = create(L0);
262 EXPECT_THAT(consume(*DocIterator), ElementsAre(4, 7, 8, 20, 42, 100));
263
264 DocIterator = create(L0);
265 EXPECT_THAT(consume(*DocIterator, 3), ElementsAre(4, 7, 8));
266
267 DocIterator = create(L0);
268 EXPECT_THAT(consume(*DocIterator, 0), ElementsAre());
269}
270
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000271TEST(DexIndexIterators, True) {
272 auto TrueIterator = createTrue(0U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000273 EXPECT_TRUE(TrueIterator->reachedEnd());
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000274 EXPECT_THAT(consume(*TrueIterator), ElementsAre());
275
276 PostingList L0 = {1, 2, 5, 7};
277 TrueIterator = createTrue(7U);
278 EXPECT_THAT(TrueIterator->peek(), 0);
279 auto AndIterator = createAnd(create(L0), move(TrueIterator));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000280 EXPECT_FALSE(AndIterator->reachedEnd());
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000281 EXPECT_THAT(consume(*AndIterator), ElementsAre(1, 2, 5));
282}
283
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000284testing::Matcher<std::vector<Token>>
285trigramsAre(std::initializer_list<std::string> Trigrams) {
286 std::vector<Token> Tokens;
287 for (const auto &Symbols : Trigrams) {
288 Tokens.push_back(Token(Token::Kind::Trigram, Symbols));
289 }
290 return testing::UnorderedElementsAreArray(Tokens);
291}
292
293TEST(DexIndexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000294 EXPECT_THAT(generateIdentifierTrigrams("X86"),
295 trigramsAre({"x86", "x$$", "x8$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000296
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000297 EXPECT_THAT(generateIdentifierTrigrams("nl"),
298 trigramsAre({"nl$", "n$$", "$$$"}));
299
300 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n$$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000301
302 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000303 trigramsAre({"c$$", "cl$", "cla", "lan", "ang", "ngd", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000304
305 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000306 trigramsAre({"a$$", "abc", "abd", "ade", "bcd", "bde", "cde",
307 "def", "ab$", "ad$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000308
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000309 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
310 trigramsAre({"a$$", "a_$", "a_b", "abc", "abd", "acd", "ace",
311 "bcd", "bce", "bde", "cde", "ab$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000312
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000313 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
314 trigramsAre({"u$$", "uni", "unp", "upt", "niq", "nip", "npt",
315 "iqu", "iqp", "ipt", "que", "qup", "qpt", "uep",
316 "ept", "ptr", "un$", "up$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000317
318 EXPECT_THAT(generateIdentifierTrigrams("TUDecl"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000319 trigramsAre({"t$$", "tud", "tde", "ude", "dec", "ecl", "tu$",
320 "td$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000321
322 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000323 trigramsAre({"i$$", "iso", "iok", "sok", "is$", "io$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000324
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000325 EXPECT_THAT(
326 generateIdentifierTrigrams("abc_defGhij__klm"),
327 trigramsAre({"a$$", "abc", "abd", "abg", "ade", "adg", "adk", "agh",
328 "agk", "bcd", "bcg", "bde", "bdg", "bdk", "bgh", "bgk",
329 "cde", "cdg", "cdk", "cgh", "cgk", "def", "deg", "dek",
330 "dgh", "dgk", "dkl", "efg", "efk", "egh", "egk", "ekl",
331 "fgh", "fgk", "fkl", "ghi", "ghk", "gkl", "hij", "hik",
332 "hkl", "ijk", "ikl", "jkl", "klm", "ab$", "ad$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000333}
334
335TEST(DexIndexTrigrams, QueryTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000336 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c$$"}));
337 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl$"}));
338 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000339
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000340 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_$$"}));
341 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__$"}));
342 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({"___"}));
343
344 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000345
346 EXPECT_THAT(generateQueryTrigrams("clangd"),
347 trigramsAre({"cla", "lan", "ang", "ngd"}));
348
349 EXPECT_THAT(generateQueryTrigrams("abc_def"),
350 trigramsAre({"abc", "bcd", "cde", "def"}));
351
352 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
353 trigramsAre({"abc", "bcd", "cde"}));
354
355 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
356 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
357
358 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
359 trigramsAre({"tud", "ude", "dec", "ecl"}));
360
361 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
362
363 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
364 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
365 "hij", "ijk", "jkl", "klm"}));
366}
367
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000368TEST(DexIndex, Lookup) {
369 DexIndex I;
370 I.build(generateSymbols({"ns::abc", "ns::xyz"}));
371 EXPECT_THAT(lookup(I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
372 EXPECT_THAT(lookup(I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
373 UnorderedElementsAre("ns::abc", "ns::xyz"));
374 EXPECT_THAT(lookup(I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
375 UnorderedElementsAre("ns::xyz"));
376 EXPECT_THAT(lookup(I, SymbolID("ns::nonono")), UnorderedElementsAre());
377}
378
379TEST(DexIndex, FuzzyFind) {
380 DexIndex Index;
381 Index.build(generateSymbols({"ns::ABC", "ns::BCD", "::ABC", "ns::nested::ABC",
382 "other::ABC", "other::A"}));
383 FuzzyFindRequest Req;
384 Req.Query = "ABC";
385 Req.Scopes = {"ns::"};
386 EXPECT_THAT(match(Index, Req), UnorderedElementsAre("ns::ABC"));
387 Req.Scopes = {"ns::", "ns::nested::"};
388 EXPECT_THAT(match(Index, Req),
389 UnorderedElementsAre("ns::ABC", "ns::nested::ABC"));
390 Req.Query = "A";
391 Req.Scopes = {"other::"};
392 EXPECT_THAT(match(Index, Req),
393 UnorderedElementsAre("other::A", "other::ABC"));
394 Req.Query = "";
395 Req.Scopes = {};
396 EXPECT_THAT(match(Index, Req),
397 UnorderedElementsAre("ns::ABC", "ns::BCD", "::ABC",
398 "ns::nested::ABC", "other::ABC",
399 "other::A"));
400}
401
402TEST(DexIndexTest, FuzzyMatchQ) {
403 DexIndex I;
404 I.build(
405 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}));
406 FuzzyFindRequest Req;
407 Req.Query = "lol";
408 Req.MaxCandidateCount = 2;
409 EXPECT_THAT(match(I, Req),
410 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
411}
412
413TEST(DexIndexTest, DexIndexSymbolsRecycled) {
414 DexIndex I;
415 std::weak_ptr<SlabAndPointers> Symbols;
416 I.build(generateNumSymbols(0, 10, &Symbols));
417 FuzzyFindRequest Req;
418 Req.Query = "7";
419 EXPECT_THAT(match(I, Req), UnorderedElementsAre("7"));
420
421 EXPECT_FALSE(Symbols.expired());
422 // Release old symbols.
423 I.build(generateNumSymbols(0, 0));
424 EXPECT_TRUE(Symbols.expired());
425}
426
427// FIXME(kbobyrev): This test is different for DexIndex and MemIndex: while
428// MemIndex manages response deduplication, DexIndex simply returns all matched
429// symbols which means there might be equivalent symbols in the response.
430// Before drop-in replacement of MemIndex with DexIndex happens, FileIndex
431// should handle deduplication instead.
432TEST(DexIndexTest, DexIndexDeduplicate) {
433 auto Symbols = generateNumSymbols(0, 10);
434
435 // Inject duplicates.
436 auto Sym = symbol("7");
437 Symbols->push_back(&Sym);
438 Symbols->push_back(&Sym);
439 Symbols->push_back(&Sym);
440
441 FuzzyFindRequest Req;
442 Req.Query = "7";
443 DexIndex I;
444 I.build(std::move(Symbols));
445 auto Matches = match(I, Req);
446 EXPECT_EQ(Matches.size(), 4u);
447}
448
449TEST(DexIndexTest, DexIndexLimitedNumMatches) {
450 DexIndex I;
451 I.build(generateNumSymbols(0, 100));
452 FuzzyFindRequest Req;
453 Req.Query = "5";
454 Req.MaxCandidateCount = 3;
455 bool Incomplete;
456 auto Matches = match(I, Req, &Incomplete);
457 EXPECT_EQ(Matches.size(), Req.MaxCandidateCount);
458 EXPECT_TRUE(Incomplete);
459}
460
461TEST(DexIndexTest, FuzzyMatch) {
462 DexIndex I;
463 I.build(
464 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}));
465 FuzzyFindRequest Req;
466 Req.Query = "lol";
467 Req.MaxCandidateCount = 2;
468 EXPECT_THAT(match(I, Req),
469 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
470}
471
472TEST(DexIndexTest, MatchQualifiedNamesWithoutSpecificScope) {
473 DexIndex I;
474 I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
475 FuzzyFindRequest Req;
476 Req.Query = "y";
477 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
478}
479
480TEST(DexIndexTest, MatchQualifiedNamesWithGlobalScope) {
481 DexIndex I;
482 I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
483 FuzzyFindRequest Req;
484 Req.Query = "y";
485 Req.Scopes = {""};
486 EXPECT_THAT(match(I, Req), UnorderedElementsAre("y3"));
487}
488
489TEST(DexIndexTest, MatchQualifiedNamesWithOneScope) {
490 DexIndex I;
491 I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}));
492 FuzzyFindRequest Req;
493 Req.Query = "y";
494 Req.Scopes = {"a::"};
495 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2"));
496}
497
498TEST(DexIndexTest, MatchQualifiedNamesWithMultipleScopes) {
499 DexIndex I;
500 I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}));
501 FuzzyFindRequest Req;
502 Req.Query = "y";
503 Req.Scopes = {"a::", "b::"};
504 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
505}
506
507TEST(DexIndexTest, NoMatchNestedScopes) {
508 DexIndex I;
509 I.build(generateSymbols({"a::y1", "a::b::y2"}));
510 FuzzyFindRequest Req;
511 Req.Query = "y";
512 Req.Scopes = {"a::"};
513 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1"));
514}
515
516TEST(DexIndexTest, IgnoreCases) {
517 DexIndex I;
518 I.build(generateSymbols({"ns::ABC", "ns::abc"}));
519 FuzzyFindRequest Req;
520 Req.Query = "AB";
521 Req.Scopes = {"ns::"};
522 EXPECT_THAT(match(I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
523}
524
525TEST(DexIndexTest, Lookup) {
526 DexIndex I;
527 I.build(generateSymbols({"ns::abc", "ns::xyz"}));
528 EXPECT_THAT(lookup(I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
529 EXPECT_THAT(lookup(I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
530 UnorderedElementsAre("ns::abc", "ns::xyz"));
531 EXPECT_THAT(lookup(I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
532 UnorderedElementsAre("ns::xyz"));
533 EXPECT_THAT(lookup(I, SymbolID("ns::nonono")), UnorderedElementsAre());
534}
535
536} // namespace
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000537} // namespace dex
538} // namespace clangd
539} // namespace clang