blob: fe7f101375028dad0707706c0ed34bd75c65a872 [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 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"
15#include "index/dex/DexIndex.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 Bobyreva522c1c2018-07-27 09:54:27 +000049TEST(DexIndexIterators, DocumentIterator) {
50 const PostingList L = {4, 7, 8, 20, 42, 100};
51 auto DocIterator = create(L);
52
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
72TEST(DexIndexIterators, AndWithEmpty) {
73 const PostingList L0;
74 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
75
76 auto AndEmpty = createAnd(create(L0));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000077 EXPECT_TRUE(AndEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000078
79 auto AndWithEmpty = createAnd(create(L0), create(L1));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000080 EXPECT_TRUE(AndWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000081
Kirill Bobyrev7413e982018-08-22 13:44:15 +000082 EXPECT_THAT(consumeIDs(*AndWithEmpty), ElementsAre());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000083}
84
85TEST(DexIndexIterators, AndTwoLists) {
86 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
87 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
88
89 auto And = createAnd(create(L1), create(L0));
90
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000091 EXPECT_FALSE(And->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +000092 EXPECT_THAT(consumeIDs(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000093
94 And = createAnd(create(L0), create(L1));
95
96 And->advanceTo(0);
97 EXPECT_EQ(And->peek(), 0U);
98 And->advanceTo(5);
99 EXPECT_EQ(And->peek(), 7U);
100 And->advanceTo(10);
101 EXPECT_EQ(And->peek(), 10U);
102 And->advanceTo(42);
103 EXPECT_EQ(And->peek(), 320U);
104 And->advanceTo(8999);
105 EXPECT_EQ(And->peek(), 9000U);
106 And->advanceTo(9001);
107}
108
109TEST(DexIndexIterators, AndThreeLists) {
110 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
111 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
112 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
113
114 auto And = createAnd(create(L0), create(L1), create(L2));
115 EXPECT_EQ(And->peek(), 7U);
116 And->advanceTo(300);
117 EXPECT_EQ(And->peek(), 320U);
118 And->advanceTo(100000);
119
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000120 EXPECT_TRUE(And->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000121}
122
123TEST(DexIndexIterators, OrWithEmpty) {
124 const PostingList L0;
125 const PostingList L1 = {0, 5, 7, 10, 42, 320, 9000};
126
127 auto OrEmpty = createOr(create(L0));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000128 EXPECT_TRUE(OrEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000129
130 auto OrWithEmpty = createOr(create(L0), create(L1));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000131 EXPECT_FALSE(OrWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000132
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000133 EXPECT_THAT(consumeIDs(*OrWithEmpty),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000134 ElementsAre(0U, 5U, 7U, 10U, 42U, 320U, 9000U));
135}
136
137TEST(DexIndexIterators, OrTwoLists) {
138 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
139 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
140
141 auto Or = createOr(create(L0), create(L1));
142
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000143 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000144 EXPECT_EQ(Or->peek(), 0U);
145 Or->advance();
146 EXPECT_EQ(Or->peek(), 4U);
147 Or->advance();
148 EXPECT_EQ(Or->peek(), 5U);
149 Or->advance();
150 EXPECT_EQ(Or->peek(), 7U);
151 Or->advance();
152 EXPECT_EQ(Or->peek(), 10U);
153 Or->advance();
154 EXPECT_EQ(Or->peek(), 30U);
155 Or->advanceTo(42);
156 EXPECT_EQ(Or->peek(), 42U);
157 Or->advanceTo(300);
158 EXPECT_EQ(Or->peek(), 320U);
159 Or->advanceTo(9000);
160 EXPECT_EQ(Or->peek(), 9000U);
161 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000162 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000163
164 Or = createOr(create(L0), create(L1));
165
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000166 EXPECT_THAT(consumeIDs(*Or),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000167 ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
168}
169
170TEST(DexIndexIterators, OrThreeLists) {
171 const PostingList L0 = {0, 5, 7, 10, 42, 320, 9000};
172 const PostingList L1 = {0, 4, 7, 10, 30, 60, 320, 9000};
173 const PostingList L2 = {1, 4, 7, 11, 30, 60, 320, 9000};
174
175 auto Or = createOr(create(L0), create(L1), create(L2));
176
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000177 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000178 EXPECT_EQ(Or->peek(), 0U);
179
180 Or->advance();
181 EXPECT_EQ(Or->peek(), 1U);
182
183 Or->advance();
184 EXPECT_EQ(Or->peek(), 4U);
185
186 Or->advanceTo(7);
187
188 Or->advanceTo(59);
189 EXPECT_EQ(Or->peek(), 60U);
190
191 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000192 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000193}
194
195// FIXME(kbobyrev): The testcase below is similar to what is expected in real
196// queries. It should be updated once new iterators (such as boosting, limiting,
197// etc iterators) appear. However, it is not exhaustive and it would be
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000198// beneficial to implement automatic generation (e.g. fuzzing) of query trees
199// for more comprehensive testing.
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000200TEST(DexIndexIterators, QueryTree) {
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000201 //
202 // +-----------------+
203 // |And Iterator:1, 5|
204 // +--------+--------+
205 // |
206 // |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000207 // +-------------+----------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000208 // | |
209 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000210 // +----------v----------+ +----------v------------+
211 // |And Iterator: 1, 5, 9| |Or Iterator: 0, 1, 3, 5|
212 // +----------+----------+ +----------+------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000213 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000214 // +------+-----+ +---------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000215 // | | | | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000216 // +-------v-----+ +----+---+ +--v--+ +---v----+ +----v---+
217 // |1, 3, 5, 8, 9| |Boost: 2| |Empty| |Boost: 3| |Boost: 4|
218 // +-------------+ +----+---+ +-----+ +---+----+ +----+---+
219 // | | |
220 // +----v-----+ +-v--+ +---v---+
221 // |1, 5, 7, 9| |1, 5| |0, 3, 5|
222 // +----------+ +----+ +-------+
223 //
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000224 const PostingList L0 = {1, 3, 5, 8, 9};
225 const PostingList L1 = {1, 5, 7, 9};
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000226 const PostingList L3;
227 const PostingList L4 = {1, 5};
228 const PostingList L5 = {0, 3, 5};
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000229
230 // Root of the query tree: [1, 5]
231 auto Root = createAnd(
232 // Lower And Iterator: [1, 5, 9]
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000233 createAnd(create(L0), createBoost(create(L1), 2U)),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000234 // Lower Or Iterator: [0, 1, 5]
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000235 createOr(create(L3), createBoost(create(L4), 3U),
236 createBoost(create(L5), 4U)));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000237
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000238 EXPECT_FALSE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000239 EXPECT_EQ(Root->peek(), 1U);
240 Root->advanceTo(0);
241 // Advance multiple times. Shouldn't do anything.
242 Root->advanceTo(1);
243 Root->advanceTo(0);
244 EXPECT_EQ(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000245 auto ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000246 EXPECT_THAT(ElementBoost, 6);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000247 Root->advance();
248 EXPECT_EQ(Root->peek(), 5U);
249 Root->advanceTo(5);
250 EXPECT_EQ(Root->peek(), 5U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000251 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000252 EXPECT_THAT(ElementBoost, 8);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000253 Root->advanceTo(9000);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000254 EXPECT_TRUE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000255}
256
257TEST(DexIndexIterators, StringRepresentation) {
258 const PostingList L0 = {4, 7, 8, 20, 42, 100};
259 const PostingList L1 = {1, 3, 5, 8, 9};
260 const PostingList L2 = {1, 5, 7, 9};
261 const PostingList L3 = {0, 5};
262 const PostingList L4 = {0, 1, 5};
263 const PostingList L5;
264
Kirill Bobyrev51534ab2018-08-16 13:19:43 +0000265 EXPECT_EQ(llvm::to_string(*(create(L0))), "[{4}, 7, 8, 20, 42, 100, END]");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000266
267 auto Nested = createAnd(createAnd(create(L1), create(L2)),
268 createOr(create(L3), create(L4), create(L5)));
269
270 EXPECT_EQ(llvm::to_string(*Nested),
Kirill Bobyrevbf3bc7112018-08-30 12:29:36 +0000271 "(& (| [0, {5}, END] [0, {1}, 5, END] [{END}]) (& [{1}, 5, 7, 9, "
Kirill Bobyrev38bdac52018-08-30 11:23:58 +0000272 "END] [{1}, 3, 5, 8, 9, END]))");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000273}
274
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000275TEST(DexIndexIterators, Limit) {
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000276 const PostingList L0 = {3, 6, 7, 20, 42, 100};
277 const PostingList L1 = {1, 3, 5, 6, 7, 30, 100};
278 const PostingList L2 = {0, 3, 5, 7, 8, 100};
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000279
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000280 auto DocIterator = createLimit(create(L0), 42);
281 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7, 20, 42, 100));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000282
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000283 DocIterator = createLimit(create(L0), 3);
284 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000285
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000286 DocIterator = createLimit(create(L0), 0);
287 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre());
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000288
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000289 auto AndIterator =
290 createAnd(createLimit(createTrue(9000), 343), createLimit(create(L0), 2),
291 createLimit(create(L1), 3), createLimit(create(L2), 42));
292 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(3, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000293}
294
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000295TEST(DexIndexIterators, True) {
296 auto TrueIterator = createTrue(0U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000297 EXPECT_TRUE(TrueIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000298 EXPECT_THAT(consumeIDs(*TrueIterator), ElementsAre());
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000299
300 PostingList L0 = {1, 2, 5, 7};
301 TrueIterator = createTrue(7U);
302 EXPECT_THAT(TrueIterator->peek(), 0);
303 auto AndIterator = createAnd(create(L0), move(TrueIterator));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000304 EXPECT_FALSE(AndIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000305 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(1, 2, 5));
306}
307
308TEST(DexIndexIterators, Boost) {
309 auto BoostIterator = createBoost(createTrue(5U), 42U);
310 EXPECT_FALSE(BoostIterator->reachedEnd());
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000311 auto ElementBoost = BoostIterator->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000312 EXPECT_THAT(ElementBoost, 42U);
313
314 const PostingList L0 = {2, 4};
315 const PostingList L1 = {1, 4};
316 auto Root = createOr(createTrue(5U), createBoost(create(L0), 2U),
317 createBoost(create(L1), 3U));
318
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000319 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000320 EXPECT_THAT(ElementBoost, Iterator::DEFAULT_BOOST_SCORE);
321 Root->advance();
322 EXPECT_THAT(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000323 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000324 EXPECT_THAT(ElementBoost, 3);
325
326 Root->advance();
327 EXPECT_THAT(Root->peek(), 2U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000328 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000329 EXPECT_THAT(ElementBoost, 2);
330
331 Root->advanceTo(4);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000332 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000333 EXPECT_THAT(ElementBoost, 3);
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000334}
335
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000336//===----------------------------------------------------------------------===//
337// Search token tests.
338//===----------------------------------------------------------------------===//
339
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000340testing::Matcher<std::vector<Token>>
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000341tokensAre(std::initializer_list<std::string> Strings, Token::Kind Kind) {
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000342 std::vector<Token> Tokens;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000343 for (const auto &TokenData : Strings) {
344 Tokens.push_back(Token(Kind, TokenData));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000345 }
346 return testing::UnorderedElementsAreArray(Tokens);
347}
348
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000349testing::Matcher<std::vector<Token>>
350trigramsAre(std::initializer_list<std::string> Trigrams) {
351 return tokensAre(Trigrams, Token::Kind::Trigram);
352}
353
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000354TEST(DexIndexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000355 EXPECT_THAT(generateIdentifierTrigrams("X86"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000356 trigramsAre({"x86", "x$$", "x8$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000357
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000358 EXPECT_THAT(generateIdentifierTrigrams("nl"), trigramsAre({"nl$", "n$$"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000359
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000360 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000361
362 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000363 trigramsAre({"c$$", "cl$", "cla", "lan", "ang", "ngd"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000364
365 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000366 trigramsAre({"a$$", "abc", "abd", "ade", "bcd", "bde", "cde",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000367 "def", "ab$", "ad$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000368
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000369 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
370 trigramsAre({"a$$", "a_$", "a_b", "abc", "abd", "acd", "ace",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000371 "bcd", "bce", "bde", "cde", "ab$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000372
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000373 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
374 trigramsAre({"u$$", "uni", "unp", "upt", "niq", "nip", "npt",
375 "iqu", "iqp", "ipt", "que", "qup", "qpt", "uep",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000376 "ept", "ptr", "un$", "up$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000377
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000378 EXPECT_THAT(
379 generateIdentifierTrigrams("TUDecl"),
380 trigramsAre({"t$$", "tud", "tde", "ude", "dec", "ecl", "tu$", "td$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000381
382 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000383 trigramsAre({"i$$", "iso", "iok", "sok", "is$", "io$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000384
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000385 EXPECT_THAT(
386 generateIdentifierTrigrams("abc_defGhij__klm"),
387 trigramsAre({"a$$", "abc", "abd", "abg", "ade", "adg", "adk", "agh",
388 "agk", "bcd", "bcg", "bde", "bdg", "bdk", "bgh", "bgk",
389 "cde", "cdg", "cdk", "cgh", "cgk", "def", "deg", "dek",
390 "dgh", "dgk", "dkl", "efg", "efk", "egh", "egk", "ekl",
391 "fgh", "fgk", "fkl", "ghi", "ghk", "gkl", "hij", "hik",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000392 "hkl", "ijk", "ikl", "jkl", "klm", "ab$", "ad$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000393}
394
395TEST(DexIndexTrigrams, QueryTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000396 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c$$"}));
397 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl$"}));
398 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000399
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000400 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_$$"}));
401 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__$"}));
402 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({"___"}));
403
404 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000405
406 EXPECT_THAT(generateQueryTrigrams("clangd"),
407 trigramsAre({"cla", "lan", "ang", "ngd"}));
408
409 EXPECT_THAT(generateQueryTrigrams("abc_def"),
410 trigramsAre({"abc", "bcd", "cde", "def"}));
411
412 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
413 trigramsAre({"abc", "bcd", "cde"}));
414
415 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
416 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
417
418 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
419 trigramsAre({"tud", "ude", "dec", "ecl"}));
420
421 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
422
423 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
424 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
425 "hij", "ijk", "jkl", "klm"}));
426}
427
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000428TEST(DexSearchTokens, SymbolPath) {
429 EXPECT_THAT(generateProximityURIs(
430 "unittest:///clang-tools-extra/clangd/index/Token.h"),
431 ElementsAre("unittest:///clang-tools-extra/clangd/index/Token.h",
432 "unittest:///clang-tools-extra/clangd/index",
433 "unittest:///clang-tools-extra/clangd",
434 "unittest:///clang-tools-extra", "unittest:///"));
435
436 EXPECT_THAT(generateProximityURIs("unittest:///a/b/c.h"),
437 ElementsAre("unittest:///a/b/c.h", "unittest:///a/b",
438 "unittest:///a", "unittest:///"));
439}
440
441//===----------------------------------------------------------------------===//
442// Index tests.
443//===----------------------------------------------------------------------===//
444
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000445TEST(DexIndex, Lookup) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000446 auto I = DexIndex::build(generateSymbols({"ns::abc", "ns::xyz"}), URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000447 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
448 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000449 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000450 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000451 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000452 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000453}
454
455TEST(DexIndex, FuzzyFind) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000456 auto Index = DexIndex::build(
457 generateSymbols({"ns::ABC", "ns::BCD", "::ABC", "ns::nested::ABC",
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000458 "other::ABC", "other::A"}),
459 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000460 FuzzyFindRequest Req;
461 Req.Query = "ABC";
462 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000463 EXPECT_THAT(match(*Index, Req), UnorderedElementsAre("ns::ABC"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000464 Req.Scopes = {"ns::", "ns::nested::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000465 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000466 UnorderedElementsAre("ns::ABC", "ns::nested::ABC"));
467 Req.Query = "A";
468 Req.Scopes = {"other::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000469 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000470 UnorderedElementsAre("other::A", "other::ABC"));
471 Req.Query = "";
472 Req.Scopes = {};
Sam McCall9c7624e2018-09-03 14:37:43 +0000473 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000474 UnorderedElementsAre("ns::ABC", "ns::BCD", "::ABC",
475 "ns::nested::ABC", "other::ABC",
476 "other::A"));
477}
478
479TEST(DexIndexTest, FuzzyMatchQ) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000480 auto I = DexIndex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000481 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}),
482 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000483 FuzzyFindRequest Req;
484 Req.Query = "lol";
485 Req.MaxCandidateCount = 2;
Sam McCall9c7624e2018-09-03 14:37:43 +0000486 EXPECT_THAT(match(*I, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000487 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
488}
489
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000490// FIXME(kbobyrev): This test is different for DexIndex and MemIndex: while
491// MemIndex manages response deduplication, DexIndex simply returns all matched
492// symbols which means there might be equivalent symbols in the response.
493// Before drop-in replacement of MemIndex with DexIndex happens, FileIndex
494// should handle deduplication instead.
495TEST(DexIndexTest, DexIndexDeduplicate) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000496 std::vector<Symbol> Symbols = {symbol("1"), symbol("2"), symbol("3"),
497 symbol("2") /* duplicate */};
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000498 FuzzyFindRequest Req;
Sam McCall9c7624e2018-09-03 14:37:43 +0000499 Req.Query = "2";
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000500 DexIndex I(Symbols, URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000501 EXPECT_THAT(match(I, Req), ElementsAre("2", "2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000502}
503
504TEST(DexIndexTest, DexIndexLimitedNumMatches) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000505 auto I = DexIndex::build(generateNumSymbols(0, 100), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000506 FuzzyFindRequest Req;
507 Req.Query = "5";
508 Req.MaxCandidateCount = 3;
509 bool Incomplete;
Sam McCall9c7624e2018-09-03 14:37:43 +0000510 auto Matches = match(*I, Req, &Incomplete);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000511 EXPECT_EQ(Matches.size(), Req.MaxCandidateCount);
512 EXPECT_TRUE(Incomplete);
513}
514
515TEST(DexIndexTest, FuzzyMatch) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000516 auto I = DexIndex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000517 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}),
518 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000519 FuzzyFindRequest Req;
520 Req.Query = "lol";
521 Req.MaxCandidateCount = 2;
Sam McCall9c7624e2018-09-03 14:37:43 +0000522 EXPECT_THAT(match(*I, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000523 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
524}
525
526TEST(DexIndexTest, MatchQualifiedNamesWithoutSpecificScope) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000527 auto I =
528 DexIndex::build(generateSymbols({"a::y1", "b::y2", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000529 FuzzyFindRequest Req;
530 Req.Query = "y";
Sam McCall9c7624e2018-09-03 14:37:43 +0000531 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000532}
533
534TEST(DexIndexTest, MatchQualifiedNamesWithGlobalScope) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000535 auto I =
536 DexIndex::build(generateSymbols({"a::y1", "b::y2", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000537 FuzzyFindRequest Req;
538 Req.Query = "y";
539 Req.Scopes = {""};
Sam McCall9c7624e2018-09-03 14:37:43 +0000540 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000541}
542
543TEST(DexIndexTest, MatchQualifiedNamesWithOneScope) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000544 auto I = DexIndex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000545 generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000546 FuzzyFindRequest Req;
547 Req.Query = "y";
548 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000549 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000550}
551
552TEST(DexIndexTest, MatchQualifiedNamesWithMultipleScopes) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000553 auto I = DexIndex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000554 generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000555 FuzzyFindRequest Req;
556 Req.Query = "y";
557 Req.Scopes = {"a::", "b::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000558 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000559}
560
561TEST(DexIndexTest, NoMatchNestedScopes) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000562 auto I = DexIndex::build(generateSymbols({"a::y1", "a::b::y2"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000563 FuzzyFindRequest Req;
564 Req.Query = "y";
565 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000566 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000567}
568
569TEST(DexIndexTest, IgnoreCases) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000570 auto I = DexIndex::build(generateSymbols({"ns::ABC", "ns::abc"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000571 FuzzyFindRequest Req;
572 Req.Query = "AB";
573 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000574 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000575}
576
577TEST(DexIndexTest, Lookup) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000578 auto I = DexIndex::build(generateSymbols({"ns::abc", "ns::xyz"}), URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000579 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
580 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000581 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000582 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000583 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000584 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000585}
586
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000587TEST(DexIndexTest, ProximityPathsBoosting) {
588 auto RootSymbol = symbol("root::abc");
589 RootSymbol.CanonicalDeclaration.FileURI = "unittest:///file.h";
590 auto CloseSymbol = symbol("close::abc");
591 CloseSymbol.CanonicalDeclaration.FileURI = "unittest:///a/b/c/d/e/f/file.h";
592
593 std::vector<Symbol> Symbols{CloseSymbol, RootSymbol};
594 DexIndex I(Symbols, URISchemes);
595
596 FuzzyFindRequest Req;
597 Req.Query = "abc";
598 // The best candidate can change depending on the proximity paths.
599 Req.MaxCandidateCount = 1;
600
601 // FuzzyFind request comes from the file which is far from the root: expect
602 // CloseSymbol to come out.
603 Req.ProximityPaths = {testPath("a/b/c/d/e/f/file.h")};
604 EXPECT_THAT(match(I, Req), ElementsAre("close::abc"));
605
606 // FuzzyFind request comes from the file which is close to the root: expect
607 // RootSymbol to come out.
608 Req.ProximityPaths = {testPath("file.h")};
609 EXPECT_THAT(match(I, Req), ElementsAre("root::abc"));
610}
611
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000612} // namespace
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000613} // namespace dex
614} // namespace clangd
615} // namespace clang