diff options
Diffstat (limited to 'unittests/DebugInfo')
-rw-r--r-- | unittests/DebugInfo/CodeView/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittests/DebugInfo/CodeView/ErrorChecking.h | 9 | ||||
-rw-r--r-- | unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp | 496 | ||||
-rw-r--r-- | unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp | 24 | ||||
-rw-r--r-- | unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp | 51 |
5 files changed, 545 insertions, 36 deletions
diff --git a/unittests/DebugInfo/CodeView/CMakeLists.txt b/unittests/DebugInfo/CodeView/CMakeLists.txt index 854182c4efb4..9576d45e77ba 100644 --- a/unittests/DebugInfo/CodeView/CMakeLists.txt +++ b/unittests/DebugInfo/CodeView/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS set(DebugInfoCodeViewSources RandomAccessVisitorTest.cpp + TypeIndexDiscoveryTest.cpp ) add_llvm_unittest(DebugInfoCodeViewTests diff --git a/unittests/DebugInfo/CodeView/ErrorChecking.h b/unittests/DebugInfo/CodeView/ErrorChecking.h index 09310883bf58..4ca74c487b3e 100644 --- a/unittests/DebugInfo/CodeView/ErrorChecking.h +++ b/unittests/DebugInfo/CodeView/ErrorChecking.h @@ -26,6 +26,15 @@ consumeError(std::move(E)); \ } +#define ASSERT_EXPECTED(Exp) \ + { \ + auto E = Exp.takeError(); \ + bool Success = static_cast<bool>(E); \ + if (!Success) \ + consumeError(std::move(E)); \ + ASSERT_FALSE(Success); \ + } + #define EXPECT_EXPECTED(Exp) \ { \ auto E = Exp.takeError(); \ diff --git a/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp b/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp new file mode 100644 index 000000000000..4eca7777a1e2 --- /dev/null +++ b/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp @@ -0,0 +1,496 @@ +//===- llvm/unittest/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" + +#include "ErrorChecking.h" +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" +#include "llvm/Support/Allocator.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::codeview; + +class TypeIndexIteratorTest : public testing::Test { +public: + TypeIndexIteratorTest() {} + + void SetUp() override { + Refs.clear(); + TTB = make_unique<TypeTableBuilder>(Storage); + FLRB = make_unique<FieldListRecordBuilder>(*TTB); + } + + void TearDown() override { + FLRB.reset(); + TTB.reset(); + } + +protected: + template <typename... Indices> + bool checkTypeReferences(uint32_t RecordIndex, Indices &&... TIs) const { + EXPECT_EQ(sizeof...(Indices), countRefs(RecordIndex)); + return checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(TIs)...); + } + + template <typename... T> void writeFieldList(T &&... MemberRecords) { + FLRB->begin(); + writeFieldListImpl(std::forward<T>(MemberRecords)...); + FLRB->end(true); + ASSERT_EQ(1u, TTB->records().size()); + discoverAllTypeIndices(); + } + + template <typename... T> void writeTypeRecords(T &&... Records) { + writeTypeRecordsImpl(std::forward<T>(Records)...); + ASSERT_EQ(sizeof...(T), TTB->records().size()); + discoverAllTypeIndices(); + } + + std::unique_ptr<TypeTableBuilder> TTB; + +private: + uint32_t countRefs(uint32_t RecordIndex) const { + auto &R = Refs[RecordIndex]; + uint32_t Count = 0; + for (auto &Ref : R) { + Count += Ref.Count; + } + return Count; + } + + bool checkOneTypeReference(uint32_t RecordIndex, ArrayRef<uint8_t> RecordData, + TypeIndex TI) const { + RecordData = RecordData.drop_front(sizeof(RecordPrefix)); + auto &RefList = Refs[RecordIndex]; + for (auto &Ref : RefList) { + uint32_t Offset = Ref.Offset; + ArrayRef<uint8_t> Loc = RecordData.drop_front(Offset); + ArrayRef<TypeIndex> Indices( + reinterpret_cast<const TypeIndex *>(Loc.data()), Ref.Count); + if (llvm::any_of(Indices, + [TI](const TypeIndex &Other) { return Other == TI; })) + return true; + } + return false; + } + + template <typename... Indices> + bool checkTypeReferencesImpl(uint32_t RecordIndex) const { + return true; + } + + template <typename... Indices> + bool checkTypeReferencesImpl(uint32_t RecordIndex, TypeIndex TI, + Indices &&... Rest) const { + ArrayRef<uint8_t> Record = TTB->records()[RecordIndex]; + bool Success = checkOneTypeReference(RecordIndex, Record, TI); + EXPECT_TRUE(Success); + return Success & + checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(Rest)...); + } + + void discoverAllTypeIndices() { + Refs.resize(TTB->records().size()); + for (uint32_t I = 0; I < TTB->records().size(); ++I) { + ArrayRef<uint8_t> Data = TTB->records()[I]; + discoverTypeIndices(Data, Refs[I]); + } + } + + // Helper function to write out a field list record with the given list + // of member records. + void writeFieldListImpl() {} + + template <typename RecType, typename... Rest> + void writeFieldListImpl(RecType &&Record, Rest &&... Records) { + FLRB->writeMemberType(Record); + writeFieldListImpl(std::forward<Rest>(Records)...); + } + + // Helper function to write out a list of type records. + void writeTypeRecordsImpl() {} + + template <typename RecType, typename... Rest> + void writeTypeRecordsImpl(RecType &&Record, Rest &&... Records) { + TTB->writeKnownType(Record); + writeTypeRecordsImpl(std::forward<Rest>(Records)...); + } + + std::vector<SmallVector<TiReference, 4>> Refs; + std::unique_ptr<FieldListRecordBuilder> FLRB; + BumpPtrAllocator Storage; +}; + +namespace leafs { +static FuncIdRecord FuncId(TypeIndex(1), TypeIndex(2), "FuncId"); +static MemberFuncIdRecord MemFuncId(TypeIndex(3), TypeIndex(4), "FuncId"); +static StringIdRecord StringId(TypeIndex(5), "TheString"); +static struct { + std::vector<TypeIndex> Ids = {TypeIndex(6), TypeIndex(7), TypeIndex(8)}; + StringListRecord Record{TypeRecordKind::StringList, Ids}; +} StringList; +static struct { + std::vector<TypeIndex> Ids = {TypeIndex(9), TypeIndex(10), TypeIndex(11)}; + BuildInfoRecord Record{Ids}; +} BuildInfo; +static UdtSourceLineRecord UdtSourceLine(TypeIndex(12), TypeIndex(13), 0); +static UdtModSourceLineRecord UdtModSourceLine(TypeIndex(14), TypeIndex(15), 0, + 0); +static ModifierRecord Modifier(TypeIndex(16), ModifierOptions::None); +static ProcedureRecord Procedure(TypeIndex(17), CallingConvention::PpcCall, + FunctionOptions::None, 0, TypeIndex(18)); +static MemberFunctionRecord MemberFunction(TypeIndex(19), TypeIndex(20), + TypeIndex(21), + CallingConvention::ThisCall, + FunctionOptions::None, 2, + TypeIndex(22), 0); +static struct { + std::vector<TypeIndex> Ids = {TypeIndex(23), TypeIndex(24), TypeIndex(25)}; + ArgListRecord Record{TypeRecordKind::ArgList, Ids}; +} ArgList; +static ArrayRecord Array(TypeIndex(26), TypeIndex(27), 10, "MyArray"); +static ClassRecord Class(TypeRecordKind::Class, 3, ClassOptions::None, + TypeIndex(28), TypeIndex(29), TypeIndex(30), 10, + "MyClass", "MyClassUniqueName"); +static ClassRecord Struct(TypeRecordKind::Struct, 3, ClassOptions::None, + TypeIndex(31), TypeIndex(32), TypeIndex(33), 10, + "MyClass", "MyClassUniqueName"); +static UnionRecord Union(1, ClassOptions::None, TypeIndex(34), 10, "MyUnion", + "MyUnionUniqueName"); +static EnumRecord Enum(1, ClassOptions::None, TypeIndex(35), "MyEnum", + "EnumUniqueName", TypeIndex(36)); +static BitFieldRecord BitField(TypeIndex(37), 1, 0); +static VFTableRecord VFTable(TypeIndex(38), TypeIndex(39), 1, "VFT", {}); +static VFTableShapeRecord VTableShape({}); +static struct { + const TypeIndex T1{40}; + const TypeIndex T2{41}; + const TypeIndex T3{42}; + const TypeIndex T4{43}; + + std::vector<OneMethodRecord> Methods{ + {T1, MemberAccess::Public, MethodKind::IntroducingVirtual, + MethodOptions::None, 0, "Method1"}, + {T2, MemberAccess::Public, MethodKind::PureVirtual, MethodOptions::None, + 0, "Method1"}, + {T3, MemberAccess::Public, MethodKind::PureIntroducingVirtual, + MethodOptions::None, 0, "Method1"}, + {T4, MemberAccess::Public, MethodKind::Static, MethodOptions::None, 0, + "Method1"}}; + + MethodOverloadListRecord Record{Methods}; +} MethodOverloadList; +static PointerRecord Pointer(TypeIndex(44), PointerKind::Near32, + PointerMode::Pointer, PointerOptions::Const, 3); +static PointerRecord MemberPointer( + TypeIndex(45), PointerKind::Near32, PointerMode::PointerToDataMember, + PointerOptions::Const, 3, + MemberPointerInfo(TypeIndex(46), + PointerToMemberRepresentation::GeneralData)); +} + +namespace members { +static BaseClassRecord BaseClass(MemberAccess::Public, TypeIndex(47), 0); +static EnumeratorRecord Enumerator(MemberAccess::Public, + APSInt(APInt(8, 3, false)), "Test"); +DataMemberRecord DataMember(MemberAccess::Public, TypeIndex(48), 0, "Test"); +OverloadedMethodRecord OverloadedMethod(3, TypeIndex(49), "MethodList"); +static struct { + const TypeIndex T1{50}; + const TypeIndex T2{51}; + const TypeIndex T3{52}; + const TypeIndex T4{53}; + OneMethodRecord R1{T1, + MemberAccess::Public, + MethodKind::IntroducingVirtual, + MethodOptions::None, + 0, + "M1"}; + OneMethodRecord R2{T2, + MemberAccess::Public, + MethodKind::PureVirtual, + MethodOptions::None, + 0, + "M2"}; + OneMethodRecord R3{T3, + MemberAccess::Public, + MethodKind::PureIntroducingVirtual, + MethodOptions::None, + 0, + "M3"}; + OneMethodRecord R4{T4, + MemberAccess::Protected, + MethodKind::Vanilla, + MethodOptions::CompilerGenerated, + 0, + "M4"}; +} OneMethod; +static NestedTypeRecord NestedType(TypeIndex(54), "MyClass"); +static StaticDataMemberRecord StaticDataMember(MemberAccess::Public, + TypeIndex(55), "Foo"); +static VirtualBaseClassRecord VirtualBaseClass(TypeRecordKind::VirtualBaseClass, + MemberAccess::Public, + TypeIndex(56), TypeIndex(57), 0, + 0); +static VFPtrRecord VFPtr(TypeIndex(58)); +static ListContinuationRecord Continuation(TypeIndex(59)); +} + +TEST_F(TypeIndexIteratorTest, FuncId) { + using namespace leafs; + writeTypeRecords(FuncId); + checkTypeReferences(0, FuncId.FunctionType, FuncId.ParentScope); +} + +TEST_F(TypeIndexIteratorTest, MemFuncId) { + using namespace leafs; + writeTypeRecords(MemFuncId); + checkTypeReferences(0, MemFuncId.ClassType, MemFuncId.FunctionType); +} + +TEST_F(TypeIndexIteratorTest, StringId) { + using namespace leafs; + writeTypeRecords(StringId); + checkTypeReferences(0, StringId.Id); +} + +TEST_F(TypeIndexIteratorTest, SubstrList) { + using namespace leafs; + writeTypeRecords(StringList.Record); + checkTypeReferences(0, StringList.Ids[0], StringList.Ids[1], + StringList.Ids[2]); +} + +TEST_F(TypeIndexIteratorTest, BuildInfo) { + using namespace leafs; + writeTypeRecords(BuildInfo.Record); + checkTypeReferences(0, BuildInfo.Ids[0], BuildInfo.Ids[1], BuildInfo.Ids[2]); +} + +TEST_F(TypeIndexIteratorTest, UdtSrcLine) { + using namespace leafs; + writeTypeRecords(UdtSourceLine); + checkTypeReferences(0, UdtSourceLine.UDT, UdtSourceLine.SourceFile); +} + +TEST_F(TypeIndexIteratorTest, UdtModSrcLine) { + using namespace leafs; + writeTypeRecords(UdtModSourceLine); + checkTypeReferences(0, UdtModSourceLine.UDT, UdtModSourceLine.SourceFile); +} + +TEST_F(TypeIndexIteratorTest, Modifier) { + using namespace leafs; + writeTypeRecords(Modifier); + checkTypeReferences(0, Modifier.ModifiedType); +} + +TEST_F(TypeIndexIteratorTest, Procedure) { + using namespace leafs; + writeTypeRecords(Procedure); + checkTypeReferences(0, Procedure.ReturnType, Procedure.ArgumentList); +} + +TEST_F(TypeIndexIteratorTest, MemFunc) { + using namespace leafs; + writeTypeRecords(MemberFunction); + checkTypeReferences(0, MemberFunction.ReturnType, MemberFunction.ClassType, + MemberFunction.ThisType, MemberFunction.ArgumentList); +} + +TEST_F(TypeIndexIteratorTest, ArgList) { + using namespace leafs; + writeTypeRecords(ArgList.Record); + checkTypeReferences(0, ArgList.Ids[0], ArgList.Ids[1], ArgList.Ids[2]); +} + +TEST_F(TypeIndexIteratorTest, Array) { + using namespace leafs; + writeTypeRecords(Array); + checkTypeReferences(0, Array.ElementType, Array.IndexType); +} + +TEST_F(TypeIndexIteratorTest, Class) { + using namespace leafs; + writeTypeRecords(Class); + checkTypeReferences(0, Class.FieldList, Class.DerivationList, + Class.VTableShape); +} + +TEST_F(TypeIndexIteratorTest, Struct) { + using namespace leafs; + writeTypeRecords(Struct); + checkTypeReferences(0, Struct.FieldList, Struct.DerivationList, + Struct.VTableShape); +} + +TEST_F(TypeIndexIteratorTest, Union) { + using namespace leafs; + writeTypeRecords(Union); + checkTypeReferences(0, Union.FieldList); +} + +TEST_F(TypeIndexIteratorTest, Enum) { + using namespace leafs; + writeTypeRecords(Enum); + checkTypeReferences(0, Enum.FieldList, Enum.UnderlyingType); +} + +TEST_F(TypeIndexIteratorTest, Bitfield) { + using namespace leafs; + writeTypeRecords(BitField); + checkTypeReferences(0, BitField.Type); +} + +TEST_F(TypeIndexIteratorTest, VTable) { + using namespace leafs; + writeTypeRecords(VFTable); + checkTypeReferences(0, VFTable.CompleteClass, VFTable.OverriddenVFTable); +} + +TEST_F(TypeIndexIteratorTest, VTShape) { + using namespace leafs; + writeTypeRecords(VTableShape); + checkTypeReferences(0); +} + +TEST_F(TypeIndexIteratorTest, OverloadList) { + using namespace leafs; + writeTypeRecords(MethodOverloadList.Record); + checkTypeReferences(0, MethodOverloadList.T1, MethodOverloadList.T2, + MethodOverloadList.T3, MethodOverloadList.T4); +} + +TEST_F(TypeIndexIteratorTest, Pointer) { + using namespace leafs; + writeTypeRecords(Pointer); + checkTypeReferences(0, Pointer.ReferentType); +} + +TEST_F(TypeIndexIteratorTest, MemberPointer) { + using namespace leafs; + writeTypeRecords(MemberPointer); + checkTypeReferences(0, MemberPointer.ReferentType, + MemberPointer.MemberInfo->ContainingType); +} + +TEST_F(TypeIndexIteratorTest, ManyTypes) { + + using namespace leafs; + writeTypeRecords(FuncId, MemFuncId, StringId, StringList.Record, + BuildInfo.Record, UdtSourceLine, UdtModSourceLine, Modifier, + Procedure, MemberFunction, ArgList.Record, Array, Class, + Union, Enum, BitField, VFTable, VTableShape, + MethodOverloadList.Record, Pointer, MemberPointer); + + checkTypeReferences(0, FuncId.FunctionType, FuncId.ParentScope); + checkTypeReferences(1, MemFuncId.ClassType, MemFuncId.FunctionType); + checkTypeReferences(2, StringId.Id); + checkTypeReferences(3, StringList.Ids[0], StringList.Ids[1], + StringList.Ids[2]); + checkTypeReferences(4, BuildInfo.Ids[0], BuildInfo.Ids[1], BuildInfo.Ids[2]); + checkTypeReferences(5, UdtSourceLine.UDT, UdtSourceLine.SourceFile); + checkTypeReferences(6, UdtModSourceLine.UDT, UdtModSourceLine.SourceFile); + checkTypeReferences(7, Modifier.ModifiedType); + checkTypeReferences(8, Procedure.ReturnType, Procedure.ArgumentList); + checkTypeReferences(9, MemberFunction.ReturnType, MemberFunction.ClassType, + MemberFunction.ThisType, MemberFunction.ArgumentList); + checkTypeReferences(10, ArgList.Ids[0], ArgList.Ids[1], ArgList.Ids[2]); + checkTypeReferences(11, Array.ElementType, Array.IndexType); + checkTypeReferences(12, Class.FieldList, Class.DerivationList, + Class.VTableShape); + checkTypeReferences(13, Union.FieldList); + checkTypeReferences(14, Enum.FieldList, Enum.UnderlyingType); + checkTypeReferences(15, BitField.Type); + checkTypeReferences(16, VFTable.CompleteClass, VFTable.OverriddenVFTable); + checkTypeReferences(17); + checkTypeReferences(18, MethodOverloadList.T1, MethodOverloadList.T2, + MethodOverloadList.T3, MethodOverloadList.T4); + checkTypeReferences(19, Pointer.ReferentType); + checkTypeReferences(20, MemberPointer.ReferentType, + MemberPointer.MemberInfo->ContainingType); +} + +TEST_F(TypeIndexIteratorTest, FieldListBaseClass) { + using namespace members; + writeFieldList(BaseClass); + checkTypeReferences(0, BaseClass.Type); +} + +TEST_F(TypeIndexIteratorTest, FieldListEnumerator) { + using namespace members; + writeFieldList(Enumerator); + checkTypeReferences(0); +} + +TEST_F(TypeIndexIteratorTest, FieldListMember) { + using namespace members; + writeFieldList(DataMember); + checkTypeReferences(0, DataMember.Type); +} + +TEST_F(TypeIndexIteratorTest, FieldListMethod) { + using namespace members; + writeFieldList(OverloadedMethod); + checkTypeReferences(0, OverloadedMethod.MethodList); +} + +TEST_F(TypeIndexIteratorTest, FieldListOneMethod) { + using namespace members; + writeFieldList(OneMethod.R1, OneMethod.R2, OneMethod.R3, OneMethod.R4); + checkTypeReferences(0, OneMethod.T1, OneMethod.T2, OneMethod.T3, + OneMethod.T4); +} + +TEST_F(TypeIndexIteratorTest, FieldListNestedType) { + using namespace members; + writeFieldList(NestedType); + checkTypeReferences(0, NestedType.Type); +} + +TEST_F(TypeIndexIteratorTest, FieldListStaticMember) { + using namespace members; + writeFieldList(StaticDataMember); + checkTypeReferences(0, StaticDataMember.Type); +} + +TEST_F(TypeIndexIteratorTest, FieldListVirtualBase) { + using namespace members; + writeFieldList(VirtualBaseClass); + checkTypeReferences(0, VirtualBaseClass.BaseType, VirtualBaseClass.VBPtrType); +} + +TEST_F(TypeIndexIteratorTest, FieldListVFTable) { + using namespace members; + writeFieldList(VFPtr); + checkTypeReferences(0, VFPtr.Type); +} + +TEST_F(TypeIndexIteratorTest, FieldListContinuation) { + using namespace members; + writeFieldList(Continuation); + checkTypeReferences(0, Continuation.ContinuationIndex); +} + +TEST_F(TypeIndexIteratorTest, ManyMembers) { + using namespace members; + writeFieldList(BaseClass, Enumerator, DataMember, OverloadedMethod, + OneMethod.R1, OneMethod.R2, OneMethod.R3, OneMethod.R4, + NestedType, StaticDataMember, VirtualBaseClass, VFPtr, + Continuation); + + checkTypeReferences( + 0, BaseClass.Type, DataMember.Type, OverloadedMethod.MethodList, + OneMethod.T1, OneMethod.T2, OneMethod.T3, OneMethod.T4, NestedType.Type, + StaticDataMember.Type, VirtualBaseClass.BaseType, + VirtualBaseClass.VBPtrType, VFPtr.Type, Continuation.ContinuationIndex); +}
\ No newline at end of file diff --git a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp index a9d0d9ef4e69..9e846674648c 100644 --- a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -311,8 +311,9 @@ void TestAllForms() { EXPECT_EQ(Data2, toReference(DieDG.find(Attr_DW_FORM_ref2), 0)); EXPECT_EQ(Data4, toReference(DieDG.find(Attr_DW_FORM_ref4), 0)); EXPECT_EQ(Data8, toReference(DieDG.find(Attr_DW_FORM_ref8), 0)); - if (Version >= 4) + if (Version >= 4) { EXPECT_EQ(Data8_2, toReference(DieDG.find(Attr_DW_FORM_ref_sig8), 0)); + } EXPECT_EQ(UData[0], toReference(DieDG.find(Attr_DW_FORM_ref_udata), 0)); //---------------------------------------------------------------------- @@ -320,15 +321,17 @@ void TestAllForms() { //---------------------------------------------------------------------- EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_true), 0)); EXPECT_EQ(0ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_false), 1)); - if (Version >= 4) + if (Version >= 4) { EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_present), 0)); + } //---------------------------------------------------------------------- // Test SLEB128 based forms //---------------------------------------------------------------------- EXPECT_EQ(SData, toSigned(DieDG.find(Attr_DW_FORM_sdata), 0)); - if (Version >= 5) + if (Version >= 5) { EXPECT_EQ(ICSData, toSigned(DieDG.find(Attr_DW_FORM_implicit_const), 0)); + } //---------------------------------------------------------------------- // Test ULEB128 based forms @@ -340,9 +343,10 @@ void TestAllForms() { //---------------------------------------------------------------------- EXPECT_EQ(Dwarf32Values[0], toReference(DieDG.find(Attr_DW_FORM_GNU_ref_alt), 0)); - if (Version >= 4) + if (Version >= 4) { EXPECT_EQ(Dwarf32Values[1], toSectionOffset(DieDG.find(Attr_DW_FORM_sec_offset), 0)); + } //---------------------------------------------------------------------- // Add an address at the end to make sure we can decode this value @@ -849,8 +853,8 @@ template <uint16_t Version, class AddrType> void TestAddresses() { // Get the compile unit DIE is valid. auto DieDG = U->getUnitDIE(false); EXPECT_TRUE(DieDG.isValid()); - - uint64_t LowPC, HighPC; + + uint64_t LowPC, HighPC, SectionIndex; Optional<uint64_t> OptU64; // Verify the that our subprogram with no PC value fails appropriately when // asked for any PC values. @@ -861,14 +865,14 @@ template <uint16_t Version, class AddrType> void TestAddresses() { EXPECT_FALSE((bool)OptU64); OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_high_pc)); EXPECT_FALSE((bool)OptU64); - EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC)); + EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC, SectionIndex)); OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_high_pc)); EXPECT_FALSE((bool)OptU64); OptU64 = toUnsigned(SubprogramDieNoPC.find(DW_AT_high_pc)); EXPECT_FALSE((bool)OptU64); OptU64 = SubprogramDieNoPC.getHighPC(ActualLowPC); EXPECT_FALSE((bool)OptU64); - EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC)); + EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC, SectionIndex)); // Verify the that our subprogram with only a low PC value succeeds when // we ask for the Low PC, but fails appropriately when asked for the high PC @@ -885,7 +889,7 @@ template <uint16_t Version, class AddrType> void TestAddresses() { EXPECT_FALSE((bool)OptU64); OptU64 = SubprogramDieLowPC.getHighPC(ActualLowPC); EXPECT_FALSE((bool)OptU64); - EXPECT_FALSE(SubprogramDieLowPC.getLowAndHighPC(LowPC, HighPC)); + EXPECT_FALSE(SubprogramDieLowPC.getLowAndHighPC(LowPC, HighPC, SectionIndex)); // Verify the that our subprogram with only a low PC value succeeds when // we ask for the Low PC, but fails appropriately when asked for the high PC @@ -919,7 +923,7 @@ template <uint16_t Version, class AddrType> void TestAddresses() { EXPECT_TRUE((bool)OptU64); EXPECT_EQ(OptU64.getValue(), ActualHighPC); - EXPECT_TRUE(SubprogramDieLowHighPC.getLowAndHighPC(LowPC, HighPC)); + EXPECT_TRUE(SubprogramDieLowHighPC.getLowAndHighPC(LowPC, HighPC, SectionIndex)); EXPECT_EQ(LowPC, ActualLowPC); EXPECT_EQ(HighPC, ActualHighPC); } diff --git a/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp b/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp index 9f8940b77f28..9d90e265df33 100644 --- a/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp +++ b/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp @@ -75,12 +75,19 @@ private: MutableArrayRef<uint8_t> Data; }; +TEST(MappedBlockStreamTest, NumBlocks) { + DiscontiguousStream F(BlocksAry, DataAry); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); + EXPECT_EQ(F.block_size(), S->getBlockSize()); + EXPECT_EQ(F.layout().Blocks.size(), S->getNumBlocks()); + +} + // Tests that a read which is entirely contained within a single block works // and does not allocate. TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), - F.layout(), F); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); BinaryStreamRef SR; @@ -95,8 +102,7 @@ TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) { // does not fail due to the length of the output buffer. TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), - F.layout(), F); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA"; @@ -110,7 +116,7 @@ TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) { // not allocate memory. TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); StringRef Str; @@ -129,8 +135,7 @@ TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) { // requested. TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), - F.layout(), F); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); StringRef Str; EXPECT_NO_ERROR(R.readFixedString(Str, 10)); @@ -142,8 +147,7 @@ TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) { // fails and allocates no memory. TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), - F.layout(), F); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); StringRef Str; @@ -156,8 +160,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) { // fails and allocates no memory. TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), - F.layout(), F); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); StringRef Str; @@ -170,8 +173,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) { // boundary fails and allocates no memory. TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), - F.layout(), F); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); StringRef Str; @@ -183,8 +185,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) { // beyond the end of a StreamRef fails. TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), - F.layout(), F); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); StringRef Str; EXPECT_NO_ERROR(R.readFixedString(Str, 1)); @@ -197,8 +198,7 @@ TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) { // previous allocation. TEST(MappedBlockStreamTest, UnalignedOverlappingRead) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), - F.layout(), F); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); StringRef Str1; StringRef Str2; @@ -218,8 +218,7 @@ TEST(MappedBlockStreamTest, UnalignedOverlappingRead) { // still works correctly and allocates again from the shared pool. TEST(MappedBlockStreamTest, UnalignedOverlappingReadFail) { DiscontiguousStream F(BlocksAry, DataAry); - auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(), - F.layout(), F); + auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F); BinaryStreamReader R(*S); StringRef Str1; StringRef Str2; @@ -243,7 +242,7 @@ TEST(MappedBlockStreamTest, WriteBeyondEndOfStream) { DiscontiguousStream F(BlocksAry, Data); auto S = WritableMappedBlockStream::createStream( - F.block_size(), F.block_count(), F.layout(), F); + F.block_size(), F.layout(), F); ArrayRef<uint8_t> Buffer; EXPECT_ERROR(S->writeBytes(0, ArrayRef<uint8_t>(LargeBuffer))); @@ -256,7 +255,7 @@ TEST(MappedBlockStreamTest, TestWriteBytesNoBreakBoundary) { static uint8_t Data[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'}; DiscontiguousStream F(BlocksAry, Data); auto S = WritableMappedBlockStream::createStream( - F.block_size(), F.block_count(), F.layout(), F); + F.block_size(), F.layout(), F); ArrayRef<uint8_t> Buffer; EXPECT_NO_ERROR(S->readBytes(0, 1, Buffer)); @@ -289,7 +288,7 @@ TEST(MappedBlockStreamTest, TestWriteBytesBreakBoundary) { DiscontiguousStream F(BlocksAry, Data); auto S = WritableMappedBlockStream::createStream( - F.block_size(), F.block_count(), F.layout(), F); + F.block_size(), F.layout(), F); ArrayRef<uint8_t> Buffer; EXPECT_NO_ERROR(S->writeBytes(0, TestData)); @@ -308,7 +307,7 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) { DiscontiguousStream F(Blocks, Data); auto S = WritableMappedBlockStream::createStream( - F.block_size(), F.block_count(), F.layout(), F); + F.block_size(), F.layout(), F); enum class MyEnum : uint32_t { Val1 = 2908234, Val2 = 120891234 }; using support::ulittle32_t; @@ -400,7 +399,7 @@ TEST(MappedBlockStreamTest, TestWriteContiguousStreamRef) { DiscontiguousStream F(DestBlocks, DestData); auto DestStream = WritableMappedBlockStream::createStream( - F.block_size(), F.block_count(), F.layout(), F); + F.block_size(), F.layout(), F); // First write "Test Str" into the source stream. MutableBinaryByteStream SourceStream(SrcData, little); @@ -435,9 +434,9 @@ TEST(MappedBlockStreamTest, TestWriteDiscontiguousStreamRef) { DiscontiguousStream SrcF(SrcBlocks, SrcData); auto Dest = WritableMappedBlockStream::createStream( - DestF.block_size(), DestF.block_count(), DestF.layout(), DestF); + DestF.block_size(), DestF.layout(), DestF); auto Src = WritableMappedBlockStream::createStream( - SrcF.block_size(), SrcF.block_count(), SrcF.layout(), SrcF); + SrcF.block_size(), SrcF.layout(), SrcF); // First write "Test Str" into the source stream. BinaryStreamWriter SourceWriter(*Src); |