1 2 /* 3 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <hwext/gtest-ext.h> 17 #include <hwext/gtest-tag.h> 18 #include "bio_latency_data_parser.h" 19 #include "cpu_filter.h" 20 #include "ebpf_data_parser.h" 21 #include "ebpf_stdtype.h" 22 #include "process_filter.h" 23 #include "trace_streamer_selector.h" 24 #include "ts_common.h" 25 using namespace testing::ext; 26 using namespace SysTuning::TraceStreamer; 27 using namespace SysTuning::EbpfStdtype; 28 namespace SysTuning ::TraceStreamer { 29 const std::string COMMAND_LINE = "hiebpf --events ptrace --duration 50"; 30 const uint64_t EPBF_ERROR_MAGIC = 0x12345678; 31 const uint32_t EPBF_ERROR_HEAD_SIZE = 0; 32 const char PROCESS_NAME_01[MAX_PROCESS_NAME_SZIE] = "process01"; 33 const uint64_t START_TIME = 1725645867369; 34 const uint64_t END_TIME = 1725645967369; 35 const uint64_t BLKCNT = 7829248; 36 const uint64_t IPS_01 = 548606407208; 37 const uint64_t IPS_02 = 548607407208; 38 const uint64_t EBPF_COMMAND_MAX_SIZE = 1000; 39 const uint32_t DURPER4K = 4096; 40 const uint64_t PID = 32; 41 const uint64_t TID = 32; 42 const uint16_t TYPE = 2; 43 44 class EbpfBioParserTest : public ::testing::Test { 45 public: SetUp()46 void SetUp() 47 { 48 stream_.InitFilter(); 49 } 50 TearDown()51 void TearDown() 52 { 53 dequeBuffer_.clear(); 54 } 55 InitData(uint32_t length,uint32_t nips,const uint64_t startTime,const uint64_t endTime,uint32_t prio=0)56 void InitData(uint32_t length, uint32_t nips, const uint64_t startTime, const uint64_t endTime, uint32_t prio = 0) 57 { 58 ebpfHeader_.header.clock = EBPF_CLOCK_BOOTTIME; 59 ebpfHeader_.header.cmdLineLen = COMMAND_LINE.length(); 60 strcpy_s(ebpfHeader_.cmdline, EBPF_COMMAND_MAX_SIZE, COMMAND_LINE.c_str()); 61 ebpfTypeAndLength_.type = ITEM_EVENT_BIO; 62 ebpfTypeAndLength_.length = length; 63 bioFixedHeader_.pid = PID; 64 bioFixedHeader_.tid = TID; 65 memcpy_s(bioFixedHeader_.processName, MAX_PROCESS_NAME_SZIE, "process", MAX_PROCESS_NAME_SZIE); 66 bioFixedHeader_.prio = 0; 67 bioFixedHeader_.size = DURPER4K; 68 bioFixedHeader_.blkcnt = BLKCNT; 69 bioFixedHeader_.type = TYPE; 70 bioFixedHeader_.nips = nips; 71 bioFixedHeader_.startTime = startTime; 72 bioFixedHeader_.endTime = endTime; 73 74 dequeBuffer_.insert(dequeBuffer_.end(), reinterpret_cast<uint8_t *>(&ebpfHeader_), 75 reinterpret_cast<uint8_t *>(&ebpfHeader_ + 1)); 76 dequeBuffer_.insert(dequeBuffer_.end(), &(reinterpret_cast<uint8_t *>(&ebpfTypeAndLength_))[0], 77 &(reinterpret_cast<uint8_t *>(&ebpfTypeAndLength_))[sizeof(EbpfTypeAndLength)]); 78 79 dequeBuffer_.insert(dequeBuffer_.end(), &(reinterpret_cast<uint8_t *>(&bioFixedHeader_))[0], 80 &(reinterpret_cast<uint8_t *>(&bioFixedHeader_))[sizeof(BIOFixedHeader)]); 81 } 82 83 public: 84 TraceStreamerSelector stream_ = {}; 85 EbpfDataHeader ebpfHeader_; 86 EbpfTypeAndLength ebpfTypeAndLength_; 87 BIOFixedHeader bioFixedHeader_; 88 std::deque<uint8_t> dequeBuffer_; 89 }; 90 91 /** 92 * @tc.name: EbpfBioParserCorrectWithoutCallback 93 * @tc.desc: Test parse BIO data without callback 94 * @tc.type: FUNC 95 */ 96 HWTEST_F(EbpfBioParserTest, EbpfBioParserCorrectWithoutCallback, TestSize.Level1) 97 { 98 TS_LOGI("test32-01"); 99 InitData(sizeof(BIOFixedHeader), 0, START_TIME, END_TIME); 100 101 std::unique_ptr<EbpfDataParser> ebpfDataParser = 102 std::make_unique<EbpfDataParser>(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); 103 EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer_, dequeBuffer_.size())); 104 EXPECT_TRUE(ebpfDataParser->reader_->GetBIOSampleMap().size()); 105 ebpfDataParser->ParseBioLatencyEvent(); 106 ebpfDataParser->Finish(); 107 EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); 108 auto sampleData = stream_.traceDataCache_->GetConstBioLatencySampleData(); 109 EXPECT_EQ(sampleData.CallChainIds()[0], INVALID_UINT32); 110 EXPECT_EQ(sampleData.Types()[0], 2); 111 EXPECT_EQ(sampleData.StartTs()[0], START_TIME); 112 EXPECT_EQ(sampleData.EndTs()[0], END_TIME); 113 auto dur = sampleData.LatencyDurs()[0]; 114 EXPECT_EQ(dur, END_TIME - START_TIME); 115 EXPECT_EQ(sampleData.Tiers()[0], 0); 116 auto size = sampleData.Sizes()[0]; 117 EXPECT_EQ(size, DURPER4K); 118 EXPECT_EQ(sampleData.BlockNumbers()[0], ebpfDataParser->ConvertToHexTextIndex(BLKCNT)); 119 EXPECT_EQ(sampleData.DurPer4k()[0], dur / (size / DURPER4K)); 120 } 121 122 /** 123 * @tc.name: EbpfBioParserwrongWithoutCallback 124 * @tc.desc: Test parse BIO data without callback and startTs > endTs 125 * @tc.type: FUNC 126 */ 127 HWTEST_F(EbpfBioParserTest, EbpfBioParserwrongWithoutCallback, TestSize.Level1) 128 { 129 TS_LOGI("test32-02"); 130 InitData(sizeof(BIOFixedHeader), 0, END_TIME, START_TIME, 1); 131 132 std::unique_ptr<EbpfDataParser> ebpfDataParser = 133 std::make_unique<EbpfDataParser>(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); 134 EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer_, dequeBuffer_.size())); 135 EXPECT_TRUE(ebpfDataParser->reader_->GetBIOSampleMap().size()); 136 ebpfDataParser->ParseBioLatencyEvent(); 137 ebpfDataParser->Finish(); 138 EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); 139 auto sampleData = stream_.traceDataCache_->GetConstBioLatencySampleData(); 140 EXPECT_NE(sampleData.CallChainIds()[0], INVALID_UINT64); 141 EXPECT_NE(sampleData.Types()[0], 2); 142 EXPECT_NE(sampleData.StartTs()[0], END_TIME); 143 EXPECT_NE(sampleData.EndTs()[0], START_TIME); 144 auto dur = sampleData.LatencyDurs()[0]; 145 EXPECT_NE(dur, START_TIME - END_TIME); 146 EXPECT_NE(sampleData.Tiers()[0], 1); 147 auto size = sampleData.Sizes()[0]; 148 EXPECT_NE(size, DURPER4K); 149 EXPECT_NE(sampleData.BlockNumbers()[0], ebpfDataParser->ConvertToHexTextIndex(BLKCNT)); 150 if (size > 0) { 151 EXPECT_NE(sampleData.DurPer4k()[0], dur / (size / DURPER4K)); 152 } 153 } 154 155 /** 156 * @tc.name: EbpfBioParserCorrectWithOneCallback 157 * @tc.desc: Test parse BIO data with one callback 158 * @tc.type: FUNC 159 */ 160 HWTEST_F(EbpfBioParserTest, EbpfBioParserCorrectWithOneCallback, TestSize.Level1) 161 { 162 TS_LOGI("test32-03"); 163 InitData(sizeof(BIOFixedHeader), 1, START_TIME, END_TIME); 164 165 const uint64_t ips[1] = {IPS_01}; 166 dequeBuffer_.insert(dequeBuffer_.end(), reinterpret_cast<const uint8_t *>(ips), 167 reinterpret_cast<const uint8_t *>(&ips + 1)); 168 std::unique_ptr<EbpfDataParser> ebpfDataParser = 169 std::make_unique<EbpfDataParser>(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); 170 EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer_, dequeBuffer_.size())); 171 EXPECT_TRUE(ebpfDataParser->reader_->GetBIOSampleMap().size()); 172 ebpfDataParser->ParseBioLatencyEvent(); 173 ebpfDataParser->Finish(); 174 EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); 175 auto sampleData = stream_.traceDataCache_->GetConstBioLatencySampleData(); 176 EXPECT_EQ(sampleData.CallChainIds()[0], 0); 177 EXPECT_EQ(sampleData.Types()[0], 2); 178 EXPECT_EQ(sampleData.Ipids()[0], 1); 179 EXPECT_EQ(sampleData.Itids()[0], 1); 180 EXPECT_EQ(sampleData.StartTs()[0], START_TIME); 181 EXPECT_EQ(sampleData.EndTs()[0], END_TIME); 182 auto dur = sampleData.LatencyDurs()[0]; 183 EXPECT_EQ(dur, END_TIME - START_TIME); 184 EXPECT_EQ(sampleData.Tiers()[0], 0); 185 auto size = sampleData.Sizes()[0]; 186 EXPECT_EQ(size, DURPER4K); 187 EXPECT_EQ(sampleData.BlockNumbers()[0], ebpfDataParser->ConvertToHexTextIndex(BLKCNT)); 188 EXPECT_EQ(sampleData.DurPer4k()[0], dur / (size / DURPER4K)); 189 auto ExpectIps0 = ebpfDataParser->ConvertToHexTextIndex(ips[0]); 190 auto ips0 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[0]; 191 EXPECT_EQ(ips0, ExpectIps0); 192 } 193 194 /** 195 * @tc.name: EbpfBioParserCorrectWithMultipleCallback 196 * @tc.desc: Test parse BIO data with multiple callback 197 * @tc.type: FUNC 198 */ 199 HWTEST_F(EbpfBioParserTest, EbpfBioParserCorrectWithMultipleCallback, TestSize.Level1) 200 { 201 TS_LOGI("test32-04"); 202 InitData(sizeof(BIOFixedHeader) + 2 * sizeof(uint64_t), 2, START_TIME, END_TIME); 203 204 const uint64_t ips[2] = {IPS_01, IPS_02}; 205 dequeBuffer_.insert(dequeBuffer_.end(), reinterpret_cast<const uint8_t *>(ips), 206 reinterpret_cast<const uint8_t *>(&ips + 1)); 207 std::unique_ptr<EbpfDataParser> ebpfDataParser = 208 std::make_unique<EbpfDataParser>(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); 209 EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer_, dequeBuffer_.size())); 210 EXPECT_TRUE(ebpfDataParser->reader_->GetBIOSampleMap().size()); 211 ebpfDataParser->ParseBioLatencyEvent(); 212 ebpfDataParser->Finish(); 213 EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); 214 auto sampleData = stream_.traceDataCache_->GetConstBioLatencySampleData(); 215 EXPECT_EQ(sampleData.CallChainIds()[0], 0); 216 EXPECT_EQ(sampleData.Types()[0], 2); 217 EXPECT_EQ(sampleData.Ipids()[0], 1); 218 EXPECT_EQ(sampleData.Itids()[0], 1); 219 EXPECT_EQ(sampleData.StartTs()[0], START_TIME); 220 EXPECT_EQ(sampleData.EndTs()[0], END_TIME); 221 auto dur = sampleData.LatencyDurs()[0]; 222 EXPECT_EQ(dur, END_TIME - START_TIME); 223 EXPECT_EQ(sampleData.Tiers()[0], 0); 224 auto size = sampleData.Sizes()[0]; 225 EXPECT_EQ(size, DURPER4K); 226 EXPECT_EQ(sampleData.BlockNumbers()[0], ebpfDataParser->ConvertToHexTextIndex(BLKCNT)); 227 EXPECT_EQ(sampleData.DurPer4k()[0], dur / (size / DURPER4K)); 228 auto ExpectIps0 = ebpfDataParser->ConvertToHexTextIndex(ips[0]); 229 auto ips0 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[1]; 230 EXPECT_EQ(ips0, ExpectIps0); 231 auto ExpectIps1 = ebpfDataParser->ConvertToHexTextIndex(ips[1]); 232 auto ips1 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[0]; 233 EXPECT_EQ(ips1, ExpectIps1); 234 } 235 } // namespace SysTuning::TraceStreamer 236