brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 24acb89 Raw
218 lines · cpp
1//===- llvm/unittest/XRay/FDRProducerConsumerTest.cpp -----------*- C++ -*-===//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// Test for round-trip record writing and reading.10//11//===----------------------------------------------------------------------===//12#include "llvm/Support/DataExtractor.h"13#include "llvm/Support/raw_ostream.h"14#include "llvm/XRay/FDRLogBuilder.h"15#include "llvm/XRay/FDRRecordConsumer.h"16#include "llvm/XRay/FDRRecordProducer.h"17#include "llvm/XRay/FDRRecords.h"18#include "llvm/XRay/FDRTraceWriter.h"19#include "llvm/XRay/FileHeaderReader.h"20#include "gmock/gmock.h"21#include "gtest/gtest.h"22#include <string>23 24namespace llvm {25namespace xray {26namespace {27 28using ::testing::Eq;29using ::testing::IsEmpty;30using ::testing::Not;31using ::testing::SizeIs;32 33template <class RecordType> std::unique_ptr<Record> MakeRecord();34 35template <> std::unique_ptr<Record> MakeRecord<NewBufferRecord>() {36  return std::make_unique<NewBufferRecord>(1);37}38 39template <> std::unique_ptr<Record> MakeRecord<NewCPUIDRecord>() {40  return std::make_unique<NewCPUIDRecord>(1, 2);41}42 43template <> std::unique_ptr<Record> MakeRecord<TSCWrapRecord>() {44  return std::make_unique<TSCWrapRecord>(1);45}46 47template <> std::unique_ptr<Record> MakeRecord<WallclockRecord>() {48  return std::make_unique<WallclockRecord>(1, 2);49}50 51template <> std::unique_ptr<Record> MakeRecord<CustomEventRecord>() {52  return std::make_unique<CustomEventRecord>(4, 1, 2, "data");53}54 55template <> std::unique_ptr<Record> MakeRecord<CallArgRecord>() {56  return std::make_unique<CallArgRecord>(1);57}58 59template <> std::unique_ptr<Record> MakeRecord<PIDRecord>() {60  return std::make_unique<PIDRecord>(1);61}62 63template <> std::unique_ptr<Record> MakeRecord<FunctionRecord>() {64  return std::make_unique<FunctionRecord>(RecordTypes::ENTER, 1, 2);65}66 67template <> std::unique_ptr<Record> MakeRecord<CustomEventRecordV5>() {68  return std::make_unique<CustomEventRecordV5>(4, 1, "data");69}70 71template <> std::unique_ptr<Record> MakeRecord<TypedEventRecord>() {72  return std::make_unique<TypedEventRecord>(4, 1, 2, "data");73}74 75template <class T> class RoundTripTest : public ::testing::Test {76public:77  RoundTripTest() : Data(), OS(Data) {78    H.Version = 4;79    H.Type = 1;80    H.ConstantTSC = true;81    H.NonstopTSC = true;82    H.CycleFrequency = 3e9;83 84    Writer = std::make_unique<FDRTraceWriter>(OS, H);85    Rec = MakeRecord<T>();86  }87 88protected:89  std::string Data;90  raw_string_ostream OS;91  XRayFileHeader H;92  std::unique_ptr<FDRTraceWriter> Writer;93  std::unique_ptr<Record> Rec;94};95 96TYPED_TEST_SUITE_P(RoundTripTest);97 98template <class T> class RoundTripTestV5 : public ::testing::Test {99public:100  RoundTripTestV5() : Data(), OS(Data) {101    H.Version = 5;102    H.Type = 1;103    H.ConstantTSC = true;104    H.NonstopTSC = true;105    H.CycleFrequency = 3e9;106 107    Writer = std::make_unique<FDRTraceWriter>(OS, H);108    Rec = MakeRecord<T>();109  }110 111protected:112  std::string Data;113  raw_string_ostream OS;114  XRayFileHeader H;115  std::unique_ptr<FDRTraceWriter> Writer;116  std::unique_ptr<Record> Rec;117};118 119TYPED_TEST_SUITE_P(RoundTripTestV5);120 121// This test ensures that the writing and reading implementations are in sync --122// that given write(read(write(R))) == R.123TYPED_TEST_P(RoundTripTest, RoundTripsSingleValue) {124  // Always write a buffer extents record which will cover the correct size of125  // the record, for version 3 and up.126  BufferExtents BE(200);127  ASSERT_FALSE(errorToBool(BE.apply(*this->Writer)));128  auto &R = this->Rec;129  ASSERT_FALSE(errorToBool(R->apply(*this->Writer)));130 131  DataExtractor DE(this->Data, sys::IsLittleEndianHost, 8);132  uint64_t OffsetPtr = 0;133  auto HeaderOrErr = readBinaryFormatHeader(DE, OffsetPtr);134  if (!HeaderOrErr)135    FAIL() << HeaderOrErr.takeError();136 137  FileBasedRecordProducer P(HeaderOrErr.get(), DE, OffsetPtr);138  std::vector<std::unique_ptr<Record>> Records;139  LogBuilderConsumer C(Records);140  while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {141    auto R = P.produce();142    if (!R)143      FAIL() << R.takeError();144    if (auto E = C.consume(std::move(R.get())))145      FAIL() << E;146  }147  ASSERT_THAT(Records, Not(IsEmpty()));148  std::string Data2;149  raw_string_ostream OS2(Data2);150  FDRTraceWriter Writer2(OS2, this->H);151  for (auto &P : Records)152    ASSERT_FALSE(errorToBool(P->apply(Writer2)));153 154  EXPECT_EQ(Data2.substr(sizeof(XRayFileHeader)),155            this->Data.substr(sizeof(XRayFileHeader)));156  ASSERT_THAT(Records, SizeIs(2));157  EXPECT_THAT(Records[1]->getRecordType(), Eq(R->getRecordType()));158}159 160REGISTER_TYPED_TEST_SUITE_P(RoundTripTest, RoundTripsSingleValue);161 162// We duplicate the above case for the V5 version using different types and163// encodings.164TYPED_TEST_P(RoundTripTestV5, RoundTripsSingleValue) {165  BufferExtents BE(200);166  ASSERT_FALSE(errorToBool(BE.apply(*this->Writer)));167  auto &R = this->Rec;168  ASSERT_FALSE(errorToBool(R->apply(*this->Writer)));169 170  DataExtractor DE(this->Data, sys::IsLittleEndianHost, 8);171  uint64_t OffsetPtr = 0;172  auto HeaderOrErr = readBinaryFormatHeader(DE, OffsetPtr);173  if (!HeaderOrErr)174    FAIL() << HeaderOrErr.takeError();175 176  FileBasedRecordProducer P(HeaderOrErr.get(), DE, OffsetPtr);177  std::vector<std::unique_ptr<Record>> Records;178  LogBuilderConsumer C(Records);179  while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {180    auto R = P.produce();181    if (!R)182      FAIL() << R.takeError();183    if (auto E = C.consume(std::move(R.get())))184      FAIL() << E;185  }186  ASSERT_THAT(Records, Not(IsEmpty()));187  std::string Data2;188  raw_string_ostream OS2(Data2);189  FDRTraceWriter Writer2(OS2, this->H);190  for (auto &P : Records)191    ASSERT_FALSE(errorToBool(P->apply(Writer2)));192 193  EXPECT_EQ(Data2.substr(sizeof(XRayFileHeader)),194            this->Data.substr(sizeof(XRayFileHeader)));195  ASSERT_THAT(Records, SizeIs(2));196  EXPECT_THAT(Records[1]->getRecordType(), Eq(R->getRecordType()));197}198 199REGISTER_TYPED_TEST_SUITE_P(RoundTripTestV5, RoundTripsSingleValue);200 201// These are the record types we support for v4 and below.202using RecordTypes =203    ::testing::Types<NewBufferRecord, NewCPUIDRecord, TSCWrapRecord,204                     WallclockRecord, CustomEventRecord, CallArgRecord,205                     PIDRecord, FunctionRecord>;206INSTANTIATE_TYPED_TEST_SUITE_P(Records, RoundTripTest, RecordTypes, );207 208// For V5, we have two new types we're supporting.209using RecordTypesV5 =210    ::testing::Types<NewBufferRecord, NewCPUIDRecord, TSCWrapRecord,211                     WallclockRecord, CustomEventRecordV5, TypedEventRecord,212                     CallArgRecord, PIDRecord, FunctionRecord>;213INSTANTIATE_TYPED_TEST_SUITE_P(Records, RoundTripTestV5, RecordTypesV5, );214 215} // namespace216} // namespace xray217} // namespace llvm218