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
18namespace llvm {
19namespace xray {
20namespace {
21
22using ::testing::Eq;
23using ::testing::Not;
24
25TEST(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>(A: 100)
31 .add<NewBufferRecord>(A: 1)
32 .add<WallclockRecord>(A: 1, A: 1)
33 .add<PIDRecord>(A: 1)
34 .add<FunctionRecord>(A: RecordTypes::ENTER, A: 1, A: 1)
35 .add<FunctionRecord>(A: RecordTypes::EXIT, A: 1, A: 100)
36 .add<CustomEventRecordV5>(A: 1, A: 4, A: "XRAY")
37 .add<TypedEventRecord>(A: 1, A: 4, A: 2, A: "XRAY")
38 .consume();
39 auto Block1 = LogBuilder()
40 .add<BufferExtents>(A: 100)
41 .add<NewBufferRecord>(A: 1)
42 .add<WallclockRecord>(A: 1, A: 2)
43 .add<PIDRecord>(A: 1)
44 .add<FunctionRecord>(A: RecordTypes::ENTER, A: 1, A: 1)
45 .add<FunctionRecord>(A: RecordTypes::EXIT, A: 1, A: 100)
46 .add<CustomEventRecordV5>(A: 1, A: 4, A: "XRAY")
47 .add<TypedEventRecord>(A: 1, A: 4, A: 2, A: "XRAY")
48 .consume();
49 auto Block2 = LogBuilder()
50 .add<BufferExtents>(A: 100)
51 .add<NewBufferRecord>(A: 2)
52 .add<WallclockRecord>(A: 1, A: 3)
53 .add<PIDRecord>(A: 1)
54 .add<FunctionRecord>(A: RecordTypes::ENTER, A: 1, A: 1)
55 .add<FunctionRecord>(A: RecordTypes::EXIT, A: 1, A: 100)
56 .add<CustomEventRecordV5>(A: 1, A: 4, A: "XRAY")
57 .add<TypedEventRecord>(A: 1, A: 4, A: 2, A: "XRAY")
58 .consume();
59 BlockIndexer::Index Index;
60 BlockIndexer Indexer(Index);
61 for (auto B : {std::ref(t&: Block0), std::ref(t&: Block1), std::ref(t&: 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(Val: {1, 1});
70 ASSERT_THAT(T1Blocks, Not(Eq(Index.end())));
71 ASSERT_THAT(T1Blocks->second.size(), Eq(2u));
72 auto T2Blocks = Index.find(Val: {1, 2});
73 ASSERT_THAT(T2Blocks, Not(Eq(Index.end())));
74 ASSERT_THAT(T2Blocks->second.size(), Eq(1u));
75}
76
77TEST(XRayFDRTest, BuilderAndBlockVerifier) {
78 auto Block = LogBuilder()
79 .add<BufferExtents>(A: 48)
80 .add<NewBufferRecord>(A: 1)
81 .add<WallclockRecord>(A: 1, A: 1)
82 .add<PIDRecord>(A: 1)
83 .add<NewCPUIDRecord>(A: 1, A: 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
91TEST(XRayFDRTest, IndexAndVerifyBlocks) {
92 auto Block0 = LogBuilder()
93 .add<BufferExtents>(A: 64)
94 .add<NewBufferRecord>(A: 1)
95 .add<WallclockRecord>(A: 1, A: 1)
96 .add<PIDRecord>(A: 1)
97 .add<NewCPUIDRecord>(A: 1, A: 2)
98 .add<FunctionRecord>(A: RecordTypes::ENTER, A: 1, A: 1)
99 .add<FunctionRecord>(A: RecordTypes::EXIT, A: 1, A: 100)
100 .add<CustomEventRecordV5>(A: 1, A: 4, A: "XRAY")
101 .add<TypedEventRecord>(A: 1, A: 4, A: 2, A: "XRAY")
102 .consume();
103 auto Block1 = LogBuilder()
104 .add<BufferExtents>(A: 64)
105 .add<NewBufferRecord>(A: 1)
106 .add<WallclockRecord>(A: 1, A: 1)
107 .add<PIDRecord>(A: 1)
108 .add<NewCPUIDRecord>(A: 1, A: 2)
109 .add<FunctionRecord>(A: RecordTypes::ENTER, A: 1, A: 1)
110 .add<FunctionRecord>(A: RecordTypes::EXIT, A: 1, A: 100)
111 .add<CustomEventRecordV5>(A: 1, A: 4, A: "XRAY")
112 .add<TypedEventRecord>(A: 1, A: 4, A: 2, A: "XRAY")
113 .consume();
114 auto Block2 = LogBuilder()
115 .add<BufferExtents>(A: 64)
116 .add<NewBufferRecord>(A: 1)
117 .add<WallclockRecord>(A: 1, A: 1)
118 .add<PIDRecord>(A: 1)
119 .add<NewCPUIDRecord>(A: 1, A: 2)
120 .add<FunctionRecord>(A: RecordTypes::ENTER, A: 1, A: 1)
121 .add<FunctionRecord>(A: RecordTypes::EXIT, A: 1, A: 100)
122 .add<CustomEventRecordV5>(A: 1, A: 4, A: "XRAY")
123 .add<TypedEventRecord>(A: 1, A: 4, A: 2, A: "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(t&: Block0), std::ref(t&: Block1), std::ref(t&: 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

source code of llvm/unittests/XRay/FDRRecordsTest.cpp