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