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