1 //===- llvm/unittest/XRay/FDRBlockVerifierTest.cpp --------------*- C++ -*-===//
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 "llvm/Testing/Support/Error.h"
9 #include "llvm/XRay/BlockIndexer.h"
10 #include "llvm/XRay/BlockVerifier.h"
11 #include "llvm/XRay/FDRLogBuilder.h"
12 #include "llvm/XRay/FDRRecords.h"
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
15 
16 namespace llvm {
17 namespace xray {
18 namespace {
19 
20 using ::testing::ElementsAre;
21 using ::testing::Not;
22 using ::testing::SizeIs;
23 
TEST(FDRBlockVerifierTest,ValidBlocksV3)24 TEST(FDRBlockVerifierTest, ValidBlocksV3) {
25   auto Block0 = LogBuilder()
26                     .add<BufferExtents>(80)
27                     .add<NewBufferRecord>(1)
28                     .add<WallclockRecord>(1, 2)
29                     .add<PIDRecord>(1)
30                     .add<NewCPUIDRecord>(1, 2)
31                     .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
32                     .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
33                     .consume();
34   auto Block1 = LogBuilder()
35                     .add<BufferExtents>(80)
36                     .add<NewBufferRecord>(1)
37                     .add<WallclockRecord>(1, 2)
38                     .add<PIDRecord>(1)
39                     .add<NewCPUIDRecord>(1, 2)
40                     .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
41                     .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
42                     .consume();
43   auto Block2 = LogBuilder()
44                     .add<BufferExtents>(80)
45                     .add<NewBufferRecord>(2)
46                     .add<WallclockRecord>(1, 2)
47                     .add<PIDRecord>(1)
48                     .add<NewCPUIDRecord>(2, 2)
49                     .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
50                     .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
51                     .consume();
52   BlockIndexer::Index Index;
53   BlockIndexer Indexer(Index);
54   for (auto B : {std::ref(Block0), std::ref(Block1), std::ref(Block2)}) {
55     for (auto &R : B.get())
56       ASSERT_FALSE(errorToBool(R->apply(Indexer)));
57     ASSERT_FALSE(errorToBool(Indexer.flush()));
58   }
59 
60   BlockVerifier Verifier;
61   for (auto &ProcessThreadBlocks : Index) {
62     auto &Blocks = ProcessThreadBlocks.second;
63     for (auto &B : Blocks) {
64       for (auto *R : B.Records)
65         ASSERT_FALSE(errorToBool(R->apply(Verifier)));
66       ASSERT_FALSE(errorToBool(Verifier.verify()));
67       Verifier.reset();
68     }
69   }
70 }
71 
TEST(FDRBlockVerifierTest,MissingPIDRecord)72 TEST(FDRBlockVerifierTest, MissingPIDRecord) {
73   auto Block = LogBuilder()
74                    .add<BufferExtents>(20)
75                    .add<NewBufferRecord>(1)
76                    .add<WallclockRecord>(1, 2)
77                    .add<NewCPUIDRecord>(1, 2)
78                    .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
79                    .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
80                    .consume();
81   BlockVerifier Verifier;
82   for (auto &R : Block)
83     ASSERT_FALSE(errorToBool(R->apply(Verifier)));
84   ASSERT_FALSE(errorToBool(Verifier.verify()));
85 }
86 
TEST(FDRBlockVerifierTest,MissingBufferExtents)87 TEST(FDRBlockVerifierTest, MissingBufferExtents) {
88   auto Block = LogBuilder()
89                    .add<NewBufferRecord>(1)
90                    .add<WallclockRecord>(1, 2)
91                    .add<NewCPUIDRecord>(1, 2)
92                    .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
93                    .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
94                    .consume();
95   BlockVerifier Verifier;
96   for (auto &R : Block)
97     ASSERT_FALSE(errorToBool(R->apply(Verifier)));
98   ASSERT_FALSE(errorToBool(Verifier.verify()));
99 }
100 
TEST(FDRBlockVerifierTest,IgnoreRecordsAfterEOB)101 TEST(FDRBlockVerifierTest, IgnoreRecordsAfterEOB) {
102   auto Block = LogBuilder()
103                    .add<NewBufferRecord>(1)
104                    .add<WallclockRecord>(1, 2)
105                    .add<NewCPUIDRecord>(1, 2)
106                    .add<EndBufferRecord>()
107                    .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
108                    .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
109                    .consume();
110   BlockVerifier Verifier;
111   for (auto &R : Block)
112     ASSERT_FALSE(errorToBool(R->apply(Verifier)));
113   ASSERT_FALSE(errorToBool(Verifier.verify()));
114 }
115 
TEST(FDRBlockVerifierTest,MalformedV2)116 TEST(FDRBlockVerifierTest, MalformedV2) {
117   auto Block = LogBuilder()
118                    .add<NewBufferRecord>(1)
119                    .add<WallclockRecord>(1, 2)
120                    .add<NewCPUIDRecord>(1, 2)
121                    .add<FunctionRecord>(RecordTypes::ENTER, 1, 1)
122                    .add<FunctionRecord>(RecordTypes::EXIT, 1, 100)
123                    .add<NewBufferRecord>(2)
124                    .consume();
125   BlockVerifier Verifier;
126 
127   ASSERT_THAT(Block, SizeIs(6u));
128   EXPECT_THAT_ERROR(Block[0]->apply(Verifier), Succeeded());
129   EXPECT_THAT_ERROR(Block[1]->apply(Verifier), Succeeded());
130   EXPECT_THAT_ERROR(Block[2]->apply(Verifier), Succeeded());
131   EXPECT_THAT_ERROR(Block[3]->apply(Verifier), Succeeded());
132   EXPECT_THAT_ERROR(Block[4]->apply(Verifier), Succeeded());
133   EXPECT_THAT_ERROR(Block[5]->apply(Verifier), Failed());
134 }
135 
136 } // namespace
137 } // namespace xray
138 } // namespace llvm
139