432 lines · cpp
1//===- llvm/unittest/DebugInfo/LogicalView/CompareElementsTest.cpp --------===//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 "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"18 19#include "gtest/gtest.h"20 21using namespace llvm;22using namespace llvm::logicalview;23 24namespace {25 26//===----------------------------------------------------------------------===//27// Basic Reader functionality.28class ReaderTestCompare : public LVReader {29#define CREATE(VARIABLE, CREATE_FUNCTION, SET_FUNCTION) \30 VARIABLE = CREATE_FUNCTION(); \31 EXPECT_NE(VARIABLE, nullptr); \32 VARIABLE->SET_FUNCTION();33 34public:35 // Types.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;45 46 // Scopes.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;54 55 // Symbols.56 LVSymbol *GlobalVariable = nullptr;57 LVSymbol *LocalVariable = nullptr;58 LVSymbol *ClassMember = nullptr;59 LVSymbol *NestedVariable = nullptr;60 LVSymbol *ParameterOne = nullptr;61 LVSymbol *ParameterTwo = nullptr;62 63 // Lines.64 LVLine *LineOne = nullptr;65 LVLine *LineTwo = nullptr;66 LVLine *LineThree = nullptr;67 68protected:69 void add(LVScope *Parent, LVElement *Element);70 void set(LVElement *Element, StringRef Name, LVOffset Offset,71 uint32_t LineNumber = 0, LVElement *Type = nullptr);72 73public:74 ReaderTestCompare(ScopedPrinter &W) : LVReader("", "", W) {75 setInstance(this);76 }77 78 Error createScopes() override { return LVReader::createScopes(); }79 Error printScopes() override { return LVReader::printScopes(); }80 81 void createElements();82 void addElements(bool IsReference, bool IsTarget);83 void initElements();84};85 86// Helper function to add a logical element to a given scope.87void ReaderTestCompare::add(LVScope *Parent, LVElement *Child) {88 Parent->addElement(Child);89 EXPECT_EQ(Child->getParent(), Parent);90 EXPECT_EQ(Child->getLevel(), Parent->getLevel() + 1);91}92 93// Helper function to set the initial values for a given logical element.94void 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);100}101 102//===----------------------------------------------------------------------===//103// Create the logical elements.104void 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);110 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);121 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);131 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);139 140 // Create the logical lines.141 CREATE(LineOne, createLine, setIsLineDebug);142 CREATE(LineTwo, createLine, setIsLineDebug);143 CREATE(LineThree, createLine, setIsLineDebug);144}145 146// Reference Reader: Target Reader:147// ---------------------- ----------------------148// Root Root149// CompileUnit CompileUnit150// IntegerType IntegerType151// UnsignedType UnsignedType152// FunctionOne FunctionOne153// ParameterOne ParameterOne154// LocalVariable ---155// LocalType LocalType156// LineOne LineOne157// NestedScope NestedScope158// NestedVariable NestedVariable159// NestedType NestedType160// LineTwo ---161// InnerScope InnerScope162// --- LineThree163// --- FunctionTwo164// --- ParameterTwo165// GlobalVariable GlobalVariable166// GlobalType GlobalType167// Namespace Namespace168// Aggregate Aggregate169// ClassMember ClassMember170// Enumeration Enumeration171// EnumeratorOne EnumeratorOne172// EnumeratorTwo EnumeratorTwo173// TypeDefinitionOne ---174// --- TypeDefinitionTwo175 176// Create the logical view adding the created logical elements.177void ReaderTestCompare::addElements(bool IsReference, bool IsTarget) {178 Root->setName(IsReference ? "Reference-Reader" : "Target-Reader");179 180 auto Insert = [&](bool Insert, auto *Parent, auto *Child) {181 if (Insert)182 add(Parent, Child);183 };184 185 setCompileUnit(CompileUnit);186 add(Root, CompileUnit);187 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);196 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);202 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);209 210 // Add elements to FunctionTwo.211 Insert(IsTarget, FunctionTwo, ParameterTwo);212 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);218 219 // Add elements to Enumeration.220 Insert(true, Enumeration, EnumeratorOne);221 Insert(true, Enumeration, EnumeratorTwo);222 223 // Add elements to Aggregate.224 Insert(true, Aggregate, ClassMember);225 226 Insert(IsTarget, InnerScope, LineThree);227}228 229// Set initial values to logical elements.230void ReaderTestCompare::initElements() {231 setFilename("LogicalElements.obj");232 233 Root->setFileFormatName("FileFormat");234 235 // Types.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);241 242 set(TypeDefinitionOne, "INTEGER", 0x1050, 1050, IntegerType);243 set(TypeDefinitionTwo, "INT", 0x1060, 1060, TypeDefinitionOne);244 245 set(EnumeratorOne, "One", 0x1070, 1070);246 EnumeratorOne->setValue("Blue");247 248 set(EnumeratorTwo, "Two", 0x1080, 1080);249 EnumeratorTwo->setValue("Red");250 251 // Scopes.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);260 261 // Symbols.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);268 269 // Lines.270 set(LineOne, "", 0x4000, 4000);271 set(LineTwo, "", 0x4010, 4010);272 set(LineThree, "", 0x4020, 4020);273}274 275// Compare the logical views.276void 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());281 282 // Get comparison table.283 LVPassTable PassTable = Compare.getPassTable();284 ASSERT_EQ(PassTable.size(), 5u);285 286 LVReader *Reader;287 LVElement *Element;288 LVComparePass Pass;289 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);295 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);301 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);307 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);313 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);319}320 321// Compare the logical elements.322void 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());327 328 // Get comparison table.329 LVPassTable PassTable = Compare.getPassTable();330 ASSERT_EQ(PassTable.size(), 7u);331 332 LVReader *Reader;333 LVElement *Element;334 LVComparePass Pass;335 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);341 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);347 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);353 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);359 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);365 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);371 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);377}378 379TEST(LogicalViewTest, CompareElements) {380 ScopedPrinter W(outs());381 382 // Reader options.383 LVOptions ReaderOptions;384 ReaderOptions.setCompareLines();385 ReaderOptions.setCompareScopes();386 ReaderOptions.setCompareSymbols();387 ReaderOptions.setCompareTypes();388 389 // The next set-ups are very similar. The only difference is the390 // comparison type, which must be set before the readers are created.391 // Views: setCompareContext()392 // Elements: resetCompareContext()393 {394 // Compare the logical views as whole unit (--compare-context).395 ReaderOptions.setCompareContext();396 ReaderOptions.resolveDependencies();397 options().setOptions(&ReaderOptions);398 399 ReaderTestCompare ReferenceReader(W);400 ReferenceReader.createElements();401 ReferenceReader.addElements(/*IsReference=*/true, /*IsTarget=*/false);402 ReferenceReader.initElements();403 404 ReaderTestCompare TargetReader(W);405 TargetReader.createElements();406 TargetReader.addElements(/*IsReference=*/false, /*IsTarget=*/true);407 TargetReader.initElements();408 409 compareReadersViews(&ReferenceReader, &TargetReader);410 }411 {412 // Compare the logical elements.413 ReaderOptions.resetCompareContext();414 ReaderOptions.resolveDependencies();415 options().setOptions(&ReaderOptions);416 417 ReaderTestCompare ReferenceReader(W);418 ReferenceReader.createElements();419 ReferenceReader.addElements(/*IsReference=*/true, /*IsTarget=*/false);420 ReferenceReader.initElements();421 422 ReaderTestCompare TargetReader(W);423 TargetReader.createElements();424 TargetReader.addElements(/*IsReference=*/false, /*IsTarget=*/true);425 TargetReader.initElements();426 427 compareReadersElements(&ReferenceReader, &TargetReader);428 }429}430 431} // namespace432