brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · cd6db5f Raw
296 lines · cpp
1//===-- UdtRecordCompleterTests.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 "Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h"10#include "llvm/ADT/StringExtras.h"11#include "gmock/gmock.h"12#include "gtest/gtest.h"13 14using namespace lldb_private::npdb;15using namespace llvm;16 17namespace {18using Member = UdtRecordCompleter::Member;19using MemberUP = std::unique_ptr<Member>;20using Record = UdtRecordCompleter::Record;21 22class WrappedMember {23public:24  WrappedMember(const Member &obj) : m_obj(obj) {}25 26private:27  const Member &m_obj;28 29  friend bool operator==(const WrappedMember &lhs, const WrappedMember &rhs) {30    return lhs.m_obj.kind == rhs.m_obj.kind &&31           lhs.m_obj.name == rhs.m_obj.name &&32           lhs.m_obj.bit_offset == rhs.m_obj.bit_offset &&33           lhs.m_obj.bit_size == rhs.m_obj.bit_size &&34           lhs.m_obj.base_offset == rhs.m_obj.base_offset &&35           std::equal(lhs.m_obj.fields.begin(), lhs.m_obj.fields.end(),36                      rhs.m_obj.fields.begin(), rhs.m_obj.fields.end(),37                      [](const MemberUP &lhs, const MemberUP &rhs) {38                        return WrappedMember(*lhs) == WrappedMember(*rhs);39                      });40  }41 42  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,43                                       const WrappedMember &w) {44    os << llvm::formatv("Member{.kind={0}, .name=\"{1}\", .bit_offset={2}, "45                        ".bit_size={3}, .base_offset={4}, .fields=[",46                        w.m_obj.kind, w.m_obj.name, w.m_obj.bit_offset,47                        w.m_obj.bit_size, w.m_obj.base_offset);48    llvm::ListSeparator sep;49    for (auto &f : w.m_obj.fields)50      os << sep << WrappedMember(*f);51    return os << "]}";52  }53};54 55class WrappedRecord {56public:57  WrappedRecord(const Record &obj) : m_obj(obj) {}58 59private:60  const Record &m_obj;61 62  friend bool operator==(const WrappedRecord &lhs, const WrappedRecord &rhs) {63    return lhs.m_obj.start_offset == rhs.m_obj.start_offset &&64           std::equal(65               lhs.m_obj.record.fields.begin(), lhs.m_obj.record.fields.end(),66               rhs.m_obj.record.fields.begin(), rhs.m_obj.record.fields.end(),67               [](const MemberUP &lhs, const MemberUP &rhs) {68                 return WrappedMember(*lhs) == WrappedMember(*rhs);69               });70  }71 72  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,73                                       const WrappedRecord &w) {74    os << llvm::formatv("Record{.start_offset={0}, .record.fields=[",75                        w.m_obj.start_offset);76    llvm::ListSeparator sep;77    for (const MemberUP &f : w.m_obj.record.fields)78      os << sep << WrappedMember(*f);79    return os << "]}";80  }81};82 83class UdtRecordCompleterRecordTests : public testing::Test {84protected:85  Record record;86 87public:88  void SetKind(Member::Kind kind) { record.record.kind = kind; }89  void CollectMember(StringRef name, uint64_t byte_offset, uint64_t byte_size) {90    record.CollectMember(name, byte_offset * 8, byte_size * 8,91                         clang::QualType(), lldb::eAccessPublic, 0);92  }93  void ConstructRecord() { record.ConstructRecord(); }94};95Member *AddField(Member *member, StringRef name, uint64_t byte_offset,96                 uint64_t byte_size, Member::Kind kind,97                 uint64_t base_offset = 0) {98  auto field =99      std::make_unique<Member>(name, byte_offset * 8, byte_size * 8,100                               clang::QualType(), lldb::eAccessPublic, 0);101  field->kind = kind;102  field->base_offset = base_offset * 8;103  member->fields.push_back(std::move(field));104  return member->fields.back().get();105}106} // namespace107 108TEST_F(UdtRecordCompleterRecordTests, TestAnonymousUnionInStruct) {109  SetKind(Member::Kind::Struct);110  CollectMember("m1", 0, 4);111  CollectMember("m2", 0, 4);112  CollectMember("m3", 0, 1);113  CollectMember("m4", 0, 8);114  CollectMember("m5", 8, 8);115  CollectMember("m6", 16, 4);116  CollectMember("m7", 16, 8);117  ConstructRecord();118 119  // struct {120  //   union {121  //       m1;122  //       m2;123  //       m3;124  //       m4;125  //   };126  //   m5;127  //   union {128  //       m6;129  //       m7;130  //   };131  // };132  Record record;133  record.start_offset = 0;134  Member *u = AddField(&record.record, "", 0, 0, Member::Union);135  AddField(u, "m1", 0, 4, Member::Field);136  AddField(u, "m2", 0, 4, Member::Field);137  AddField(u, "m3", 0, 1, Member::Field);138  AddField(u, "m4", 0, 8, Member::Field);139  AddField(&record.record, "m5", 8, 8, Member::Field);140  Member *u2 = AddField(&record.record, "", 16, 0, Member::Union);141  AddField(u2, "m6", 16, 4, Member::Field);142  AddField(u2, "m7", 16, 8, Member::Field);143  EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));144}145 146TEST_F(UdtRecordCompleterRecordTests, TestAnonymousUnionInUnion) {147  SetKind(Member::Kind::Union);148  CollectMember("m1", 0, 4);149  CollectMember("m2", 0, 4);150  CollectMember("m3", 0, 1);151  CollectMember("m4", 0, 8);152  ConstructRecord();153 154  // union {155  //   m1;156  //   m2;157  //   m3;158  //   m4;159  // };160  Record record;161  record.start_offset = 0;162  AddField(&record.record, "m1", 0, 4, Member::Field);163  AddField(&record.record, "m2", 0, 4, Member::Field);164  AddField(&record.record, "m3", 0, 1, Member::Field);165  AddField(&record.record, "m4", 0, 8, Member::Field);166  EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));167}168 169TEST_F(UdtRecordCompleterRecordTests, TestAnonymousStructInUnion) {170  SetKind(Member::Kind::Union);171  CollectMember("m1", 0, 4);172  CollectMember("m2", 4, 4);173  CollectMember("m3", 8, 1);174  ConstructRecord();175 176  // union {177  //   struct {178  //     m1;179  //     m2;180  //     m3;181  //   };182  // };183  Record record;184  record.start_offset = 0;185  Member *s = AddField(&record.record, "", 0, 0, Member::Kind::Struct);186  AddField(s, "m1", 0, 4, Member::Field);187  AddField(s, "m2", 4, 4, Member::Field);188  AddField(s, "m3", 8, 1, Member::Field);189  EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));190}191 192TEST_F(UdtRecordCompleterRecordTests, TestNestedUnionStructInStruct) {193  SetKind(Member::Kind::Struct);194  CollectMember("m1", 0, 4);195  CollectMember("m2", 0, 2);196  CollectMember("m3", 0, 2);197  CollectMember("m4", 2, 4);198  CollectMember("m5", 3, 2);199  ConstructRecord();200 201  // struct {202  //   union {203  //       m1;204  //       struct {205  //           m2;206  //           m5;207  //       };208  //       struct {209  //           m3;210  //           m4;211  //       };212  //   };213  // };214  Record record;215  record.start_offset = 0;216  Member *u = AddField(&record.record, "", 0, 0, Member::Union);217  AddField(u, "m1", 0, 4, Member::Field);218  Member *s1 = AddField(u, "", 0, 0, Member::Struct);219  Member *s2 = AddField(u, "", 0, 0, Member::Struct);220  AddField(s1, "m2", 0, 2, Member::Field);221  AddField(s1, "m5", 3, 2, Member::Field);222  AddField(s2, "m3", 0, 2, Member::Field);223  AddField(s2, "m4", 2, 4, Member::Field);224  EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));225}226 227TEST_F(UdtRecordCompleterRecordTests, TestNestedUnionStructInUnion) {228  SetKind(Member::Kind::Union);229  CollectMember("m1", 0, 4);230  CollectMember("m2", 0, 2);231  CollectMember("m3", 0, 2);232  CollectMember("m4", 2, 4);233  CollectMember("m5", 3, 2);234  ConstructRecord();235 236  // union {237  //   m1;238  //   struct {239  //       m2;240  //       m5;241  //   };242  //   struct {243  //       m3;244  //       m4;245  //   };246  // };247  Record record;248  record.start_offset = 0;249  AddField(&record.record, "m1", 0, 4, Member::Field);250  Member *s1 = AddField(&record.record, "", 0, 0, Member::Struct);251  Member *s2 = AddField(&record.record, "", 0, 0, Member::Struct);252  AddField(s1, "m2", 0, 2, Member::Field);253  AddField(s1, "m5", 3, 2, Member::Field);254  AddField(s2, "m3", 0, 2, Member::Field);255  AddField(s2, "m4", 2, 4, Member::Field);256  EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));257}258 259TEST_F(UdtRecordCompleterRecordTests, TestNestedStructInUnionInStructInUnion) {260  SetKind(Member::Kind::Union);261  CollectMember("m1", 0, 4);262  CollectMember("m2", 0, 2);263  CollectMember("m3", 0, 2);264  CollectMember("m4", 2, 4);265  CollectMember("m5", 6, 2);266  CollectMember("m6", 6, 2);267  CollectMember("m7", 8, 2);268  ConstructRecord();269 270  // union {271  //   m1;272  //   m2;273  //   struct {274  //       m3;275  //       m4;276  //       union {277  //           m5;278  //           m6;279  //       };280  //       m7;281  //   };282  // };283  Record record;284  record.start_offset = 0;285  AddField(&record.record, "m1", 0, 4, Member::Field);286  AddField(&record.record, "m2", 0, 2, Member::Field);287  Member *s = AddField(&record.record, "", 0, 0, Member::Struct);288  AddField(s, "m3", 0, 2, Member::Field);289  AddField(s, "m4", 2, 4, Member::Field);290  Member *u = AddField(s, "", 6, 0, Member::Union);291  AddField(u, "m5", 6, 2, Member::Field);292  AddField(u, "m6", 6, 2, Member::Field);293  AddField(s, "m7", 8, 2, Member::Field);294  EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));295}296