blob: a022e96ae49aea0684b21ebdc6d263ce116ca058 [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;
29
Sam McCallc008af62018-10-20 15:30:37 +000030using namespace llvm;
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();
Sam McCallc008af62018-10-20 15:30:37 +0000253 EXPECT_EQ(to_string(*I1), "[1 3 5]");
Sam McCall74028362018-10-02 11:51:36 +0000254
255 // Token given, uses token's string representation.
256 Token Tok(Token::Kind::Trigram, "L2");
257 auto I2 = L1.iterator(&Tok);
Sam McCallc008af62018-10-20 15:30:37 +0000258 EXPECT_EQ(to_string(*I2), "T=L2");
Sam McCall74028362018-10-02 11:51:36 +0000259
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.
Sam McCallc008af62018-10-20 15:30:37 +0000262 EXPECT_THAT(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
Sam McCallc008af62018-10-20 15:30:37 +0000328 EXPECT_EQ(to_string(*C.intersect()), "true");
329 EXPECT_EQ(to_string(*C.unionOf()), "false");
Sam McCall87f69eaf2018-10-04 13:12:23 +0000330
331 // true/false inside and/or short-circuit
Sam McCallc008af62018-10-20 15:30:37 +0000332 EXPECT_EQ(to_string(*C.intersect(L1.iterator(), C.all())), "[1]");
333 EXPECT_EQ(to_string(*C.intersect(L1.iterator(), C.none())), "false");
Sam McCall87f69eaf2018-10-04 13:12:23 +0000334 // Not optimized to avoid breaking boosts.
Sam McCallc008af62018-10-20 15:30:37 +0000335 EXPECT_EQ(to_string(*C.unionOf(L1.iterator(), C.all())), "(| [1] true)");
336 EXPECT_EQ(to_string(*C.unionOf(L1.iterator(), C.none())), "[1]");
Sam McCall87f69eaf2018-10-04 13:12:23 +0000337
338 // and/or nested inside and/or are flattened
Sam McCallc008af62018-10-20 15:30:37 +0000339 EXPECT_EQ(to_string(*C.intersect(L1.iterator(),
340 C.intersect(L1.iterator(), L1.iterator()))),
Sam McCall87f69eaf2018-10-04 13:12:23 +0000341 "(& [1] [1] [1])");
Sam McCallc008af62018-10-20 15:30:37 +0000342 EXPECT_EQ(to_string(*C.unionOf(L1.iterator(),
343 C.unionOf(L2.iterator(), L3.iterator()))),
Sam McCall87f69eaf2018-10-04 13:12:23 +0000344 "(| [1] [2] [3])");
345
346 // optimizations combine over multiple levels
Sam McCallc008af62018-10-20 15:30:37 +0000347 EXPECT_EQ(to_string(*C.intersect(C.intersect(L1.iterator(), C.intersect()),
348 C.unionOf(C.all()))),
Sam McCall87f69eaf2018-10-04 13:12:23 +0000349 "[1]");
350}
351
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000352//===----------------------------------------------------------------------===//
353// Search token tests.
354//===----------------------------------------------------------------------===//
355
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000356testing::Matcher<std::vector<Token>>
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000357tokensAre(std::initializer_list<std::string> Strings, Token::Kind Kind) {
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000358 std::vector<Token> Tokens;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000359 for (const auto &TokenData : Strings) {
360 Tokens.push_back(Token(Kind, TokenData));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000361 }
362 return testing::UnorderedElementsAreArray(Tokens);
363}
364
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000365testing::Matcher<std::vector<Token>>
366trigramsAre(std::initializer_list<std::string> Trigrams) {
367 return tokensAre(Trigrams, Token::Kind::Trigram);
368}
369
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000370TEST(DexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000371 EXPECT_THAT(generateIdentifierTrigrams("X86"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000372 trigramsAre({"x86", "x", "x8"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000373
Sam McCallb5bbfef2018-10-04 14:01:55 +0000374 EXPECT_THAT(generateIdentifierTrigrams("nl"), trigramsAre({"nl", "n"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000375
Sam McCallb5bbfef2018-10-04 14:01:55 +0000376 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000377
378 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000379 trigramsAre({"c", "cl", "cla", "lan", "ang", "ngd"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000380
381 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000382 trigramsAre({"a", "ab", "ad", "abc", "abd", "ade", "bcd", "bde",
383 "cde", "def"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000384
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000385 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
Sam McCall2ec5a102018-10-04 14:08:11 +0000386 trigramsAre({"a", "a_", "ab", "abc", "bcd", "cde"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000387
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000388 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000389 trigramsAre({"u", "un", "up", "uni", "unp", "upt", "niq", "nip",
390 "npt", "iqu", "iqp", "ipt", "que", "qup", "qpt",
391 "uep", "ept", "ptr"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000392
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000393 EXPECT_THAT(
394 generateIdentifierTrigrams("TUDecl"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000395 trigramsAre({"t", "tu", "td", "tud", "tde", "ude", "dec", "ecl"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000396
397 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Sam McCallb5bbfef2018-10-04 14:01:55 +0000398 trigramsAre({"i", "is", "io", "iso", "iok", "sok"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000399
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000400 EXPECT_THAT(
401 generateIdentifierTrigrams("abc_defGhij__klm"),
Sam McCall2ec5a102018-10-04 14:08:11 +0000402 trigramsAre({"a", "ab", "ad", "abc", "abd", "ade", "adg", "bcd",
403 "bde", "bdg", "cde", "cdg", "def", "deg", "dgh", "dgk",
404 "efg", "egh", "egk", "fgh", "fgk", "ghi", "ghk", "gkl",
Sam McCallb5bbfef2018-10-04 14:01:55 +0000405 "hij", "hik", "hkl", "ijk", "ikl", "jkl", "klm"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000406}
407
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000408TEST(DexTrigrams, QueryTrigrams) {
Sam McCallb5bbfef2018-10-04 14:01:55 +0000409 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c"}));
410 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000411 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000412
Sam McCall50b89f02018-10-04 17:18:55 +0000413 EXPECT_THAT(generateQueryTrigrams(""), trigramsAre({}));
Sam McCallb5bbfef2018-10-04 14:01:55 +0000414 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_"}));
415 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__"}));
416 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000417
418 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000419
420 EXPECT_THAT(generateQueryTrigrams("clangd"),
421 trigramsAre({"cla", "lan", "ang", "ngd"}));
422
423 EXPECT_THAT(generateQueryTrigrams("abc_def"),
424 trigramsAre({"abc", "bcd", "cde", "def"}));
425
426 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
427 trigramsAre({"abc", "bcd", "cde"}));
428
429 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
430 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
431
432 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
433 trigramsAre({"tud", "ude", "dec", "ecl"}));
434
435 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
436
437 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
438 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
439 "hij", "ijk", "jkl", "klm"}));
440}
441
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000442TEST(DexSearchTokens, SymbolPath) {
443 EXPECT_THAT(generateProximityURIs(
444 "unittest:///clang-tools-extra/clangd/index/Token.h"),
445 ElementsAre("unittest:///clang-tools-extra/clangd/index/Token.h",
446 "unittest:///clang-tools-extra/clangd/index",
447 "unittest:///clang-tools-extra/clangd",
448 "unittest:///clang-tools-extra", "unittest:///"));
449
450 EXPECT_THAT(generateProximityURIs("unittest:///a/b/c.h"),
451 ElementsAre("unittest:///a/b/c.h", "unittest:///a/b",
452 "unittest:///a", "unittest:///"));
453}
454
455//===----------------------------------------------------------------------===//
456// Index tests.
457//===----------------------------------------------------------------------===//
458
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000459TEST(Dex, Lookup) {
Sam McCalld9eae392018-10-04 09:16:12 +0000460 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), RefSlab(),
461 URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000462 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
463 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000464 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000465 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000466 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000467 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000468}
469
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000470TEST(Dex, FuzzyFind) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000471 auto Index =
472 Dex::build(generateSymbols({"ns::ABC", "ns::BCD", "::ABC",
473 "ns::nested::ABC", "other::ABC", "other::A"}),
Sam McCalld9eae392018-10-04 09:16:12 +0000474 RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000475 FuzzyFindRequest Req;
476 Req.Query = "ABC";
477 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000478 EXPECT_THAT(match(*Index, Req), UnorderedElementsAre("ns::ABC"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000479 Req.Scopes = {"ns::", "ns::nested::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000480 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000481 UnorderedElementsAre("ns::ABC", "ns::nested::ABC"));
482 Req.Query = "A";
483 Req.Scopes = {"other::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000484 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000485 UnorderedElementsAre("other::A", "other::ABC"));
486 Req.Query = "";
487 Req.Scopes = {};
Sam McCall9c7624e2018-09-03 14:37:43 +0000488 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000489 UnorderedElementsAre("ns::ABC", "ns::BCD", "::ABC",
490 "ns::nested::ABC", "other::ABC",
491 "other::A"));
492}
493
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000494TEST(DexTest, DexDeduplicate) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000495 std::vector<Symbol> Symbols = {symbol("1"), symbol("2"), symbol("3"),
496 symbol("2") /* duplicate */};
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000497 FuzzyFindRequest Req;
Sam McCall9c7624e2018-09-03 14:37:43 +0000498 Req.Query = "2";
Sam McCalld9eae392018-10-04 09:16:12 +0000499 Dex I(Symbols, RefSlab(), URISchemes);
Sam McCall96f24892018-10-16 08:53:52 +0000500 EXPECT_THAT(match(I, Req), ElementsAre("2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000501}
502
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000503TEST(DexTest, DexLimitedNumMatches) {
Sam McCalld9eae392018-10-04 09:16:12 +0000504 auto I = Dex::build(generateNumSymbols(0, 100), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000505 FuzzyFindRequest Req;
506 Req.Query = "5";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000507 Req.Limit = 3;
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000508 bool Incomplete;
Sam McCall9c7624e2018-09-03 14:37:43 +0000509 auto Matches = match(*I, Req, &Incomplete);
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000510 EXPECT_TRUE(Req.Limit);
511 EXPECT_EQ(Matches.size(), *Req.Limit);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000512 EXPECT_TRUE(Incomplete);
513}
514
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000515TEST(DexTest, FuzzyMatch) {
516 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000517 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}),
Sam McCalld9eae392018-10-04 09:16:12 +0000518 RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000519 FuzzyFindRequest Req;
520 Req.Query = "lol";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000521 Req.Limit = 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
Sam McCallb5bbfef2018-10-04 14:01:55 +0000526TEST(DexTest, ShortQuery) {
527 auto I =
528 Dex::build(generateSymbols({"OneTwoThreeFour"}), RefSlab(), URISchemes);
529 FuzzyFindRequest Req;
530 bool Incomplete;
531
532 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre("OneTwoThreeFour"));
533 EXPECT_FALSE(Incomplete) << "Empty string is not a short query";
534
535 Req.Query = "t";
536 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre());
537 EXPECT_TRUE(Incomplete) << "Short queries have different semantics";
538
539 Req.Query = "tt";
540 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre());
541 EXPECT_TRUE(Incomplete) << "Short queries have different semantics";
542
543 Req.Query = "ttf";
544 EXPECT_THAT(match(*I, Req, &Incomplete), ElementsAre("OneTwoThreeFour"));
545 EXPECT_FALSE(Incomplete) << "3-char string is not a short query";
546}
Sam McCallb5bbfef2018-10-04 14:01:55 +0000547
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000548TEST(DexTest, MatchQualifiedNamesWithoutSpecificScope) {
Sam McCalld9eae392018-10-04 09:16:12 +0000549 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), RefSlab(),
550 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000551 FuzzyFindRequest Req;
552 Req.Query = "y";
Sam McCall9c7624e2018-09-03 14:37:43 +0000553 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000554}
555
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000556TEST(DexTest, MatchQualifiedNamesWithGlobalScope) {
Sam McCalld9eae392018-10-04 09:16:12 +0000557 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), RefSlab(),
558 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000559 FuzzyFindRequest Req;
560 Req.Query = "y";
561 Req.Scopes = {""};
Sam McCall9c7624e2018-09-03 14:37:43 +0000562 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000563}
564
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000565TEST(DexTest, MatchQualifiedNamesWithOneScope) {
Sam McCalld9eae392018-10-04 09:16:12 +0000566 auto I =
567 Dex::build(generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}),
568 RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000569 FuzzyFindRequest Req;
570 Req.Query = "y";
571 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000572 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000573}
574
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000575TEST(DexTest, MatchQualifiedNamesWithMultipleScopes) {
576 auto I = Dex::build(
Sam McCalld9eae392018-10-04 09:16:12 +0000577 generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000578 FuzzyFindRequest Req;
579 Req.Query = "y";
580 Req.Scopes = {"a::", "b::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000581 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000582}
583
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000584TEST(DexTest, NoMatchNestedScopes) {
Sam McCalld9eae392018-10-04 09:16:12 +0000585 auto I = Dex::build(generateSymbols({"a::y1", "a::b::y2"}), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000586 FuzzyFindRequest Req;
587 Req.Query = "y";
588 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000589 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000590}
591
Eric Liu670c1472018-09-27 18:46:00 +0000592TEST(DexTest, WildcardScope) {
593 auto I =
Sam McCalld9eae392018-10-04 09:16:12 +0000594 Dex::build(generateSymbols({"a::y1", "a::b::y2", "c::y3"}), RefSlab(), URISchemes);
Eric Liu670c1472018-09-27 18:46:00 +0000595 FuzzyFindRequest Req;
596 Req.Query = "y";
597 Req.Scopes = {"a::"};
598 Req.AnyScope = true;
599 EXPECT_THAT(match(*I, Req),
600 UnorderedElementsAre("a::y1", "a::b::y2", "c::y3"));
601}
602
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000603TEST(DexTest, IgnoreCases) {
Sam McCalld9eae392018-10-04 09:16:12 +0000604 auto I = Dex::build(generateSymbols({"ns::ABC", "ns::abc"}), RefSlab(), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000605 FuzzyFindRequest Req;
606 Req.Query = "AB";
607 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000608 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000609}
610
Sam McCall50b89f02018-10-04 17:18:55 +0000611TEST(DexTest, UnknownPostingList) {
612 // Regression test: we used to ignore unknown scopes and accept any symbol.
613 auto I = Dex::build(generateSymbols({"ns::ABC", "ns::abc"}), RefSlab(),
614 URISchemes);
615 FuzzyFindRequest Req;
616 Req.Scopes = {"ns2::"};
617 EXPECT_THAT(match(*I, Req), UnorderedElementsAre());
618}
619
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000620TEST(DexTest, Lookup) {
Sam McCalld9eae392018-10-04 09:16:12 +0000621 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), RefSlab(), URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000622 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
623 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000624 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000625 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000626 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000627 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000628}
629
Kirill Bobyrev94af0612018-09-24 08:45:18 +0000630TEST(DexTest, SymbolIndexOptionsFilter) {
631 auto CodeCompletionSymbol = symbol("Completion");
632 auto NonCodeCompletionSymbol = symbol("NoCompletion");
633 CodeCompletionSymbol.Flags = Symbol::SymbolFlag::IndexedForCodeCompletion;
634 NonCodeCompletionSymbol.Flags = Symbol::SymbolFlag::None;
635 std::vector<Symbol> Symbols{CodeCompletionSymbol, NonCodeCompletionSymbol};
Sam McCalld9eae392018-10-04 09:16:12 +0000636 Dex I(Symbols, RefSlab(), URISchemes);
Kirill Bobyrev94af0612018-09-24 08:45:18 +0000637 FuzzyFindRequest Req;
638 Req.RestrictForCodeCompletion = false;
639 EXPECT_THAT(match(I, Req), ElementsAre("Completion", "NoCompletion"));
640 Req.RestrictForCodeCompletion = true;
641 EXPECT_THAT(match(I, Req), ElementsAre("Completion"));
642}
643
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000644TEST(DexTest, ProximityPathsBoosting) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000645 auto RootSymbol = symbol("root::abc");
646 RootSymbol.CanonicalDeclaration.FileURI = "unittest:///file.h";
647 auto CloseSymbol = symbol("close::abc");
648 CloseSymbol.CanonicalDeclaration.FileURI = "unittest:///a/b/c/d/e/f/file.h";
649
650 std::vector<Symbol> Symbols{CloseSymbol, RootSymbol};
Sam McCalld9eae392018-10-04 09:16:12 +0000651 Dex I(Symbols, RefSlab(), URISchemes);
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000652
653 FuzzyFindRequest Req;
654 Req.Query = "abc";
655 // The best candidate can change depending on the proximity paths.
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000656 Req.Limit = 1;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000657
658 // FuzzyFind request comes from the file which is far from the root: expect
659 // CloseSymbol to come out.
660 Req.ProximityPaths = {testPath("a/b/c/d/e/f/file.h")};
661 EXPECT_THAT(match(I, Req), ElementsAre("close::abc"));
662
663 // FuzzyFind request comes from the file which is close to the root: expect
664 // RootSymbol to come out.
665 Req.ProximityPaths = {testPath("file.h")};
666 EXPECT_THAT(match(I, Req), ElementsAre("root::abc"));
667}
668
Sam McCalld9eae392018-10-04 09:16:12 +0000669TEST(DexTests, Refs) {
670 DenseMap<SymbolID, std::vector<Ref>> Refs;
671 auto AddRef = [&](const Symbol& Sym, StringRef Filename, RefKind Kind) {
672 auto& SymbolRefs = Refs[Sym.ID];
673 SymbolRefs.emplace_back();
674 SymbolRefs.back().Kind = Kind;
675 SymbolRefs.back().Location.FileURI = Filename;
676 };
677 auto Foo = symbol("foo");
678 auto Bar = symbol("bar");
679 AddRef(Foo, "foo.h", RefKind::Declaration);
680 AddRef(Foo, "reffoo.h", RefKind::Reference);
681 AddRef(Bar, "bar.h", RefKind::Declaration);
682
683 std::vector<std::string> Files;
684 RefsRequest Req;
685 Req.IDs.insert(Foo.ID);
686 Req.Filter = RefKind::Declaration | RefKind::Definition;
687 Dex(std::vector<Symbol>{Foo, Bar}, Refs, {}).refs(Req, [&](const Ref &R) {
688 Files.push_back(R.Location.FileURI);
689 });
690
691 EXPECT_THAT(Files, ElementsAre("foo.h"));
692}
693
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000694} // namespace
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000695} // namespace dex
696} // namespace clangd
697} // namespace clang