1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
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 <fstream>
17 #include <gtest/gtest.h>
18 #include <iostream>
19 #include <string>
20 #include <unistd.h>
21 #include <vector>
22
23 #include "common_define.h"
24 #include "common_utils.h"
25 #include "hitrace_cmd.h"
26
27 using namespace testing::ext;
28 using namespace OHOS::HiviewDFX::Hitrace;
29
30 namespace OHOS {
31 namespace HiviewDFX {
32 namespace HitraceTest {
33 class HitraceCMDTest : public testing::Test {
34 public:
SetUpTestCase(void)35 static void SetUpTestCase(void) {}
TearDownTestCase(void)36 static void TearDownTestCase(void)
37 {
38 RunCmd("hitrace --trace_finish_nodump");
39 RunCmd("hitrace --trace_finish --record");
40 RunCmd("hitrace --stop_bgsrv");
41 }
42
SetUp()43 void SetUp()
44 {
45 Reset();
46 originalCoutBuf = std::cout.rdbuf();
47 std::cout.rdbuf(coutBuffer.rdbuf());
48 RunCmd("hitrace --trace_finish_nodump");
49 RunCmd("hitrace --trace_finish --record");
50 RunCmd("hitrace --stop_bgsrv");
51 coutBuffer.str("");
52 }
53
TearDown()54 void TearDown()
55 {
56 std::cout.rdbuf(originalCoutBuf);
57 }
58
GetOutput()59 std::string GetOutput()
60 {
61 std::string output = coutBuffer.str();
62 coutBuffer.str("");
63 return output;
64 }
65
RunCmd(const string & cmd)66 static void RunCmd(const string& cmd)
67 {
68 std::vector<std::string> args;
69 std::stringstream ss(cmd);
70 std::string arg;
71
72 while (ss >> arg) {
73 args.push_back(arg);
74 }
75 std::vector<char*> argv;
76 for (auto& arg : args) {
77 argv.push_back(const_cast<char*>(arg.c_str()));
78 }
79
80 (void)HiTraceCMDTestMain(static_cast<int>(args.size()), argv.data());
81 Reset();
82 }
83
CheckTraceCommandOutput(const string & cmd,const std::vector<std::string> & keywords)84 bool CheckTraceCommandOutput(const string& cmd, const std::vector<std::string>& keywords)
85 {
86 RunCmd(cmd);
87
88 std::string output = GetOutput();
89 int matchNum = 0;
90 for (auto& keyword : keywords) {
91 if (output.find(keyword) == std::string::npos) {
92 GTEST_LOG_(INFO) << "command:" << cmd;
93 GTEST_LOG_(INFO) << "command output:" << output;
94 break;
95 } else {
96 matchNum++;
97 }
98 }
99 return matchNum == keywords.size();
100 }
101 private:
102 std::streambuf* originalCoutBuf;
103 std::stringstream coutBuffer;
104 };
105
106 namespace {
ReadBufferSizeKB()107 std::string ReadBufferSizeKB()
108 {
109 std::ifstream file(TRACEFS_DIR + "buffer_size_kb");
110 if (!file.is_open()) {
111 GTEST_LOG_(ERROR) << "Failed to open buffer_size_kb";
112 return "Unknown";
113 }
114 std::string line;
115 if (std::getline(file, line)) {
116 GTEST_LOG_(INFO) << "Reading buffer_size_kb: " << line;
117 return line;
118 }
119 return "Unknown";
120 }
121 }
122
123 /**
124 * @tc.name: HitraceCMDTest001
125 * @tc.desc: test --trace_level command with correct parameters
126 * @tc.type: FUNC
127 */
128 HWTEST_F(HitraceCMDTest, HitraceCMDTest001, TestSize.Level1)
129 {
130 GTEST_LOG_(INFO) << "HitraceCMDTest001: start.";
131
132 std::string cmd = "hitrace --trace_level I";
133 std::vector<std::string> keywords = {
134 "SET_TRACE_LEVEL",
135 "success to set trace level",
136 };
137 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
138
139 GTEST_LOG_(INFO) << "HitraceCMDTest001: end.";
140 }
141
142 /**
143 * @tc.name: HitraceCMDTest002
144 * @tc.desc: test --trace_level command with wrong parameters
145 * @tc.type: FUNC
146 */
147 HWTEST_F(HitraceCMDTest, HitraceCMDTest002, TestSize.Level1)
148 {
149 GTEST_LOG_(INFO) << "HitraceCMDTest002: start.";
150
151 std::string cmd = "hitrace --trace_level K";
152 std::vector<std::string> keywords = {
153 "error: trace level is illegal input",
154 "parsing args failed",
155 };
156 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
157
158 GTEST_LOG_(INFO) << "HitraceCMDTest002: end.";
159 }
160
161 /**
162 * @tc.name: HitraceCMDTest003
163 * @tc.desc: test --get_level command when the value of level is normal
164 * @tc.type: FUNC
165 */
166 HWTEST_F(HitraceCMDTest, HitraceCMDTest003, TestSize.Level1)
167 {
168 GTEST_LOG_(INFO) << "HitraceCMDTest003: start.";
169
170 std::string cmd = "hitrace --trace_level I";
171 std::vector<std::string> keywords = {
172 "SET_TRACE_LEVEL",
173 "success to set trace level",
174 };
175 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
176
177 cmd = "hitrace --get_level";
178 keywords = {
179 "GET_TRACE_LEVEL",
180 "the current trace level threshold is Info",
181 };
182 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
183
184 GTEST_LOG_(INFO) << "HitraceCMDTest003: end.";
185 }
186
187 /**
188 * @tc.name: HitraceCMDTest004
189 * @tc.desc: test --get_level command when the value of level is abnormal
190 * @tc.type: FUNC
191 */
192 HWTEST_F(HitraceCMDTest, HitraceCMDTest004, TestSize.Level1)
193 {
194 GTEST_LOG_(INFO) << "HitraceCMDTest004: start.";
195
196 constexpr int invalidLevel = -1;
197 ASSERT_TRUE(SetPropertyInner(TRACE_LEVEL_THRESHOLD, std::to_string(invalidLevel)));
198
199 std::string cmd = "hitrace --get_level";
200 std::vector<std::string> keywords = {
201 "GET_TRACE_LEVEL",
202 "error: get trace level threshold failed, level(-1) cannot be parsed",
203 };
204 EXPECT_TRUE(CheckTraceCommandOutput(cmd, keywords));
205
206 constexpr int infoLevel = 1;
207 ASSERT_TRUE(SetPropertyInner(TRACE_LEVEL_THRESHOLD, std::to_string(infoLevel)));
208
209 GTEST_LOG_(INFO) << "HitraceCMDTest004: end.";
210 }
211
212 /**
213 * @tc.name: HitraceCMDTest005
214 * @tc.desc: test the normal custom buffer size in recording mode
215 * @tc.type: FUNC
216 */
217 HWTEST_F(HitraceCMDTest, HitraceCMDTest005, TestSize.Level1)
218 {
219 GTEST_LOG_(INFO) << "HitraceCMDTest005: start.";
220
221 std::string cmd = "hitrace --trace_begin --record sched -b 102400";
222 std::vector<std::string> keywords = {
223 "RECORDING_LONG_BEGIN_RECORD",
224 "tags:sched",
225 "bufferSize:102400",
226 "trace capturing",
227 };
228 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
229 ASSERT_EQ(ReadBufferSizeKB(), IsHmKernel() ? "102400" : "102402");
230
231 GTEST_LOG_(INFO) << "HitraceCMDTest005: end.";
232 }
233
234 /**
235 * @tc.name: HitraceCMDTest006
236 * @tc.desc: test the lower limit of the custom buffer size in recording mode in hm kernel: [256, 1048576]
237 * @tc.type: FUNC
238 */
239 HWTEST_F(HitraceCMDTest, HitraceCMDTest006, TestSize.Level1)
240 {
241 GTEST_LOG_(INFO) << "HitraceCMDTest006: start.";
242
243 if (IsHmKernel()) {
244 std::string cmd = "hitrace --trace_begin --record sched -b 255";
245 std::vector<std::string> keywords = {
246 "buffer size must be from 256 KB to 1024 MB",
247 "parsing args failed, exit",
248 };
249 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
250
251 cmd = "hitrace --trace_begin --record sched -b 256";
252 keywords = {
253 "RECORDING_LONG_BEGIN_RECORD",
254 "tags:sched",
255 "bufferSize:256",
256 "trace capturing",
257 };
258 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
259 ASSERT_EQ(ReadBufferSizeKB(), "512");
260 }
261
262 GTEST_LOG_(INFO) << "HitraceCMDTest006: end.";
263 }
264
265 /**
266 * @tc.name: HitraceCMDTest007
267 * @tc.desc: test the upper limit of the custom buffer size in recording mode in hm kernel: [256, 1048576]
268 * @tc.type: FUNC
269 */
270 HWTEST_F(HitraceCMDTest, HitraceCMDTest007, TestSize.Level1)
271 {
272 GTEST_LOG_(INFO) << "HitraceCMDTest007: start.";
273
274 if (IsHmKernel()) {
275 std::string cmd = "hitrace --trace_begin --record sched -b 1048577";
276 std::vector<std::string> keywords = {
277 "buffer size must be from 256 KB to 1024 MB",
278 "parsing args failed, exit",
279 };
280 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
281
282 cmd = "hitrace --trace_begin --record sched -b 1048576";
283 keywords = {
284 "RECORDING_LONG_BEGIN_RECORD",
285 "tags:sched",
286 "bufferSize:1048576",
287 "trace capturing",
288 };
289 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
290 ASSERT_EQ(ReadBufferSizeKB(), "1048576");
291 }
292
293 GTEST_LOG_(INFO) << "HitraceCMDTest007: end.";
294 }
295
296 /**
297 * @tc.name: HitraceCMDTest008
298 * @tc.desc: test the lower limit of the custom buffer size in recording mode in linux kernel:[256, 307200]
299 * @tc.type: FUNC
300 */
301 HWTEST_F(HitraceCMDTest, HitraceCMDTest008, TestSize.Level1)
302 {
303 GTEST_LOG_(INFO) << "HitraceCMDTest008: start.";
304
305 if (!IsHmKernel()) {
306 std::string cmd = "hitrace --trace_begin --record sched -b 255";
307 std::vector<std::string> keywords = {
308 "buffer size must be from 256 KB to 300 MB",
309 "parsing args failed, exit",
310 };
311 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
312
313 cmd = "hitrace --trace_begin --record sched -b 256";
314 keywords = {
315 "RECORDING_LONG_BEGIN_RECORD",
316 "tags:sched",
317 "bufferSize:256",
318 "trace capturing",
319 };
320 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
321 ASSERT_EQ(ReadBufferSizeKB(), "258");
322 }
323
324 GTEST_LOG_(INFO) << "HitraceCMDTest008: end.";
325 }
326
327 /**
328 * @tc.name: HitraceCMDTest009
329 * @tc.desc: test the upper limit of the custom buffer size in recording mode in linux kernel:[256, 307200]
330 * @tc.type: FUNC
331 */
332 HWTEST_F(HitraceCMDTest, HitraceCMDTest009, TestSize.Level1)
333 {
334 GTEST_LOG_(INFO) << "HitraceCMDTest009: start.";
335
336 if (!IsHmKernel()) {
337 std::string cmd = "hitrace --trace_begin --record sched -b 307201";
338 std::vector<std::string> keywords = {
339 "buffer size must be from 256 KB to 300 MB",
340 "parsing args failed, exit",
341 };
342 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
343
344 cmd = "hitrace --trace_begin --record sched -b 307200";
345 keywords = {
346 "RECORDING_LONG_BEGIN_RECORD",
347 "tags:sched",
348 "bufferSize",
349 "trace capturing",
350 };
351 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
352 }
353
354 GTEST_LOG_(INFO) << "HitraceCMDTest009: end.";
355 }
356
357 /**
358 * @tc.name: HitraceCMDTest010
359 * @tc.desc: test the abnormal custom buffer size in recording mode
360 * @tc.type: FUNC
361 */
362 HWTEST_F(HitraceCMDTest, HitraceCMDTest010, TestSize.Level1)
363 {
364 GTEST_LOG_(INFO) << "HitraceCMDTest010: start.";
365
366 std::string cmd = "hitrace --trace_begin ace -b abc";
367 std::vector<std::string> keywords = {
368 "buffer size is illegal input",
369 "parsing args failed, exit",
370 };
371 ASSERT_TRUE(CheckTraceCommandOutput(cmd, keywords));
372
373 GTEST_LOG_(INFO) << "HitraceCMDTest010: end.";
374 }
375 }
376 }
377 }
378