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