1 //===- llvm/unittest/XRay/FDRRecordPrinterTest.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 #include "llvm/Support/raw_ostream.h"
10 #include "llvm/XRay/FDRRecords.h"
11 #include "llvm/XRay/RecordPrinter.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 #include <string>
15 
16 namespace llvm {
17 namespace xray {
18 namespace {
19 
20 using ::testing::Eq;
21 
22 template <class RecordType> struct Helper {};
23 
24 template <> struct Helper<BufferExtents> {
25   static std::unique_ptr<Record> construct() {
26     return make_unique<BufferExtents>(1);
27   }
28 
29   static const char *expected() { return "<Buffer: size = 1 bytes>"; }
30 };
31 
32 template <> struct Helper<WallclockRecord> {
33   static std::unique_ptr<Record> construct() {
34     return make_unique<WallclockRecord>(1, 2);
35   }
36 
37   static const char *expected() { return "<Wall Time: seconds = 1.000002>"; }
38 };
39 
40 template <> struct Helper<NewCPUIDRecord> {
41   static std::unique_ptr<Record> construct() {
42     return make_unique<NewCPUIDRecord>(1, 2);
43   }
44 
45   static const char *expected() { return "<CPU: id = 1, tsc = 2>"; }
46 };
47 
48 template <> struct Helper<TSCWrapRecord> {
49   static std::unique_ptr<Record> construct() {
50     return make_unique<TSCWrapRecord>(1);
51   }
52 
53   static const char *expected() { return "<TSC Wrap: base = 1>"; }
54 };
55 
56 template <> struct Helper<CustomEventRecord> {
57   static std::unique_ptr<Record> construct() {
58     return make_unique<CustomEventRecord>(4, 1, 2, "data");
59   }
60 
61   static const char *expected() {
62     return "<Custom Event: tsc = 1, cpu = 2, size = 4, data = 'data'>";
63   }
64 };
65 
66 template <> struct Helper<CallArgRecord> {
67   static std::unique_ptr<Record> construct() {
68     return make_unique<CallArgRecord>(1);
69   }
70 
71   static const char *expected() {
72     return "<Call Argument: data = 1 (hex = 0x1)>";
73   }
74 };
75 
76 template <> struct Helper<PIDRecord> {
77   static std::unique_ptr<Record> construct() {
78     return make_unique<PIDRecord>(1);
79   }
80 
81   static const char *expected() { return "<PID: 1>"; }
82 };
83 
84 template <> struct Helper<NewBufferRecord> {
85   static std::unique_ptr<Record> construct() {
86     return make_unique<NewBufferRecord>(1);
87   }
88 
89   static const char *expected() { return "<Thread ID: 1>"; }
90 };
91 
92 template <> struct Helper<EndBufferRecord> {
93   static std::unique_ptr<Record> construct() {
94     return make_unique<EndBufferRecord>();
95   }
96 
97   static const char *expected() { return "<End of Buffer>"; }
98 };
99 
100 template <class T> class PrinterTest : public ::testing::Test {
101 protected:
102   std::string Data;
103   raw_string_ostream OS;
104   RecordPrinter P;
105   std::unique_ptr<Record> R;
106 
107 public:
108   PrinterTest() : Data(), OS(Data), P(OS), R(Helper<T>::construct()) {}
109 };
110 
111 TYPED_TEST_CASE_P(PrinterTest);
112 
113 TYPED_TEST_P(PrinterTest, PrintsRecord) {
114   ASSERT_NE(nullptr, this->R);
115   ASSERT_FALSE(errorToBool(this->R->apply(this->P)));
116   this->OS.flush();
117   EXPECT_THAT(this->Data, Eq(Helper<TypeParam>::expected()));
118 }
119 
120 REGISTER_TYPED_TEST_CASE_P(PrinterTest, PrintsRecord);
121 using FDRRecordTypes =
122     ::testing::Types<BufferExtents, NewBufferRecord, EndBufferRecord,
123                      NewCPUIDRecord, TSCWrapRecord, WallclockRecord,
124                      CustomEventRecord, CallArgRecord, BufferExtents,
125                      PIDRecord>;
126 INSTANTIATE_TYPED_TEST_CASE_P(Records, PrinterTest, FDRRecordTypes);
127 
128 TEST(FDRRecordPrinterTest, WriteFunctionRecordEnter) {
129   std::string Data;
130   raw_string_ostream OS(Data);
131   RecordPrinter P(OS);
132   FunctionRecord R(RecordTypes::ENTER, 1, 2);
133   ASSERT_FALSE(errorToBool(R.apply(P)));
134   OS.flush();
135   EXPECT_THAT(Data, Eq("<Function Enter: #1 delta = +2>"));
136 }
137 
138 TEST(FDRRecordPrinterTest, WriteFunctionRecordExit) {
139   std::string Data;
140   raw_string_ostream OS(Data);
141   RecordPrinter P(OS);
142   FunctionRecord R(RecordTypes::EXIT, 1, 2);
143   ASSERT_FALSE(errorToBool(R.apply(P)));
144   OS.flush();
145   EXPECT_THAT(Data, Eq("<Function Exit: #1 delta = +2>"));
146 }
147 
148 TEST(FDRRecordPrinterTest, WriteFunctionRecordTailExit) {
149   std::string Data;
150   raw_string_ostream OS(Data);
151   RecordPrinter P(OS);
152   FunctionRecord R(RecordTypes::TAIL_EXIT, 1, 2);
153   ASSERT_FALSE(errorToBool(R.apply(P)));
154   OS.flush();
155   EXPECT_THAT(Data, Eq("<Function Tail Exit: #1 delta = +2>"));
156 }
157 
158 TEST(FDRRecordPrinterTest, WriteFunctionRecordEnterArg) {
159   std::string Data;
160   raw_string_ostream OS(Data);
161   RecordPrinter P(OS);
162   FunctionRecord R(RecordTypes::ENTER_ARG, 1, 2);
163   ASSERT_FALSE(errorToBool(R.apply(P)));
164   OS.flush();
165   EXPECT_THAT(Data, Eq("<Function Enter With Arg: #1 delta = +2>"));
166 }
167 
168 } // namespace
169 } // namespace xray
170 } // namespace llvm
171