[llvm-readobj] - Stop treating ".stack_sizes.*" sections as stack sizes sections.
[llvm-complete.git] / unittests / XRay / FDRProducerConsumerTest.cpp
blob6eff4dfcc505f874a518a2ceba96179d4910fa60
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Test for round-trip record writing and reading.
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 #include <tuple>
25 namespace llvm {
26 namespace xray {
27 namespace {
29 using ::testing::Eq;
30 using ::testing::IsEmpty;
31 using ::testing::Not;
32 using ::testing::SizeIs;
34 template <class RecordType> std::unique_ptr<Record> MakeRecord();
36 template <> std::unique_ptr<Record> MakeRecord<NewBufferRecord>() {
37 return std::make_unique<NewBufferRecord>(1);
40 template <> std::unique_ptr<Record> MakeRecord<NewCPUIDRecord>() {
41 return std::make_unique<NewCPUIDRecord>(1, 2);
44 template <> std::unique_ptr<Record> MakeRecord<TSCWrapRecord>() {
45 return std::make_unique<TSCWrapRecord>(1);
48 template <> std::unique_ptr<Record> MakeRecord<WallclockRecord>() {
49 return std::make_unique<WallclockRecord>(1, 2);
52 template <> std::unique_ptr<Record> MakeRecord<CustomEventRecord>() {
53 return std::make_unique<CustomEventRecord>(4, 1, 2, "data");
56 template <> std::unique_ptr<Record> MakeRecord<CallArgRecord>() {
57 return std::make_unique<CallArgRecord>(1);
60 template <> std::unique_ptr<Record> MakeRecord<PIDRecord>() {
61 return std::make_unique<PIDRecord>(1);
64 template <> std::unique_ptr<Record> MakeRecord<FunctionRecord>() {
65 return std::make_unique<FunctionRecord>(RecordTypes::ENTER, 1, 2);
68 template <> std::unique_ptr<Record> MakeRecord<CustomEventRecordV5>() {
69 return std::make_unique<CustomEventRecordV5>(4, 1, "data");
72 template <> std::unique_ptr<Record> MakeRecord<TypedEventRecord>() {
73 return std::make_unique<TypedEventRecord>(4, 1, 2, "data");
76 template <class T> class RoundTripTest : public ::testing::Test {
77 public:
78 RoundTripTest() : Data(), OS(Data) {
79 H.Version = 4;
80 H.Type = 1;
81 H.ConstantTSC = true;
82 H.NonstopTSC = true;
83 H.CycleFrequency = 3e9;
85 Writer = std::make_unique<FDRTraceWriter>(OS, H);
86 Rec = MakeRecord<T>();
89 protected:
90 std::string Data;
91 raw_string_ostream OS;
92 XRayFileHeader H;
93 std::unique_ptr<FDRTraceWriter> Writer;
94 std::unique_ptr<Record> Rec;
97 TYPED_TEST_CASE_P(RoundTripTest);
99 template <class T> class RoundTripTestV5 : public ::testing::Test {
100 public:
101 RoundTripTestV5() : Data(), OS(Data) {
102 H.Version = 5;
103 H.Type = 1;
104 H.ConstantTSC = true;
105 H.NonstopTSC = true;
106 H.CycleFrequency = 3e9;
108 Writer = std::make_unique<FDRTraceWriter>(OS, H);
109 Rec = MakeRecord<T>();
112 protected:
113 std::string Data;
114 raw_string_ostream OS;
115 XRayFileHeader H;
116 std::unique_ptr<FDRTraceWriter> Writer;
117 std::unique_ptr<Record> Rec;
120 TYPED_TEST_CASE_P(RoundTripTestV5);
122 // This test ensures that the writing and reading implementations are in sync --
123 // that given write(read(write(R))) == R.
124 TYPED_TEST_P(RoundTripTest, RoundTripsSingleValue) {
125 // Always write a buffer extents record which will cover the correct size of
126 // the record, for version 3 and up.
127 BufferExtents BE(200);
128 ASSERT_FALSE(errorToBool(BE.apply(*this->Writer)));
129 auto &R = this->Rec;
130 ASSERT_FALSE(errorToBool(R->apply(*this->Writer)));
131 this->OS.flush();
133 DataExtractor DE(this->Data, sys::IsLittleEndianHost, 8);
134 uint64_t OffsetPtr = 0;
135 auto HeaderOrErr = readBinaryFormatHeader(DE, OffsetPtr);
136 if (!HeaderOrErr)
137 FAIL() << HeaderOrErr.takeError();
139 FileBasedRecordProducer P(HeaderOrErr.get(), DE, OffsetPtr);
140 std::vector<std::unique_ptr<Record>> Records;
141 LogBuilderConsumer C(Records);
142 while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {
143 auto R = P.produce();
144 if (!R)
145 FAIL() << R.takeError();
146 if (auto E = C.consume(std::move(R.get())))
147 FAIL() << E;
149 ASSERT_THAT(Records, Not(IsEmpty()));
150 std::string Data2;
151 raw_string_ostream OS2(Data2);
152 FDRTraceWriter Writer2(OS2, this->H);
153 for (auto &P : Records)
154 ASSERT_FALSE(errorToBool(P->apply(Writer2)));
155 OS2.flush();
157 EXPECT_EQ(Data2.substr(sizeof(XRayFileHeader)),
158 this->Data.substr(sizeof(XRayFileHeader)));
159 ASSERT_THAT(Records, SizeIs(2));
160 EXPECT_THAT(Records[1]->getRecordType(), Eq(R->getRecordType()));
163 REGISTER_TYPED_TEST_CASE_P(RoundTripTest, RoundTripsSingleValue);
165 // We duplicate the above case for the V5 version using different types and
166 // encodings.
167 TYPED_TEST_P(RoundTripTestV5, RoundTripsSingleValue) {
168 BufferExtents BE(200);
169 ASSERT_FALSE(errorToBool(BE.apply(*this->Writer)));
170 auto &R = this->Rec;
171 ASSERT_FALSE(errorToBool(R->apply(*this->Writer)));
172 this->OS.flush();
174 DataExtractor DE(this->Data, sys::IsLittleEndianHost, 8);
175 uint64_t OffsetPtr = 0;
176 auto HeaderOrErr = readBinaryFormatHeader(DE, OffsetPtr);
177 if (!HeaderOrErr)
178 FAIL() << HeaderOrErr.takeError();
180 FileBasedRecordProducer P(HeaderOrErr.get(), DE, OffsetPtr);
181 std::vector<std::unique_ptr<Record>> Records;
182 LogBuilderConsumer C(Records);
183 while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {
184 auto R = P.produce();
185 if (!R)
186 FAIL() << R.takeError();
187 if (auto E = C.consume(std::move(R.get())))
188 FAIL() << E;
190 ASSERT_THAT(Records, Not(IsEmpty()));
191 std::string Data2;
192 raw_string_ostream OS2(Data2);
193 FDRTraceWriter Writer2(OS2, this->H);
194 for (auto &P : Records)
195 ASSERT_FALSE(errorToBool(P->apply(Writer2)));
196 OS2.flush();
198 EXPECT_EQ(Data2.substr(sizeof(XRayFileHeader)),
199 this->Data.substr(sizeof(XRayFileHeader)));
200 ASSERT_THAT(Records, SizeIs(2));
201 EXPECT_THAT(Records[1]->getRecordType(), Eq(R->getRecordType()));
204 REGISTER_TYPED_TEST_CASE_P(RoundTripTestV5, RoundTripsSingleValue);
206 // These are the record types we support for v4 and below.
207 using RecordTypes =
208 ::testing::Types<NewBufferRecord, NewCPUIDRecord, TSCWrapRecord,
209 WallclockRecord, CustomEventRecord, CallArgRecord,
210 PIDRecord, FunctionRecord>;
211 INSTANTIATE_TYPED_TEST_CASE_P(Records, RoundTripTest, RecordTypes);
213 // For V5, we have two new types we're supporting.
214 using RecordTypesV5 =
215 ::testing::Types<NewBufferRecord, NewCPUIDRecord, TSCWrapRecord,
216 WallclockRecord, CustomEventRecordV5, TypedEventRecord,
217 CallArgRecord, PIDRecord, FunctionRecord>;
218 INSTANTIATE_TYPED_TEST_CASE_P(Records, RoundTripTestV5, RecordTypesV5);
220 } // namespace
221 } // namespace xray
222 } // namespace llvm