forked from OSchip/llvm-project
457 lines
16 KiB
C++
457 lines
16 KiB
C++
//===- llvm/unittest/DebugInfo/LogicalView/CompareElementsTest.cpp --------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
|
|
#include "llvm/Support/ScopedPrinter.h"
|
|
#include "llvm/Support/ToolOutputFile.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::logicalview;
|
|
|
|
namespace {
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Basic Reader functionality.
|
|
class ReaderTestCompare : public LVReader {
|
|
// Elements created but not added to any logical scope. They are
|
|
// deleted when the logical Reader is destroyed.
|
|
LVAutoSmallVector<LVElement *> OrphanElements;
|
|
|
|
public:
|
|
// Types.
|
|
LVType *IntegerType = nullptr;
|
|
LVType *UnsignedType = nullptr;
|
|
LVType *GlobalType = nullptr;
|
|
LVType *LocalType = nullptr;
|
|
LVType *NestedType = nullptr;
|
|
LVTypeDefinition *TypeDefinitionOne = nullptr;
|
|
LVTypeDefinition *TypeDefinitionTwo = nullptr;
|
|
LVTypeEnumerator *EnumeratorOne = nullptr;
|
|
LVTypeEnumerator *EnumeratorTwo = nullptr;
|
|
|
|
// Scopes.
|
|
LVScope *NestedScope = nullptr;
|
|
LVScope *InnerScope = nullptr;
|
|
LVScopeAggregate *Aggregate = nullptr;
|
|
LVScopeEnumeration *Enumeration = nullptr;
|
|
LVScopeFunction *FunctionOne = nullptr;
|
|
LVScopeFunction *FunctionTwo = nullptr;
|
|
LVScopeNamespace *Namespace = nullptr;
|
|
|
|
// Symbols.
|
|
LVSymbol *GlobalVariable = nullptr;
|
|
LVSymbol *LocalVariable = nullptr;
|
|
LVSymbol *ClassMember = nullptr;
|
|
LVSymbol *NestedVariable = nullptr;
|
|
LVSymbol *ParameterOne = nullptr;
|
|
LVSymbol *ParameterTwo = nullptr;
|
|
|
|
// Lines.
|
|
LVLine *LineOne = nullptr;
|
|
LVLine *LineTwo = nullptr;
|
|
LVLine *LineThree = nullptr;
|
|
|
|
protected:
|
|
void add(LVScope *Parent, LVElement *Element);
|
|
template <typename T, typename F> T *create(F Function) {
|
|
// 'Function' will update a specific kind of the logical element to
|
|
// have the ability of kind selection.
|
|
T *Element = new (std::nothrow) T();
|
|
EXPECT_NE(Element, nullptr);
|
|
(Element->*Function)();
|
|
return Element;
|
|
}
|
|
void set(LVElement *Element, StringRef Name, LVOffset Offset,
|
|
uint32_t LineNumber = 0, LVElement *Type = nullptr);
|
|
|
|
public:
|
|
ReaderTestCompare(ScopedPrinter &W) : LVReader("", "", W) {
|
|
setInstance(this);
|
|
}
|
|
|
|
Error createScopes() { return LVReader::createScopes(); }
|
|
Error printScopes() { return LVReader::printScopes(); }
|
|
|
|
void createElements();
|
|
void addElements(bool IsReference, bool IsTarget);
|
|
void initElements();
|
|
};
|
|
|
|
// Helper function to add a logical element to a given scope.
|
|
void ReaderTestCompare::add(LVScope *Parent, LVElement *Child) {
|
|
Parent->addElement(Child);
|
|
EXPECT_EQ(Child->getParent(), Parent);
|
|
EXPECT_EQ(Child->getLevel(), Parent->getLevel() + 1);
|
|
}
|
|
|
|
// Helper function to set the initial values for a given logical element.
|
|
void ReaderTestCompare::set(LVElement *Element, StringRef Name, LVOffset Offset,
|
|
uint32_t LineNumber, LVElement *Type) {
|
|
Element->setName(Name);
|
|
Element->setOffset(Offset);
|
|
Element->setLineNumber(LineNumber);
|
|
Element->setType(Type);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Create the logical elements.
|
|
void ReaderTestCompare::createElements() {
|
|
// Create scope root.
|
|
Error Err = createScopes();
|
|
ASSERT_THAT_ERROR(std::move(Err), Succeeded());
|
|
Root = getScopesRoot();
|
|
ASSERT_NE(Root, nullptr);
|
|
|
|
// Create the logical types.
|
|
IntegerType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
|
|
UnsignedType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
|
|
GlobalType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
|
|
LocalType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
|
|
NestedType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
|
|
EnumeratorOne =
|
|
create<LVTypeEnumerator, LVTypeSetFunction>(&LVType::setIsEnumerator);
|
|
EnumeratorTwo =
|
|
create<LVTypeEnumerator, LVTypeSetFunction>(&LVType::setIsEnumerator);
|
|
TypeDefinitionOne =
|
|
create<LVTypeDefinition, LVTypeSetFunction>(&LVType::setIsTypedef);
|
|
TypeDefinitionTwo =
|
|
create<LVTypeDefinition, LVTypeSetFunction>(&LVType::setIsTypedef);
|
|
|
|
// Create the logical scopes.
|
|
NestedScope =
|
|
create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
|
|
InnerScope = create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
|
|
Aggregate =
|
|
create<LVScopeAggregate, LVScopeSetFunction>(&LVScope::setIsAggregate);
|
|
CompileUnit = create<LVScopeCompileUnit, LVScopeSetFunction>(
|
|
&LVScope::setIsCompileUnit);
|
|
Enumeration = create<LVScopeEnumeration, LVScopeSetFunction>(
|
|
&LVScope::setIsEnumeration);
|
|
FunctionOne =
|
|
create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
|
|
FunctionTwo =
|
|
create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
|
|
Namespace =
|
|
create<LVScopeNamespace, LVScopeSetFunction>(&LVScope::setIsNamespace);
|
|
|
|
// Create the logical symbols.
|
|
GlobalVariable =
|
|
create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
|
|
LocalVariable =
|
|
create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
|
|
ClassMember = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsMember);
|
|
NestedVariable =
|
|
create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
|
|
ParameterOne =
|
|
create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
|
|
ParameterTwo =
|
|
create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
|
|
|
|
// Create the logical lines.
|
|
LineOne = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
|
|
LineTwo = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
|
|
LineThree = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
|
|
}
|
|
|
|
// Reference Reader: Target Reader:
|
|
// ---------------------- ----------------------
|
|
// Root Root
|
|
// CompileUnit CompileUnit
|
|
// IntegerType IntegerType
|
|
// UnsignedType UnsignedType
|
|
// FunctionOne FunctionOne
|
|
// ParameterOne ParameterOne
|
|
// LocalVariable ---
|
|
// LocalType LocalType
|
|
// LineOne LineOne
|
|
// NestedScope NestedScope
|
|
// NestedVariable NestedVariable
|
|
// NestedType NestedType
|
|
// LineTwo ---
|
|
// InnerScope InnerScope
|
|
// --- LineThree
|
|
// --- FunctionTwo
|
|
// --- ParameterTwo
|
|
// GlobalVariable GlobalVariable
|
|
// GlobalType GlobalType
|
|
// Namespace Namespace
|
|
// Aggregate Aggregate
|
|
// ClassMember ClassMember
|
|
// Enumeration Enumeration
|
|
// EnumeratorOne EnumeratorOne
|
|
// EnumeratorTwo EnumeratorTwo
|
|
// TypeDefinitionOne ---
|
|
// --- TypeDefinitionTwo
|
|
|
|
// Create the logical view adding the created logical elements.
|
|
void ReaderTestCompare::addElements(bool IsReference, bool IsTarget) {
|
|
Root->setName(IsReference ? "Reference-Reader" : "Target-Reader");
|
|
|
|
auto Insert = [&](bool Insert, auto *Parent, auto *Child) {
|
|
if (Insert)
|
|
add(Parent, Child);
|
|
else
|
|
OrphanElements.push_back(Child);
|
|
};
|
|
|
|
setCompileUnit(CompileUnit);
|
|
add(Root, CompileUnit);
|
|
|
|
// Add elements to CompileUnit.
|
|
Insert(true, CompileUnit, IntegerType);
|
|
Insert(true, CompileUnit, UnsignedType);
|
|
Insert(true, CompileUnit, FunctionOne);
|
|
Insert(IsTarget, CompileUnit, FunctionTwo);
|
|
Insert(true, CompileUnit, GlobalVariable);
|
|
Insert(true, CompileUnit, GlobalType);
|
|
Insert(true, CompileUnit, Namespace);
|
|
|
|
// Add elements to Namespace.
|
|
Insert(true, Namespace, Aggregate);
|
|
Insert(true, Namespace, Enumeration);
|
|
Insert(IsReference, Namespace, TypeDefinitionOne);
|
|
Insert(IsTarget, Namespace, TypeDefinitionTwo);
|
|
|
|
// Add elements to FunctionOne.
|
|
Insert(true, FunctionOne, ParameterOne);
|
|
Insert(IsReference, FunctionOne, LocalVariable);
|
|
Insert(true, FunctionOne, LocalType);
|
|
Insert(true, FunctionOne, LineOne);
|
|
Insert(true, FunctionOne, NestedScope);
|
|
|
|
// Add elements to FunctionTwo.
|
|
Insert(IsTarget, FunctionTwo, ParameterTwo);
|
|
|
|
// Add elements to NestedScope.
|
|
Insert(true, NestedScope, NestedVariable);
|
|
Insert(true, NestedScope, NestedType);
|
|
Insert(IsReference, NestedScope, LineTwo);
|
|
Insert(true, NestedScope, InnerScope);
|
|
|
|
// Add elements to Enumeration.
|
|
Insert(true, Enumeration, EnumeratorOne);
|
|
Insert(true, Enumeration, EnumeratorTwo);
|
|
|
|
// Add elements to Aggregate.
|
|
Insert(true, Aggregate, ClassMember);
|
|
|
|
Insert(IsTarget, InnerScope, LineThree);
|
|
}
|
|
|
|
// Set initial values to logical elements.
|
|
void ReaderTestCompare::initElements() {
|
|
setFilename("LogicalElements.obj");
|
|
|
|
Root->setFileFormatName("FileFormat");
|
|
|
|
// Types.
|
|
set(IntegerType, "int", 0x1000);
|
|
set(UnsignedType, "unsigned", 0x1010);
|
|
set(GlobalType, "GlobalType", 0x1020, 1020);
|
|
set(LocalType, "LocalType", 0x1030, 1030);
|
|
set(NestedType, "NestedType", 0x1040, 1040);
|
|
|
|
set(TypeDefinitionOne, "INTEGER", 0x1050, 1050, IntegerType);
|
|
set(TypeDefinitionTwo, "INT", 0x1060, 1060, TypeDefinitionOne);
|
|
|
|
set(EnumeratorOne, "One", 0x1070, 1070);
|
|
EnumeratorOne->setValue("Blue");
|
|
|
|
set(EnumeratorTwo, "Two", 0x1080, 1080);
|
|
EnumeratorTwo->setValue("Red");
|
|
|
|
// Scopes.
|
|
set(Aggregate, "Class", 0x2000, 2000);
|
|
set(Enumeration, "Colors", 0x2010, 2010);
|
|
set(FunctionOne, "FunctionOne", 0x2020, 2020, GlobalType);
|
|
set(FunctionTwo, "FunctionTwo", 0x2030, 2030, GlobalType);
|
|
set(Namespace, "Namespace", 0x2040, 2040);
|
|
set(NestedScope, "", 0x2050, 2050);
|
|
set(InnerScope, "", 0x2060, 2060);
|
|
set(CompileUnit, "test.cpp", 0x2070, 2070);
|
|
|
|
// Symbols.
|
|
set(GlobalVariable, "GlobalVariable", 0x3000, 3000);
|
|
set(LocalVariable, "LocalVariable", 0x3010, 3010, UnsignedType);
|
|
set(ClassMember, "ClassMember", 0x3020, 3020, IntegerType);
|
|
set(ParameterOne, "ParameterOne", 0x3030, 3030, UnsignedType);
|
|
set(ParameterTwo, "ParameterTwo", 0x3040, 3040, UnsignedType);
|
|
set(NestedVariable, "NestedVariable", 0x3050, 3050);
|
|
|
|
// Lines.
|
|
set(LineOne, "", 0x4000, 4000);
|
|
set(LineTwo, "", 0x4010, 4010);
|
|
set(LineThree, "", 0x4020, 4020);
|
|
}
|
|
|
|
// Compare the logical views.
|
|
void compareReadersViews(ReaderTestCompare *ReferenceReader,
|
|
ReaderTestCompare *TargetReader) {
|
|
LVCompare Compare(nulls());
|
|
Error Err = Compare.execute(ReferenceReader, TargetReader);
|
|
ASSERT_THAT_ERROR(std::move(Err), Succeeded());
|
|
|
|
// Get comparison table.
|
|
LVPassTable PassTable = Compare.getPassTable();
|
|
ASSERT_EQ(PassTable.size(), 5u);
|
|
|
|
LVReader *Reader;
|
|
LVElement *Element;
|
|
LVComparePass Pass;
|
|
|
|
// Reference: Missing 'FunctionOne'
|
|
std::tie(Reader, Element, Pass) = PassTable[0];
|
|
EXPECT_EQ(Reader, ReferenceReader);
|
|
EXPECT_EQ(Element, ReferenceReader->FunctionOne);
|
|
EXPECT_EQ(Pass, LVComparePass::Missing);
|
|
|
|
// Reference: Missing 'TypeDefinitionOne'
|
|
std::tie(Reader, Element, Pass) = PassTable[1];
|
|
EXPECT_EQ(Reader, ReferenceReader);
|
|
EXPECT_EQ(Element, ReferenceReader->TypeDefinitionOne);
|
|
EXPECT_EQ(Pass, LVComparePass::Missing);
|
|
|
|
// Target: Added 'FunctionOne'
|
|
std::tie(Reader, Element, Pass) = PassTable[2];
|
|
EXPECT_EQ(Reader, TargetReader);
|
|
EXPECT_EQ(Element, TargetReader->FunctionOne);
|
|
EXPECT_EQ(Pass, LVComparePass::Added);
|
|
|
|
// Target: Added 'FunctionTwo'
|
|
std::tie(Reader, Element, Pass) = PassTable[3];
|
|
EXPECT_EQ(Reader, TargetReader);
|
|
EXPECT_EQ(Element, TargetReader->FunctionTwo);
|
|
EXPECT_EQ(Pass, LVComparePass::Added);
|
|
|
|
// Target: Added 'TypeDefinitionTwo'
|
|
std::tie(Reader, Element, Pass) = PassTable[4];
|
|
EXPECT_EQ(Reader, TargetReader);
|
|
EXPECT_EQ(Element, TargetReader->TypeDefinitionTwo);
|
|
EXPECT_EQ(Pass, LVComparePass::Added);
|
|
}
|
|
|
|
// Compare the logical elements.
|
|
void compareReadersElements(ReaderTestCompare *ReferenceReader,
|
|
ReaderTestCompare *TargetReader) {
|
|
LVCompare Compare(nulls());
|
|
Error Err = Compare.execute(ReferenceReader, TargetReader);
|
|
ASSERT_THAT_ERROR(std::move(Err), Succeeded());
|
|
|
|
// Get comparison table.
|
|
LVPassTable PassTable = Compare.getPassTable();
|
|
ASSERT_EQ(PassTable.size(), 7u);
|
|
|
|
LVReader *Reader;
|
|
LVElement *Element;
|
|
LVComparePass Pass;
|
|
|
|
// Reference: Missing 'LocalVariable'
|
|
std::tie(Reader, Element, Pass) = PassTable[0];
|
|
EXPECT_EQ(Reader, ReferenceReader);
|
|
EXPECT_EQ(Element, ReferenceReader->LocalVariable);
|
|
EXPECT_EQ(Pass, LVComparePass::Missing);
|
|
|
|
// Reference: Missing 'TypeDefinitionOne'
|
|
std::tie(Reader, Element, Pass) = PassTable[1];
|
|
EXPECT_EQ(Reader, ReferenceReader);
|
|
EXPECT_EQ(Element, ReferenceReader->TypeDefinitionOne);
|
|
EXPECT_EQ(Pass, LVComparePass::Missing);
|
|
|
|
// Reference: Missing 'LineTwo'
|
|
std::tie(Reader, Element, Pass) = PassTable[2];
|
|
EXPECT_EQ(Reader, ReferenceReader);
|
|
EXPECT_EQ(Element, ReferenceReader->LineTwo);
|
|
EXPECT_EQ(Pass, LVComparePass::Missing);
|
|
|
|
// Target: Added 'FunctionTwo'
|
|
std::tie(Reader, Element, Pass) = PassTable[3];
|
|
EXPECT_EQ(Reader, TargetReader);
|
|
EXPECT_EQ(Element, TargetReader->FunctionTwo);
|
|
EXPECT_EQ(Pass, LVComparePass::Added);
|
|
|
|
// Target: Added 'ParameterTwo'
|
|
std::tie(Reader, Element, Pass) = PassTable[4];
|
|
EXPECT_EQ(Reader, TargetReader);
|
|
EXPECT_EQ(Element, TargetReader->ParameterTwo);
|
|
EXPECT_EQ(Pass, LVComparePass::Added);
|
|
|
|
// Target: Added 'TypeDefinitionTwo'
|
|
std::tie(Reader, Element, Pass) = PassTable[5];
|
|
EXPECT_EQ(Reader, TargetReader);
|
|
EXPECT_EQ(Element, TargetReader->TypeDefinitionTwo);
|
|
EXPECT_EQ(Pass, LVComparePass::Added);
|
|
|
|
// Target: Added 'LineThree'
|
|
std::tie(Reader, Element, Pass) = PassTable[6];
|
|
EXPECT_EQ(Reader, TargetReader);
|
|
EXPECT_EQ(Element, TargetReader->LineThree);
|
|
EXPECT_EQ(Pass, LVComparePass::Added);
|
|
}
|
|
|
|
TEST(LogicalViewTest, CompareElements) {
|
|
ScopedPrinter W(outs());
|
|
|
|
// Reader options.
|
|
LVOptions ReaderOptions;
|
|
ReaderOptions.setCompareLines();
|
|
ReaderOptions.setCompareScopes();
|
|
ReaderOptions.setCompareSymbols();
|
|
ReaderOptions.setCompareTypes();
|
|
|
|
// The next set-ups are very similar. The only difference is the
|
|
// comparison type, which must be set before the readers are created.
|
|
// Views: setCompareContext()
|
|
// Elements: resetCompareContext()
|
|
{
|
|
// Compare the logical views as whole unit (--compare-context).
|
|
ReaderOptions.setCompareContext();
|
|
ReaderOptions.resolveDependencies();
|
|
options().setOptions(&ReaderOptions);
|
|
|
|
ReaderTestCompare ReferenceReader(W);
|
|
ReferenceReader.createElements();
|
|
ReferenceReader.addElements(/*IsReference=*/true, /*IsTarget=*/false);
|
|
ReferenceReader.initElements();
|
|
|
|
ReaderTestCompare TargetReader(W);
|
|
TargetReader.createElements();
|
|
TargetReader.addElements(/*IsReference=*/false, /*IsTarget=*/true);
|
|
TargetReader.initElements();
|
|
|
|
compareReadersViews(&ReferenceReader, &TargetReader);
|
|
}
|
|
{
|
|
// Compare the logical elements.
|
|
ReaderOptions.resetCompareContext();
|
|
ReaderOptions.resolveDependencies();
|
|
options().setOptions(&ReaderOptions);
|
|
|
|
ReaderTestCompare ReferenceReader(W);
|
|
ReferenceReader.createElements();
|
|
ReferenceReader.addElements(/*IsReference=*/true, /*IsTarget=*/false);
|
|
ReferenceReader.initElements();
|
|
|
|
ReaderTestCompare TargetReader(W);
|
|
TargetReader.createElements();
|
|
TargetReader.addElements(/*IsReference=*/false, /*IsTarget=*/true);
|
|
TargetReader.initElements();
|
|
|
|
compareReadersElements(&ReferenceReader, &TargetReader);
|
|
}
|
|
}
|
|
|
|
} // namespace
|