blob: 02eb9a283ba89713f8362f959334864a87e7cd53 [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
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 Bobyrev5abe4782018-09-10 08:23:53 +000049TEST(DexIterators, DocumentIterator) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +000050 const PostingList L({4, 7, 8, 20, 42, 100});
51 auto DocIterator = L.iterator();
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000052
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
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000072TEST(DexIterators, AndTwoLists) {
Sam McCalla659d772018-10-02 19:59:23 +000073 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +000074 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
75 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000076
Sam McCalla659d772018-10-02 19:59:23 +000077 auto And = C.intersect(L1.iterator(), L0.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000078
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000079 EXPECT_FALSE(And->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +000080 EXPECT_THAT(consumeIDs(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000081
Sam McCalla659d772018-10-02 19:59:23 +000082 And = C.intersect(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000083
84 And->advanceTo(0);
85 EXPECT_EQ(And->peek(), 0U);
86 And->advanceTo(5);
87 EXPECT_EQ(And->peek(), 7U);
88 And->advanceTo(10);
89 EXPECT_EQ(And->peek(), 10U);
90 And->advanceTo(42);
91 EXPECT_EQ(And->peek(), 320U);
92 And->advanceTo(8999);
93 EXPECT_EQ(And->peek(), 9000U);
94 And->advanceTo(9001);
95}
96
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000097TEST(DexIterators, AndThreeLists) {
Sam McCalla659d772018-10-02 19:59:23 +000098 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +000099 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
100 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
101 const PostingList L2({1, 4, 7, 11, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000102
Sam McCalla659d772018-10-02 19:59:23 +0000103 auto And = C.intersect(L0.iterator(), L1.iterator(), L2.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000104 EXPECT_EQ(And->peek(), 7U);
105 And->advanceTo(300);
106 EXPECT_EQ(And->peek(), 320U);
107 And->advanceTo(100000);
108
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000109 EXPECT_TRUE(And->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000110}
111
Sam McCall87f69eaf2018-10-04 13:12:23 +0000112TEST(DexIterators, AndEmpty) {
113 Corpus C{10000};
Sam McCalla4c17dd2018-10-04 16:05:22 +0000114 const PostingList L1{1};
115 const PostingList L2{2};
Sam McCall87f69eaf2018-10-04 13:12:23 +0000116 // These iterators are empty, but the optimizer can't tell.
117 auto Empty1 = C.intersect(L1.iterator(), L2.iterator());
118 auto Empty2 = C.intersect(L1.iterator(), L2.iterator());
119 // And syncs iterators on construction, and used to fail on empty children.
120 auto And = C.intersect(std::move(Empty1), std::move(Empty2));
121 EXPECT_TRUE(And->reachedEnd());
122}
123
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000124TEST(DexIterators, OrTwoLists) {
Sam McCalla659d772018-10-02 19:59:23 +0000125 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000126 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
127 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000128
Sam McCalla659d772018-10-02 19:59:23 +0000129 auto Or = C.unionOf(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000130
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000131 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000132 EXPECT_EQ(Or->peek(), 0U);
133 Or->advance();
134 EXPECT_EQ(Or->peek(), 4U);
135 Or->advance();
136 EXPECT_EQ(Or->peek(), 5U);
137 Or->advance();
138 EXPECT_EQ(Or->peek(), 7U);
139 Or->advance();
140 EXPECT_EQ(Or->peek(), 10U);
141 Or->advance();
142 EXPECT_EQ(Or->peek(), 30U);
143 Or->advanceTo(42);
144 EXPECT_EQ(Or->peek(), 42U);
145 Or->advanceTo(300);
146 EXPECT_EQ(Or->peek(), 320U);
147 Or->advanceTo(9000);
148 EXPECT_EQ(Or->peek(), 9000U);
149 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000150 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000151
Sam McCalla659d772018-10-02 19:59:23 +0000152 Or = C.unionOf(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000153
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000154 EXPECT_THAT(consumeIDs(*Or),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000155 ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
156}
157
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000158TEST(DexIterators, OrThreeLists) {
Sam McCalla659d772018-10-02 19:59:23 +0000159 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000160 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
161 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
162 const PostingList L2({1, 4, 7, 11, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000163
Sam McCalla659d772018-10-02 19:59:23 +0000164 auto Or = C.unionOf(L0.iterator(), L1.iterator(), L2.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000165
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000166 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000167 EXPECT_EQ(Or->peek(), 0U);
168
169 Or->advance();
170 EXPECT_EQ(Or->peek(), 1U);
171
172 Or->advance();
173 EXPECT_EQ(Or->peek(), 4U);
174
175 Or->advanceTo(7);
176
177 Or->advanceTo(59);
178 EXPECT_EQ(Or->peek(), 60U);
179
180 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000181 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000182}
183
184// FIXME(kbobyrev): The testcase below is similar to what is expected in real
185// queries. It should be updated once new iterators (such as boosting, limiting,
186// etc iterators) appear. However, it is not exhaustive and it would be
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000187// beneficial to implement automatic generation (e.g. fuzzing) of query trees
188// for more comprehensive testing.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000189TEST(DexIterators, QueryTree) {
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000190 //
191 // +-----------------+
192 // |And Iterator:1, 5|
193 // +--------+--------+
194 // |
195 // |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000196 // +-------------+----------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000197 // | |
198 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000199 // +----------v----------+ +----------v------------+
200 // |And Iterator: 1, 5, 9| |Or Iterator: 0, 1, 3, 5|
201 // +----------+----------+ +----------+------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000202 // | |
Kirill Bobyrev6c2f5bd2018-09-25 11:54:51 +0000203 // +------+-----+ ------------+
204 // | | | |
205 // +-------v-----+ +----+---+ +---v----+ +----v---+
206 // |1, 3, 5, 8, 9| |Boost: 2| |Boost: 3| |Boost: 4|
207 // +-------------+ +----+---+ +---+----+ +----+---+
208 // | | |
209 // +----v-----+ +-v--+ +---v---+
210 // |1, 5, 7, 9| |1, 5| |0, 3, 5|
211 // +----------+ +----+ +-------+
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000212 //
Sam McCalla659d772018-10-02 19:59:23 +0000213 Corpus C{10};
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000214 const PostingList L0({1, 3, 5, 8, 9});
215 const PostingList L1({1, 5, 7, 9});
Kirill Bobyrev6c2f5bd2018-09-25 11:54:51 +0000216 const PostingList L2({1, 5});
217 const PostingList L3({0, 3, 5});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000218
219 // Root of the query tree: [1, 5]
Sam McCalla659d772018-10-02 19:59:23 +0000220 auto Root = C.intersect(
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000221 // Lower And Iterator: [1, 5, 9]
Sam McCalla659d772018-10-02 19:59:23 +0000222 C.intersect(L0.iterator(), C.boost(L1.iterator(), 2U)),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000223 // Lower Or Iterator: [0, 1, 5]
Sam McCalla659d772018-10-02 19:59:23 +0000224 C.unionOf(C.boost(L2.iterator(), 3U), C.boost(L3.iterator(), 4U)));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000225
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000226 EXPECT_FALSE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000227 EXPECT_EQ(Root->peek(), 1U);
228 Root->advanceTo(0);
229 // Advance multiple times. Shouldn't do anything.
230 Root->advanceTo(1);
231 Root->advanceTo(0);
232 EXPECT_EQ(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000233 auto ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000234 EXPECT_THAT(ElementBoost, 6);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000235 Root->advance();
236 EXPECT_EQ(Root->peek(), 5U);
237 Root->advanceTo(5);
238 EXPECT_EQ(Root->peek(), 5U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000239 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000240 EXPECT_THAT(ElementBoost, 8);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000241 Root->advanceTo(9000);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000242 EXPECT_TRUE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000243}
244
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000245TEST(DexIterators, StringRepresentation) {
Sam McCalla659d772018-10-02 19:59:23 +0000246 Corpus C{10};
Sam McCall74028362018-10-02 11:51:36 +0000247 const PostingList L1({1, 3, 5});
248 const PostingList L2({1, 7, 9});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000249
Sam McCall74028362018-10-02 11:51:36 +0000250 // No token given, prints full posting list.
251 auto I1 = L1.iterator();
252 EXPECT_EQ(llvm::to_string(*I1), "[1 3 5]");
253
254 // Token given, uses token's string representation.
255 Token Tok(Token::Kind::Trigram, "L2");
256 auto I2 = L1.iterator(&Tok);
257 EXPECT_EQ(llvm::to_string(*I2), "T=L2");
258
Sam McCalla659d772018-10-02 19:59:23 +0000259 auto Tree = C.limit(C.intersect(move(I1), move(I2)), 10);
Sam McCall74028362018-10-02 11:51:36 +0000260 EXPECT_EQ(llvm::to_string(*Tree), "(LIMIT 10 (& [1 3 5] T=L2))");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000261}
262
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000263TEST(DexIterators, Limit) {
Sam McCalla659d772018-10-02 19:59:23 +0000264 Corpus C{10000};
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000265 const PostingList L0({3, 6, 7, 20, 42, 100});
266 const PostingList L1({1, 3, 5, 6, 7, 30, 100});
267 const PostingList L2({0, 3, 5, 7, 8, 100});
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000268
Sam McCalla659d772018-10-02 19:59:23 +0000269 auto DocIterator = C.limit(L0.iterator(), 42);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000270 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7, 20, 42, 100));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000271
Sam McCalla659d772018-10-02 19:59:23 +0000272 DocIterator = C.limit(L0.iterator(), 3);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000273 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000274
Sam McCalla659d772018-10-02 19:59:23 +0000275 DocIterator = C.limit(L0.iterator(), 0);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000276 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre());
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000277
Sam McCalla659d772018-10-02 19:59:23 +0000278 auto AndIterator =
279 C.intersect(C.limit(C.all(), 343), C.limit(L0.iterator(), 2),
280 C.limit(L1.iterator(), 3), C.limit(L2.iterator(), 42));
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000281 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(3, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000282}
283
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000284TEST(DexIterators, True) {
Sam McCall87f69eaf2018-10-04 13:12:23 +0000285 EXPECT_TRUE(Corpus{0}.all()->reachedEnd());
286 EXPECT_THAT(consumeIDs(*Corpus{4}.all()), ElementsAre(0, 1, 2, 3));
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000287}
288
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000289TEST(DexIterators, Boost) {
Sam McCalla659d772018-10-02 19:59:23 +0000290 Corpus C{5};
291 auto BoostIterator = C.boost(C.all(), 42U);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000292 EXPECT_FALSE(BoostIterator->reachedEnd());
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000293 auto ElementBoost = BoostIterator->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000294 EXPECT_THAT(ElementBoost, 42U);
295
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000296 const PostingList L0({2, 4});
297 const PostingList L1({1, 4});
Sam McCalla659d772018-10-02 19:59:23 +0000298 auto Root = C.unionOf(C.all(), C.boost(L0.iterator(), 2U),
299 C.boost(L1.iterator(), 3U));
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000300
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000301 ElementBoost = Root->consume();
Sam McCalla659d772018-10-02 19:59:23 +0000302 EXPECT_THAT(ElementBoost, 1);
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000303 Root->advance();
304 EXPECT_THAT(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000305 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000306 EXPECT_THAT(ElementBoost, 3);
307
308 Root->advance();
309 EXPECT_THAT(Root->peek(), 2U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000310 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000311 EXPECT_THAT(ElementBoost, 2);
312
313 Root->advanceTo(4);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000314 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000315 EXPECT_THAT(ElementBoost, 3);
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000316}
317
Sam McCall87f69eaf2018-10-04 13:12:23 +0000318TEST(DexIterators, Optimizations) {
319 Corpus C{5};
320 const PostingList L1({1});
321 const PostingList L2({2});
322 const PostingList L3({3});
323
324 // empty and/or yield true/false
325 EXPECT_EQ(llvm::to_string(*C.intersect()), "true");
326 EXPECT_EQ(llvm::to_string(*C.unionOf()), "false");
327
328 // true/false inside and/or short-circuit
329 EXPECT_EQ(llvm::to_string(*C.intersect(L1.iterator(), C.all())), "[1]");
330 EXPECT_EQ(llvm::to_string(*C.intersect(L1.iterator(), C.none())), "false");
331 // Not optimized to avoid breaking boosts.
332 EXPECT_EQ(llvm::to_string(*C.unionOf(L1.iterator(), C.all())),
333 "(| [1] true)");
334 EXPECT_EQ(llvm::to_string(*C.unionOf(L1.iterator(), C.none())), "[1]");
335
336 // and/or nested inside and/or are flattened
337 EXPECT_EQ(llvm::to_string(*C.intersect(
338 L1.iterator(), C.intersect(L1.iterator(), L1.iterator()))),
339 "(& [1] [1] [1])");
340 EXPECT_EQ(llvm::to_string(*C.unionOf(
341 L1.iterator(), C.unionOf(L2.iterator(), L3.iterator()))),
342 "(| [1] [2] [3])");
343
344 // optimizations combine over multiple levels
345 EXPECT_EQ(llvm::to_string(*C.intersect(
346 C.intersect(L1.iterator(), C.intersect()), C.unionOf(C.all()))),
347 "[1]");
348}
349
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000350//===----------------------------------------------------------------------===//
351// Search token tests.
352//===----------------------------------------------------------------------===//
353
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000354testing::Matcher<std::vector<Token>>
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000355tokensAre(std::initializer_list<std::string> Strings, Token::Kind Kind) {
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000356 std::vector<Token> Tokens;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000357 for (const auto &TokenData : Strings) {
358 Tokens.push_back(Token(Kind, TokenData));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000359 }
360 return testing::UnorderedElementsAreArray(Tokens);
361}
362
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000363testing::Matcher<std::vector<Token>>
364trigramsAre(std::initializer_list<std::string> Trigrams) {
365 return tokensAre(Trigrams, Token::Kind::Trigram);
366}
367
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000368TEST(DexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000369 EXPECT_THAT(generateIdentifierTrigrams("X86"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000370 trigramsAre({"x86", "x", "x8"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000371
Sam McCallb5bbfef2018-10-04 14:01:55 +0000372 EXPECT_THAT(generateIdentifierTrigrams("nl"), trigramsAre({"nl", "n"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000373
Sam McCallb5bbfef2018-10-04 14:01:55 +0000374 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000375
376 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000377 trigramsAre({"c", "cl", "cla", "lan", "ang", "ngd"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000378
379 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000380 trigramsAre({"a", "ab", "ad", "abc", "abd", "ade", "bcd", "bde",
381 "cde", "def"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000382
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000383 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
Sam McCall2ec5a102018-10-04 14:08:11 +0000384 trigramsAre({"a", "a_", "ab", "abc", "bcd", "cde"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000385
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000386 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000387 trigramsAre({"u", "un", "up", "uni", "unp", "upt", "niq", "nip",
388 "npt", "iqu", "iqp", "ipt", "que", "qup", "qpt",
389 "uep", "ept", "ptr"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000390
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000391 EXPECT_THAT(
392 generateIdentifierTrigrams("TUDecl"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000393 trigramsAre({"t", "tu", "td", "tud", "tde", "ude", "dec", "ecl"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000394
395 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000396 trigramsAre({"i", "is", "io", "iso", "iok", "sok"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000397
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000398 EXPECT_THAT(
399 generateIdentifierTrigrams("abc_defGhij__klm"),
Sam McCall2ec5a102018-10-04 14:08:11 +0000400 trigramsAre({"a", "ab", "ad", "abc", "abd", "ade", "adg", "bcd",
401 "bde", "bdg", "cde", "cdg", "def", "deg", "dgh", "dgk",
402 "efg", "egh", "egk", "fgh", "fgk", "ghi", "ghk", "gkl",
Sam McCallb5bbfef2018-10-04 14:01:55 +0000403 "hij", "hik", "hkl", "ijk", "ikl", "jkl", "klm"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000404}
405
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000406TEST(DexTrigrams, QueryTrigrams) {
Sam McCallb5bbfef2018-10-04 14:01:55 +0000407 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c"}));
408 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000409 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000410
Sam McCallb5bbfef2018-10-04 14:01:55 +0000411 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_"}));
412 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__"}));
413 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000414
415 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000416
417 EXPECT_THAT(generateQueryTrigrams("clangd"),
418 trigramsAre({"cla", "lan", "ang", "ngd"}));
419
420 EXPECT_THAT(generateQueryTrigrams("abc_def"),
421 trigramsAre({"abc", "bcd", "cde", "def"}));
422
423 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
424 trigramsAre({"abc", "bcd", "cde"}));
425
426 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
427 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
428
429 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
430 trigramsAre({"tud", "ude", "dec", "ecl"}));
431
432 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
433
434 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
435 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
436 "hij", "ijk", "jkl", "klm"}));
437}
438
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000439TEST(DexSearchTokens, SymbolPath) {
440 EXPECT_THAT(generateProximityURIs(
441 "unittest:///clang-tools-extra/clangd/index/Token.h"),
442 ElementsAre("unittest:///clang-tools-extra/clangd/index/Token.h",
443 "unittest:///clang-tools-extra/clangd/index",
444 "unittest:///clang-tools-extra/clangd",
445 "unittest:///clang-tools-extra", "unittest:///"));
446
447 EXPECT_THAT(generateProximityURIs("unittest:///a/b/c.h"),
448 ElementsAre("unittest:///a/b/c.h", "unittest:///a/b",
449 "unittest:///a", "unittest:///"));
450}
451
452//===----------------------------------------------------------------------===//
453// Index tests.
454//===----------------------------------------------------------------------===//
455
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000456TEST(Dex, Lookup) {
Sam McCalld9eae392018-10-04 09:16:12 +0000457 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), RefSlab(),
458 URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000459 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
460 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000461 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000462 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000463 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000464 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000465}
466
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000467TEST(Dex, FuzzyFind) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000468 auto Index =
469 Dex::build(generateSymbols({"ns::ABC", "ns::BCD", "::ABC",
470 "ns::nested::ABC", "other::ABC", "other::A"}),
Sam McCalld9eae392018-10-04 09:16:12 +0000471 RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000472 FuzzyFindRequest Req;
473 Req.Query = "ABC";
474 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000475 EXPECT_THAT(match(*Index, Req), UnorderedElementsAre("ns::ABC"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000476 Req.Scopes = {"ns::", "ns::nested::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000477 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000478 UnorderedElementsAre("ns::ABC", "ns::nested::ABC"));
479 Req.Query = "A";
480 Req.Scopes = {"other::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000481 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000482 UnorderedElementsAre("other::A", "other::ABC"));
483 Req.Query = "";
484 Req.Scopes = {};
Sam McCall9c7624e2018-09-03 14:37:43 +0000485 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000486 UnorderedElementsAre("ns::ABC", "ns::BCD", "::ABC",
487 "ns::nested::ABC", "other::ABC",
488 "other::A"));
489}
490
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000491// FIXME(kbobyrev): This test is different for Dex and MemIndex: while
492// MemIndex manages response deduplication, Dex simply returns all matched
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000493// symbols which means there might be equivalent symbols in the response.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000494// Before drop-in replacement of MemIndex with Dex happens, FileIndex
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000495// should handle deduplication instead.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000496TEST(DexTest, DexDeduplicate) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000497 std::vector<Symbol> Symbols = {symbol("1"), symbol("2"), symbol("3"),
498 symbol("2") /* duplicate */};
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000499 FuzzyFindRequest Req;
Sam McCall9c7624e2018-09-03 14:37:43 +0000500 Req.Query = "2";
Sam McCalld9eae392018-10-04 09:16:12 +0000501 Dex I(Symbols, RefSlab(), URISchemes);
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000502 EXPECT_FALSE(Req.Limit);
Sam McCall9c7624e2018-09-03 14:37:43 +0000503 EXPECT_THAT(match(I, Req), ElementsAre("2", "2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000504}
505
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000506TEST(DexTest, DexLimitedNumMatches) {
Sam McCalld9eae392018-10-04 09:16:12 +0000507 auto I = Dex::build(generateNumSymbols(0, 100), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000508 FuzzyFindRequest Req;
509 Req.Query = "5";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000510 Req.Limit = 3;
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000511 bool Incomplete;
Sam McCall9c7624e2018-09-03 14:37:43 +0000512 auto Matches = match(*I, Req, &Incomplete);
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000513 EXPECT_TRUE(Req.Limit);
514 EXPECT_EQ(Matches.size(), *Req.Limit);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000515 EXPECT_TRUE(Incomplete);
516}
517
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000518TEST(DexTest, FuzzyMatch) {
519 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000520 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}),
Sam McCalld9eae392018-10-04 09:16:12 +0000521 RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000522 FuzzyFindRequest Req;
523 Req.Query = "lol";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000524 Req.Limit = 2;
Sam McCall9c7624e2018-09-03 14:37:43 +0000525 EXPECT_THAT(match(*I, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000526 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
527}
528
Sam McCallb5bbfef2018-10-04 14:01:55 +0000529// TODO(sammccall): enable after D52796 bugfix.
530#if 0
531TEST(DexTest, ShortQuery) {
532 auto I =
533 Dex::build(generateSymbols({"OneTwoThreeFour"}), RefSlab(), URISchemes);
534 FuzzyFindRequest Req;
535 bool Incomplete;
536
537 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre("OneTwoThreeFour"));
538 EXPECT_FALSE(Incomplete) << "Empty string is not a short query";
539
540 Req.Query = "t";
541 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre());
542 EXPECT_TRUE(Incomplete) << "Short queries have different semantics";
543
544 Req.Query = "tt";
545 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre());
546 EXPECT_TRUE(Incomplete) << "Short queries have different semantics";
547
548 Req.Query = "ttf";
549 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre("OneTwoThreeFour"));
550 EXPECT_FALSE(Incomplete) << "3-char string is not a short query";
551}
552#endif
553
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000554TEST(DexTest, MatchQualifiedNamesWithoutSpecificScope) {
Sam McCalld9eae392018-10-04 09:16:12 +0000555 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), RefSlab(),
556 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000557 FuzzyFindRequest Req;
558 Req.Query = "y";
Sam McCall9c7624e2018-09-03 14:37:43 +0000559 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000560}
561
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000562TEST(DexTest, MatchQualifiedNamesWithGlobalScope) {
Sam McCalld9eae392018-10-04 09:16:12 +0000563 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), RefSlab(),
564 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000565 FuzzyFindRequest Req;
566 Req.Query = "y";
567 Req.Scopes = {""};
Sam McCall9c7624e2018-09-03 14:37:43 +0000568 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000569}
570
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000571TEST(DexTest, MatchQualifiedNamesWithOneScope) {
Sam McCalld9eae392018-10-04 09:16:12 +0000572 auto I =
573 Dex::build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}),
574 RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000575 FuzzyFindRequest Req;
576 Req.Query = "y";
577 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000578 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000579}
580
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000581TEST(DexTest, MatchQualifiedNamesWithMultipleScopes) {
582 auto I = Dex::build(
Sam McCalld9eae392018-10-04 09:16:12 +0000583 generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000584 FuzzyFindRequest Req;
585 Req.Query = "y";
586 Req.Scopes = {"a::", "b::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000587 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000588}
589
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000590TEST(DexTest, NoMatchNestedScopes) {
Sam McCalld9eae392018-10-04 09:16:12 +0000591 auto I = Dex::build(generateSymbols({"a::y1", "a::b::y2"}), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000592 FuzzyFindRequest Req;
593 Req.Query = "y";
594 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000595 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000596}
597
Eric Liu670c1472018-09-27 18:46:00 +0000598TEST(DexTest, WildcardScope) {
599 auto I =
Sam McCalld9eae392018-10-04 09:16:12 +0000600 Dex::build(generateSymbols({"a::y1", "a::b::y2", "c::y3"}), RefSlab(), URISchemes);
Eric Liu670c1472018-09-27 18:46:00 +0000601 FuzzyFindRequest Req;
602 Req.Query = "y";
603 Req.Scopes = {"a::"};
604 Req.AnyScope = true;
605 EXPECT_THAT(match(*I, Req),
606 UnorderedElementsAre("a::y1", "a::b::y2", "c::y3"));
607}
608
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000609TEST(DexTest, IgnoreCases) {
Sam McCalld9eae392018-10-04 09:16:12 +0000610 auto I = Dex::build(generateSymbols({"ns::ABC", "ns::abc"}), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000611 FuzzyFindRequest Req;
612 Req.Query = "AB";
613 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000614 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000615}
616
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000617TEST(DexTest, Lookup) {
Sam McCalld9eae392018-10-04 09:16:12 +0000618 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), RefSlab(), URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000619 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
620 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000621 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000622 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000623 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000624 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000625}
626
Kirill Bobyrev94af0612018-09-24 08:45:18 +0000627TEST(DexTest, SymbolIndexOptionsFilter) {
628 auto CodeCompletionSymbol = symbol("Completion");
629 auto NonCodeCompletionSymbol = symbol("NoCompletion");
630 CodeCompletionSymbol.Flags = Symbol::SymbolFlag::IndexedForCodeCompletion;
631 NonCodeCompletionSymbol.Flags = Symbol::SymbolFlag::None;
632 std::vector<Symbol> Symbols{CodeCompletionSymbol, NonCodeCompletionSymbol};
Sam McCalld9eae392018-10-04 09:16:12 +0000633 Dex I(Symbols, RefSlab(), URISchemes);
Kirill Bobyrev94af0612018-09-24 08:45:18 +0000634 FuzzyFindRequest Req;
635 Req.RestrictForCodeCompletion = false;
636 EXPECT_THAT(match(I, Req), ElementsAre("Completion", "NoCompletion"));
637 Req.RestrictForCodeCompletion = true;
638 EXPECT_THAT(match(I, Req), ElementsAre("Completion"));
639}
640
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000641TEST(DexTest, ProximityPathsBoosting) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000642 auto RootSymbol = symbol("root::abc");
643 RootSymbol.CanonicalDeclaration.FileURI = "unittest:///file.h";
644 auto CloseSymbol = symbol("close::abc");
645 CloseSymbol.CanonicalDeclaration.FileURI = "unittest:///a/b/c/d/e/f/file.h";
646
647 std::vector<Symbol> Symbols{CloseSymbol, RootSymbol};
Sam McCalld9eae392018-10-04 09:16:12 +0000648 Dex I(Symbols, RefSlab(), URISchemes);
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000649
650 FuzzyFindRequest Req;
651 Req.Query = "abc";
652 // The best candidate can change depending on the proximity paths.
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000653 Req.Limit = 1;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000654
655 // FuzzyFind request comes from the file which is far from the root: expect
656 // CloseSymbol to come out.
657 Req.ProximityPaths = {testPath("a/b/c/d/e/f/file.h")};
658 EXPECT_THAT(match(I, Req), ElementsAre("close::abc"));
659
660 // FuzzyFind request comes from the file which is close to the root: expect
661 // RootSymbol to come out.
662 Req.ProximityPaths = {testPath("file.h")};
663 EXPECT_THAT(match(I, Req), ElementsAre("root::abc"));
664}
665
Sam McCalld9eae392018-10-04 09:16:12 +0000666TEST(DexTests, Refs) {
667 DenseMap<SymbolID, std::vector<Ref>> Refs;
668 auto AddRef = [&](const Symbol& Sym, StringRef Filename, RefKind Kind) {
669 auto& SymbolRefs = Refs[Sym.ID];
670 SymbolRefs.emplace_back();
671 SymbolRefs.back().Kind = Kind;
672 SymbolRefs.back().Location.FileURI = Filename;
673 };
674 auto Foo = symbol("foo");
675 auto Bar = symbol("bar");
676 AddRef(Foo, "foo.h", RefKind::Declaration);
677 AddRef(Foo, "reffoo.h", RefKind::Reference);
678 AddRef(Bar, "bar.h", RefKind::Declaration);
679
680 std::vector<std::string> Files;
681 RefsRequest Req;
682 Req.IDs.insert(Foo.ID);
683 Req.Filter = RefKind::Declaration | RefKind::Definition;
684 Dex(std::vector<Symbol>{Foo, Bar}, Refs, {}).refs(Req, [&](const Ref &R) {
685 Files.push_back(R.Location.FileURI);
686 });
687
688 EXPECT_THAT(Files, ElementsAre("foo.h"));
689}
690
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000691} // namespace
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000692} // namespace dex
693} // namespace clangd
694} // namespace clang