1 //===- FDRRecords.cpp - Unit Tests for XRay FDR Record Loading ------------===// 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 "gmock/gmock.h" 10 #include "gtest/gtest.h" 11 12 #include "llvm/XRay/BlockIndexer.h" 13 #include "llvm/XRay/BlockPrinter.h" 14 #include "llvm/XRay/BlockVerifier.h" 15 #include "llvm/XRay/FDRLogBuilder.h" 16 #include "llvm/XRay/FDRRecords.h" 17 #include "llvm/XRay/RecordPrinter.h" 18 19 namespace llvm { 20 namespace xray { 21 namespace { 22 23 using ::testing::Eq; 24 using ::testing::Not; 25 26 TEST(XRayFDRTest, BuilderAndBlockIndexer) { 27 // We recreate a single block of valid records, then ensure that we find all 28 // of them belonging in the same index. We do this for three blocks, and 29 // ensure we find the same records in the blocks we deduce. 30 auto Block0 = LogBuilder() 31 .add<BufferExtents>(100) 32 .add<NewBufferRecord>(1) 33 .add<WallclockRecord>(1, 1) 34 .add<PIDRecord>(1) 35 .add<FunctionRecord>(RecordTypes::ENTER, 1, 1) 36 .add<FunctionRecord>(RecordTypes::EXIT, 1, 100) 37 .add<CustomEventRecordV5>(1, 4, "XRAY") 38 .add<TypedEventRecord>(1, 4, 2, "XRAY") 39 .consume(); 40 auto Block1 = LogBuilder() 41 .add<BufferExtents>(100) 42 .add<NewBufferRecord>(1) 43 .add<WallclockRecord>(1, 2) 44 .add<PIDRecord>(1) 45 .add<FunctionRecord>(RecordTypes::ENTER, 1, 1) 46 .add<FunctionRecord>(RecordTypes::EXIT, 1, 100) 47 .add<CustomEventRecordV5>(1, 4, "XRAY") 48 .add<TypedEventRecord>(1, 4, 2, "XRAY") 49 .consume(); 50 auto Block2 = LogBuilder() 51 .add<BufferExtents>(100) 52 .add<NewBufferRecord>(2) 53 .add<WallclockRecord>(1, 3) 54 .add<PIDRecord>(1) 55 .add<FunctionRecord>(RecordTypes::ENTER, 1, 1) 56 .add<FunctionRecord>(RecordTypes::EXIT, 1, 100) 57 .add<CustomEventRecordV5>(1, 4, "XRAY") 58 .add<TypedEventRecord>(1, 4, 2, "XRAY") 59 .consume(); 60 BlockIndexer::Index Index; 61 BlockIndexer Indexer(Index); 62 for (auto B : {std::ref(Block0), std::ref(Block1), std::ref(Block2)}) { 63 for (auto &R : B.get()) 64 ASSERT_FALSE(errorToBool(R->apply(Indexer))); 65 ASSERT_FALSE(errorToBool(Indexer.flush())); 66 } 67 68 // We have two threads worth of blocks. 69 ASSERT_THAT(Index.size(), Eq(2u)); 70 auto T1Blocks = Index.find({1, 1}); 71 ASSERT_THAT(T1Blocks, Not(Eq(Index.end()))); 72 ASSERT_THAT(T1Blocks->second.size(), Eq(2u)); 73 auto T2Blocks = Index.find({1, 2}); 74 ASSERT_THAT(T2Blocks, Not(Eq(Index.end()))); 75 ASSERT_THAT(T2Blocks->second.size(), Eq(1u)); 76 } 77 78 TEST(XRayFDRTest, BuilderAndBlockVerifier) { 79 auto Block = LogBuilder() 80 .add<BufferExtents>(48) 81 .add<NewBufferRecord>(1) 82 .add<WallclockRecord>(1, 1) 83 .add<PIDRecord>(1) 84 .add<NewCPUIDRecord>(1, 2) 85 .consume(); 86 BlockVerifier Verifier; 87 for (auto &R : Block) 88 ASSERT_FALSE(errorToBool(R->apply(Verifier))); 89 ASSERT_FALSE(errorToBool(Verifier.verify())); 90 } 91 92 TEST(XRayFDRTest, IndexAndVerifyBlocks) { 93 auto Block0 = LogBuilder() 94 .add<BufferExtents>(64) 95 .add<NewBufferRecord>(1) 96 .add<WallclockRecord>(1, 1) 97 .add<PIDRecord>(1) 98 .add<NewCPUIDRecord>(1, 2) 99 .add<FunctionRecord>(RecordTypes::ENTER, 1, 1) 100 .add<FunctionRecord>(RecordTypes::EXIT, 1, 100) 101 .add<CustomEventRecordV5>(1, 4, "XRAY") 102 .add<TypedEventRecord>(1, 4, 2, "XRAY") 103 .consume(); 104 auto Block1 = LogBuilder() 105 .add<BufferExtents>(64) 106 .add<NewBufferRecord>(1) 107 .add<WallclockRecord>(1, 1) 108 .add<PIDRecord>(1) 109 .add<NewCPUIDRecord>(1, 2) 110 .add<FunctionRecord>(RecordTypes::ENTER, 1, 1) 111 .add<FunctionRecord>(RecordTypes::EXIT, 1, 100) 112 .add<CustomEventRecordV5>(1, 4, "XRAY") 113 .add<TypedEventRecord>(1, 4, 2, "XRAY") 114 .consume(); 115 auto Block2 = LogBuilder() 116 .add<BufferExtents>(64) 117 .add<NewBufferRecord>(1) 118 .add<WallclockRecord>(1, 1) 119 .add<PIDRecord>(1) 120 .add<NewCPUIDRecord>(1, 2) 121 .add<FunctionRecord>(RecordTypes::ENTER, 1, 1) 122 .add<FunctionRecord>(RecordTypes::EXIT, 1, 100) 123 .add<CustomEventRecordV5>(1, 4, "XRAY") 124 .add<TypedEventRecord>(1, 4, 2, "XRAY") 125 .consume(); 126 127 // First, index the records in different blocks. 128 BlockIndexer::Index Index; 129 BlockIndexer Indexer(Index); 130 for (auto B : {std::ref(Block0), std::ref(Block1), std::ref(Block2)}) { 131 for (auto &R : B.get()) 132 ASSERT_FALSE(errorToBool(R->apply(Indexer))); 133 ASSERT_FALSE(errorToBool(Indexer.flush())); 134 } 135 136 // Next, verify that each block is consistently defined. 137 BlockVerifier Verifier; 138 for (auto &ProcessThreadBlocks : Index) { 139 auto &Blocks = ProcessThreadBlocks.second; 140 for (auto &B : Blocks) { 141 for (auto *R : B.Records) 142 ASSERT_FALSE(errorToBool(R->apply(Verifier))); 143 ASSERT_FALSE(errorToBool(Verifier.verify())); 144 Verifier.reset(); 145 } 146 } 147 148 // Then set up the printing mechanisms. 149 std::string Output; 150 raw_string_ostream OS(Output); 151 RecordPrinter RP(OS); 152 BlockPrinter BP(OS, RP); 153 for (auto &ProcessThreadBlocks : Index) { 154 auto &Blocks = ProcessThreadBlocks.second; 155 for (auto &B : Blocks) { 156 for (auto *R : B.Records) 157 ASSERT_FALSE(errorToBool(R->apply(BP))); 158 BP.reset(); 159 } 160 } 161 162 OS.flush(); 163 EXPECT_THAT(Output, Not(Eq(""))); 164 } 165 166 } // namespace 167 } // namespace xray 168 } // namespace llvm 169