brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.8 KiB · 85e79ea Raw
456 lines · cpp
1//===--- MarshallingTests.cpp ------------------------------------*- C++-*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "../TestTU.h"10#include "Index.pb.h"11#include "TestFS.h"12#include "index/Index.h"13#include "index/Ref.h"14#include "index/Relation.h"15#include "index/Serialization.h"16#include "index/Symbol.h"17#include "index/SymbolID.h"18#include "index/SymbolLocation.h"19#include "index/SymbolOrigin.h"20#include "index/remote/marshalling/Marshalling.h"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"30#include <cstring>31 32namespace clang {33namespace clangd {34namespace remote {35namespace {36 37using llvm::sys::path::convert_to_slash;38 39const char *testPathURI(llvm::StringRef Path,40                        llvm::UniqueStringSaver &Strings) {41  auto URI = URI::createFile(testPath(Path));42  return Strings.save(URI.toString()).begin();43}44 45clangd::Symbol createSymbol(llvm::StringRef PathPrefix,46                            llvm::UniqueStringSaver &Strings) {47  clangd::Symbol Sym;48  Sym.ID = llvm::cantFail(SymbolID::fromStr("057557CEBF6E6B2D"));49 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);56  Sym.SymInfo = Info;57 58  Sym.Name = Strings.save("Foo");59  Sym.Scope = Strings.save("llvm::foo::bar::");60 61  clangd::SymbolLocation Location;62  Location.Start.setLine(1);63  Location.Start.setColumn(15);64  Location.End.setLine(3);65  Location.End.setColumn(121);66  Location.FileURI = testPathURI(PathPrefix.str() + "Definition.cpp", Strings);67  Sym.Definition = Location;68 69  Location.Start.setLine(42);70  Location.Start.setColumn(31);71  Location.End.setLine(20);72  Location.End.setColumn(400);73  Location.FileURI = testPathURI(PathPrefix.str() + "Declaration.h", Strings);74  Sym.CanonicalDeclaration = Location;75 76  Sym.References = 9000;77  Sym.Origin = clangd::SymbolOrigin::Static;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");84 85  Sym.Flags = clangd::Symbol::SymbolFlag::IndexedForCodeCompletion;86 87  return Sym;88}89 90TEST(RemoteMarshallingTest, URITranslation) {91  llvm::BumpPtrAllocator Arena;92  llvm::UniqueStringSaver Strings(Arena);93  Marshaller ProtobufMarshaller(94      testPath("remote/machine/projects/llvm-project/"),95      testPath("home/my-projects/llvm-project/"));96  clangd::Ref Original;97  Original.Location.FileURI =98      testPathURI("remote/machine/projects/llvm-project/clang-tools-extra/"99                  "clangd/unittests/remote/MarshallingTests.cpp",100                  Strings);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",110                           Strings));111 112  // Can't have empty paths.113  *Serialized->mutable_location()->mutable_file_path() = std::string();114  Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);115  EXPECT_FALSE(bool(Deserialized));116  llvm::consumeError(Deserialized.takeError());117 118  clangd::Ref WithInvalidURI;119  // Invalid URI results in serialization failure.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());124 125  // Can not use URIs with scheme different from "file".126  auto UnittestURI =127      URI::create(testPath("project/lib/HelloWorld.cpp"), "unittest");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());134 135  // Paths transmitted over the wire can not be absolute, they have to be136  // relative.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());143}144 145TEST(RemoteMarshallingTest, SymbolSerialization) {146  llvm::BumpPtrAllocator Arena;147  llvm::UniqueStringSaver Strings(Arena);148 149  clangd::Symbol Sym = createSymbol("home/", Strings);150  Marshaller ProtobufMarshaller(testPath("home/"), testPath("home/"));151 152  // Check that symbols are exactly the same if the path to indexed project is153  // the same on indexing machine and the client.154  auto Serialized = ProtobufMarshaller.toProtobuf(Sym);155  ASSERT_TRUE(bool(Serialized));156  auto Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);157  ASSERT_TRUE(bool(Deserialized));158  // Origin is overwritten when deserializing.159  Sym.Origin = SymbolOrigin::Remote;160  EXPECT_EQ(toYAML(Sym), toYAML(*Deserialized));161  // Serialized paths are relative and have UNIX slashes.162  EXPECT_EQ(convert_to_slash(Serialized->definition().file_path(),163                             llvm::sys::path::Style::posix),164            Serialized->definition().file_path());165  EXPECT_TRUE(166      llvm::sys::path::is_relative(Serialized->definition().file_path()));167 168  // Missing definition is OK.169  Sym.Definition = clangd::SymbolLocation();170  Serialized = ProtobufMarshaller.toProtobuf(Sym);171  ASSERT_TRUE(bool(Serialized));172  ASSERT_TRUE(bool(ProtobufMarshaller.fromProtobuf(*Serialized)));173 174  // Relative path is absolute.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());180 181  // Fail with an invalid URI.182  Sym.Definition.FileURI = "Not A URI";183  Serialized = ProtobufMarshaller.toProtobuf(Sym);184  EXPECT_FALSE(bool(Serialized));185  llvm::consumeError(Serialized.takeError());186 187  // Schemes other than "file" can not be used.188  auto UnittestURI = URI::create(testPath("home/SomePath.h"), "unittest");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());194 195  // Passing root that is not prefix of the original file path.196  Sym.Definition.FileURI = testPathURI("home/File.h", Strings);197  // Check that the symbol is valid and passing the correct path works.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));204  // Fail with a wrong root.205  Marshaller WrongMarshaller(testPath("nothome/"), testPath("home/"));206  Serialized = WrongMarshaller.toProtobuf(Sym);207  EXPECT_FALSE(Serialized);208  llvm::consumeError(Serialized.takeError());209}210 211TEST(RemoteMarshallingTest, RefSerialization) {212  clangd::Ref Ref;213  Ref.Kind = clangd::RefKind::Spelled | clangd::RefKind::Declaration;214 215  llvm::BumpPtrAllocator Arena;216  llvm::UniqueStringSaver Strings(Arena);217 218  clangd::SymbolLocation Location;219  Location.Start.setLine(124);220  Location.Start.setColumn(21);221  Location.End.setLine(3213);222  Location.End.setColumn(541);223  Location.FileURI = testPathURI(224      "llvm-project/llvm/clang-tools-extra/clangd/Protocol.h", Strings);225  Ref.Location = Location;226  Ref.Container = llvm::cantFail(SymbolID::fromStr("0000000000000001"));227 228  Marshaller ProtobufMarshaller(testPath("llvm-project/"),229                                testPath("llvm-project/"));230 231  auto Serialized = ProtobufMarshaller.toProtobuf(Ref);232  ASSERT_TRUE(bool(Serialized));233  auto Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);234  ASSERT_TRUE(bool(Deserialized));235  EXPECT_EQ(toYAML(Ref), toYAML(*Deserialized));236}237 238TEST(RemoteMarshallingTest, IncludeHeaderURIs) {239  llvm::BumpPtrAllocator Arena;240  llvm::UniqueStringSaver Strings(Arena);241 242  clangd::Symbol Sym = createSymbol("remote/", Strings);243 244  clangd::Symbol::IncludeHeaderWithReferences Header;245  // Add only valid headers.246  Header.IncludeHeader =247      Strings.save(URI::createFile(testPath("project/Header.h")).toString());248  Header.References = 21;249  Sym.IncludeHeaders.push_back(Header);250  Header.IncludeHeader = Strings.save("<iostream>");251  Header.References = 100;252  Sym.IncludeHeaders.push_back(Header);253  Header.IncludeHeader = Strings.save("\"cstdio\"");254  Header.References = 200;255  Sym.IncludeHeaders.push_back(Header);256 257  Marshaller ProtobufMarshaller(testPath(""), testPath(""));258 259  auto Serialized = ProtobufMarshaller.toProtobuf(Sym);260  ASSERT_TRUE(bool(Serialized));261  EXPECT_EQ(static_cast<size_t>(Serialized->headers_size()),262            Sym.IncludeHeaders.size());263  auto Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);264  ASSERT_TRUE(bool(Deserialized));265  Sym.Origin = SymbolOrigin::Remote;266  EXPECT_EQ(toYAML(Sym), toYAML(*Deserialized));267 268  // This is an absolute path to a header: can not be transmitted over the wire.269  Header.IncludeHeader = Strings.save(testPath("project/include/Common.h"));270  Header.References = 42;271  Sym.IncludeHeaders.push_back(Header);272  Serialized = ProtobufMarshaller.toProtobuf(Sym);273  EXPECT_FALSE(bool(Serialized));274  llvm::consumeError(Serialized.takeError());275 276  // Remove last invalid header.277  Sym.IncludeHeaders.pop_back();278  // This is not a valid header: can not be transmitted over the wire;279  Header.IncludeHeader = Strings.save("NotAHeader");280  Header.References = 5;281  Sym.IncludeHeaders.push_back(Header);282  Serialized = ProtobufMarshaller.toProtobuf(Sym);283  EXPECT_FALSE(bool(Serialized));284  llvm::consumeError(Serialized.takeError());285 286  // Try putting an invalid header into already serialized symbol.287  Sym.IncludeHeaders.pop_back();288  Serialized = ProtobufMarshaller.toProtobuf(Sym);289  ASSERT_TRUE(bool(Serialized));290  HeaderWithReferences InvalidHeader;291  InvalidHeader.set_header(convert_to_slash("/absolute/path/Header.h"));292  InvalidHeader.set_references(9000);293  *Serialized->add_headers() = InvalidHeader;294  Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);295  EXPECT_FALSE(bool(Deserialized));296  llvm::consumeError(Deserialized.takeError());297}298 299TEST(RemoteMarshallingTest, LookupRequestSerialization) {300  clangd::LookupRequest Request;301  Request.IDs.insert(llvm::cantFail(SymbolID::fromStr("0000000000000001")));302  Request.IDs.insert(llvm::cantFail(SymbolID::fromStr("0000000000000002")));303 304  Marshaller ProtobufMarshaller(testPath("remote/"), testPath("local/"));305 306  auto Serialized = ProtobufMarshaller.toProtobuf(Request);307  EXPECT_EQ(static_cast<unsigned>(Serialized.ids_size()), Request.IDs.size());308  auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);309  ASSERT_TRUE(bool(Deserialized));310  EXPECT_EQ(Deserialized->IDs, Request.IDs);311}312 313TEST(RemoteMarshallingTest, LookupRequestFailingSerialization) {314  clangd::LookupRequest Request;315  Marshaller ProtobufMarshaller(testPath("remote/"), testPath("local/"));316  auto Serialized = ProtobufMarshaller.toProtobuf(Request);317  Serialized.add_ids("Invalid Symbol ID");318  auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);319  EXPECT_FALSE(bool(Deserialized));320  llvm::consumeError(Deserialized.takeError());321}322 323TEST(RemoteMarshallingTest, FuzzyFindRequestSerialization) {324  clangd::FuzzyFindRequest Request;325  Request.ProximityPaths = {testPath("local/Header.h"),326                            testPath("local/subdir/OtherHeader.h"),327                            testPath("remote/File.h"), "Not a Path."};328  Marshaller ProtobufMarshaller(testPath("remote/"), testPath("local/"));329  auto Serialized = ProtobufMarshaller.toProtobuf(Request);330  EXPECT_EQ(Serialized.proximity_paths_size(), 2);331  auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);332  ASSERT_TRUE(bool(Deserialized));333  EXPECT_THAT(Deserialized->ProximityPaths,334              testing::ElementsAre(testPath("remote/Header.h"),335                                   testPath("remote/subdir/OtherHeader.h")));336}337 338TEST(RemoteMarshallingTest, RefsRequestSerialization) {339  clangd::RefsRequest Request;340  Request.IDs.insert(llvm::cantFail(SymbolID::fromStr("0000000000000001")));341  Request.IDs.insert(llvm::cantFail(SymbolID::fromStr("0000000000000002")));342 343  Request.Limit = 9000;344  Request.Filter = RefKind::Spelled | RefKind::Declaration;345 346  Marshaller ProtobufMarshaller(testPath("remote/"), testPath("local/"));347 348  auto Serialized = ProtobufMarshaller.toProtobuf(Request);349  EXPECT_EQ(static_cast<unsigned>(Serialized.ids_size()), Request.IDs.size());350  EXPECT_EQ(Serialized.limit(), Request.Limit);351  auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);352  ASSERT_TRUE(bool(Deserialized));353  EXPECT_EQ(Deserialized->IDs, Request.IDs);354  ASSERT_TRUE(Deserialized->Limit);355  EXPECT_EQ(*Deserialized->Limit, Request.Limit);356  EXPECT_EQ(Deserialized->Filter, Request.Filter);357}358 359TEST(RemoteMarshallingTest, RefsRequestFailingSerialization) {360  clangd::RefsRequest Request;361  Marshaller ProtobufMarshaller(testPath("remote/"), testPath("local/"));362  auto Serialized = ProtobufMarshaller.toProtobuf(Request);363  Serialized.add_ids("Invalid Symbol ID");364  auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);365  EXPECT_FALSE(bool(Deserialized));366  llvm::consumeError(Deserialized.takeError());367}368 369TEST(RemoteMarshallingTest, RelationsRequestSerialization) {370  clangd::RelationsRequest Request;371  Request.Subjects.insert(372      llvm::cantFail(SymbolID::fromStr("0000000000000001")));373  Request.Subjects.insert(374      llvm::cantFail(SymbolID::fromStr("0000000000000002")));375 376  Request.Limit = 9000;377  Request.Predicate = RelationKind::BaseOf;378 379  Marshaller ProtobufMarshaller(testPath("remote/"), testPath("local/"));380 381  auto Serialized = ProtobufMarshaller.toProtobuf(Request);382  EXPECT_EQ(static_cast<unsigned>(Serialized.subjects_size()),383            Request.Subjects.size());384  EXPECT_EQ(Serialized.limit(), Request.Limit);385  EXPECT_EQ(static_cast<RelationKind>(Serialized.predicate()),386            Request.Predicate);387  auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);388  ASSERT_TRUE(bool(Deserialized));389  EXPECT_EQ(Deserialized->Subjects, Request.Subjects);390  ASSERT_TRUE(Deserialized->Limit);391  EXPECT_EQ(*Deserialized->Limit, Request.Limit);392  EXPECT_EQ(Deserialized->Predicate, Request.Predicate);393}394 395TEST(RemoteMarshallingTest, RelationsRequestFailingSerialization) {396  RelationsRequest Serialized;397  Serialized.add_subjects("ZZZZZZZZZZZZZZZZ");398  Marshaller ProtobufMarshaller(testPath("remote/"), testPath("local/"));399  auto Deserialized = ProtobufMarshaller.fromProtobuf(&Serialized);400  EXPECT_FALSE(bool(Deserialized));401  llvm::consumeError(Deserialized.takeError());402}403 404TEST(RemoteMarshallingTest, RelationsSerializion) {405  llvm::BumpPtrAllocator Arena;406  llvm::UniqueStringSaver Strings(Arena);407 408  clangd::Symbol Sym = createSymbol("remote/", Strings);409  SymbolID ID = llvm::cantFail(SymbolID::fromStr("0000000000000002"));410  Marshaller ProtobufMarshaller(testPath("remote/"), testPath("local/"));411  auto Serialized = ProtobufMarshaller.toProtobuf(ID, Sym);412  ASSERT_TRUE(bool(Serialized));413  auto Deserialized = ProtobufMarshaller.fromProtobuf(*Serialized);414  ASSERT_TRUE(bool(Deserialized));415  EXPECT_THAT(Deserialized->first, ID);416  EXPECT_THAT(Deserialized->second.ID, Sym.ID);417}418 419TEST(RemoteMarshallingTest, RelativePathToURITranslation) {420  Marshaller ProtobufMarshaller(/*RemoteIndexRoot=*/"",421                                /*LocalIndexRoot=*/testPath("home/project/"));422  auto URIString = ProtobufMarshaller.relativePathToURI("lib/File.cpp");423  ASSERT_TRUE(bool(URIString));424  // RelativePath can not be absolute.425  URIString = ProtobufMarshaller.relativePathToURI("/lib/File.cpp");426  EXPECT_FALSE(bool(URIString));427  llvm::consumeError(URIString.takeError());428  // RelativePath can not be empty.429  URIString = ProtobufMarshaller.relativePathToURI(std::string());430  EXPECT_FALSE(bool(URIString));431  llvm::consumeError(URIString.takeError());432}433 434TEST(RemoteMarshallingTest, URIToRelativePathTranslation) {435  llvm::BumpPtrAllocator Arena;436  llvm::UniqueStringSaver Strings(Arena);437  Marshaller ProtobufMarshaller(/*RemoteIndexRoot=*/testPath("remote/project/"),438                                /*LocalIndexRoot=*/"");439  auto RelativePath = ProtobufMarshaller.uriToRelativePath(440      testPathURI("remote/project/lib/File.cpp", Strings));441  ASSERT_TRUE(bool(RelativePath));442  // RemoteIndexRoot has to be a prefix of the file path.443  Marshaller WrongMarshaller(444      /*RemoteIndexRoot=*/testPath("remote/other/project/"),445      /*LocalIndexRoot=*/"");446  RelativePath = WrongMarshaller.uriToRelativePath(447      testPathURI("remote/project/lib/File.cpp", Strings));448  EXPECT_FALSE(bool(RelativePath));449  llvm::consumeError(RelativePath.takeError());450}451 452} // namespace453} // namespace remote454} // namespace clangd455} // namespace clang456