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>(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>(1, 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>(1, 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>(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>(4, 1, 2, "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>(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>(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>(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 EXPECT_THAT(this->Data, Eq(Helper<TypeParam>::expected())); 116 } 117 118 REGISTER_TYPED_TEST_SUITE_P(PrinterTest, PrintsRecord); 119 using FDRRecordTypes = 120 ::testing::Types<BufferExtents, NewBufferRecord, EndBufferRecord, 121 NewCPUIDRecord, TSCWrapRecord, WallclockRecord, 122 CustomEventRecord, CallArgRecord, BufferExtents, 123 PIDRecord>; 124 INSTANTIATE_TYPED_TEST_SUITE_P(Records, PrinterTest, FDRRecordTypes, ); 125 126 TEST(FDRRecordPrinterTest, WriteFunctionRecordEnter) { 127 std::string Data; 128 raw_string_ostream OS(Data); 129 RecordPrinter P(OS); 130 FunctionRecord R(RecordTypes::ENTER, 1, 2); 131 ASSERT_FALSE(errorToBool(R.apply(P))); 132 EXPECT_THAT(Data, Eq("<Function Enter: #1 delta = +2>")); 133 } 134 135 TEST(FDRRecordPrinterTest, WriteFunctionRecordExit) { 136 std::string Data; 137 raw_string_ostream OS(Data); 138 RecordPrinter P(OS); 139 FunctionRecord R(RecordTypes::EXIT, 1, 2); 140 ASSERT_FALSE(errorToBool(R.apply(P))); 141 EXPECT_THAT(Data, Eq("<Function Exit: #1 delta = +2>")); 142 } 143 144 TEST(FDRRecordPrinterTest, WriteFunctionRecordTailExit) { 145 std::string Data; 146 raw_string_ostream OS(Data); 147 RecordPrinter P(OS); 148 FunctionRecord R(RecordTypes::TAIL_EXIT, 1, 2); 149 ASSERT_FALSE(errorToBool(R.apply(P))); 150 EXPECT_THAT(Data, Eq("<Function Tail Exit: #1 delta = +2>")); 151 } 152 153 TEST(FDRRecordPrinterTest, WriteFunctionRecordEnterArg) { 154 std::string Data; 155 raw_string_ostream OS(Data); 156 RecordPrinter P(OS); 157 FunctionRecord R(RecordTypes::ENTER_ARG, 1, 2); 158 ASSERT_FALSE(errorToBool(R.apply(P))); 159 EXPECT_THAT(Data, Eq("<Function Enter With Arg: #1 delta = +2>")); 160 } 161 162 } // namespace 163 } // namespace xray 164 } // namespace llvm 165