21#include "clang/Index/IndexSymbol.h"
22#include "llvm/ADT/SmallString.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/ADT/Twine.h"
25#include "llvm/Support/Error.h"
26#include "llvm/Support/Path.h"
27#include "llvm/Support/StringSaver.h"
28#include "gmock/gmock.h"
29#include "gtest/gtest.h"
37using llvm::sys::path::convert_to_slash;
39const char *testPathURI(llvm::StringRef
Path,
40 llvm::UniqueStringSaver &
Strings) {
42 return Strings.save(URI.toString()).begin();
45clangd::Symbol createSymbol(llvm::StringRef PathPrefix,
46 llvm::UniqueStringSaver &
Strings) {
50 index::SymbolInfo
Info;
51 Info.Kind = index::SymbolKind::Function;
52 Info.SubKind = index::SymbolSubKind::AccessorGetter;
53 Info.Lang = index::SymbolLanguage::CXX;
54 Info.Properties =
static_cast<index::SymbolPropertySet
>(
55 index::SymbolProperty::TemplateSpecialization);
59 Sym.Scope =
Strings.save(
"llvm::foo::bar::");
66 Location.FileURI = testPathURI(PathPrefix.str() +
"Definition.cpp",
Strings);
73 Location.FileURI = testPathURI(PathPrefix.str() +
"Declaration.h",
Strings);
76 Sym.References = 9000;
78 Sym.Signature =
Strings.save(
"(int X, char Y, Type T)");
79 Sym.TemplateSpecializationArgs =
Strings.save(
"<int, char, bool, Type>");
80 Sym.CompletionSnippetSuffix =
81 Strings.save(
"({1: int X}, {2: char Y}, {3: Type T})");
82 Sym.Documentation =
Strings.save(
"This is my amazing Foo constructor!");
83 Sym.ReturnType =
Strings.save(
"Foo");
90TEST(RemoteMarshallingTest, URITranslation) {
91 llvm::BumpPtrAllocator
Arena;
93 Marshaller ProtobufMarshaller(
94 testPath(
"remote/machine/projects/llvm-project/"),
95 testPath(
"home/my-projects/llvm-project/"));
97 Original.Location.FileURI =
98 testPathURI(
"remote/machine/projects/llvm-project/clang-tools-extra/"
99 "clangd/unittests/remote/MarshallingTests.cpp",
101 auto Serialized = ProtobufMarshaller.toProtobuf(Original);
102 ASSERT_TRUE(
bool(Serialized));
103 EXPECT_EQ(Serialized->location().file_path(),
104 "clang-tools-extra/clangd/unittests/remote/MarshallingTests.cpp");
105 auto Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);
106 ASSERT_TRUE(
bool(Deserialized));
107 EXPECT_STREQ(Deserialized->Location.FileURI,
108 testPathURI(
"home/my-projects/llvm-project/clang-tools-extra/"
109 "clangd/unittests/remote/MarshallingTests.cpp",
113 *Serialized->mutable_location()->mutable_file_path() = std::string();
114 Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);
115 EXPECT_FALSE(
bool(Deserialized));
116 llvm::consumeError(Deserialized.takeError());
118 clangd::Ref WithInvalidURI;
120 WithInvalidURI.Location.FileURI =
"This is not a URI";
121 auto DeserializedRef = ProtobufMarshaller.toProtobuf(WithInvalidURI);
122 EXPECT_FALSE(
bool(DeserializedRef));
123 llvm::consumeError(DeserializedRef.takeError());
128 ASSERT_TRUE(
bool(UnittestURI));
129 WithInvalidURI.Location.FileURI =
130 Strings.save(UnittestURI->toString()).begin();
131 auto DeserializedSymbol = ProtobufMarshaller.toProtobuf(WithInvalidURI);
132 EXPECT_FALSE(
bool(DeserializedSymbol));
133 llvm::consumeError(DeserializedSymbol.takeError());
137 Ref WithAbsolutePath;
138 *WithAbsolutePath.mutable_location()->mutable_file_path() =
139 "/usr/local/user/home/HelloWorld.cpp";
140 Deserialized = ProtobufMarshaller.fromProtobuf(WithAbsolutePath);
141 EXPECT_FALSE(
bool(Deserialized));
142 llvm::consumeError(Deserialized.takeError());
145TEST(RemoteMarshallingTest, SymbolSerialization) {
146 llvm::BumpPtrAllocator
Arena;
149 clangd::Symbol Sym = createSymbol(
"home/",
Strings);
154 auto Serialized = ProtobufMarshaller.toProtobuf(Sym);
155 ASSERT_TRUE(
bool(Serialized));
156 auto Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);
157 ASSERT_TRUE(
bool(Deserialized));
162 EXPECT_EQ(convert_to_slash(Serialized->definition().file_path(),
163 llvm::sys::path::Style::posix),
164 Serialized->definition().file_path());
166 llvm::sys::path::is_relative(Serialized->definition().file_path()));
169 Sym.Definition = clangd::SymbolLocation();
170 Serialized = ProtobufMarshaller.toProtobuf(Sym);
171 ASSERT_TRUE(
bool(Serialized));
172 ASSERT_TRUE(
bool(ProtobufMarshaller.fromProtobuf(*Serialized)));
175 *Serialized->mutable_canonical_declaration()->mutable_file_path() =
176 convert_to_slash(
"/path/to/Declaration.h");
177 Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);
178 EXPECT_FALSE(
bool(Deserialized));
179 llvm::consumeError(Deserialized.takeError());
182 Sym.Definition.FileURI =
"Not A URI";
183 Serialized = ProtobufMarshaller.toProtobuf(Sym);
184 EXPECT_FALSE(
bool(Serialized));
185 llvm::consumeError(Serialized.takeError());
189 ASSERT_TRUE(
bool(UnittestURI));
190 Sym.Definition.FileURI =
Strings.save(UnittestURI->toString()).begin();
191 Serialized = ProtobufMarshaller.toProtobuf(Sym);
192 EXPECT_FALSE(
bool(Serialized));
193 llvm::consumeError(Serialized.takeError());
196 Sym.Definition.FileURI = testPathURI(
"home/File.h",
Strings);
198 Serialized = ProtobufMarshaller.toProtobuf(Sym);
199 ASSERT_TRUE(
bool(Serialized));
200 Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);
201 ASSERT_TRUE(
bool(Deserialized));
202 EXPECT_STREQ(Deserialized->Definition.FileURI,
203 testPathURI(
"home/File.h",
Strings));
206 Serialized = WrongMarshaller.toProtobuf(Sym);
207 EXPECT_FALSE(Serialized);
208 llvm::consumeError(Serialized.takeError());
211TEST(RemoteMarshallingTest, RefSerialization) {
215 llvm::BumpPtrAllocator
Arena;
224 "llvm-project/llvm/clang-tools-extra/clangd/Protocol.h",
Strings);
227 Marshaller ProtobufMarshaller(
testPath(
"llvm-project/"),
230 auto Serialized = ProtobufMarshaller.toProtobuf(Ref);
231 ASSERT_TRUE(
bool(Serialized));
232 auto Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);
233 ASSERT_TRUE(
bool(Deserialized));
237TEST(RemoteMarshallingTest, IncludeHeaderURIs) {
238 llvm::BumpPtrAllocator
Arena;
241 clangd::Symbol Sym = createSymbol(
"remote/",
Strings);
243 clangd::Symbol::IncludeHeaderWithReferences Header;
245 Header.IncludeHeader =
247 Header.References = 21;
248 Sym.IncludeHeaders.push_back(Header);
249 Header.IncludeHeader =
Strings.save(
"<iostream>");
250 Header.References = 100;
251 Sym.IncludeHeaders.push_back(Header);
252 Header.IncludeHeader =
Strings.save(
"\"cstdio\"");
253 Header.References = 200;
254 Sym.IncludeHeaders.push_back(Header);
258 auto Serialized = ProtobufMarshaller.toProtobuf(Sym);
259 ASSERT_TRUE(
bool(Serialized));
260 EXPECT_EQ(
static_cast<size_t>(Serialized->headers_size()),
261 Sym.IncludeHeaders.size());
262 auto Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);
263 ASSERT_TRUE(
bool(Deserialized));
268 Header.IncludeHeader =
Strings.save(
testPath(
"project/include/Common.h"));
269 Header.References = 42;
270 Sym.IncludeHeaders.push_back(Header);
271 Serialized = ProtobufMarshaller.toProtobuf(Sym);
272 EXPECT_FALSE(
bool(Serialized));
273 llvm::consumeError(Serialized.takeError());
276 Sym.IncludeHeaders.pop_back();
278 Header.IncludeHeader =
Strings.save(
"NotAHeader");
279 Header.References = 5;
280 Sym.IncludeHeaders.push_back(Header);
281 Serialized = ProtobufMarshaller.toProtobuf(Sym);
282 EXPECT_FALSE(
bool(Serialized));
283 llvm::consumeError(Serialized.takeError());
286 Sym.IncludeHeaders.pop_back();
287 Serialized = ProtobufMarshaller.toProtobuf(Sym);
288 ASSERT_TRUE(
bool(Serialized));
289 HeaderWithReferences InvalidHeader;
290 InvalidHeader.set_header(convert_to_slash(
"/absolute/path/Header.h"));
291 InvalidHeader.set_references(9000);
292 *Serialized->add_headers() = InvalidHeader;
293 Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);
294 EXPECT_FALSE(
bool(Deserialized));
295 llvm::consumeError(Deserialized.takeError());
298TEST(RemoteMarshallingTest, LookupRequestSerialization) {
299 clangd::LookupRequest Request;
305 auto Serialized = ProtobufMarshaller.toProtobuf(Request);
306 EXPECT_EQ(
static_cast<unsigned>(Serialized.ids_size()), Request.IDs.size());
307 auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);
308 ASSERT_TRUE(
bool(Deserialized));
309 EXPECT_EQ(Deserialized->IDs, Request.IDs);
312TEST(RemoteMarshallingTest, LookupRequestFailingSerialization) {
313 clangd::LookupRequest Request;
315 auto Serialized = ProtobufMarshaller.toProtobuf(Request);
316 Serialized.add_ids(
"Invalid Symbol ID");
317 auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);
318 EXPECT_FALSE(
bool(Deserialized));
319 llvm::consumeError(Deserialized.takeError());
322TEST(RemoteMarshallingTest, FuzzyFindRequestSerialization) {
323 clangd::FuzzyFindRequest Request;
324 Request.ProximityPaths = {
testPath(
"local/Header.h"),
325 testPath(
"local/subdir/OtherHeader.h"),
326 testPath(
"remote/File.h"),
"Not a Path."};
328 auto Serialized = ProtobufMarshaller.toProtobuf(Request);
329 EXPECT_EQ(Serialized.proximity_paths_size(), 2);
330 auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);
331 ASSERT_TRUE(
bool(Deserialized));
332 EXPECT_THAT(Deserialized->ProximityPaths,
333 testing::ElementsAre(
testPath(
"remote/Header.h"),
334 testPath(
"remote/subdir/OtherHeader.h")));
337TEST(RemoteMarshallingTest, RefsRequestSerialization) {
338 clangd::RefsRequest Request;
342 Request.Limit = 9000;
347 auto Serialized = ProtobufMarshaller.toProtobuf(Request);
348 EXPECT_EQ(
static_cast<unsigned>(Serialized.ids_size()), Request.IDs.size());
349 EXPECT_EQ(Serialized.limit(), Request.Limit);
350 auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);
351 ASSERT_TRUE(
bool(Deserialized));
352 EXPECT_EQ(Deserialized->IDs, Request.IDs);
353 ASSERT_TRUE(Deserialized->Limit);
354 EXPECT_EQ(*Deserialized->Limit, Request.Limit);
355 EXPECT_EQ(Deserialized->Filter, Request.Filter);
358TEST(RemoteMarshallingTest, RefsRequestFailingSerialization) {
359 clangd::RefsRequest Request;
361 auto Serialized = ProtobufMarshaller.toProtobuf(Request);
362 Serialized.add_ids(
"Invalid Symbol ID");
363 auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);
364 EXPECT_FALSE(
bool(Deserialized));
365 llvm::consumeError(Deserialized.takeError());
368TEST(RemoteMarshallingTest, RelationsRequestSerialization) {
369 clangd::RelationsRequest Request;
370 Request.Subjects.insert(
372 Request.Subjects.insert(
375 Request.Limit = 9000;
380 auto Serialized = ProtobufMarshaller.toProtobuf(Request);
381 EXPECT_EQ(
static_cast<unsigned>(Serialized.subjects_size()),
382 Request.Subjects.size());
383 EXPECT_EQ(Serialized.limit(), Request.Limit);
384 EXPECT_EQ(
static_cast<RelationKind>(Serialized.predicate()),
386 auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);
387 ASSERT_TRUE(
bool(Deserialized));
388 EXPECT_EQ(Deserialized->Subjects, Request.Subjects);
389 ASSERT_TRUE(Deserialized->Limit);
390 EXPECT_EQ(*Deserialized->Limit, Request.Limit);
391 EXPECT_EQ(Deserialized->Predicate, Request.Predicate);
394TEST(RemoteMarshallingTest, RelationsRequestFailingSerialization) {
395 RelationsRequest Serialized;
396 Serialized.add_subjects(
"ZZZZZZZZZZZZZZZZ");
398 auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);
399 EXPECT_FALSE(
bool(Deserialized));
400 llvm::consumeError(Deserialized.takeError());
403TEST(RemoteMarshallingTest, RelationsSerializion) {
404 llvm::BumpPtrAllocator
Arena;
407 clangd::Symbol Sym = createSymbol(
"remote/",
Strings);
410 auto Serialized = ProtobufMarshaller.toProtobuf(
ID, Sym);
411 ASSERT_TRUE(
bool(Serialized));
412 auto Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);
413 ASSERT_TRUE(
bool(Deserialized));
414 EXPECT_THAT(Deserialized->first,
ID);
415 EXPECT_THAT(Deserialized->second.ID, Sym.ID);
418TEST(RemoteMarshallingTest, RelativePathToURITranslation) {
419 Marshaller ProtobufMarshaller(
"",
421 auto URIString = ProtobufMarshaller.relativePathToURI(
"lib/File.cpp");
422 ASSERT_TRUE(
bool(URIString));
424 URIString = ProtobufMarshaller.relativePathToURI(
"/lib/File.cpp");
425 EXPECT_FALSE(
bool(URIString));
426 llvm::consumeError(URIString.takeError());
428 URIString = ProtobufMarshaller.relativePathToURI(std::string());
429 EXPECT_FALSE(
bool(URIString));
430 llvm::consumeError(URIString.takeError());
433TEST(RemoteMarshallingTest, URIToRelativePathTranslation) {
434 llvm::BumpPtrAllocator
Arena;
436 Marshaller ProtobufMarshaller(
testPath(
"remote/project/"),
438 auto RelativePath = ProtobufMarshaller.uriToRelativePath(
439 testPathURI(
"remote/project/lib/File.cpp",
Strings));
440 ASSERT_TRUE(
bool(RelativePath));
442 Marshaller WrongMarshaller(
445 RelativePath = WrongMarshaller.uriToRelativePath(
446 testPathURI(
"remote/project/lib/File.cpp",
Strings));
447 EXPECT_FALSE(
bool(RelativePath));
448 llvm::consumeError(RelativePath.takeError());
std::vector< llvm::StringRef > Strings
llvm::BumpPtrAllocator Arena
static llvm::Expected< SymbolID > fromStr(llvm::StringRef)
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
static URI createFile(llvm::StringRef AbsolutePath)
This creates a file:// URI for AbsolutePath. The path must be absolute.
@ Info
An information message.
std::string Path
A typedef to represent a file path.
static const char * toString(OffsetEncoding OE)
std::string testPath(PathRef File, llvm::sys::path::Style Style)
TEST(BackgroundQueueTest, Priority)
std::string toYAML(const Symbol &)
std::array< uint8_t, 20 > SymbolID
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
@ IndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.