1 //===- llvm/unittest/XRay/FDRProducerConsumerTest.cpp -----------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Test for round-trip record writing and reading.
12 //===----------------------------------------------------------------------===//
13 #include "llvm/Support/DataExtractor.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/XRay/FDRLogBuilder.h"
16 #include "llvm/XRay/FDRRecordConsumer.h"
17 #include "llvm/XRay/FDRRecordProducer.h"
18 #include "llvm/XRay/FDRRecords.h"
19 #include "llvm/XRay/FDRTraceWriter.h"
20 #include "llvm/XRay/FileHeaderReader.h"
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
31 using ::testing::IsEmpty
;
34 template <class RecordType
> std::unique_ptr
<Record
> MakeRecord();
36 template <> std::unique_ptr
<Record
> MakeRecord
<BufferExtents
>() {
37 return make_unique
<BufferExtents
>(1);
40 template <> std::unique_ptr
<Record
> MakeRecord
<NewBufferRecord
>() {
41 return make_unique
<NewBufferRecord
>(1);
44 template <> std::unique_ptr
<Record
> MakeRecord
<NewCPUIDRecord
>() {
45 return make_unique
<NewCPUIDRecord
>(1, 2);
48 template <> std::unique_ptr
<Record
> MakeRecord
<TSCWrapRecord
>() {
49 return make_unique
<TSCWrapRecord
>(1);
52 template <> std::unique_ptr
<Record
> MakeRecord
<WallclockRecord
>() {
53 return make_unique
<WallclockRecord
>(1, 2);
56 template <> std::unique_ptr
<Record
> MakeRecord
<CustomEventRecord
>() {
57 return make_unique
<CustomEventRecord
>(4, 1, "data");
60 template <> std::unique_ptr
<Record
> MakeRecord
<CallArgRecord
>() {
61 return make_unique
<CallArgRecord
>(1);
64 template <> std::unique_ptr
<Record
> MakeRecord
<PIDRecord
>() {
65 return make_unique
<PIDRecord
>(1);
68 template <> std::unique_ptr
<Record
> MakeRecord
<FunctionRecord
>() {
69 return make_unique
<FunctionRecord
>(RecordTypes::ENTER
, 1, 2);
72 template <class T
> class RoundTripTest
: public ::testing::Test
{
74 RoundTripTest() : Data(), OS(Data
) {
79 H
.CycleFrequency
= 3e9
;
81 Writer
= make_unique
<FDRTraceWriter
>(OS
, H
);
82 Rec
= MakeRecord
<T
>();
87 raw_string_ostream OS
;
89 std::unique_ptr
<FDRTraceWriter
> Writer
;
90 std::unique_ptr
<Record
> Rec
;
93 TYPED_TEST_CASE_P(RoundTripTest
);
95 // This test ensures that the writing and reading implementations are in sync --
96 // that given write(read(write(R))) == R.
97 TYPED_TEST_P(RoundTripTest
, RoundTripsSingleValue
) {
99 ASSERT_FALSE(errorToBool(R
->apply(*this->Writer
)));
102 DataExtractor
DE(this->Data
, sys::IsLittleEndianHost
, 8);
103 uint32_t OffsetPtr
= 0;
104 auto HeaderOrErr
= readBinaryFormatHeader(DE
, OffsetPtr
);
106 FAIL() << HeaderOrErr
.takeError();
108 FileBasedRecordProducer
P(HeaderOrErr
.get(), DE
, OffsetPtr
);
109 std::vector
<std::unique_ptr
<Record
>> Records
;
110 LogBuilderConsumer
C(Records
);
111 while (DE
.isValidOffsetForDataOfSize(OffsetPtr
, 1)) {
112 auto R
= P
.produce();
114 FAIL() << R
.takeError();
115 if (auto E
= C
.consume(std::move(R
.get())))
118 ASSERT_THAT(Records
, Not(IsEmpty()));
120 raw_string_ostream
OS2(Data2
);
121 FDRTraceWriter
Writer2(OS2
, this->H
);
122 for (auto &P
: Records
)
123 ASSERT_FALSE(errorToBool(P
->apply(Writer2
)));
126 EXPECT_EQ(Data2
.substr(sizeof(XRayFileHeader
)),
127 this->Data
.substr(sizeof(XRayFileHeader
)));
128 EXPECT_THAT(Records
[0]->type(), Eq(R
->type()));
131 REGISTER_TYPED_TEST_CASE_P(RoundTripTest
, RoundTripsSingleValue
);
134 ::testing::Types
<BufferExtents
, NewBufferRecord
, NewCPUIDRecord
,
135 TSCWrapRecord
, WallclockRecord
, CustomEventRecord
,
136 CallArgRecord
, BufferExtents
, PIDRecord
, FunctionRecord
>;
137 INSTANTIATE_TYPED_TEST_CASE_P(Records
, RoundTripTest
, RecordTypes
);