clang-tools 10.0.0

SerializationTests.cpp
Go to the documentation of this file.
1 //===-- SerializationTests.cpp - Binary and YAML serialization unit tests -===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "Headers.h"
10 #include "index/Index.h"
11 #include "index/Serialization.h"
12 #include "clang/Tooling/CompilationDatabase.h"
13 #include "llvm/Support/ScopedPrinter.h"
14 #include "gmock/gmock.h"
15 #include "gtest/gtest.h"
16
17 using ::testing::_;
18 using ::testing::AllOf;
19 using ::testing::Pair;
20 using ::testing::UnorderedElementsAre;
21 using ::testing::UnorderedElementsAreArray;
22
23 namespace clang {
24 namespace clangd {
25 namespace {
26
27 const char *YAML = R"(
28 ---
29 !Symbol
30 ID: 057557CEBF6E6B2D
31 Name: 'Foo1'
32 Scope: 'clang::'
33 SymInfo:
34 Kind: Function
35 Lang: Cpp
36 CanonicalDeclaration:
37 FileURI: file:///path/foo.h
38 Start:
39 Line: 1
40 Column: 0
41 End:
42 Line: 1
43 Column: 1
44 Origin: 128
45 Flags: 129
46 Documentation: 'Foo doc'
47 ReturnType: 'int'
48 IncludeHeaders:
49 - Header: 'include1'
50 References: 7
51 - Header: 'include2'
52 References: 3
53 ...
54 ---
55 !Symbol
56 ID: 057557CEBF6E6B2E
57 Name: 'Foo2'
58 Scope: 'clang::'
59 SymInfo:
60 Kind: Function
61 Lang: Cpp
62 CanonicalDeclaration:
63 FileURI: file:///path/bar.h
64 Start:
65 Line: 1
66 Column: 0
67 End:
68 Line: 1
69 Column: 1
70 Flags: 2
71 Signature: '-sig'
72 CompletionSnippetSuffix: '-snippet'
73 ...
74 !Refs
75 ID: 057557CEBF6E6B2D
76 References:
77 - Kind: 4
78 Location:
79 FileURI: file:///path/foo.cc
80 Start:
81 Line: 5
82 Column: 3
83 End:
84 Line: 5
85 Column: 8
86 ...
87 --- !Relations
88 Subject:
89 ID: 6481EE7AF2841756
90 Predicate: 0
91 Object:
92 ID: 6512AEC512EA3A2D
93 ...
94 )";
95
96 MATCHER_P(ID, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
97 MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
98 MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
99 return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
100 }
101
102 TEST(SerializationTest, NoCrashOnEmptyYAML) {
103 EXPECT_TRUE(bool(readIndexFile("")));
104 }
105
106 TEST(SerializationTest, YAMLConversions) {
107 auto In = readIndexFile(YAML);
108 EXPECT_TRUE(bool(In)) << In.takeError();
109
110 auto ParsedYAML = readIndexFile(YAML);
111 ASSERT_TRUE(bool(ParsedYAML)) << ParsedYAML.takeError();
112 ASSERT_TRUE(bool(ParsedYAML->Symbols));
113 EXPECT_THAT(
114 *ParsedYAML->Symbols,
115 UnorderedElementsAre(ID("057557CEBF6E6B2D"), ID("057557CEBF6E6B2E")));
116
117 auto Sym1 = *ParsedYAML->Symbols->find(
118 cantFail(SymbolID::fromStr("057557CEBF6E6B2D")));
119 auto Sym2 = *ParsedYAML->Symbols->find(
120 cantFail(SymbolID::fromStr("057557CEBF6E6B2E")));
121
122 EXPECT_THAT(Sym1, QName("clang::Foo1"));
123 EXPECT_EQ(Sym1.Signature, "");
124 EXPECT_EQ(Sym1.Documentation, "Foo doc");
125 EXPECT_EQ(Sym1.ReturnType, "int");
126 EXPECT_EQ(StringRef(Sym1.CanonicalDeclaration.FileURI), "file:///path/foo.h");
127 EXPECT_EQ(Sym1.Origin, static_cast<SymbolOrigin>(1 << 7));
128 EXPECT_EQ(static_cast<uint8_t>(Sym1.Flags), 129);
129 EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
130 EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
131 EXPECT_THAT(Sym1.IncludeHeaders,
132 UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
133 IncludeHeaderWithRef("include2", 3u)));
134
135 EXPECT_THAT(Sym2, QName("clang::Foo2"));
136 EXPECT_EQ(Sym2.Signature, "-sig");
137 EXPECT_EQ(Sym2.ReturnType, "");
138 EXPECT_EQ(llvm::StringRef(Sym2.CanonicalDeclaration.FileURI),
139 "file:///path/bar.h");
140 EXPECT_FALSE(Sym2.Flags & Symbol::IndexedForCodeCompletion);
141 EXPECT_TRUE(Sym2.Flags & Symbol::Deprecated);
142
143 ASSERT_TRUE(bool(ParsedYAML->Refs));
144 EXPECT_THAT(
145 *ParsedYAML->Refs,
146 UnorderedElementsAre(Pair(cantFail(SymbolID::fromStr("057557CEBF6E6B2D")),
147 ::testing::SizeIs(1))));
148 auto Ref1 = ParsedYAML->Refs->begin()->second.front();
149 EXPECT_EQ(Ref1.Kind, RefKind::Reference);
150 EXPECT_EQ(StringRef(Ref1.Location.FileURI), "file:///path/foo.cc");
151
152 SymbolID Base = cantFail(SymbolID::fromStr("6481EE7AF2841756"));
153 SymbolID Derived = cantFail(SymbolID::fromStr("6512AEC512EA3A2D"));
154 ASSERT_TRUE(bool(ParsedYAML->Relations));
155 EXPECT_THAT(
156 *ParsedYAML->Relations,
157 UnorderedElementsAre(Relation{Base, RelationKind::BaseOf, Derived}));
158 }
159
160 std::vector<std::string> YAMLFromSymbols(const SymbolSlab &Slab) {
161 std::vector<std::string> Result;
162 for (const auto &Sym : Slab)
163 Result.push_back(toYAML(Sym));
164 return Result;
165 }
166 std::vector<std::string> YAMLFromRefs(const RefSlab &Slab) {
167 std::vector<std::string> Result;
168 for (const auto &Refs : Slab)
169 Result.push_back(toYAML(Refs));
170 return Result;
171 }
172
173 std::vector<std::string> YAMLFromRelations(const RelationSlab &Slab) {
174 std::vector<std::string> Result;
175 for (const auto &Rel : Slab)
176 Result.push_back(toYAML(Rel));
177 return Result;
178 }
179
180 TEST(SerializationTest, BinaryConversions) {
181 auto In = readIndexFile(YAML);
182 EXPECT_TRUE(bool(In)) << In.takeError();
183
184 // Write to binary format, and parse again.
185 IndexFileOut Out(*In);
186 Out.Format = IndexFileFormat::RIFF;
187 std::string Serialized = llvm::to_string(Out);
188
189 auto In2 = readIndexFile(Serialized);
190 ASSERT_TRUE(bool(In2)) << In.takeError();
191 ASSERT_TRUE(In2->Symbols);
192 ASSERT_TRUE(In2->Refs);
193 ASSERT_TRUE(In2->Relations);
194
195 // Assert the YAML serializations match, for nice comparisons and diffs.
196 EXPECT_THAT(YAMLFromSymbols(*In2->Symbols),
197 UnorderedElementsAreArray(YAMLFromSymbols(*In->Symbols)));
198 EXPECT_THAT(YAMLFromRefs(*In2->Refs),
199 UnorderedElementsAreArray(YAMLFromRefs(*In->Refs)));
200 EXPECT_THAT(YAMLFromRelations(*In2->Relations),
201 UnorderedElementsAreArray(YAMLFromRelations(*In->Relations)));
202 }
203
204 TEST(SerializationTest, SrcsTest) {
205 auto In = readIndexFile(YAML);
206 EXPECT_TRUE(bool(In)) << In.takeError();
207
208 std::string TestContent("TestContent");
209 IncludeGraphNode IGN;
210 IGN.Digest = digest(TestContent);
211 IGN.DirectIncludes = {"inc1", "inc2"};
212 IGN.URI = "URI";
213 IGN.Flags |= IncludeGraphNode::SourceFlag::IsTU;
214 IGN.Flags |= IncludeGraphNode::SourceFlag::HadErrors;
215 IncludeGraph Sources;
216 Sources[IGN.URI] = IGN;
217 // Write to binary format, and parse again.
218 IndexFileOut Out(*In);
219 Out.Format = IndexFileFormat::RIFF;
220 Out.Sources = &Sources;
221 {
222 std::string Serialized = llvm::to_string(Out);
223
224 auto In = readIndexFile(Serialized);
225 ASSERT_TRUE(bool(In)) << In.takeError();
226 ASSERT_TRUE(In->Symbols);
227 ASSERT_TRUE(In->Refs);
228 ASSERT_TRUE(In->Sources);
229 ASSERT_TRUE(In->Sources->count(IGN.URI));
230 // Assert the YAML serializations match, for nice comparisons and diffs.
231 EXPECT_THAT(YAMLFromSymbols(*In->Symbols),
232 UnorderedElementsAreArray(YAMLFromSymbols(*In->Symbols)));
233 EXPECT_THAT(YAMLFromRefs(*In->Refs),
234 UnorderedElementsAreArray(YAMLFromRefs(*In->Refs)));
235 auto IGNDeserialized = In->Sources->lookup(IGN.URI);
236 EXPECT_EQ(IGNDeserialized.Digest, IGN.Digest);
237 EXPECT_EQ(IGNDeserialized.DirectIncludes, IGN.DirectIncludes);
238 EXPECT_EQ(IGNDeserialized.URI, IGN.URI);
239 EXPECT_EQ(IGNDeserialized.Flags, IGN.Flags);
240 }
241 }
242
243 TEST(SerializationTest, CmdlTest) {
244 auto In = readIndexFile(YAML);
245 EXPECT_TRUE(bool(In)) << In.takeError();
246
247 tooling::CompileCommand Cmd;
248 Cmd.Directory = "testdir";
249 Cmd.CommandLine.push_back("cmd1");
250 Cmd.CommandLine.push_back("cmd2");
251 Cmd.Filename = "ignored";
252 Cmd.Heuristic = "ignored";
253 Cmd.Output = "ignored";
254
255 IndexFileOut Out(*In);
256 Out.Format = IndexFileFormat::RIFF;
257 Out.Cmd = &Cmd;
258 {
259 std::string Serialized = llvm::to_string(Out);
260
261 auto In = readIndexFile(Serialized);
262 ASSERT_TRUE(bool(In)) << In.takeError();
263 ASSERT_TRUE(In->Cmd);
264
265 const tooling::CompileCommand &SerializedCmd = In->Cmd.getValue();
266 EXPECT_EQ(SerializedCmd.CommandLine, Cmd.CommandLine);
267 EXPECT_EQ(SerializedCmd.Directory, Cmd.Directory);
268 EXPECT_NE(SerializedCmd.Filename, Cmd.Filename);
269 EXPECT_NE(SerializedCmd.Heuristic, Cmd.Heuristic);
270 EXPECT_NE(SerializedCmd.Output, Cmd.Output);
271 }
272 }
273 } // namespace
274 } // namespace clangd
275 } // namespace clang
clang::clangd::MATCHER_P
MATCHER_P(Named, N, "")
Definition: BackgroundIndexTests.cpp:26
Index.h
clang::clangd::SymbolID::fromStr
static llvm::Expected< SymbolID > fromStr(llvm::StringRef)
Definition: SymbolID.cpp:35
clang::clangd::IndexFileFormat::YAML
clang::clangd::IndexFileFormat::RIFF
clang::clangd::RelationKind::BaseOf
clang::clangd::readIndexFile
llvm::Expected< IndexFileIn > readIndexFile(llvm::StringRef Data)
Definition: Serialization.cpp:652
clang::clangd::toYAML
std::string toYAML(const Symbol &)
Definition: YAMLSerialization.cpp:388
Serialization.h
Headers.h
clang::clangd::IncludeGraph
llvm::StringMap< IncludeGraphNode > IncludeGraph
Definition: Headers.h:82
QName
std::string QName
Definition: DiagnosticsTests.cpp:523
clang::clangd::Symbol::IndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.
Definition: Symbol.h:119
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:647
Name
static constexpr llvm::StringLiteral Name
Definition: UppercaseLiteralSuffixCheck.cpp:27
clang::clangd::IncludeGraphNode::SourceFlag::HadErrors
clang::clangd::digest
FileDigest digest(llvm::StringRef Content)
Definition: SourceCode.cpp:675
clang::clangd::RefKind::Reference
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
References
unsigned References
Definition: CodeComplete.cpp:157
IncludeHeader
std::string IncludeHeader
Definition: DiagnosticsTests.cpp:525
clang::clangd::Symbol::Deprecated
Indicates if the symbol is deprecated.
Definition: Symbol.h:121
Refs
RefSlab Refs
Definition: SymbolCollectorTests.cpp:296
Base
std::unique_ptr< GlobalCompilationDatabase > Base
Definition: GlobalCompilationDatabaseTests.cpp:83
clang::doc::SymbolID
std::array< uint8_t, 20 > SymbolID
Definition: Representation.h:30
clang::clangd::IncludeGraphNode::SourceFlag::IsTU