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 */
HWTEST_F(SplitFileDataTest, SplitFileDataByHtraceTest, TestSize.Level1)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 */
HWTEST_F(SplitFileDataTest, SplitFileDataBySystraceTest, TestSize.Level1)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 */
HWTEST_F(SplitFileDataTest, SplitFileDataByEbpfTest, TestSize.Level1)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 */
HWTEST_F(SplitFileDataTest, SplitFileDataByNativehookTest, TestSize.Level1)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 */
HWTEST_F(SplitFileDataTest, SplitFileDataByPerfTest, TestSize.Level1)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