1 //===- FDRRecords.cpp - Unit Tests for XRay FDR Record Loading ------------===//
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
7 //===----------------------------------------------------------------------===//
8 #include "gmock/gmock.h"
9 #include "gtest/gtest.h"
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"
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)
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")
39 auto Block1
= LogBuilder()
40 .add
<BufferExtents
>(100)
41 .add
<NewBufferRecord
>(1)
42 .add
<WallclockRecord
>(1, 2)
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")
49 auto Block2
= LogBuilder()
50 .add
<BufferExtents
>(100)
51 .add
<NewBufferRecord
>(2)
52 .add
<WallclockRecord
>(1, 3)
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")
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()));
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));
77 TEST(XRayFDRTest
, BuilderAndBlockVerifier
) {
78 auto Block
= LogBuilder()
79 .add
<BufferExtents
>(48)
80 .add
<NewBufferRecord
>(1)
81 .add
<WallclockRecord
>(1, 1)
83 .add
<NewCPUIDRecord
>(1, 2)
85 BlockVerifier Verifier
;
87 ASSERT_FALSE(errorToBool(R
->apply(Verifier
)));
88 ASSERT_FALSE(errorToBool(Verifier
.verify()));
91 TEST(XRayFDRTest
, IndexAndVerifyBlocks
) {
92 auto Block0
= LogBuilder()
93 .add
<BufferExtents
>(64)
94 .add
<NewBufferRecord
>(1)
95 .add
<WallclockRecord
>(1, 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")
103 auto Block1
= LogBuilder()
104 .add
<BufferExtents
>(64)
105 .add
<NewBufferRecord
>(1)
106 .add
<WallclockRecord
>(1, 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")
114 auto Block2
= LogBuilder()
115 .add
<BufferExtents
>(64)
116 .add
<NewBufferRecord
>(1)
117 .add
<WallclockRecord
>(1, 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")
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()));
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()));
147 // Then set up the printing mechanisms.
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
)));
162 EXPECT_THAT(Output
, Not(Eq("")));