blob: 6a98f307269ac2c40f7064439ea0cb73ce3af91a [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 Bobyreva522c1c2018-07-27 09:54:27 +000010#include "index/dex/Iterator.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000011#include "index/dex/Token.h"
12#include "index/dex/Trigram.h"
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000013#include "llvm/Support/ScopedPrinter.h"
14#include "llvm/Support/raw_ostream.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000015#include "gmock/gmock.h"
16#include "gtest/gtest.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000017#include <string>
18#include <vector>
19
20namespace clang {
21namespace clangd {
22namespace dex {
23
Kirill Bobyrevbea258d2018-07-26 10:42:31 +000024using ::testing::ElementsAre;
25
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000026TEST(DexIndexIterators, DocumentIterator) {
27 const PostingList L = {4, 7, 8, 20, 42, 100};
28 auto DocIterator = create(L);
29
30 EXPECT_EQ(DocIterator->peek(), 4U);
31 EXPECT_EQ(DocIterator->reachedEnd(), false);
32
33 DocIterator->advance();
34 EXPECT_EQ(DocIterator->peek(), 7U);
35 EXPECT_EQ(DocIterator->reachedEnd(), false);
36
37 DocIterator->advanceTo(20);
38 EXPECT_EQ(DocIterator->peek(), 20U);
39 EXPECT_EQ(DocIterator->reachedEnd(), false);
40
41 DocIterator->advanceTo(65);
42 EXPECT_EQ(DocIterator->peek(), 100U);
43 EXPECT_EQ(DocIterator->reachedEnd(), false);
44
45 DocIterator->advanceTo(420);
46 EXPECT_EQ(DocIterator->reachedEnd(), true);
47}
48
49TEST(DexIndexIterators, AndWithEmpty) {
50 const PostingList L0;
51 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
52
53 auto AndEmpty = createAnd(create(L0));
54 EXPECT_EQ(AndEmpty->reachedEnd(), true);
55
56 auto AndWithEmpty = createAnd(create(L0), create(L1));
57 EXPECT_EQ(AndWithEmpty->reachedEnd(), true);
58
59 EXPECT_THAT(consume(*AndWithEmpty), ElementsAre());
60}
61
62TEST(DexIndexIterators, AndTwoLists) {
63 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
64 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
65
66 auto And = createAnd(create(L1), create(L0));
67
68 EXPECT_EQ(And->reachedEnd(), false);
69 EXPECT_THAT(consume(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
70
71 And = createAnd(create(L0), create(L1));
72
73 And->advanceTo(0);
74 EXPECT_EQ(And->peek(), 0U);
75 And->advanceTo(5);
76 EXPECT_EQ(And->peek(), 7U);
77 And->advanceTo(10);
78 EXPECT_EQ(And->peek(), 10U);
79 And->advanceTo(42);
80 EXPECT_EQ(And->peek(), 320U);
81 And->advanceTo(8999);
82 EXPECT_EQ(And->peek(), 9000U);
83 And->advanceTo(9001);
84}
85
86TEST(DexIndexIterators, AndThreeLists) {
87 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
88 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
89 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
90
91 auto And = createAnd(create(L0), create(L1), create(L2));
92 EXPECT_EQ(And->peek(), 7U);
93 And->advanceTo(300);
94 EXPECT_EQ(And->peek(), 320U);
95 And->advanceTo(100000);
96
97 EXPECT_EQ(And->reachedEnd(), true);
98}
99
100TEST(DexIndexIterators, OrWithEmpty) {
101 const PostingList L0;
102 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
103
104 auto OrEmpty = createOr(create(L0));
105 EXPECT_EQ(OrEmpty->reachedEnd(), true);
106
107 auto OrWithEmpty = createOr(create(L0), create(L1));
108 EXPECT_EQ(OrWithEmpty->reachedEnd(), false);
109
110 EXPECT_THAT(consume(*OrWithEmpty),
111 ElementsAre(0U, 5U, 7U, 10U, 42U, 320U, 9000U));
112}
113
114TEST(DexIndexIterators, OrTwoLists) {
115 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
116 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
117
118 auto Or = createOr(create(L0), create(L1));
119
120 EXPECT_EQ(Or->reachedEnd(), false);
121 EXPECT_EQ(Or->peek(), 0U);
122 Or->advance();
123 EXPECT_EQ(Or->peek(), 4U);
124 Or->advance();
125 EXPECT_EQ(Or->peek(), 5U);
126 Or->advance();
127 EXPECT_EQ(Or->peek(), 7U);
128 Or->advance();
129 EXPECT_EQ(Or->peek(), 10U);
130 Or->advance();
131 EXPECT_EQ(Or->peek(), 30U);
132 Or->advanceTo(42);
133 EXPECT_EQ(Or->peek(), 42U);
134 Or->advanceTo(300);
135 EXPECT_EQ(Or->peek(), 320U);
136 Or->advanceTo(9000);
137 EXPECT_EQ(Or->peek(), 9000U);
138 Or->advanceTo(9001);
139 EXPECT_EQ(Or->reachedEnd(), true);
140
141 Or = createOr(create(L0), create(L1));
142
143 EXPECT_THAT(consume(*Or),
144 ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
145}
146
147TEST(DexIndexIterators, OrThreeLists) {
148 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
149 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
150 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
151
152 auto Or = createOr(create(L0), create(L1), create(L2));
153
154 EXPECT_EQ(Or->reachedEnd(), false);
155 EXPECT_EQ(Or->peek(), 0U);
156
157 Or->advance();
158 EXPECT_EQ(Or->peek(), 1U);
159
160 Or->advance();
161 EXPECT_EQ(Or->peek(), 4U);
162
163 Or->advanceTo(7);
164
165 Or->advanceTo(59);
166 EXPECT_EQ(Or->peek(), 60U);
167
168 Or->advanceTo(9001);
169 EXPECT_EQ(Or->reachedEnd(), true);
170}
171
172// FIXME(kbobyrev): The testcase below is similar to what is expected in real
173// queries. It should be updated once new iterators (such as boosting, limiting,
174// etc iterators) appear. However, it is not exhaustive and it would be
175// beneficial to implement automatic generation of query trees for more
176// comprehensive testing.
177TEST(DexIndexIterators, QueryTree) {
178 // An example of more complicated query
179 //
180 // +-----------------+
181 // |And Iterator:1, 5|
182 // +--------+--------+
183 // |
184 // |
185 // +------------------------------------+
186 // | |
187 // | |
188 // +----------v----------+ +----------v---------+
189 // |And Iterator: 1, 5, 9| |Or Iterator: 0, 1, 5|
190 // +----------+----------+ +----------+---------+
191 // | |
192 // +------+-----+ +---------+-----------+
193 // | | | | |
194 // +-------v-----+ +----v-----+ +--v--+ +-V--+ +---v---+
195 // |1, 3, 5, 8, 9| |1, 5, 7, 9| |Empty| |0, 5| |0, 1, 5|
196 // +-------------+ +----------+ +-----+ +----+ +-------+
197
198 const PostingList L0 = {1, 3, 5, 8, 9};
199 const PostingList L1 = {1, 5, 7, 9};
200 const PostingList L2 = {0, 5};
201 const PostingList L3 = {0, 1, 5};
202 const PostingList L4;
203
204 // Root of the query tree: [1, 5]
205 auto Root = createAnd(
206 // Lower And Iterator: [1, 5, 9]
207 createAnd(create(L0), create(L1)),
208 // Lower Or Iterator: [0, 1, 5]
209 createOr(create(L2), create(L3), create(L4)));
210
211 EXPECT_EQ(Root->reachedEnd(), false);
212 EXPECT_EQ(Root->peek(), 1U);
213 Root->advanceTo(0);
214 // Advance multiple times. Shouldn't do anything.
215 Root->advanceTo(1);
216 Root->advanceTo(0);
217 EXPECT_EQ(Root->peek(), 1U);
218 Root->advance();
219 EXPECT_EQ(Root->peek(), 5U);
220 Root->advanceTo(5);
221 EXPECT_EQ(Root->peek(), 5U);
222 Root->advanceTo(9000);
223 EXPECT_EQ(Root->reachedEnd(), true);
224}
225
226TEST(DexIndexIterators, StringRepresentation) {
227 const PostingList L0 = {4, 7, 8, 20, 42, 100};
228 const PostingList L1 = {1, 3, 5, 8, 9};
229 const PostingList L2 = {1, 5, 7, 9};
230 const PostingList L3 = {0, 5};
231 const PostingList L4 = {0, 1, 5};
232 const PostingList L5;
233
Kirill Bobyrev51534ab2018-08-16 13:19:43 +0000234 EXPECT_EQ(llvm::to_string(*(create(L0))), "[{4}, 7, 8, 20, 42, 100, END]");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000235
236 auto Nested = createAnd(createAnd(create(L1), create(L2)),
237 createOr(create(L3), create(L4), create(L5)));
238
239 EXPECT_EQ(llvm::to_string(*Nested),
Kirill Bobyrev51534ab2018-08-16 13:19:43 +0000240 "(& (& [{1}, 3, 5, 8, 9, END] [{1}, 5, 7, 9, END]) (| [0, {5}, "
241 "END] [0, {1}, 5, END] [{END}]))");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000242}
243
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000244TEST(DexIndexIterators, Limit) {
245 const PostingList L0 = {4, 7, 8, 20, 42, 100};
246 const PostingList L1 = {1, 3, 5, 8, 9};
247 const PostingList L2 = {1, 5, 7, 9};
248 const PostingList L3 = {0, 5};
249 const PostingList L4 = {0, 1, 5};
250 const PostingList L5;
251
252 auto DocIterator = create(L0);
253 EXPECT_THAT(consume(*DocIterator, 42), ElementsAre(4, 7, 8, 20, 42, 100));
254
255 DocIterator = create(L0);
256 EXPECT_THAT(consume(*DocIterator), ElementsAre(4, 7, 8, 20, 42, 100));
257
258 DocIterator = create(L0);
259 EXPECT_THAT(consume(*DocIterator, 3), ElementsAre(4, 7, 8));
260
261 DocIterator = create(L0);
262 EXPECT_THAT(consume(*DocIterator, 0), ElementsAre());
263}
264
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000265TEST(DexIndexIterators, True) {
266 auto TrueIterator = createTrue(0U);
267 EXPECT_THAT(TrueIterator->reachedEnd(), true);
268 EXPECT_THAT(consume(*TrueIterator), ElementsAre());
269
270 PostingList L0 = {1, 2, 5, 7};
271 TrueIterator = createTrue(7U);
272 EXPECT_THAT(TrueIterator->peek(), 0);
273 auto AndIterator = createAnd(create(L0), move(TrueIterator));
274 EXPECT_THAT(AndIterator->reachedEnd(), false);
275 EXPECT_THAT(consume(*AndIterator), ElementsAre(1, 2, 5));
276}
277
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000278testing::Matcher<std::vector<Token>>
279trigramsAre(std::initializer_list<std::string> Trigrams) {
280 std::vector<Token> Tokens;
281 for (const auto &Symbols : Trigrams) {
282 Tokens.push_back(Token(Token::Kind::Trigram, Symbols));
283 }
284 return testing::UnorderedElementsAreArray(Tokens);
285}
286
287TEST(DexIndexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000288 EXPECT_THAT(generateIdentifierTrigrams("X86"),
289 trigramsAre({"x86", "x$$", "x8$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000290
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000291 EXPECT_THAT(generateIdentifierTrigrams("nl"),
292 trigramsAre({"nl$", "n$$", "$$$"}));
293
294 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n$$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000295
296 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000297 trigramsAre({"c$$", "cl$", "cla", "lan", "ang", "ngd", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000298
299 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000300 trigramsAre({"a$$", "abc", "abd", "ade", "bcd", "bde", "cde",
301 "def", "ab$", "ad$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000302
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000303 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
304 trigramsAre({"a$$", "a_$", "a_b", "abc", "abd", "acd", "ace",
305 "bcd", "bce", "bde", "cde", "ab$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000306
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000307 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
308 trigramsAre({"u$$", "uni", "unp", "upt", "niq", "nip", "npt",
309 "iqu", "iqp", "ipt", "que", "qup", "qpt", "uep",
310 "ept", "ptr", "un$", "up$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000311
312 EXPECT_THAT(generateIdentifierTrigrams("TUDecl"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000313 trigramsAre({"t$$", "tud", "tde", "ude", "dec", "ecl", "tu$",
314 "td$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000315
316 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000317 trigramsAre({"i$$", "iso", "iok", "sok", "is$", "io$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000318
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000319 EXPECT_THAT(
320 generateIdentifierTrigrams("abc_defGhij__klm"),
321 trigramsAre({"a$$", "abc", "abd", "abg", "ade", "adg", "adk", "agh",
322 "agk", "bcd", "bcg", "bde", "bdg", "bdk", "bgh", "bgk",
323 "cde", "cdg", "cdk", "cgh", "cgk", "def", "deg", "dek",
324 "dgh", "dgk", "dkl", "efg", "efk", "egh", "egk", "ekl",
325 "fgh", "fgk", "fkl", "ghi", "ghk", "gkl", "hij", "hik",
326 "hkl", "ijk", "ikl", "jkl", "klm", "ab$", "ad$", "$$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000327}
328
329TEST(DexIndexTrigrams, QueryTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000330 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c$$"}));
331 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl$"}));
332 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000333
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000334 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_$$"}));
335 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__$"}));
336 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({"___"}));
337
338 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000339
340 EXPECT_THAT(generateQueryTrigrams("clangd"),
341 trigramsAre({"cla", "lan", "ang", "ngd"}));
342
343 EXPECT_THAT(generateQueryTrigrams("abc_def"),
344 trigramsAre({"abc", "bcd", "cde", "def"}));
345
346 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
347 trigramsAre({"abc", "bcd", "cde"}));
348
349 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
350 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
351
352 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
353 trigramsAre({"tud", "ude", "dec", "ecl"}));
354
355 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
356
357 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
358 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
359 "hij", "ijk", "jkl", "klm"}));
360}
361
362} // namespace dex
363} // namespace clangd
364} // namespace clang