1 /* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include <fcntl.h> 17 #include <hwext/gtest-ext.h> 18 #include <hwext/gtest-tag.h> 19 #include <iostream> 20 #include <string> 21 #include <unistd.h> 22 23 #include "ptreader_parser.h" 24 #include "file.h" 25 #include "pbreader_parser.h" 26 #include "trace_streamer_selector.h" 27 28 using namespace testing::ext; 29 using namespace SysTuning; 30 using namespace SysTuning::TraceStreamer; 31 namespace SysTuning { 32 namespace TraceStreamer { 33 constexpr size_t G_FILE_PERMISSION = 664; 34 const uint32_t PROFILE_HEADER = 1024; 35 constexpr size_t READ_SIZE = 1024; 36 37 class SplitFileDataTest : public testing::Test { 38 protected: SetUpTestCase()39 static void SetUpTestCase() {} TearDownTestCase()40 static void TearDownTestCase() {} 41 ParseData(std::unique_ptr<TraceStreamerSelector> & ta,const std::string path)42 void ParseData(std::unique_ptr<TraceStreamerSelector> &ta, const std::string path) 43 { 44 ta->EnableMetaTable(false); 45 46 size_t readSize = 0; 47 int32_t fd(base::OpenFile(path, O_RDONLY, G_FILE_PERMISSION)); 48 while (true) { 49 std::unique_ptr<uint8_t[]> buf = std::make_unique<uint8_t[]>(READ_SIZE); 50 auto rsize = base::Read(fd, buf.get(), READ_SIZE); 51 if (rsize == 0) { 52 break; 53 } 54 if (rsize < 0) { 55 TS_LOGD("Reading trace file over (errno: %d, %s)", errno, strerror(errno)); 56 break; 57 } 58 if (!ta->ParseTraceDataSegment(std::move(buf), rsize, 1, 1)) { 59 break; 60 }; 61 62 dataBuf_ = std::make_unique<uint8_t[]>(readSize + rsize); 63 memcpy_s(dataBuf_.get() + readSize, rsize, buf.get(), rsize); 64 readSize += rsize; 65 } 66 67 ta->WaitForParserEnd(); 68 close(fd); 69 } 70 CheckData(std::unique_ptr<TraceStreamerSelector> & ta,const std::string path)71 bool CheckData(std::unique_ptr<TraceStreamerSelector> &ta, const std::string path) 72 { 73 std::ifstream inputFile(path, std::ios::binary); 74 if (!inputFile.is_open()) { 75 std::cerr << "Failed to open file: " << path << std::endl; 76 return false; 77 } 78 79 auto splitResult = ta->GetPbreaderParser()->GetEbpfDataParser()->GetEbpfSplitResult(); 80 uint64_t headDataSize = 0; 81 for (const auto &itemHtrace : ta->GetPbreaderParser()->GetPbreaderSplitData()) { 82 headDataSize += itemHtrace.second; 83 } 84 auto profilerHeader = ta->GetPbreaderParser()->GetProfilerHeader(); 85 profilerHeader.data.length = PROFILE_HEADER + headDataSize; 86 std::string bufferData(reinterpret_cast<char *>(&profilerHeader), sizeof(profilerHeader)); 87 uint64_t dataSize = 0; 88 for (auto it = splitResult.begin(); it != splitResult.end(); ++it) { 89 if (it->type == (int32_t)SplitDataDataType::SPLIT_FILE_JSON) { 90 dataSize += it->originSeg.size; 91 } 92 } 93 auto combinedBuf = std::make_unique<uint8_t[]>(dataSize + PROFILE_HEADER + headDataSize); 94 std::copy(bufferData.begin(), bufferData.end(), combinedBuf.get()); 95 std::streamsize currentOffset = PROFILE_HEADER; 96 for (const auto &itemHtrace : ta->GetPbreaderParser()->GetPbreaderSplitData()) { 97 inputFile.seekg(itemHtrace.first); 98 inputFile.read(reinterpret_cast<char *>(combinedBuf.get()) + currentOffset, itemHtrace.second); 99 currentOffset += itemHtrace.second; 100 } 101 for (auto it = splitResult.begin(); it != splitResult.end(); ++it) { 102 if (it->type == (int32_t)SplitDataDataType::SPLIT_FILE_JSON) { 103 inputFile.seekg(it->originSeg.offset); 104 inputFile.read(reinterpret_cast<char *>(combinedBuf.get()) + currentOffset, it->originSeg.size); 105 currentOffset += it->originSeg.size; 106 } 107 if (!inputFile) { 108 std::cerr << "Error reading from file." << std::endl; 109 return false; 110 } 111 } 112 std::unique_ptr<TraceStreamerSelector> ts = std::make_unique<TraceStreamerSelector>(); 113 bool ret = ts->ParseTraceDataSegment(std::move(combinedBuf), dataSize + PROFILE_HEADER + headDataSize, 1, 1); 114 return ret; 115 } 116 117 public: 118 std::unique_ptr<uint8_t[]> dataBuf_; 119 }; 120 121 /** 122 * @tc.name: SplitFileDataByHtraceTest 123 * @tc.desc: Test htrace parsing binary file export database 124 * @tc.type: FUNC 125 */ 126 HWTEST_F(SplitFileDataTest, SplitFileDataByHtraceTest, TestSize.Level1) 127 { 128 TS_LOGI("test43-1"); 129 const std::string tracePath = "../../test/resource/hiprofiler_data_ability.htrace"; 130 if (access(tracePath.c_str(), F_OK) == 0) { 131 auto ta = std::make_unique<TraceStreamerSelector>(); 132 ta->minTs_ = 1502026311556913964; 133 ta->maxTs_ = 1502026330073755298; 134 ParseData(ta, tracePath); 135 136 std::ifstream inputFile(tracePath, std::ios::binary); 137 if (!inputFile.is_open()) { 138 std::cerr << "Failed to open file: " << tracePath << std::endl; 139 EXPECT_TRUE(false); 140 } 141 uint64_t dataSize = 0; 142 auto profilerHeader = ta->GetPbreaderParser()->GetProfilerHeader(); 143 144 for (const auto &itemHtrace : ta->GetPbreaderParser()->GetPbreaderSplitData()) { 145 dataSize += itemHtrace.second; 146 } 147 profilerHeader.data.length = PROFILE_HEADER + dataSize; 148 std::string buffer(reinterpret_cast<char *>(&profilerHeader), sizeof(profilerHeader)); 149 std::unique_ptr<uint8_t[]> combinedBuf = std::make_unique<uint8_t[]>(dataSize + PROFILE_HEADER); 150 std::copy(buffer.begin(), buffer.end(), combinedBuf.get()); 151 std::streamsize currentOffset = PROFILE_HEADER; 152 for (const auto &itemHtrace : ta->GetPbreaderParser()->GetPbreaderSplitData()) { 153 inputFile.seekg(itemHtrace.first); 154 inputFile.read(reinterpret_cast<char *>(combinedBuf.get()) + currentOffset, itemHtrace.second); 155 currentOffset += itemHtrace.second; 156 if (!inputFile) { 157 std::cerr << "Error reading from file." << std::endl; 158 EXPECT_TRUE(false); 159 } 160 } 161 std::unique_ptr<TraceStreamerSelector> ts = std::make_unique<TraceStreamerSelector>(); 162 EXPECT_TRUE(ts->ParseTraceDataSegment(std::move(combinedBuf), dataSize + PROFILE_HEADER, 1, 1)); 163 } else { 164 EXPECT_TRUE(false); 165 } 166 } 167 168 /** 169 * @tc.name: SplitFileDataByHtraceTest 170 * @tc.desc: Test htrace parsing binary file export database 171 * @tc.type: FUNC 172 */ 173 HWTEST_F(SplitFileDataTest, SplitFileDataBySystraceTest, TestSize.Level1) 174 { 175 TS_LOGI("test43-2"); 176 const std::string tracePath = "../../test/resource/trace_small_10.systrace"; 177 if (access(tracePath.c_str(), F_OK) == 0) { 178 auto ta = std::make_unique<SysTuning::TraceStreamer::TraceStreamerSelector>(); 179 ta->minTs_ = 88029692887000; 180 ta->maxTs_ = 88032820831000; 181 ParseData(ta, tracePath); 182 183 std::unique_ptr<TraceStreamerSelector> ts = std::make_unique<TraceStreamerSelector>(); 184 EXPECT_TRUE(ts->ParseTraceDataSegment(std::move(dataBuf_), 185 ta->GetPtreaderParser()->GetPtreaderSplitData().size(), 1, 1)); 186 } else { 187 EXPECT_TRUE(false); 188 } 189 } 190 191 /** 192 * @tc.name: SplitFileDataByHtraceTest 193 * @tc.desc: Test htrace parsing binary file export database 194 * @tc.type: FUNC 195 */ 196 HWTEST_F(SplitFileDataTest, SplitFileDataByEbpfTest, TestSize.Level1) 197 { 198 TS_LOGI("test43-3"); 199 const std::string tracePath = "../../test/resource/ebpf_bio.htrace"; 200 if (access(tracePath.c_str(), F_OK) == 0) { 201 auto ta = std::make_unique<SysTuning::TraceStreamer::TraceStreamerSelector>(); 202 ta->minTs_ = 800423789228; 203 ta->maxTs_ = 810586732842; 204 ParseData(ta, tracePath); 205 EXPECT_TRUE(CheckData(ta, tracePath)); 206 } else { 207 EXPECT_TRUE(false); 208 } 209 } 210 211 /** 212 * @tc.name: SplitFileDataByNativehookTest 213 * @tc.desc: Test htrace parsing binary file export database 214 * @tc.type: FUNC 215 */ 216 HWTEST_F(SplitFileDataTest, SplitFileDataByNativehookTest, TestSize.Level1) 217 { 218 TS_LOGI("test43-4"); 219 const std::string tracePath = "../../test/resource/Mmap.htrace"; 220 ASSERT_EQ(access(tracePath.c_str(), F_OK), 0); 221 222 auto ta = std::make_unique<SysTuning::TraceStreamer::TraceStreamerSelector>(); 223 ta->minTs_ = 1502031384794922107; 224 ta->maxTs_ = 1502031423412858932; 225 ParseData(ta, tracePath); 226 EXPECT_TRUE(CheckData(ta, tracePath)); 227 } 228 229 /** 230 * @tc.name: SplitFileDataByPerfTest 231 * @tc.desc: Test htrace parsing binary file export database 232 * @tc.type: FUNC 233 */ 234 HWTEST_F(SplitFileDataTest, SplitFileDataByPerfTest, TestSize.Level1) 235 { 236 TS_LOGI("test43-5"); 237 const std::string tracePath = "../../test/resource/hiprofiler_data_perf.htrace"; 238 ASSERT_EQ(access(tracePath.c_str(), F_OK), 0); 239 240 auto ta = std::make_unique<SysTuning::TraceStreamer::TraceStreamerSelector>(); 241 ta->minTs_ = 30389799963682; 242 ta->maxTs_ = 30408971157414; 243 ParseData(ta, tracePath); 244 EXPECT_TRUE(CheckData(ta, tracePath)); 245 } 246 247 } // namespace TraceStreamer 248 } // namespace SysTuning 249