1 //===- llvm/unittest/DebugInfo/LogicalView/CompareElementsTest.cpp --------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
10 #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
11 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
12 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
13 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
14 #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
15 #include "llvm/Support/ScopedPrinter.h"
16 #include "llvm/Support/ToolOutputFile.h"
17 #include "llvm/Testing/Support/Error.h"
19 #include "gtest/gtest.h"
22 using namespace llvm::logicalview
;
26 //===----------------------------------------------------------------------===//
27 // Basic Reader functionality.
28 class ReaderTestCompare
: public LVReader
{
29 #define CREATE(VARIABLE, CREATE_FUNCTION, SET_FUNCTION) \
30 VARIABLE = CREATE_FUNCTION(); \
31 EXPECT_NE(VARIABLE, nullptr); \
32 VARIABLE->SET_FUNCTION();
36 LVType
*IntegerType
= nullptr;
37 LVType
*UnsignedType
= nullptr;
38 LVType
*GlobalType
= nullptr;
39 LVType
*LocalType
= nullptr;
40 LVType
*NestedType
= nullptr;
41 LVTypeDefinition
*TypeDefinitionOne
= nullptr;
42 LVTypeDefinition
*TypeDefinitionTwo
= nullptr;
43 LVTypeEnumerator
*EnumeratorOne
= nullptr;
44 LVTypeEnumerator
*EnumeratorTwo
= nullptr;
47 LVScope
*NestedScope
= nullptr;
48 LVScope
*InnerScope
= nullptr;
49 LVScopeAggregate
*Aggregate
= nullptr;
50 LVScopeEnumeration
*Enumeration
= nullptr;
51 LVScopeFunction
*FunctionOne
= nullptr;
52 LVScopeFunction
*FunctionTwo
= nullptr;
53 LVScopeNamespace
*Namespace
= nullptr;
56 LVSymbol
*GlobalVariable
= nullptr;
57 LVSymbol
*LocalVariable
= nullptr;
58 LVSymbol
*ClassMember
= nullptr;
59 LVSymbol
*NestedVariable
= nullptr;
60 LVSymbol
*ParameterOne
= nullptr;
61 LVSymbol
*ParameterTwo
= nullptr;
64 LVLine
*LineOne
= nullptr;
65 LVLine
*LineTwo
= nullptr;
66 LVLine
*LineThree
= nullptr;
69 void add(LVScope
*Parent
, LVElement
*Element
);
70 void set(LVElement
*Element
, StringRef Name
, LVOffset Offset
,
71 uint32_t LineNumber
= 0, LVElement
*Type
= nullptr);
74 ReaderTestCompare(ScopedPrinter
&W
) : LVReader("", "", W
) {
78 Error
createScopes() { return LVReader::createScopes(); }
79 Error
printScopes() { return LVReader::printScopes(); }
81 void createElements();
82 void addElements(bool IsReference
, bool IsTarget
);
86 // Helper function to add a logical element to a given scope.
87 void ReaderTestCompare::add(LVScope
*Parent
, LVElement
*Child
) {
88 Parent
->addElement(Child
);
89 EXPECT_EQ(Child
->getParent(), Parent
);
90 EXPECT_EQ(Child
->getLevel(), Parent
->getLevel() + 1);
93 // Helper function to set the initial values for a given logical element.
94 void ReaderTestCompare::set(LVElement
*Element
, StringRef Name
, LVOffset Offset
,
95 uint32_t LineNumber
, LVElement
*Type
) {
96 Element
->setName(Name
);
97 Element
->setOffset(Offset
);
98 Element
->setLineNumber(LineNumber
);
99 Element
->setType(Type
);
102 //===----------------------------------------------------------------------===//
103 // Create the logical elements.
104 void ReaderTestCompare::createElements() {
105 // Create scope root.
106 Error Err
= createScopes();
107 ASSERT_THAT_ERROR(std::move(Err
), Succeeded());
108 Root
= getScopesRoot();
109 ASSERT_NE(Root
, nullptr);
111 // Create the logical types.
112 CREATE(IntegerType
, createType
, setIsBase
);
113 CREATE(UnsignedType
, createType
, setIsBase
);
114 CREATE(GlobalType
, createType
, setIsBase
);
115 CREATE(LocalType
, createType
, setIsBase
);
116 CREATE(NestedType
, createType
, setIsBase
);
117 CREATE(EnumeratorOne
, createTypeEnumerator
, setIsEnumerator
);
118 CREATE(EnumeratorTwo
, createTypeEnumerator
, setIsEnumerator
);
119 CREATE(TypeDefinitionOne
, createTypeDefinition
, setIsTypedef
);
120 CREATE(TypeDefinitionTwo
, createTypeDefinition
, setIsTypedef
);
122 // Create the logical scopes.
123 CREATE(NestedScope
, createScope
, setIsLexicalBlock
);
124 CREATE(InnerScope
, createScope
, setIsLexicalBlock
);
125 CREATE(Aggregate
, createScopeAggregate
, setIsAggregate
);
126 CREATE(CompileUnit
, createScopeCompileUnit
, setIsCompileUnit
);
127 CREATE(Enumeration
, createScopeEnumeration
, setIsEnumeration
);
128 CREATE(FunctionOne
, createScopeFunction
, setIsFunction
);
129 CREATE(FunctionTwo
, createScopeFunction
, setIsFunction
);
130 CREATE(Namespace
, createScopeNamespace
, setIsNamespace
);
132 // Create the logical symbols.
133 CREATE(GlobalVariable
, createSymbol
, setIsVariable
);
134 CREATE(LocalVariable
, createSymbol
, setIsVariable
);
135 CREATE(ClassMember
, createSymbol
, setIsMember
);
136 CREATE(NestedVariable
, createSymbol
, setIsVariable
);
137 CREATE(ParameterOne
, createSymbol
, setIsParameter
);
138 CREATE(ParameterTwo
, createSymbol
, setIsParameter
);
140 // Create the logical lines.
141 CREATE(LineOne
, createLine
, setIsLineDebug
);
142 CREATE(LineTwo
, createLine
, setIsLineDebug
);
143 CREATE(LineThree
, createLine
, setIsLineDebug
);
146 // Reference Reader: Target Reader:
147 // ---------------------- ----------------------
149 // CompileUnit CompileUnit
150 // IntegerType IntegerType
151 // UnsignedType UnsignedType
152 // FunctionOne FunctionOne
153 // ParameterOne ParameterOne
155 // LocalType LocalType
157 // NestedScope NestedScope
158 // NestedVariable NestedVariable
159 // NestedType NestedType
161 // InnerScope InnerScope
165 // GlobalVariable GlobalVariable
166 // GlobalType GlobalType
167 // Namespace Namespace
168 // Aggregate Aggregate
169 // ClassMember ClassMember
170 // Enumeration Enumeration
171 // EnumeratorOne EnumeratorOne
172 // EnumeratorTwo EnumeratorTwo
173 // TypeDefinitionOne ---
174 // --- TypeDefinitionTwo
176 // Create the logical view adding the created logical elements.
177 void ReaderTestCompare::addElements(bool IsReference
, bool IsTarget
) {
178 Root
->setName(IsReference
? "Reference-Reader" : "Target-Reader");
180 auto Insert
= [&](bool Insert
, auto *Parent
, auto *Child
) {
185 setCompileUnit(CompileUnit
);
186 add(Root
, CompileUnit
);
188 // Add elements to CompileUnit.
189 Insert(true, CompileUnit
, IntegerType
);
190 Insert(true, CompileUnit
, UnsignedType
);
191 Insert(true, CompileUnit
, FunctionOne
);
192 Insert(IsTarget
, CompileUnit
, FunctionTwo
);
193 Insert(true, CompileUnit
, GlobalVariable
);
194 Insert(true, CompileUnit
, GlobalType
);
195 Insert(true, CompileUnit
, Namespace
);
197 // Add elements to Namespace.
198 Insert(true, Namespace
, Aggregate
);
199 Insert(true, Namespace
, Enumeration
);
200 Insert(IsReference
, Namespace
, TypeDefinitionOne
);
201 Insert(IsTarget
, Namespace
, TypeDefinitionTwo
);
203 // Add elements to FunctionOne.
204 Insert(true, FunctionOne
, ParameterOne
);
205 Insert(IsReference
, FunctionOne
, LocalVariable
);
206 Insert(true, FunctionOne
, LocalType
);
207 Insert(true, FunctionOne
, LineOne
);
208 Insert(true, FunctionOne
, NestedScope
);
210 // Add elements to FunctionTwo.
211 Insert(IsTarget
, FunctionTwo
, ParameterTwo
);
213 // Add elements to NestedScope.
214 Insert(true, NestedScope
, NestedVariable
);
215 Insert(true, NestedScope
, NestedType
);
216 Insert(IsReference
, NestedScope
, LineTwo
);
217 Insert(true, NestedScope
, InnerScope
);
219 // Add elements to Enumeration.
220 Insert(true, Enumeration
, EnumeratorOne
);
221 Insert(true, Enumeration
, EnumeratorTwo
);
223 // Add elements to Aggregate.
224 Insert(true, Aggregate
, ClassMember
);
226 Insert(IsTarget
, InnerScope
, LineThree
);
229 // Set initial values to logical elements.
230 void ReaderTestCompare::initElements() {
231 setFilename("LogicalElements.obj");
233 Root
->setFileFormatName("FileFormat");
236 set(IntegerType
, "int", 0x1000);
237 set(UnsignedType
, "unsigned", 0x1010);
238 set(GlobalType
, "GlobalType", 0x1020, 1020);
239 set(LocalType
, "LocalType", 0x1030, 1030);
240 set(NestedType
, "NestedType", 0x1040, 1040);
242 set(TypeDefinitionOne
, "INTEGER", 0x1050, 1050, IntegerType
);
243 set(TypeDefinitionTwo
, "INT", 0x1060, 1060, TypeDefinitionOne
);
245 set(EnumeratorOne
, "One", 0x1070, 1070);
246 EnumeratorOne
->setValue("Blue");
248 set(EnumeratorTwo
, "Two", 0x1080, 1080);
249 EnumeratorTwo
->setValue("Red");
252 set(Aggregate
, "Class", 0x2000, 2000);
253 set(Enumeration
, "Colors", 0x2010, 2010);
254 set(FunctionOne
, "FunctionOne", 0x2020, 2020, GlobalType
);
255 set(FunctionTwo
, "FunctionTwo", 0x2030, 2030, GlobalType
);
256 set(Namespace
, "Namespace", 0x2040, 2040);
257 set(NestedScope
, "", 0x2050, 2050);
258 set(InnerScope
, "", 0x2060, 2060);
259 set(CompileUnit
, "test.cpp", 0x2070, 2070);
262 set(GlobalVariable
, "GlobalVariable", 0x3000, 3000);
263 set(LocalVariable
, "LocalVariable", 0x3010, 3010, UnsignedType
);
264 set(ClassMember
, "ClassMember", 0x3020, 3020, IntegerType
);
265 set(ParameterOne
, "ParameterOne", 0x3030, 3030, UnsignedType
);
266 set(ParameterTwo
, "ParameterTwo", 0x3040, 3040, UnsignedType
);
267 set(NestedVariable
, "NestedVariable", 0x3050, 3050);
270 set(LineOne
, "", 0x4000, 4000);
271 set(LineTwo
, "", 0x4010, 4010);
272 set(LineThree
, "", 0x4020, 4020);
275 // Compare the logical views.
276 void compareReadersViews(ReaderTestCompare
*ReferenceReader
,
277 ReaderTestCompare
*TargetReader
) {
278 LVCompare
Compare(nulls());
279 Error Err
= Compare
.execute(ReferenceReader
, TargetReader
);
280 ASSERT_THAT_ERROR(std::move(Err
), Succeeded());
282 // Get comparison table.
283 LVPassTable PassTable
= Compare
.getPassTable();
284 ASSERT_EQ(PassTable
.size(), 5u);
290 // Reference: Missing 'FunctionOne'
291 std::tie(Reader
, Element
, Pass
) = PassTable
[0];
292 EXPECT_EQ(Reader
, ReferenceReader
);
293 EXPECT_EQ(Element
, ReferenceReader
->FunctionOne
);
294 EXPECT_EQ(Pass
, LVComparePass::Missing
);
296 // Reference: Missing 'TypeDefinitionOne'
297 std::tie(Reader
, Element
, Pass
) = PassTable
[1];
298 EXPECT_EQ(Reader
, ReferenceReader
);
299 EXPECT_EQ(Element
, ReferenceReader
->TypeDefinitionOne
);
300 EXPECT_EQ(Pass
, LVComparePass::Missing
);
302 // Target: Added 'FunctionOne'
303 std::tie(Reader
, Element
, Pass
) = PassTable
[2];
304 EXPECT_EQ(Reader
, TargetReader
);
305 EXPECT_EQ(Element
, TargetReader
->FunctionOne
);
306 EXPECT_EQ(Pass
, LVComparePass::Added
);
308 // Target: Added 'FunctionTwo'
309 std::tie(Reader
, Element
, Pass
) = PassTable
[3];
310 EXPECT_EQ(Reader
, TargetReader
);
311 EXPECT_EQ(Element
, TargetReader
->FunctionTwo
);
312 EXPECT_EQ(Pass
, LVComparePass::Added
);
314 // Target: Added 'TypeDefinitionTwo'
315 std::tie(Reader
, Element
, Pass
) = PassTable
[4];
316 EXPECT_EQ(Reader
, TargetReader
);
317 EXPECT_EQ(Element
, TargetReader
->TypeDefinitionTwo
);
318 EXPECT_EQ(Pass
, LVComparePass::Added
);
321 // Compare the logical elements.
322 void compareReadersElements(ReaderTestCompare
*ReferenceReader
,
323 ReaderTestCompare
*TargetReader
) {
324 LVCompare
Compare(nulls());
325 Error Err
= Compare
.execute(ReferenceReader
, TargetReader
);
326 ASSERT_THAT_ERROR(std::move(Err
), Succeeded());
328 // Get comparison table.
329 LVPassTable PassTable
= Compare
.getPassTable();
330 ASSERT_EQ(PassTable
.size(), 7u);
336 // Reference: Missing 'LocalVariable'
337 std::tie(Reader
, Element
, Pass
) = PassTable
[0];
338 EXPECT_EQ(Reader
, ReferenceReader
);
339 EXPECT_EQ(Element
, ReferenceReader
->LocalVariable
);
340 EXPECT_EQ(Pass
, LVComparePass::Missing
);
342 // Reference: Missing 'TypeDefinitionOne'
343 std::tie(Reader
, Element
, Pass
) = PassTable
[1];
344 EXPECT_EQ(Reader
, ReferenceReader
);
345 EXPECT_EQ(Element
, ReferenceReader
->TypeDefinitionOne
);
346 EXPECT_EQ(Pass
, LVComparePass::Missing
);
348 // Reference: Missing 'LineTwo'
349 std::tie(Reader
, Element
, Pass
) = PassTable
[2];
350 EXPECT_EQ(Reader
, ReferenceReader
);
351 EXPECT_EQ(Element
, ReferenceReader
->LineTwo
);
352 EXPECT_EQ(Pass
, LVComparePass::Missing
);
354 // Target: Added 'FunctionTwo'
355 std::tie(Reader
, Element
, Pass
) = PassTable
[3];
356 EXPECT_EQ(Reader
, TargetReader
);
357 EXPECT_EQ(Element
, TargetReader
->FunctionTwo
);
358 EXPECT_EQ(Pass
, LVComparePass::Added
);
360 // Target: Added 'ParameterTwo'
361 std::tie(Reader
, Element
, Pass
) = PassTable
[4];
362 EXPECT_EQ(Reader
, TargetReader
);
363 EXPECT_EQ(Element
, TargetReader
->ParameterTwo
);
364 EXPECT_EQ(Pass
, LVComparePass::Added
);
366 // Target: Added 'TypeDefinitionTwo'
367 std::tie(Reader
, Element
, Pass
) = PassTable
[5];
368 EXPECT_EQ(Reader
, TargetReader
);
369 EXPECT_EQ(Element
, TargetReader
->TypeDefinitionTwo
);
370 EXPECT_EQ(Pass
, LVComparePass::Added
);
372 // Target: Added 'LineThree'
373 std::tie(Reader
, Element
, Pass
) = PassTable
[6];
374 EXPECT_EQ(Reader
, TargetReader
);
375 EXPECT_EQ(Element
, TargetReader
->LineThree
);
376 EXPECT_EQ(Pass
, LVComparePass::Added
);
379 TEST(LogicalViewTest
, CompareElements
) {
380 ScopedPrinter
W(outs());
383 LVOptions ReaderOptions
;
384 ReaderOptions
.setCompareLines();
385 ReaderOptions
.setCompareScopes();
386 ReaderOptions
.setCompareSymbols();
387 ReaderOptions
.setCompareTypes();
389 // The next set-ups are very similar. The only difference is the
390 // comparison type, which must be set before the readers are created.
391 // Views: setCompareContext()
392 // Elements: resetCompareContext()
394 // Compare the logical views as whole unit (--compare-context).
395 ReaderOptions
.setCompareContext();
396 ReaderOptions
.resolveDependencies();
397 options().setOptions(&ReaderOptions
);
399 ReaderTestCompare
ReferenceReader(W
);
400 ReferenceReader
.createElements();
401 ReferenceReader
.addElements(/*IsReference=*/true, /*IsTarget=*/false);
402 ReferenceReader
.initElements();
404 ReaderTestCompare
TargetReader(W
);
405 TargetReader
.createElements();
406 TargetReader
.addElements(/*IsReference=*/false, /*IsTarget=*/true);
407 TargetReader
.initElements();
409 compareReadersViews(&ReferenceReader
, &TargetReader
);
412 // Compare the logical elements.
413 ReaderOptions
.resetCompareContext();
414 ReaderOptions
.resolveDependencies();
415 options().setOptions(&ReaderOptions
);
417 ReaderTestCompare
ReferenceReader(W
);
418 ReferenceReader
.createElements();
419 ReferenceReader
.addElements(/*IsReference=*/true, /*IsTarget=*/false);
420 ReferenceReader
.initElements();
422 ReaderTestCompare
TargetReader(W
);
423 TargetReader
.createElements();
424 TargetReader
.addElements(/*IsReference=*/false, /*IsTarget=*/true);
425 TargetReader
.initElements();
427 compareReadersElements(&ReferenceReader
, &TargetReader
);