blob: 68ef1a13084c07de21cbfb5bbf3dfb94fa1d1803 [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 Bobyreva98961b2018-08-24 11:25:43 +000032std::vector<DocID> consumeIDs(Iterator &It) {
33 auto IDAndScore = consume(It);
Kirill Bobyrev7413e982018-08-22 13:44:15 +000034 std::vector<DocID> IDs(IDAndScore.size());
35 for (size_t I = 0; I < IDAndScore.size(); ++I)
36 IDs[I] = IDAndScore[I].first;
37 return IDs;
38}
39
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000040TEST(DexIndexIterators, DocumentIterator) {
41 const PostingList L = {4, 7, 8, 20, 42, 100};
42 auto DocIterator = create(L);
43
44 EXPECT_EQ(DocIterator->peek(), 4U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000045 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000046
47 DocIterator->advance();
48 EXPECT_EQ(DocIterator->peek(), 7U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000049 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000050
51 DocIterator->advanceTo(20);
52 EXPECT_EQ(DocIterator->peek(), 20U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000053 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000054
55 DocIterator->advanceTo(65);
56 EXPECT_EQ(DocIterator->peek(), 100U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000057 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000058
59 DocIterator->advanceTo(420);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000060 EXPECT_TRUE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000061}
62
63TEST(DexIndexIterators, AndWithEmpty) {
64 const PostingList L0;
65 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
66
67 auto AndEmpty = createAnd(create(L0));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000068 EXPECT_TRUE(AndEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000069
70 auto AndWithEmpty = createAnd(create(L0), create(L1));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000071 EXPECT_TRUE(AndWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000072
Kirill Bobyrev7413e982018-08-22 13:44:15 +000073 EXPECT_THAT(consumeIDs(*AndWithEmpty), ElementsAre());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000074}
75
76TEST(DexIndexIterators, AndTwoLists) {
77 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
78 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
79
80 auto And = createAnd(create(L1), create(L0));
81
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000082 EXPECT_FALSE(And->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +000083 EXPECT_THAT(consumeIDs(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000084
85 And = createAnd(create(L0), create(L1));
86
87 And->advanceTo(0);
88 EXPECT_EQ(And->peek(), 0U);
89 And->advanceTo(5);
90 EXPECT_EQ(And->peek(), 7U);
91 And->advanceTo(10);
92 EXPECT_EQ(And->peek(), 10U);
93 And->advanceTo(42);
94 EXPECT_EQ(And->peek(), 320U);
95 And->advanceTo(8999);
96 EXPECT_EQ(And->peek(), 9000U);
97 And->advanceTo(9001);
98}
99
100TEST(DexIndexIterators, AndThreeLists) {
101 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
102 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
103 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
104
105 auto And = createAnd(create(L0), create(L1), create(L2));
106 EXPECT_EQ(And->peek(), 7U);
107 And->advanceTo(300);
108 EXPECT_EQ(And->peek(), 320U);
109 And->advanceTo(100000);
110
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000111 EXPECT_TRUE(And->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000112}
113
114TEST(DexIndexIterators, OrWithEmpty) {
115 const PostingList L0;
116 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
117
118 auto OrEmpty = createOr(create(L0));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000119 EXPECT_TRUE(OrEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000120
121 auto OrWithEmpty = createOr(create(L0), create(L1));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000122 EXPECT_FALSE(OrWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000123
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000124 EXPECT_THAT(consumeIDs(*OrWithEmpty),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000125 ElementsAre(0U, 5U, 7U, 10U, 42U, 320U, 9000U));
126}
127
128TEST(DexIndexIterators, OrTwoLists) {
129 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
130 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
131
132 auto Or = createOr(create(L0), create(L1));
133
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000134 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000135 EXPECT_EQ(Or->peek(), 0U);
136 Or->advance();
137 EXPECT_EQ(Or->peek(), 4U);
138 Or->advance();
139 EXPECT_EQ(Or->peek(), 5U);
140 Or->advance();
141 EXPECT_EQ(Or->peek(), 7U);
142 Or->advance();
143 EXPECT_EQ(Or->peek(), 10U);
144 Or->advance();
145 EXPECT_EQ(Or->peek(), 30U);
146 Or->advanceTo(42);
147 EXPECT_EQ(Or->peek(), 42U);
148 Or->advanceTo(300);
149 EXPECT_EQ(Or->peek(), 320U);
150 Or->advanceTo(9000);
151 EXPECT_EQ(Or->peek(), 9000U);
152 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000153 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000154
155 Or = createOr(create(L0), create(L1));
156
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000157 EXPECT_THAT(consumeIDs(*Or),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000158 ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
159}
160
161TEST(DexIndexIterators, OrThreeLists) {
162 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
163 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
164 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
165
166 auto Or = createOr(create(L0), create(L1), create(L2));
167
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000168 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000169 EXPECT_EQ(Or->peek(), 0U);
170
171 Or->advance();
172 EXPECT_EQ(Or->peek(), 1U);
173
174 Or->advance();
175 EXPECT_EQ(Or->peek(), 4U);
176
177 Or->advanceTo(7);
178
179 Or->advanceTo(59);
180 EXPECT_EQ(Or->peek(), 60U);
181
182 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000183 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000184}
185
186// FIXME(kbobyrev): The testcase below is similar to what is expected in real
187// queries. It should be updated once new iterators (such as boosting, limiting,
188// etc iterators) appear. However, it is not exhaustive and it would be
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000189// beneficial to implement automatic generation (e.g. fuzzing) of query trees
190// for more comprehensive testing.
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000191TEST(DexIndexIterators, QueryTree) {
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000192 //
193 // +-----------------+
194 // |And Iterator:1, 5|
195 // +--------+--------+
196 // |
197 // |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000198 // +-------------+----------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000199 // | |
200 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000201 // +----------v----------+ +----------v------------+
202 // |And Iterator: 1, 5, 9| |Or Iterator: 0, 1, 3, 5|
203 // +----------+----------+ +----------+------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000204 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000205 // +------+-----+ +---------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000206 // | | | | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000207 // +-------v-----+ +----+---+ +--v--+ +---v----+ +----v---+
208 // |1, 3, 5, 8, 9| |Boost: 2| |Empty| |Boost: 3| |Boost: 4|
209 // +-------------+ +----+---+ +-----+ +---+----+ +----+---+
210 // | | |
211 // +----v-----+ +-v--+ +---v---+
212 // |1, 5, 7, 9| |1, 5| |0, 3, 5|
213 // +----------+ +----+ +-------+
214 //
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000215 const PostingList L0 = {1, 3, 5, 8, 9};
216 const PostingList L1 = {1, 5, 7, 9};
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000217 const PostingList L3;
218 const PostingList L4 = {1, 5};
219 const PostingList L5 = {0, 3, 5};
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000220
221 // Root of the query tree: [1, 5]
222 auto Root = createAnd(
223 // Lower And Iterator: [1, 5, 9]
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000224 createAnd(create(L0), createBoost(create(L1), 2U)),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000225 // Lower Or Iterator: [0, 1, 5]
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000226 createOr(create(L3), createBoost(create(L4), 3U),
227 createBoost(create(L5), 4U)));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000228
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000229 EXPECT_FALSE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000230 EXPECT_EQ(Root->peek(), 1U);
231 Root->advanceTo(0);
232 // Advance multiple times. Shouldn't do anything.
233 Root->advanceTo(1);
234 Root->advanceTo(0);
235 EXPECT_EQ(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000236 auto ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000237 EXPECT_THAT(ElementBoost, 6);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000238 Root->advance();
239 EXPECT_EQ(Root->peek(), 5U);
240 Root->advanceTo(5);
241 EXPECT_EQ(Root->peek(), 5U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000242 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000243 EXPECT_THAT(ElementBoost, 8);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000244 Root->advanceTo(9000);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000245 EXPECT_TRUE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000246}
247
248TEST(DexIndexIterators, StringRepresentation) {
249 const PostingList L0 = {4, 7, 8, 20, 42, 100};
250 const PostingList L1 = {1, 3, 5, 8, 9};
251 const PostingList L2 = {1, 5, 7, 9};
252 const PostingList L3 = {0, 5};
253 const PostingList L4 = {0, 1, 5};
254 const PostingList L5;
255
Kirill Bobyrev51534ab2018-08-16 13:19:43 +0000256 EXPECT_EQ(llvm::to_string(*(create(L0))), "[{4}, 7, 8, 20, 42, 100, END]");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000257
258 auto Nested = createAnd(createAnd(create(L1), create(L2)),
259 createOr(create(L3), create(L4), create(L5)));
260
261 EXPECT_EQ(llvm::to_string(*Nested),
Kirill Bobyrev51534ab2018-08-16 13:19:43 +0000262 "(& (& [{1}, 3, 5, 8, 9, END] [{1}, 5, 7, 9, END]) (| [0, {5}, "
263 "END] [0, {1}, 5, END] [{END}]))");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000264}
265
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000266TEST(DexIndexIterators, Limit) {
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000267 const PostingList L0 = {3, 6, 7, 20, 42, 100};
268 const PostingList L1 = {1, 3, 5, 6, 7, 30, 100};
269 const PostingList L2 = {0, 3, 5, 7, 8, 100};
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000270
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000271 auto DocIterator = createLimit(create(L0), 42);
272 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7, 20, 42, 100));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000273
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000274 DocIterator = createLimit(create(L0), 3);
275 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000276
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000277 DocIterator = createLimit(create(L0), 0);
278 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre());
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000279
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000280 auto AndIterator =
281 createAnd(createLimit(createTrue(9000), 343), createLimit(create(L0), 2),
282 createLimit(create(L1), 3), createLimit(create(L2), 42));
283 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(3, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000284}
285
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000286TEST(DexIndexIterators, True) {
287 auto TrueIterator = createTrue(0U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000288 EXPECT_TRUE(TrueIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000289 EXPECT_THAT(consumeIDs(*TrueIterator), ElementsAre());
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000290
291 PostingList L0 = {1, 2, 5, 7};
292 TrueIterator = createTrue(7U);
293 EXPECT_THAT(TrueIterator->peek(), 0);
294 auto AndIterator = createAnd(create(L0), move(TrueIterator));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000295 EXPECT_FALSE(AndIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000296 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(1, 2, 5));
297}
298
299TEST(DexIndexIterators, Boost) {
300 auto BoostIterator = createBoost(createTrue(5U), 42U);
301 EXPECT_FALSE(BoostIterator->reachedEnd());
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000302 auto ElementBoost = BoostIterator->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000303 EXPECT_THAT(ElementBoost, 42U);
304
305 const PostingList L0 = {2, 4};
306 const PostingList L1 = {1, 4};
307 auto Root = createOr(createTrue(5U), createBoost(create(L0), 2U),
308 createBoost(create(L1), 3U));
309
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000310 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000311 EXPECT_THAT(ElementBoost, Iterator::DEFAULT_BOOST_SCORE);
312 Root->advance();
313 EXPECT_THAT(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000314 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000315 EXPECT_THAT(ElementBoost, 3);
316
317 Root->advance();
318 EXPECT_THAT(Root->peek(), 2U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000319 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000320 EXPECT_THAT(ElementBoost, 2);
321
322 Root->advanceTo(4);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000323 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000324 EXPECT_THAT(ElementBoost, 3);
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000325}
326
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000327testing::Matcher<std::vector<Token>>
328trigramsAre(std::initializer_list<std::string> Trigrams) {
329 std::vector<Token> Tokens;
330 for (const auto &Symbols : Trigrams) {
331 Tokens.push_back(Token(Token::Kind::Trigram, Symbols));
332 }
333 return testing::UnorderedElementsAreArray(Tokens);
334}
335
336TEST(DexIndexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000337 EXPECT_THAT(generateIdentifierTrigrams("X86"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000338 trigramsAre({"x86", "x$$", "x8$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000339
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000340 EXPECT_THAT(generateIdentifierTrigrams("nl"), trigramsAre({"nl$", "n$$"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000341
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000342 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000343
344 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000345 trigramsAre({"c$$", "cl$", "cla", "lan", "ang", "ngd"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000346
347 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000348 trigramsAre({"a$$", "abc", "abd", "ade", "bcd", "bde", "cde",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000349 "def", "ab$", "ad$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000350
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000351 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
352 trigramsAre({"a$$", "a_$", "a_b", "abc", "abd", "acd", "ace",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000353 "bcd", "bce", "bde", "cde", "ab$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000354
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000355 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
356 trigramsAre({"u$$", "uni", "unp", "upt", "niq", "nip", "npt",
357 "iqu", "iqp", "ipt", "que", "qup", "qpt", "uep",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000358 "ept", "ptr", "un$", "up$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000359
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000360 EXPECT_THAT(
361 generateIdentifierTrigrams("TUDecl"),
362 trigramsAre({"t$$", "tud", "tde", "ude", "dec", "ecl", "tu$", "td$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000363
364 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000365 trigramsAre({"i$$", "iso", "iok", "sok", "is$", "io$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000366
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000367 EXPECT_THAT(
368 generateIdentifierTrigrams("abc_defGhij__klm"),
369 trigramsAre({"a$$", "abc", "abd", "abg", "ade", "adg", "adk", "agh",
370 "agk", "bcd", "bcg", "bde", "bdg", "bdk", "bgh", "bgk",
371 "cde", "cdg", "cdk", "cgh", "cgk", "def", "deg", "dek",
372 "dgh", "dgk", "dkl", "efg", "efk", "egh", "egk", "ekl",
373 "fgh", "fgk", "fkl", "ghi", "ghk", "gkl", "hij", "hik",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000374 "hkl", "ijk", "ikl", "jkl", "klm", "ab$", "ad$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000375}
376
377TEST(DexIndexTrigrams, QueryTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000378 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c$$"}));
379 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl$"}));
380 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000381
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000382 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_$$"}));
383 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__$"}));
384 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({"___"}));
385
386 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000387
388 EXPECT_THAT(generateQueryTrigrams("clangd"),
389 trigramsAre({"cla", "lan", "ang", "ngd"}));
390
391 EXPECT_THAT(generateQueryTrigrams("abc_def"),
392 trigramsAre({"abc", "bcd", "cde", "def"}));
393
394 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
395 trigramsAre({"abc", "bcd", "cde"}));
396
397 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
398 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
399
400 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
401 trigramsAre({"tud", "ude", "dec", "ecl"}));
402
403 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
404
405 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
406 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
407 "hij", "ijk", "jkl", "klm"}));
408}
409
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000410TEST(DexIndex, Lookup) {
411 DexIndex I;
412 I.build(generateSymbols({"ns::abc", "ns::xyz"}));
413 EXPECT_THAT(lookup(I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
414 EXPECT_THAT(lookup(I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
415 UnorderedElementsAre("ns::abc", "ns::xyz"));
416 EXPECT_THAT(lookup(I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
417 UnorderedElementsAre("ns::xyz"));
418 EXPECT_THAT(lookup(I, SymbolID("ns::nonono")), UnorderedElementsAre());
419}
420
421TEST(DexIndex, FuzzyFind) {
422 DexIndex Index;
423 Index.build(generateSymbols({"ns::ABC", "ns::BCD", "::ABC", "ns::nested::ABC",
424 "other::ABC", "other::A"}));
425 FuzzyFindRequest Req;
426 Req.Query = "ABC";
427 Req.Scopes = {"ns::"};
428 EXPECT_THAT(match(Index, Req), UnorderedElementsAre("ns::ABC"));
429 Req.Scopes = {"ns::", "ns::nested::"};
430 EXPECT_THAT(match(Index, Req),
431 UnorderedElementsAre("ns::ABC", "ns::nested::ABC"));
432 Req.Query = "A";
433 Req.Scopes = {"other::"};
434 EXPECT_THAT(match(Index, Req),
435 UnorderedElementsAre("other::A", "other::ABC"));
436 Req.Query = "";
437 Req.Scopes = {};
438 EXPECT_THAT(match(Index, Req),
439 UnorderedElementsAre("ns::ABC", "ns::BCD", "::ABC",
440 "ns::nested::ABC", "other::ABC",
441 "other::A"));
442}
443
444TEST(DexIndexTest, FuzzyMatchQ) {
445 DexIndex I;
446 I.build(
447 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}));
448 FuzzyFindRequest Req;
449 Req.Query = "lol";
450 Req.MaxCandidateCount = 2;
451 EXPECT_THAT(match(I, Req),
452 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
453}
454
455TEST(DexIndexTest, DexIndexSymbolsRecycled) {
456 DexIndex I;
457 std::weak_ptr<SlabAndPointers> Symbols;
458 I.build(generateNumSymbols(0, 10, &Symbols));
459 FuzzyFindRequest Req;
460 Req.Query = "7";
461 EXPECT_THAT(match(I, Req), UnorderedElementsAre("7"));
462
463 EXPECT_FALSE(Symbols.expired());
464 // Release old symbols.
465 I.build(generateNumSymbols(0, 0));
466 EXPECT_TRUE(Symbols.expired());
467}
468
469// FIXME(kbobyrev): This test is different for DexIndex and MemIndex: while
470// MemIndex manages response deduplication, DexIndex simply returns all matched
471// symbols which means there might be equivalent symbols in the response.
472// Before drop-in replacement of MemIndex with DexIndex happens, FileIndex
473// should handle deduplication instead.
474TEST(DexIndexTest, DexIndexDeduplicate) {
475 auto Symbols = generateNumSymbols(0, 10);
476
477 // Inject duplicates.
478 auto Sym = symbol("7");
479 Symbols->push_back(&Sym);
480 Symbols->push_back(&Sym);
481 Symbols->push_back(&Sym);
482
483 FuzzyFindRequest Req;
484 Req.Query = "7";
485 DexIndex I;
486 I.build(std::move(Symbols));
487 auto Matches = match(I, Req);
488 EXPECT_EQ(Matches.size(), 4u);
489}
490
491TEST(DexIndexTest, DexIndexLimitedNumMatches) {
492 DexIndex I;
493 I.build(generateNumSymbols(0, 100));
494 FuzzyFindRequest Req;
495 Req.Query = "5";
496 Req.MaxCandidateCount = 3;
497 bool Incomplete;
498 auto Matches = match(I, Req, &Incomplete);
499 EXPECT_EQ(Matches.size(), Req.MaxCandidateCount);
500 EXPECT_TRUE(Incomplete);
501}
502
503TEST(DexIndexTest, FuzzyMatch) {
504 DexIndex I;
505 I.build(
506 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}));
507 FuzzyFindRequest Req;
508 Req.Query = "lol";
509 Req.MaxCandidateCount = 2;
510 EXPECT_THAT(match(I, Req),
511 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
512}
513
514TEST(DexIndexTest, MatchQualifiedNamesWithoutSpecificScope) {
515 DexIndex I;
516 I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
517 FuzzyFindRequest Req;
518 Req.Query = "y";
519 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
520}
521
522TEST(DexIndexTest, MatchQualifiedNamesWithGlobalScope) {
523 DexIndex I;
524 I.build(generateSymbols({"a::y1", "b::y2", "y3"}));
525 FuzzyFindRequest Req;
526 Req.Query = "y";
527 Req.Scopes = {""};
528 EXPECT_THAT(match(I, Req), UnorderedElementsAre("y3"));
529}
530
531TEST(DexIndexTest, MatchQualifiedNamesWithOneScope) {
532 DexIndex I;
533 I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}));
534 FuzzyFindRequest Req;
535 Req.Query = "y";
536 Req.Scopes = {"a::"};
537 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2"));
538}
539
540TEST(DexIndexTest, MatchQualifiedNamesWithMultipleScopes) {
541 DexIndex I;
542 I.build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}));
543 FuzzyFindRequest Req;
544 Req.Query = "y";
545 Req.Scopes = {"a::", "b::"};
546 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
547}
548
549TEST(DexIndexTest, NoMatchNestedScopes) {
550 DexIndex I;
551 I.build(generateSymbols({"a::y1", "a::b::y2"}));
552 FuzzyFindRequest Req;
553 Req.Query = "y";
554 Req.Scopes = {"a::"};
555 EXPECT_THAT(match(I, Req), UnorderedElementsAre("a::y1"));
556}
557
558TEST(DexIndexTest, IgnoreCases) {
559 DexIndex I;
560 I.build(generateSymbols({"ns::ABC", "ns::abc"}));
561 FuzzyFindRequest Req;
562 Req.Query = "AB";
563 Req.Scopes = {"ns::"};
564 EXPECT_THAT(match(I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
565}
566
567TEST(DexIndexTest, Lookup) {
568 DexIndex I;
569 I.build(generateSymbols({"ns::abc", "ns::xyz"}));
570 EXPECT_THAT(lookup(I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
571 EXPECT_THAT(lookup(I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
572 UnorderedElementsAre("ns::abc", "ns::xyz"));
573 EXPECT_THAT(lookup(I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
574 UnorderedElementsAre("ns::xyz"));
575 EXPECT_THAT(lookup(I, SymbolID("ns::nonono")), UnorderedElementsAre());
576}
577
578} // namespace
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000579} // namespace dex
580} // namespace clangd
581} // namespace clang