blob: 130659247805d10f68986023fc8534aeba07283b [file] [log] [blame]
Kirill Bobyrev5abe4782018-09-10 08:23:53 +00001//===-- DexTests.cpp ---------------------------------*- C++ -*-----------===//
Kirill Bobyrev5e82f052018-07-25 10:34:57 +00002//
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"
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000015#include "index/dex/Dex.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
Sam McCallc92e4f32018-10-09 10:02:02 +000026using ::testing::AnyOf;
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000027using ::testing::ElementsAre;
28using ::testing::UnorderedElementsAre;
Sam McCall9c7624e2018-09-03 14:37:43 +000029using namespace llvm;
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000030
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000031namespace clang {
32namespace clangd {
33namespace dex {
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000034namespace {
Kirill Bobyrevbea258d2018-07-26 10:42:31 +000035
Kirill Bobyrev19a94612018-09-06 12:54:43 +000036std::vector<std::string> URISchemes = {"unittest"};
37
38//===----------------------------------------------------------------------===//
39// Query iterator tests.
40//===----------------------------------------------------------------------===//
41
Kirill Bobyreva98961b2018-08-24 11:25:43 +000042std::vector<DocID> consumeIDs(Iterator &It) {
43 auto IDAndScore = consume(It);
Kirill Bobyrev7413e982018-08-22 13:44:15 +000044 std::vector<DocID> IDs(IDAndScore.size());
45 for (size_t I = 0; I < IDAndScore.size(); ++I)
46 IDs[I] = IDAndScore[I].first;
47 return IDs;
48}
49
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000050TEST(DexIterators, DocumentIterator) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +000051 const PostingList L({4, 7, 8, 20, 42, 100});
52 auto DocIterator = L.iterator();
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000053
54 EXPECT_EQ(DocIterator->peek(), 4U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000055 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000056
57 DocIterator->advance();
58 EXPECT_EQ(DocIterator->peek(), 7U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000059 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000060
61 DocIterator->advanceTo(20);
62 EXPECT_EQ(DocIterator->peek(), 20U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000063 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000064
65 DocIterator->advanceTo(65);
66 EXPECT_EQ(DocIterator->peek(), 100U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000067 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000068
69 DocIterator->advanceTo(420);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000070 EXPECT_TRUE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000071}
72
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000073TEST(DexIterators, AndTwoLists) {
Sam McCalla659d772018-10-02 19:59:23 +000074 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +000075 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
76 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000077
Sam McCalla659d772018-10-02 19:59:23 +000078 auto And = C.intersect(L1.iterator(), L0.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000079
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000080 EXPECT_FALSE(And->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +000081 EXPECT_THAT(consumeIDs(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000082
Sam McCalla659d772018-10-02 19:59:23 +000083 And = C.intersect(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000084
85 And->advanceTo(0);
86 EXPECT_EQ(And->peek(), 0U);
87 And->advanceTo(5);
88 EXPECT_EQ(And->peek(), 7U);
89 And->advanceTo(10);
90 EXPECT_EQ(And->peek(), 10U);
91 And->advanceTo(42);
92 EXPECT_EQ(And->peek(), 320U);
93 And->advanceTo(8999);
94 EXPECT_EQ(And->peek(), 9000U);
95 And->advanceTo(9001);
96}
97
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000098TEST(DexIterators, AndThreeLists) {
Sam McCalla659d772018-10-02 19:59:23 +000099 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000100 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
101 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
102 const PostingList L2({1, 4, 7, 11, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000103
Sam McCalla659d772018-10-02 19:59:23 +0000104 auto And = C.intersect(L0.iterator(), L1.iterator(), L2.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000105 EXPECT_EQ(And->peek(), 7U);
106 And->advanceTo(300);
107 EXPECT_EQ(And->peek(), 320U);
108 And->advanceTo(100000);
109
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000110 EXPECT_TRUE(And->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000111}
112
Sam McCall87f69eaf2018-10-04 13:12:23 +0000113TEST(DexIterators, AndEmpty) {
114 Corpus C{10000};
Sam McCalla4c17dd2018-10-04 16:05:22 +0000115 const PostingList L1{1};
116 const PostingList L2{2};
Sam McCall87f69eaf2018-10-04 13:12:23 +0000117 // These iterators are empty, but the optimizer can't tell.
118 auto Empty1 = C.intersect(L1.iterator(), L2.iterator());
119 auto Empty2 = C.intersect(L1.iterator(), L2.iterator());
120 // And syncs iterators on construction, and used to fail on empty children.
121 auto And = C.intersect(std::move(Empty1), std::move(Empty2));
122 EXPECT_TRUE(And->reachedEnd());
123}
124
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000125TEST(DexIterators, OrTwoLists) {
Sam McCalla659d772018-10-02 19:59:23 +0000126 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000127 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
128 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000129
Sam McCalla659d772018-10-02 19:59:23 +0000130 auto Or = C.unionOf(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000131
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000132 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000133 EXPECT_EQ(Or->peek(), 0U);
134 Or->advance();
135 EXPECT_EQ(Or->peek(), 4U);
136 Or->advance();
137 EXPECT_EQ(Or->peek(), 5U);
138 Or->advance();
139 EXPECT_EQ(Or->peek(), 7U);
140 Or->advance();
141 EXPECT_EQ(Or->peek(), 10U);
142 Or->advance();
143 EXPECT_EQ(Or->peek(), 30U);
144 Or->advanceTo(42);
145 EXPECT_EQ(Or->peek(), 42U);
146 Or->advanceTo(300);
147 EXPECT_EQ(Or->peek(), 320U);
148 Or->advanceTo(9000);
149 EXPECT_EQ(Or->peek(), 9000U);
150 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000151 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000152
Sam McCalla659d772018-10-02 19:59:23 +0000153 Or = C.unionOf(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000154
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000155 EXPECT_THAT(consumeIDs(*Or),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000156 ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
157}
158
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000159TEST(DexIterators, OrThreeLists) {
Sam McCalla659d772018-10-02 19:59:23 +0000160 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000161 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
162 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
163 const PostingList L2({1, 4, 7, 11, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000164
Sam McCalla659d772018-10-02 19:59:23 +0000165 auto Or = C.unionOf(L0.iterator(), L1.iterator(), L2.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000166
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000167 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000168 EXPECT_EQ(Or->peek(), 0U);
169
170 Or->advance();
171 EXPECT_EQ(Or->peek(), 1U);
172
173 Or->advance();
174 EXPECT_EQ(Or->peek(), 4U);
175
176 Or->advanceTo(7);
177
178 Or->advanceTo(59);
179 EXPECT_EQ(Or->peek(), 60U);
180
181 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000182 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000183}
184
185// FIXME(kbobyrev): The testcase below is similar to what is expected in real
186// queries. It should be updated once new iterators (such as boosting, limiting,
187// etc iterators) appear. However, it is not exhaustive and it would be
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000188// beneficial to implement automatic generation (e.g. fuzzing) of query trees
189// for more comprehensive testing.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000190TEST(DexIterators, QueryTree) {
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000191 //
192 // +-----------------+
193 // |And Iterator:1, 5|
194 // +--------+--------+
195 // |
196 // |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000197 // +-------------+----------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000198 // | |
199 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000200 // +----------v----------+ +----------v------------+
201 // |And Iterator: 1, 5, 9| |Or Iterator: 0, 1, 3, 5|
202 // +----------+----------+ +----------+------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000203 // | |
Kirill Bobyrev6c2f5bd2018-09-25 11:54:51 +0000204 // +------+-----+ ------------+
205 // | | | |
206 // +-------v-----+ +----+---+ +---v----+ +----v---+
207 // |1, 3, 5, 8, 9| |Boost: 2| |Boost: 3| |Boost: 4|
208 // +-------------+ +----+---+ +---+----+ +----+---+
209 // | | |
210 // +----v-----+ +-v--+ +---v---+
211 // |1, 5, 7, 9| |1, 5| |0, 3, 5|
212 // +----------+ +----+ +-------+
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000213 //
Sam McCalla659d772018-10-02 19:59:23 +0000214 Corpus C{10};
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000215 const PostingList L0({1, 3, 5, 8, 9});
216 const PostingList L1({1, 5, 7, 9});
Kirill Bobyrev6c2f5bd2018-09-25 11:54:51 +0000217 const PostingList L2({1, 5});
218 const PostingList L3({0, 3, 5});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000219
220 // Root of the query tree: [1, 5]
Sam McCalla659d772018-10-02 19:59:23 +0000221 auto Root = C.intersect(
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000222 // Lower And Iterator: [1, 5, 9]
Sam McCalla659d772018-10-02 19:59:23 +0000223 C.intersect(L0.iterator(), C.boost(L1.iterator(), 2U)),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000224 // Lower Or Iterator: [0, 1, 5]
Sam McCalla659d772018-10-02 19:59:23 +0000225 C.unionOf(C.boost(L2.iterator(), 3U), C.boost(L3.iterator(), 4U)));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000226
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000227 EXPECT_FALSE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000228 EXPECT_EQ(Root->peek(), 1U);
229 Root->advanceTo(0);
230 // Advance multiple times. Shouldn't do anything.
231 Root->advanceTo(1);
232 Root->advanceTo(0);
233 EXPECT_EQ(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000234 auto ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000235 EXPECT_THAT(ElementBoost, 6);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000236 Root->advance();
237 EXPECT_EQ(Root->peek(), 5U);
238 Root->advanceTo(5);
239 EXPECT_EQ(Root->peek(), 5U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000240 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000241 EXPECT_THAT(ElementBoost, 8);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000242 Root->advanceTo(9000);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000243 EXPECT_TRUE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000244}
245
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000246TEST(DexIterators, StringRepresentation) {
Sam McCalla659d772018-10-02 19:59:23 +0000247 Corpus C{10};
Sam McCall74028362018-10-02 11:51:36 +0000248 const PostingList L1({1, 3, 5});
249 const PostingList L2({1, 7, 9});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000250
Sam McCall74028362018-10-02 11:51:36 +0000251 // No token given, prints full posting list.
252 auto I1 = L1.iterator();
253 EXPECT_EQ(llvm::to_string(*I1), "[1 3 5]");
254
255 // Token given, uses token's string representation.
256 Token Tok(Token::Kind::Trigram, "L2");
257 auto I2 = L1.iterator(&Tok);
258 EXPECT_EQ(llvm::to_string(*I2), "T=L2");
259
Sam McCalla659d772018-10-02 19:59:23 +0000260 auto Tree = C.limit(C.intersect(move(I1), move(I2)), 10);
Sam McCallc92e4f32018-10-09 10:02:02 +0000261 // AND reorders its children, we don't care which order it prints.
262 EXPECT_THAT(llvm::to_string(*Tree), AnyOf("(LIMIT 10 (& [1 3 5] T=L2))",
263 "(LIMIT 10 (& T=L2 [1 3 5]))"));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000264}
265
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000266TEST(DexIterators, Limit) {
Sam McCalla659d772018-10-02 19:59:23 +0000267 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000268 const PostingList L0({3, 6, 7, 20, 42, 100});
269 const PostingList L1({1, 3, 5, 6, 7, 30, 100});
270 const PostingList L2({0, 3, 5, 7, 8, 100});
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000271
Sam McCalla659d772018-10-02 19:59:23 +0000272 auto DocIterator = C.limit(L0.iterator(), 42);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000273 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7, 20, 42, 100));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000274
Sam McCalla659d772018-10-02 19:59:23 +0000275 DocIterator = C.limit(L0.iterator(), 3);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000276 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000277
Sam McCalla659d772018-10-02 19:59:23 +0000278 DocIterator = C.limit(L0.iterator(), 0);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000279 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre());
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000280
Sam McCalla659d772018-10-02 19:59:23 +0000281 auto AndIterator =
282 C.intersect(C.limit(C.all(), 343), C.limit(L0.iterator(), 2),
283 C.limit(L1.iterator(), 3), C.limit(L2.iterator(), 42));
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000284 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(3, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000285}
286
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000287TEST(DexIterators, True) {
Sam McCall87f69eaf2018-10-04 13:12:23 +0000288 EXPECT_TRUE(Corpus{0}.all()->reachedEnd());
289 EXPECT_THAT(consumeIDs(*Corpus{4}.all()), ElementsAre(0, 1, 2, 3));
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000290}
291
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000292TEST(DexIterators, Boost) {
Sam McCalla659d772018-10-02 19:59:23 +0000293 Corpus C{5};
294 auto BoostIterator = C.boost(C.all(), 42U);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000295 EXPECT_FALSE(BoostIterator->reachedEnd());
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000296 auto ElementBoost = BoostIterator->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000297 EXPECT_THAT(ElementBoost, 42U);
298
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000299 const PostingList L0({2, 4});
300 const PostingList L1({1, 4});
Sam McCalla659d772018-10-02 19:59:23 +0000301 auto Root = C.unionOf(C.all(), C.boost(L0.iterator(), 2U),
302 C.boost(L1.iterator(), 3U));
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000303
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000304 ElementBoost = Root->consume();
Sam McCalla659d772018-10-02 19:59:23 +0000305 EXPECT_THAT(ElementBoost, 1);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000306 Root->advance();
307 EXPECT_THAT(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000308 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000309 EXPECT_THAT(ElementBoost, 3);
310
311 Root->advance();
312 EXPECT_THAT(Root->peek(), 2U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000313 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000314 EXPECT_THAT(ElementBoost, 2);
315
316 Root->advanceTo(4);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000317 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000318 EXPECT_THAT(ElementBoost, 3);
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000319}
320
Sam McCall87f69eaf2018-10-04 13:12:23 +0000321TEST(DexIterators, Optimizations) {
322 Corpus C{5};
Jonas Toth04514402018-10-04 16:29:58 +0000323 const PostingList L1{1};
324 const PostingList L2{2};
325 const PostingList L3{3};
Sam McCall87f69eaf2018-10-04 13:12:23 +0000326
327 // empty and/or yield true/false
328 EXPECT_EQ(llvm::to_string(*C.intersect()), "true");
329 EXPECT_EQ(llvm::to_string(*C.unionOf()), "false");
330
331 // true/false inside and/or short-circuit
332 EXPECT_EQ(llvm::to_string(*C.intersect(L1.iterator(), C.all())), "[1]");
333 EXPECT_EQ(llvm::to_string(*C.intersect(L1.iterator(), C.none())), "false");
334 // Not optimized to avoid breaking boosts.
335 EXPECT_EQ(llvm::to_string(*C.unionOf(L1.iterator(), C.all())),
336 "(| [1] true)");
337 EXPECT_EQ(llvm::to_string(*C.unionOf(L1.iterator(), C.none())), "[1]");
338
339 // and/or nested inside and/or are flattened
340 EXPECT_EQ(llvm::to_string(*C.intersect(
341 L1.iterator(), C.intersect(L1.iterator(), L1.iterator()))),
342 "(& [1] [1] [1])");
343 EXPECT_EQ(llvm::to_string(*C.unionOf(
344 L1.iterator(), C.unionOf(L2.iterator(), L3.iterator()))),
345 "(| [1] [2] [3])");
346
347 // optimizations combine over multiple levels
348 EXPECT_EQ(llvm::to_string(*C.intersect(
349 C.intersect(L1.iterator(), C.intersect()), C.unionOf(C.all()))),
350 "[1]");
351}
352
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000353//===----------------------------------------------------------------------===//
354// Search token tests.
355//===----------------------------------------------------------------------===//
356
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000357testing::Matcher<std::vector<Token>>
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000358tokensAre(std::initializer_list<std::string> Strings, Token::Kind Kind) {
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000359 std::vector<Token> Tokens;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000360 for (const auto &TokenData : Strings) {
361 Tokens.push_back(Token(Kind, TokenData));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000362 }
363 return testing::UnorderedElementsAreArray(Tokens);
364}
365
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000366testing::Matcher<std::vector<Token>>
367trigramsAre(std::initializer_list<std::string> Trigrams) {
368 return tokensAre(Trigrams, Token::Kind::Trigram);
369}
370
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000371TEST(DexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000372 EXPECT_THAT(generateIdentifierTrigrams("X86"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000373 trigramsAre({"x86", "x", "x8"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000374
Sam McCallb5bbfef2018-10-04 14:01:55 +0000375 EXPECT_THAT(generateIdentifierTrigrams("nl"), trigramsAre({"nl", "n"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000376
Sam McCallb5bbfef2018-10-04 14:01:55 +0000377 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000378
379 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000380 trigramsAre({"c", "cl", "cla", "lan", "ang", "ngd"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000381
382 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000383 trigramsAre({"a", "ab", "ad", "abc", "abd", "ade", "bcd", "bde",
384 "cde", "def"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000385
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000386 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
Sam McCall2ec5a102018-10-04 14:08:11 +0000387 trigramsAre({"a", "a_", "ab", "abc", "bcd", "cde"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000388
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000389 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000390 trigramsAre({"u", "un", "up", "uni", "unp", "upt", "niq", "nip",
391 "npt", "iqu", "iqp", "ipt", "que", "qup", "qpt",
392 "uep", "ept", "ptr"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000393
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000394 EXPECT_THAT(
395 generateIdentifierTrigrams("TUDecl"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000396 trigramsAre({"t", "tu", "td", "tud", "tde", "ude", "dec", "ecl"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000397
398 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000399 trigramsAre({"i", "is", "io", "iso", "iok", "sok"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000400
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000401 EXPECT_THAT(
402 generateIdentifierTrigrams("abc_defGhij__klm"),
Sam McCall2ec5a102018-10-04 14:08:11 +0000403 trigramsAre({"a", "ab", "ad", "abc", "abd", "ade", "adg", "bcd",
404 "bde", "bdg", "cde", "cdg", "def", "deg", "dgh", "dgk",
405 "efg", "egh", "egk", "fgh", "fgk", "ghi", "ghk", "gkl",
Sam McCallb5bbfef2018-10-04 14:01:55 +0000406 "hij", "hik", "hkl", "ijk", "ikl", "jkl", "klm"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000407}
408
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000409TEST(DexTrigrams, QueryTrigrams) {
Sam McCallb5bbfef2018-10-04 14:01:55 +0000410 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c"}));
411 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000412 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000413
Sam McCall50b89f02018-10-04 17:18:55 +0000414 EXPECT_THAT(generateQueryTrigrams(""), trigramsAre({}));
Sam McCallb5bbfef2018-10-04 14:01:55 +0000415 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_"}));
416 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__"}));
417 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000418
419 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000420
421 EXPECT_THAT(generateQueryTrigrams("clangd"),
422 trigramsAre({"cla", "lan", "ang", "ngd"}));
423
424 EXPECT_THAT(generateQueryTrigrams("abc_def"),
425 trigramsAre({"abc", "bcd", "cde", "def"}));
426
427 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
428 trigramsAre({"abc", "bcd", "cde"}));
429
430 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
431 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
432
433 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
434 trigramsAre({"tud", "ude", "dec", "ecl"}));
435
436 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
437
438 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
439 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
440 "hij", "ijk", "jkl", "klm"}));
441}
442
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000443TEST(DexSearchTokens, SymbolPath) {
444 EXPECT_THAT(generateProximityURIs(
445 "unittest:///clang-tools-extra/clangd/index/Token.h"),
446 ElementsAre("unittest:///clang-tools-extra/clangd/index/Token.h",
447 "unittest:///clang-tools-extra/clangd/index",
448 "unittest:///clang-tools-extra/clangd",
449 "unittest:///clang-tools-extra", "unittest:///"));
450
451 EXPECT_THAT(generateProximityURIs("unittest:///a/b/c.h"),
452 ElementsAre("unittest:///a/b/c.h", "unittest:///a/b",
453 "unittest:///a", "unittest:///"));
454}
455
456//===----------------------------------------------------------------------===//
457// Index tests.
458//===----------------------------------------------------------------------===//
459
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000460TEST(Dex, Lookup) {
Sam McCalld9eae392018-10-04 09:16:12 +0000461 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), RefSlab(),
462 URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000463 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
464 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000465 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000466 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000467 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000468 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000469}
470
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000471TEST(Dex, FuzzyFind) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000472 auto Index =
473 Dex::build(generateSymbols({"ns::ABC", "ns::BCD", "::ABC",
474 "ns::nested::ABC", "other::ABC", "other::A"}),
Sam McCalld9eae392018-10-04 09:16:12 +0000475 RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000476 FuzzyFindRequest Req;
477 Req.Query = "ABC";
478 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000479 EXPECT_THAT(match(*Index, Req), UnorderedElementsAre("ns::ABC"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000480 Req.Scopes = {"ns::", "ns::nested::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000481 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000482 UnorderedElementsAre("ns::ABC", "ns::nested::ABC"));
483 Req.Query = "A";
484 Req.Scopes = {"other::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000485 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000486 UnorderedElementsAre("other::A", "other::ABC"));
487 Req.Query = "";
488 Req.Scopes = {};
Sam McCall9c7624e2018-09-03 14:37:43 +0000489 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000490 UnorderedElementsAre("ns::ABC", "ns::BCD", "::ABC",
491 "ns::nested::ABC", "other::ABC",
492 "other::A"));
493}
494
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000495// FIXME(kbobyrev): This test is different for Dex and MemIndex: while
496// MemIndex manages response deduplication, Dex simply returns all matched
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000497// symbols which means there might be equivalent symbols in the response.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000498// Before drop-in replacement of MemIndex with Dex happens, FileIndex
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000499// should handle deduplication instead.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000500TEST(DexTest, DexDeduplicate) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000501 std::vector<Symbol> Symbols = {symbol("1"), symbol("2"), symbol("3"),
502 symbol("2") /* duplicate */};
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000503 FuzzyFindRequest Req;
Sam McCall9c7624e2018-09-03 14:37:43 +0000504 Req.Query = "2";
Sam McCalld9eae392018-10-04 09:16:12 +0000505 Dex I(Symbols, RefSlab(), URISchemes);
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000506 EXPECT_FALSE(Req.Limit);
Sam McCall9c7624e2018-09-03 14:37:43 +0000507 EXPECT_THAT(match(I, Req), ElementsAre("2", "2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000508}
509
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000510TEST(DexTest, DexLimitedNumMatches) {
Sam McCalld9eae392018-10-04 09:16:12 +0000511 auto I = Dex::build(generateNumSymbols(0, 100), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000512 FuzzyFindRequest Req;
513 Req.Query = "5";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000514 Req.Limit = 3;
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000515 bool Incomplete;
Sam McCall9c7624e2018-09-03 14:37:43 +0000516 auto Matches = match(*I, Req, &Incomplete);
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000517 EXPECT_TRUE(Req.Limit);
518 EXPECT_EQ(Matches.size(), *Req.Limit);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000519 EXPECT_TRUE(Incomplete);
520}
521
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000522TEST(DexTest, FuzzyMatch) {
523 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000524 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}),
Sam McCalld9eae392018-10-04 09:16:12 +0000525 RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000526 FuzzyFindRequest Req;
527 Req.Query = "lol";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000528 Req.Limit = 2;
Sam McCall9c7624e2018-09-03 14:37:43 +0000529 EXPECT_THAT(match(*I, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000530 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
531}
532
Sam McCallb5bbfef2018-10-04 14:01:55 +0000533TEST(DexTest, ShortQuery) {
534 auto I =
535 Dex::build(generateSymbols({"OneTwoThreeFour"}), RefSlab(), URISchemes);
536 FuzzyFindRequest Req;
537 bool Incomplete;
538
539 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre("OneTwoThreeFour"));
540 EXPECT_FALSE(Incomplete) << "Empty string is not a short query";
541
542 Req.Query = "t";
543 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre());
544 EXPECT_TRUE(Incomplete) << "Short queries have different semantics";
545
546 Req.Query = "tt";
547 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre());
548 EXPECT_TRUE(Incomplete) << "Short queries have different semantics";
549
550 Req.Query = "ttf";
551 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre("OneTwoThreeFour"));
552 EXPECT_FALSE(Incomplete) << "3-char string is not a short query";
553}
Sam McCallb5bbfef2018-10-04 14:01:55 +0000554
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000555TEST(DexTest, MatchQualifiedNamesWithoutSpecificScope) {
Sam McCalld9eae392018-10-04 09:16:12 +0000556 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), RefSlab(),
557 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000558 FuzzyFindRequest Req;
559 Req.Query = "y";
Sam McCall9c7624e2018-09-03 14:37:43 +0000560 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000561}
562
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000563TEST(DexTest, MatchQualifiedNamesWithGlobalScope) {
Sam McCalld9eae392018-10-04 09:16:12 +0000564 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), RefSlab(),
565 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000566 FuzzyFindRequest Req;
567 Req.Query = "y";
568 Req.Scopes = {""};
Sam McCall9c7624e2018-09-03 14:37:43 +0000569 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000570}
571
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000572TEST(DexTest, MatchQualifiedNamesWithOneScope) {
Sam McCalld9eae392018-10-04 09:16:12 +0000573 auto I =
574 Dex::build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}),
575 RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000576 FuzzyFindRequest Req;
577 Req.Query = "y";
578 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000579 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000580}
581
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000582TEST(DexTest, MatchQualifiedNamesWithMultipleScopes) {
583 auto I = Dex::build(
Sam McCalld9eae392018-10-04 09:16:12 +0000584 generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000585 FuzzyFindRequest Req;
586 Req.Query = "y";
587 Req.Scopes = {"a::", "b::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000588 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000589}
590
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000591TEST(DexTest, NoMatchNestedScopes) {
Sam McCalld9eae392018-10-04 09:16:12 +0000592 auto I = Dex::build(generateSymbols({"a::y1", "a::b::y2"}), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000593 FuzzyFindRequest Req;
594 Req.Query = "y";
595 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000596 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000597}
598
Eric Liu670c1472018-09-27 18:46:00 +0000599TEST(DexTest, WildcardScope) {
600 auto I =
Sam McCalld9eae392018-10-04 09:16:12 +0000601 Dex::build(generateSymbols({"a::y1", "a::b::y2", "c::y3"}), RefSlab(), URISchemes);
Eric Liu670c1472018-09-27 18:46:00 +0000602 FuzzyFindRequest Req;
603 Req.Query = "y";
604 Req.Scopes = {"a::"};
605 Req.AnyScope = true;
606 EXPECT_THAT(match(*I, Req),
607 UnorderedElementsAre("a::y1", "a::b::y2", "c::y3"));
608}
609
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000610TEST(DexTest, IgnoreCases) {
Sam McCalld9eae392018-10-04 09:16:12 +0000611 auto I = Dex::build(generateSymbols({"ns::ABC", "ns::abc"}), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000612 FuzzyFindRequest Req;
613 Req.Query = "AB";
614 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000615 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000616}
617
Sam McCall50b89f02018-10-04 17:18:55 +0000618TEST(DexTest, UnknownPostingList) {
619 // Regression test: we used to ignore unknown scopes and accept any symbol.
620 auto I = Dex::build(generateSymbols({"ns::ABC", "ns::abc"}), RefSlab(),
621 URISchemes);
622 FuzzyFindRequest Req;
623 Req.Scopes = {"ns2::"};
624 EXPECT_THAT(match(*I, Req), UnorderedElementsAre());
625}
626
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000627TEST(DexTest, Lookup) {
Sam McCalld9eae392018-10-04 09:16:12 +0000628 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), RefSlab(), URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000629 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
630 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000631 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000632 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000633 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000634 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000635}
636
Kirill Bobyrev94af0612018-09-24 08:45:18 +0000637TEST(DexTest, SymbolIndexOptionsFilter) {
638 auto CodeCompletionSymbol = symbol("Completion");
639 auto NonCodeCompletionSymbol = symbol("NoCompletion");
640 CodeCompletionSymbol.Flags = Symbol::SymbolFlag::IndexedForCodeCompletion;
641 NonCodeCompletionSymbol.Flags = Symbol::SymbolFlag::None;
642 std::vector<Symbol> Symbols{CodeCompletionSymbol, NonCodeCompletionSymbol};
Sam McCalld9eae392018-10-04 09:16:12 +0000643 Dex I(Symbols, RefSlab(), URISchemes);
Kirill Bobyrev94af0612018-09-24 08:45:18 +0000644 FuzzyFindRequest Req;
645 Req.RestrictForCodeCompletion = false;
646 EXPECT_THAT(match(I, Req), ElementsAre("Completion", "NoCompletion"));
647 Req.RestrictForCodeCompletion = true;
648 EXPECT_THAT(match(I, Req), ElementsAre("Completion"));
649}
650
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000651TEST(DexTest, ProximityPathsBoosting) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000652 auto RootSymbol = symbol("root::abc");
653 RootSymbol.CanonicalDeclaration.FileURI = "unittest:///file.h";
654 auto CloseSymbol = symbol("close::abc");
655 CloseSymbol.CanonicalDeclaration.FileURI = "unittest:///a/b/c/d/e/f/file.h";
656
657 std::vector<Symbol> Symbols{CloseSymbol, RootSymbol};
Sam McCalld9eae392018-10-04 09:16:12 +0000658 Dex I(Symbols, RefSlab(), URISchemes);
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000659
660 FuzzyFindRequest Req;
661 Req.Query = "abc";
662 // The best candidate can change depending on the proximity paths.
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000663 Req.Limit = 1;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000664
665 // FuzzyFind request comes from the file which is far from the root: expect
666 // CloseSymbol to come out.
667 Req.ProximityPaths = {testPath("a/b/c/d/e/f/file.h")};
668 EXPECT_THAT(match(I, Req), ElementsAre("close::abc"));
669
670 // FuzzyFind request comes from the file which is close to the root: expect
671 // RootSymbol to come out.
672 Req.ProximityPaths = {testPath("file.h")};
673 EXPECT_THAT(match(I, Req), ElementsAre("root::abc"));
674}
675
Sam McCalld9eae392018-10-04 09:16:12 +0000676TEST(DexTests, Refs) {
677 DenseMap<SymbolID, std::vector<Ref>> Refs;
678 auto AddRef = [&](const Symbol& Sym, StringRef Filename, RefKind Kind) {
679 auto& SymbolRefs = Refs[Sym.ID];
680 SymbolRefs.emplace_back();
681 SymbolRefs.back().Kind = Kind;
682 SymbolRefs.back().Location.FileURI = Filename;
683 };
684 auto Foo = symbol("foo");
685 auto Bar = symbol("bar");
686 AddRef(Foo, "foo.h", RefKind::Declaration);
687 AddRef(Foo, "reffoo.h", RefKind::Reference);
688 AddRef(Bar, "bar.h", RefKind::Declaration);
689
690 std::vector<std::string> Files;
691 RefsRequest Req;
692 Req.IDs.insert(Foo.ID);
693 Req.Filter = RefKind::Declaration | RefKind::Definition;
694 Dex(std::vector<Symbol>{Foo, Bar}, Refs, {}).refs(Req, [&](const Ref &R) {
695 Files.push_back(R.Location.FileURI);
696 });
697
698 EXPECT_THAT(Files, ElementsAre("foo.h"));
699}
700
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000701} // namespace
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000702} // namespace dex
703} // namespace clangd
704} // namespace clang