blob: 58e252dd25b997dbbab889661223a02951784cb9 [file] [log] [blame]
Dean Michael Berris146d57912018-08-31 08:04:56 +00001//===- llvm/unittest/XRay/FDRProducerConsumerTest.cpp -----------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Test for round-trip record writing and reading.
11//
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"
23#include <string>
24#include <tuple>
25
26namespace llvm {
27namespace xray {
28namespace {
29
30using ::testing::Eq;
31using ::testing::IsEmpty;
32using ::testing::Not;
33
34template <class RecordType> std::unique_ptr<Record> MakeRecord();
35
36template <> std::unique_ptr<Record> MakeRecord<BufferExtents>() {
37 return make_unique<BufferExtents>(1);
38}
39
40template <> std::unique_ptr<Record> MakeRecord<NewBufferRecord>() {
41 return make_unique<NewBufferRecord>(1);
42}
43
44template <> std::unique_ptr<Record> MakeRecord<NewCPUIDRecord>() {
45 return make_unique<NewCPUIDRecord>(1);
46}
47
48template <> std::unique_ptr<Record> MakeRecord<TSCWrapRecord>() {
49 return make_unique<TSCWrapRecord>(1);
50}
51
52template <> std::unique_ptr<Record> MakeRecord<WallclockRecord>() {
53 return make_unique<WallclockRecord>(1, 2);
54}
55
56template <> std::unique_ptr<Record> MakeRecord<CustomEventRecord>() {
57 return make_unique<CustomEventRecord>(4, 1, "data");
58}
59
60template <> std::unique_ptr<Record> MakeRecord<CallArgRecord>() {
61 return make_unique<CallArgRecord>(1);
62}
63
64template <> std::unique_ptr<Record> MakeRecord<PIDRecord>() {
65 return make_unique<PIDRecord>(1);
66}
67
68template <> std::unique_ptr<Record> MakeRecord<FunctionRecord>() {
69 return make_unique<FunctionRecord>(RecordTypes::ENTER, 1, 2);
70}
71
72template <class T> class RoundTripTest : public ::testing::Test {
73public:
74 RoundTripTest() : Data(), OS(Data) {
75 H.Version = 3;
76 H.Type = 1;
77 H.ConstantTSC = true;
78 H.NonstopTSC = true;
79 H.CycleFrequency = 3e9;
80
81 Writer = make_unique<FDRTraceWriter>(OS, H);
Roman Lebedeva8c22c02018-08-31 08:59:15 +000082 Rec = MakeRecord<T>();
Dean Michael Berris146d57912018-08-31 08:04:56 +000083 }
84
85protected:
86 std::string Data;
87 raw_string_ostream OS;
88 XRayFileHeader H;
89 std::unique_ptr<FDRTraceWriter> Writer;
Roman Lebedeva8c22c02018-08-31 08:59:15 +000090 std::unique_ptr<Record> Rec;
Dean Michael Berris146d57912018-08-31 08:04:56 +000091};
92
93TYPED_TEST_CASE_P(RoundTripTest);
94
95// This test ensures that the writing and reading implementations are in sync --
96// that given write(read(write(R))) == R.
97TYPED_TEST_P(RoundTripTest, RoundTripsSingleValue) {
Roman Lebedeva8c22c02018-08-31 08:59:15 +000098 auto &R = this->Rec;
Dean Michael Berris146d57912018-08-31 08:04:56 +000099 ASSERT_FALSE(errorToBool(R->apply(*this->Writer)));
100 this->OS.flush();
101
Dean Michael Berris98717972018-08-31 16:08:38 +0000102 DataExtractor DE(this->Data, sys::IsLittleEndianHost, 8);
Dean Michael Berris146d57912018-08-31 08:04:56 +0000103 uint32_t OffsetPtr = 0;
104 auto HeaderOrErr = readBinaryFormatHeader(DE, OffsetPtr);
105 if (!HeaderOrErr)
106 FAIL() << HeaderOrErr.takeError();
107
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();
113 if (!R)
114 FAIL() << R.takeError();
115 if (auto E = C.consume(std::move(R.get())))
116 FAIL() << E;
117 }
118 ASSERT_THAT(Records, Not(IsEmpty()));
119 std::string Data2;
120 raw_string_ostream OS2(Data2);
121 FDRTraceWriter Writer2(OS2, this->H);
122 for (auto &P : Records)
123 ASSERT_FALSE(errorToBool(P->apply(Writer2)));
124 OS2.flush();
125
126 EXPECT_EQ(Data2.substr(sizeof(XRayFileHeader)),
127 this->Data.substr(sizeof(XRayFileHeader)));
128 EXPECT_THAT(Records[0]->type(), Eq(R->type()));
129}
130
131REGISTER_TYPED_TEST_CASE_P(RoundTripTest, RoundTripsSingleValue);
132
133using RecordTypes =
134 ::testing::Types<BufferExtents, NewBufferRecord, NewCPUIDRecord,
135 TSCWrapRecord, WallclockRecord, CustomEventRecord,
136 CallArgRecord, BufferExtents, PIDRecord, FunctionRecord>;
137INSTANTIATE_TYPED_TEST_CASE_P(Records, RoundTripTest, RecordTypes);
138
139} // namespace
140} // namespace xray
141} // namespace llvm