1 /*
2 * Copyright (C) 2024 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 #include "hitrace_dump.h"
16
17 #include <fstream>
18 #include <gtest/gtest.h>
19 #include <iostream>
20 #include <string>
21 #include <unistd.h>
22 #include <vector>
23
24 #include "common_define.h"
25 #include "common_utils.h"
26 #include "test_utils.h"
27 #include "securec.h"
28
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace Hitrace {
32 using namespace testing::ext;
33 namespace {
34 const int TIME_COUNT = 10000;
35 const int CMD_OUTPUT_BUF = 1024;
36 const int BYTE_PER_MB = 1024 * 1024;
37 constexpr uint64_t S_TO_MS = 1000;
38 const std::string TRACE_SNAPSHOT_PREFIX = "trace_";
39 const std::string TRACE_RECORDING_PREFIX = "record_trace_";
40 const std::string TRACE_CACHE_PREFIX = "cache_trace_";
41 struct FileWithInfo {
42 std::string filename;
43 time_t ctime;
44 uint64_t fileSize;
45 uint64_t duration;
46 };
47 enum TRACE_TYPE : uint8_t {
48 TRACE_SNAPSHOT = 0,
49 TRACE_RECORDING = 1,
50 TRACE_CACHE = 2,
51 };
52 std::map<TRACE_TYPE, std::string> tracePrefixMap = {
53 {TRACE_SNAPSHOT, TRACE_SNAPSHOT_PREFIX},
54 {TRACE_RECORDING, TRACE_RECORDING_PREFIX},
55 {TRACE_CACHE, TRACE_CACHE_PREFIX},
56 };
57 }
58 class HitraceSystemTest : public testing::Test {
59 public:
SetUpTestCase(void)60 static void SetUpTestCase(void) {}
TearDownTestCase(void)61 static void TearDownTestCase(void)
62 {
63 ASSERT_TRUE(RunCmd("hitrace --trace_finish_nodump"));
64 ASSERT_TRUE(RunCmd("hitrace --trace_finish --record"));
65 ASSERT_TRUE(RunCmd("hitrace --stop_bgsrv"));
66 }
67
SetUp()68 void SetUp()
69 {
70 ASSERT_TRUE(RunCmd("hitrace --trace_finish_nodump"));
71 ASSERT_TRUE(RunCmd("hitrace --trace_finish --record"));
72 ASSERT_TRUE(RunCmd("hitrace --stop_bgsrv"));
73 }
TearDown()74 void TearDown() {}
75
RunCmd(const string & cmdstr)76 static bool RunCmd(const string& cmdstr)
77 {
78 if (cmdstr.empty()) {
79 return false;
80 }
81 FILE *fp = popen(cmdstr.c_str(), "r");
82 if (fp == nullptr) {
83 return false;
84 }
85 char res[CMD_OUTPUT_BUF] = { '\0' };
86 while (fgets(res, sizeof(res), fp) != nullptr) {
87 std::cout << res;
88 }
89 pclose(fp);
90 return true;
91 }
92 };
93
94 namespace {
CheckTraceCommandOutput(const std::string & cmd,const std::vector<std::string> & keywords,std::vector<std::string> & traceLists)95 bool CheckTraceCommandOutput(const std::string& cmd, const std::vector<std::string>& keywords,
96 std::vector<std::string>& traceLists)
97 {
98 if (cmd.empty()) {
99 return false;
100 }
101 FILE* fp = popen(cmd.c_str(), "r");
102 if (fp == nullptr) {
103 return false;
104 }
105
106 char buffer[CMD_OUTPUT_BUF];
107 int checkIdx = 0;
108 while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
109 while (checkIdx < keywords.size() && strstr(buffer, keywords[checkIdx].c_str()) != nullptr) {
110 GTEST_LOG_(INFO) << "match keyword :" << keywords[checkIdx];
111 checkIdx++;
112 if (checkIdx == keywords.size()) {
113 break;
114 }
115 }
116 char* tracefile = strstr(buffer, TRACE_FILE_DEFAULT_DIR.c_str());
117 tracefile += TRACE_FILE_DEFAULT_DIR.length();
118 if (tracefile != nullptr) {
119 tracefile[strcspn(tracefile, "\n")] = '\0'; // replace "\n" with "\0"
120 GTEST_LOG_(INFO) << "match trace file : " << tracefile;
121 traceLists.push_back(std::string(tracefile));
122 }
123 }
124
125 pclose(fp);
126 if (checkIdx < keywords.size()) {
127 GTEST_LOG_(ERROR) << "Failed to match keyword : " << keywords[checkIdx];
128 }
129 return checkIdx == keywords.size();
130 }
131
IsTracingOn()132 bool IsTracingOn()
133 {
134 std::ifstream tracingOnFile(TRACEFS_DIR + TRACING_ON_NODE);
135 if (!tracingOnFile.is_open()) {
136 std::cout << "Failed to open /sys/kernel/tracing/tracing_on." << std::endl;
137 return false;
138 }
139 std::string content;
140 getline(tracingOnFile, content);
141 tracingOnFile.close();
142 return content == "1";
143 }
144
IsFileIncludeAllKeyWords(const string & fileName,const std::vector<std::string> & keywords)145 bool IsFileIncludeAllKeyWords(const string& fileName, const std::vector<std::string>& keywords)
146 {
147 std::ifstream readFile;
148 readFile.open(fileName.c_str(), std::ios::in);
149 if (readFile.fail()) {
150 GTEST_LOG_(ERROR) << "Failed to open file " << fileName;
151 return false;
152 }
153 int keywordIdx = 0;
154 std::string readLine;
155 while (getline(readFile, readLine, '\n') && keywordIdx < keywords.size()) {
156 if (readLine.find(keywords[keywordIdx]) == std::string::npos) {
157 continue;
158 }
159 keywordIdx++;
160 }
161 readFile.close();
162 if (keywordIdx < keywords.size()) {
163 GTEST_LOG_(ERROR) << "Failed to find keyword: " << keywords[keywordIdx];
164 }
165 return keywordIdx == keywords.size();
166 }
167
IsFileExcludeAllKeyWords(const string & fileName,const std::vector<std::string> & keywords)168 bool IsFileExcludeAllKeyWords(const string& fileName, const std::vector<std::string>& keywords)
169 {
170 std::ifstream readFile;
171 readFile.open(fileName.c_str(), std::ios::in);
172 if (readFile.fail()) {
173 GTEST_LOG_(ERROR) << "Failed to open file " << fileName;
174 return false;
175 }
176 std::string readLine;
177 while (getline(readFile, readLine, '\n')) {
178 for (auto& word : keywords) {
179 if (readLine.find(word) != std::string::npos) {
180 GTEST_LOG_(ERROR) << "File contained keyword: " << word;
181 readFile.close();
182 return false;
183 }
184 }
185 }
186 readFile.close();
187 return true;
188 }
189
ReadBufferSizeKB()190 std::string ReadBufferSizeKB()
191 {
192 std::ifstream file(TRACEFS_DIR + "buffer_size_kb");
193 if (!file.is_open()) {
194 GTEST_LOG_(ERROR) << "Failed to open buffer_size_kb";
195 return "Unknown";
196 }
197 std::string line;
198 if (std::getline(file, line)) {
199 GTEST_LOG_(INFO) << "Reading buffer_size_kb: " << line;
200 return line;
201 }
202 return "Unknown";
203 }
204
GetDurationFromFileName(const std::string & fileName,uint64_t & duration)205 bool GetDurationFromFileName(const std::string& fileName, uint64_t& duration)
206 {
207 auto index = fileName.find("-");
208 if (index == std::string::npos) {
209 return false;
210 }
211 uint32_t number;
212 if (sscanf_s(fileName.substr(index, fileName.size() - index).c_str(), "-%u.sys", &number) != 1) {
213 GTEST_LOG_(INFO) << "sscanf_s failed.";
214 return false;
215 }
216 duration = static_cast<uint64_t>(number);
217 return true;
218 }
219
GetFileInfo(const TRACE_TYPE & traceType,const std::vector<std::string> & outputFiles,std::vector<FileWithInfo> & fileList)220 bool GetFileInfo(const TRACE_TYPE& traceType, const std::vector<std::string>& outputFiles,
221 std::vector<FileWithInfo>& fileList)
222 {
223 struct stat fileStat;
224 for (auto i = 0; i < outputFiles.size(); i++) {
225 if (outputFiles[i].substr(TRACE_FILE_DEFAULT_DIR.size(), tracePrefixMap[traceType].size()) ==
226 tracePrefixMap[traceType]) {
227 uint64_t duration = 0;
228 if (GetDurationFromFileName(outputFiles[i].substr(TRACE_FILE_DEFAULT_DIR.size(),
229 outputFiles[i].size() - TRACE_FILE_DEFAULT_DIR.size()), duration)) {
230 if (stat(outputFiles[i].c_str(), &fileStat) == 0) {
231 fileList.push_back({outputFiles[i], fileStat.st_ctime, static_cast<uint64_t>(fileStat.st_size),
232 duration});
233 } else {
234 GTEST_LOG_(INFO) << "stat file failed, file is " << outputFiles[i].c_str();
235 return false;
236 }
237 } else {
238 GTEST_LOG_(INFO) << "GetDurationFromFileName failed, file is " << outputFiles[i].c_str();
239 return false;
240 }
241 }
242 }
243 std::sort(fileList.begin(), fileList.end(), [](const FileWithInfo& a, const FileWithInfo& b) {
244 return a.ctime < b.ctime;
245 });
246 return true;
247 }
248
GetTraceFilesInDir(const TRACE_TYPE & traceType)249 std::vector<std::string> GetTraceFilesInDir(const TRACE_TYPE& traceType)
250 {
251 std::vector<std::string> fileVec;
252 for (const auto &entry : std::filesystem::directory_iterator(TRACE_FILE_DEFAULT_DIR)) {
253 if (!entry.is_regular_file()) {
254 continue;
255 }
256 std::string fileName = entry.path().filename().string();
257 if (fileName.substr(0, tracePrefixMap[traceType].size()) == tracePrefixMap[traceType]) {
258 fileVec.push_back(TRACE_FILE_DEFAULT_DIR + fileName);
259 }
260 }
261 return fileVec;
262 }
263
264 /**
265 * @tc.name: HitraceSystemTest001
266 * @tc.desc: when excute hitrace record command, check tracing_on switcher status
267 * @tc.type: FUNC
268 */
269 HWTEST_F(HitraceSystemTest, HitraceSystemTest001, TestSize.Level2)
270 {
271 ASSERT_TRUE(RunCmd("hitrace --trace_begin ace"));
272 int testCnt = TIME_COUNT;
273 while (testCnt > 0) {
274 usleep(10);
275 ASSERT_TRUE(IsTracingOn()) << "tracing_on switcher status is not 1";
276 testCnt--;
277 }
278 ASSERT_TRUE(RunCmd("hitrace --trace_finish_nodump"));
279 }
280
281 /**
282 * @tc.name: HitraceSystemTest003
283 * @tc.desc: when excute hitrace record command, check record file aging rules.
284 * @tc.type: FUNC
285 */
286 HWTEST_F(HitraceSystemTest, HitraceSystemTest003, TestSize.Level2)
287 {
288 if (IsRootVersion()) {
289 const int recordCnt = 20;
290 for (int i = 0; i < recordCnt; ++i) {
291 ASSERT_TRUE(RunCmd("hitrace --trace_begin --record sched"));
292 ASSERT_TRUE(RunCmd("hitrace --trace_finish --record"));
293 }
294 int filecnt = CountRecordingTraceFile();
295 GTEST_LOG_(INFO) << "Filecnt: " << filecnt;
296 ASSERT_GE(filecnt, recordCnt);
297 }
298 }
299
300 /**
301 * @tc.name: SnapShotModeTest001
302 * @tc.desc: test open snapshot mode
303 * @tc.type: FUNC
304 */
305 HWTEST_F(HitraceSystemTest, SnapShotModeTest001, TestSize.Level1)
306 {
307 std::vector<std::string> traceLists = {};
308 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --start_bgsrv", {"SNAPSHOT_START", "OpenSnapshot done"}, traceLists));
309 ASSERT_TRUE(traceLists.empty());
310 }
311
312 /**
313 * @tc.name: SnapShotModeTest002
314 * @tc.desc: test open snapshot mode duplicately
315 * @tc.type: FUNC
316 */
317 HWTEST_F(HitraceSystemTest, SnapShotModeTest002, TestSize.Level1)
318 {
319 ASSERT_TRUE(RunCmd("hitrace --start_bgsrv"));
320 std::vector<std::string> traceLists = {};
321 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --start_bgsrv",
322 {"SNAPSHOT_START", "OpenSnapshot failed", "errorCode(1013)"}, traceLists));
323 ASSERT_TRUE(traceLists.empty());
324 }
325
326 /**
327 * @tc.name: SnapShotModeTest003
328 * @tc.desc: test close snapshot mode
329 * @tc.type: FUNC
330 */
331 HWTEST_F(HitraceSystemTest, SnapShotModeTest003, TestSize.Level1)
332 {
333 ASSERT_TRUE(RunCmd("hitrace --start_bgsrv"));
334 std::vector<std::string> traceLists = {};
335 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --stop_bgsrv", {"SNAPSHOT_STOP", "CloseSnapshot done"}, traceLists));
336 ASSERT_TRUE(traceLists.empty());
337 }
338
339 /**
340 * @tc.name: SnapShotModeTest004
341 * @tc.desc: test close snapshot mode duplicately
342 * @tc.type: FUNC
343 */
344 HWTEST_F(HitraceSystemTest, SnapShotModeTest004, TestSize.Level2)
345 {
346 ASSERT_TRUE(RunCmd("hitrace --start_bgsrv"));
347 ASSERT_TRUE(RunCmd("hitrace --stop_bgsrv"));
348 std::vector<std::string> traceLists = {};
349 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --stop_bgsrv", {"SNAPSHOT_STOP", "CloseSnapshot done"}, traceLists));
350 ASSERT_TRUE(traceLists.empty());
351 }
352
353 /**
354 * @tc.name: SnapShotModeTest005
355 * @tc.desc: test dump snapshot trace
356 * @tc.type: FUNC
357 */
358 HWTEST_F(HitraceSystemTest, SnapShotModeTest005, TestSize.Level1)
359 {
360 ASSERT_TRUE(RunCmd("hitrace --start_bgsrv"));
361 std::vector<std::string> traceLists = {};
362 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --dump_bgsrv", {"SNAPSHOT_DUMP", "DumpSnapshot done"}, traceLists));
363 ASSERT_FALSE(traceLists.empty());
364 ASSERT_TRUE(RunCmd("hitrace --stop_bgsrv"));
365 }
366
367 /**
368 * @tc.name: SnapShotModeTest006
369 * @tc.desc: test dump snapshot trace when snapshot mode not open
370 * @tc.type: FUNC
371 */
372 HWTEST_F(HitraceSystemTest, SnapShotModeTest006, TestSize.Level1)
373 {
374 std::vector<std::string> traceLists = {};
375 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --dump_bgsrv",
376 {"SNAPSHOT_DUMP", "DumpSnapshot failed", "errorCode(1012)"}, traceLists));
377 ASSERT_TRUE(traceLists.empty());
378 }
379
380 /**
381 * @tc.name: SnapShotModeTest007
382 * @tc.desc: test dump snapshot trace twice within 30s offset
383 * @tc.type: FUNC
384 */
385 HWTEST_F(HitraceSystemTest, SnapShotModeTest007, TestSize.Level1)
386 {
387 ASSERT_TRUE(RunCmd("hitrace --start_bgsrv"));
388 sleep(30);
389 std::vector<std::string> traceLists1 = {};
390 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --dump_bgsrv", {"SNAPSHOT_DUMP", "DumpSnapshot done"}, traceLists1));
391 ASSERT_FALSE(traceLists1.empty());
392 sleep(10); // 10 : sleep 10 seconds
393 std::vector<std::string> traceLists2 = {};
394 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --dump_bgsrv", {"SNAPSHOT_DUMP", "DumpSnapshot done"}, traceLists2));
395 ASSERT_FALSE(traceLists2.empty());
396 for (const auto& tracefile : traceLists1) {
397 ASSERT_NE(std::find(traceLists2.begin(), traceLists2.end(), tracefile), traceLists2.end());
398 }
399 ASSERT_TRUE(RunCmd("hitrace --stop_bgsrv"));
400 }
401
402 /**
403 * @tc.name: SnapShotModeTest008
404 * @tc.desc: test dump snapshot trace twice with 30s offset
405 * @tc.type: FUNC
406 */
407 HWTEST_F(HitraceSystemTest, SnapShotModeTest008, TestSize.Level1)
408 {
409 ASSERT_TRUE(RunCmd("hitrace --start_bgsrv"));
410 std::vector<std::string> traceLists1 = {};
411 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --dump_bgsrv", {"SNAPSHOT_DUMP", "DumpSnapshot done"}, traceLists1));
412 ASSERT_FALSE(traceLists1.empty());
413 sleep(31); // 31 : sleep 32 seconds, 1s is tolorance
414 std::vector<std::string> traceLists2 = {};
415 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --dump_bgsrv", {"SNAPSHOT_DUMP", "DumpSnapshot done"}, traceLists2));
416 ASSERT_FALSE(traceLists2.empty());
417 for (const auto& tracefile : traceLists1) {
418 ASSERT_EQ(std::find(traceLists2.begin(), traceLists2.end(), tracefile), traceLists2.end());
419 }
420 ASSERT_TRUE(RunCmd("hitrace --stop_bgsrv"));
421 }
422
423 /**
424 * @tc.name: SnapShotModeTest009
425 * @tc.desc: test dump snapshot trace with 20 files aging
426 * @tc.type: FUNC
427 */
428 HWTEST_F(HitraceSystemTest, SnapShotModeTest009, TestSize.Level1)
429 {
430 ASSERT_TRUE(RunCmd("hitrace --start_bgsrv"));
431 const int snapshotFileAge = 20;
432 for (int i = 0; i < snapshotFileAge; ++i) {
433 ASSERT_TRUE(RunCmd("hitrace --dump_bgsrv"));
434 sleep(1); // wait 1s
435 }
436 std::vector<std::string> traceLists = {};
437 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --dump_bgsrv", {"SNAPSHOT_DUMP", "DumpSnapshot done"}, traceLists));
438 ASSERT_GE(traceLists.size(), snapshotFileAge);
439 ASSERT_TRUE(RunCmd("hitrace --stop_bgsrv"));
440 int filecnt = CountSnapShotTraceFile();
441 GTEST_LOG_(INFO) << "Filecnt: " << filecnt;
442 ASSERT_LE(filecnt, snapshotFileAge);
443 }
444
445 /**
446 * @tc.name: SnapShotModeTest010
447 * @tc.desc: test dump snapshot trace with 20 files aging
448 * @tc.type: FUNC
449 */
450 HWTEST_F(HitraceSystemTest, SnapShotModeTest010, TestSize.Level1)
451 {
452 ASSERT_TRUE(RunCmd("hitrace --start_bgsrv"));
453 const int dumpCnt = 30; // 30 : dump 30 times
454 for (int i = 0; i < dumpCnt; ++i) {
455 ASSERT_TRUE(RunCmd("hitrace --dump_bgsrv"));
456 }
457 const int snapshotFileAge = 20;
458 std::vector<std::string> traceLists = {};
459 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --dump_bgsrv", {"SNAPSHOT_DUMP", "DumpSnapshot done"}, traceLists));
460 ASSERT_GE(traceLists.size(), snapshotFileAge);
461 ASSERT_TRUE(RunCmd("hitrace --stop_bgsrv"));
462 std::vector<std::string> dirTraceLists = {};
463 GetSnapShotTraceFileList(dirTraceLists);
464 ASSERT_LE(dirTraceLists.size(), snapshotFileAge);
465 for (int i = 0; i < dirTraceLists.size(); ++i) {
466 ASSERT_NE(std::find(traceLists.begin(), traceLists.end(), dirTraceLists[i]), traceLists.end()) <<
467 "not found: " << dirTraceLists[i];
468 }
469 }
470
471 /**
472 * @tc.name: SnapShotModeTest011
473 * @tc.desc: test open snapshot mode can not be opened when reocording mode was opened.
474 * @tc.type: FUNC
475 */
476 HWTEST_F(HitraceSystemTest, SnapShotModeTest011, TestSize.Level1)
477 {
478 ASSERT_TRUE(RunCmd("hitrace --trace_begin --record ohos"));
479 std::vector<std::string> traceLists = {};
480 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --start_bgsrv",
481 {"SNAPSHOT_START", "OpenSnapshot failed", "errorCode(1013)"}, traceLists));
482 ASSERT_TRUE(traceLists.empty());
483 ASSERT_TRUE(RunCmd("hitrace --trace_finish --record"));
484 }
485
486 /**
487 * @tc.name: CacheModeTest001
488 * @tc.desc: test dumptrace when cache trace was opened.
489 * @tc.type: FUNC
490 */
491 HWTEST_F(HitraceSystemTest, CacheModeTest001, TestSize.Level1)
492 {
493 const std::vector<std::string> tagGroups = {"default"};
494 ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
495 // total cache filesize limit: 800MB, sliceduration: 20s
496 ASSERT_TRUE(CacheTraceOn(800, 5) == TraceErrorCode::SUCCESS);
497 sleep(8); // wait 8s
498 TraceRetInfo ret = DumpTrace();
499 ASSERT_EQ(ret.errorCode, TraceErrorCode::SUCCESS);
500 std::vector<FileWithInfo> fileList;
501 ASSERT_TRUE(GetFileInfo(TRACE_CACHE, ret.outputFiles, fileList));
502 ASSERT_GE(fileList.size(), 2); // cache_trace_ file count > 2
503 uint64_t totalDuartion = 0;
504 for (auto i = 0; i < fileList.size(); i++) {
505 GTEST_LOG_(INFO) << "file: " << fileList[i].filename.c_str() << ", size: " << fileList[i].fileSize
506 << ", duration:" << fileList[i].duration;
507 ASSERT_LE(fileList[i].fileSize, 17 * BYTE_PER_MB); // 17: single cache trace file max size limit(MB)
508 totalDuartion += fileList[i].duration;
509 ASSERT_TRUE(IsFileIncludeAllKeyWords(fileList[i].filename, {"name: sched_wakeup"}));
510 }
511 totalDuartion /= S_TO_MS;
512 ASSERT_GE(totalDuartion, 7); // total trace duration over 7s, given 1 second of tolerance
513 ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
514 }
515
516 /**
517 * @tc.name: CacheModeTest002
518 * @tc.desc: test dumptrace when cache trace was closed.
519 * @tc.type: FUNC
520 */
521 HWTEST_F(HitraceSystemTest, CacheModeTest002, TestSize.Level1)
522 {
523 const std::vector<std::string> tagGroups = {"default"};
524 TraceErrorCode retCode = OpenTrace(tagGroups);
525 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
526 // total cache filesize limit: 800MB, sliceduration: 20s
527 retCode = CacheTraceOn(800, 5);
528 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
529 sleep(8); // wait 8s
530 retCode = CacheTraceOff();
531 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
532 sleep(2); // wait 2s
533 TraceRetInfo ret = DumpTrace();
534 ASSERT_EQ(ret.errorCode, TraceErrorCode::SUCCESS);
535 std::vector<FileWithInfo> cacheFileList;
536 std::vector<FileWithInfo> traceFileList;
537 ASSERT_TRUE(GetFileInfo(TRACE_CACHE, ret.outputFiles, cacheFileList));
538 ASSERT_TRUE(GetFileInfo(TRACE_SNAPSHOT, ret.outputFiles, traceFileList));
539 uint64_t totalDuartion = 0;
540 ASSERT_GE(cacheFileList.size(), 2); // cache_trace_ file count > 2
541 for (auto i = 0; i < cacheFileList.size(); i++) {
542 GTEST_LOG_(INFO) << "file: " << cacheFileList[i].filename.c_str() << ", size: " << cacheFileList[i].fileSize
543 << ", duration:" << cacheFileList[i].duration;
544 ASSERT_LE(cacheFileList[i].fileSize, 17 * BYTE_PER_MB); // 17: single cache trace file max size limit(MB)
545 totalDuartion += cacheFileList[i].duration;
546 ASSERT_TRUE(IsFileIncludeAllKeyWords(cacheFileList[i].filename, {"name: sched_wakeup"}));
547 }
548 ASSERT_GE(traceFileList.size(), 1); // cache_trace_ file count > 1
549 for (auto i = 0; i < traceFileList.size(); i++) {
550 GTEST_LOG_(INFO) << "file: " << traceFileList[i].filename.c_str() << ", size: " << traceFileList[i].fileSize
551 << ", duration:" << traceFileList[i].duration;
552 totalDuartion += traceFileList[i].duration;
553 ASSERT_TRUE(IsFileIncludeAllKeyWords(traceFileList[i].filename, {"name: sched_wakeup"}));
554 }
555 totalDuartion /= S_TO_MS;
556 ASSERT_GE(totalDuartion, 10); // total trace duration over 10s
557 ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
558 }
559
560 /**
561 * @tc.name: CacheModeTest003
562 * @tc.desc: Test aging cache trace file when OpenTrace over 30s.
563 * @tc.type: FUNC
564 */
565 HWTEST_F(HitraceSystemTest, CacheModeTest003, TestSize.Level0)
566 {
567 const std::vector<std::string> tagGroups = {"default"};
568 TraceErrorCode retCode = OpenTrace(tagGroups);
569 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
570 // total cache filesize limit: 800MB, sliceduration: 5s
571 retCode = CacheTraceOn(800, 5);
572 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
573 sleep(8); // wait 8s
574 retCode = CloseTrace();
575 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
576 sleep(30); // wait 30s: start aging file
577 retCode = OpenTrace(tagGroups);
578 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
579 ASSERT_EQ(GetTraceFilesInDir(TRACE_CACHE).size(), 0); // no cache trace file
580 retCode = CloseTrace();
581 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
582 }
583
584 /**
585 * @tc.name: CacheModeTest004
586 * @tc.desc: Test aging cache trace file when file size overflow
587 * @tc.type: FUNC
588 */
589 HWTEST_F(HitraceSystemTest, CacheModeTest004, TestSize.Level0)
590 {
591 const std::vector<std::string> tagGroups = {"default"};
592 TraceErrorCode retCode = OpenTrace(tagGroups);
593 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
594 // total cache filesize limit: 5MB, sliceduration: 2s
595 retCode = CacheTraceOn(5, 2);
596 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
597 sleep(10); // wait 10s
598 retCode = CacheTraceOff();
599 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
600 std::vector<std::string> fileVec = GetTraceFilesInDir(TRACE_CACHE);
601 std::vector<FileWithInfo> cacheFileList;
602 ASSERT_TRUE(GetFileInfo(TRACE_CACHE, fileVec, cacheFileList));
603 uint64_t totalFileSize = 0;
604 for (auto i = 0; i < cacheFileList.size(); i++) {
605 GTEST_LOG_(INFO) << "file: " << cacheFileList[i].filename.c_str() << ", size: " << cacheFileList[i].fileSize;
606 totalFileSize += cacheFileList[i].fileSize;
607 }
608 ASSERT_LT(totalFileSize, 6 * BYTE_PER_MB); // aging file in 5MB - 6MB
609 retCode = CloseTrace();
610 ASSERT_EQ(retCode, TraceErrorCode::SUCCESS) << "errorCode: " << static_cast<int>(retCode);
611 }
612
613 /**
614 * @tc.name: RecordingModeTest001
615 * @tc.desc: test open recording mode with sched tag
616 * @tc.type: FUNC
617 */
618 HWTEST_F(HitraceSystemTest, RecordingModeTest001, TestSize.Level1)
619 {
620 std::vector<std::string> traceLists = {};
621 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched",
622 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:18432", "trace capturing"}, traceLists));
623 ASSERT_TRUE(traceLists.empty());
624 ASSERT_TRUE(IsFileIncludeAllKeyWords(TRACE_FILE_DEFAULT_DIR + TRACE_SAVED_EVENTS_FORMAT,
625 {"name: print", "name: sched_wakeup", "name: sched_switch"}));
626 ASSERT_TRUE(IsFileExcludeAllKeyWords(TRACE_FILE_DEFAULT_DIR + TRACE_SAVED_EVENTS_FORMAT,
627 {"name: binder_transaction", "name: binder_transaction_received"}));
628 }
629
630 /**
631 * @tc.name: RecordingModeTest002
632 * @tc.desc: test open recording mode twice, the recording mode should be closed
633 * @tc.type: FUNC
634 */
635 HWTEST_F(HitraceSystemTest, RecordingModeTest002, TestSize.Level2)
636 {
637 std::vector<std::string> traceLists = {};
638 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched",
639 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:18432", "trace capturing"}, traceLists));
640 ASSERT_TRUE(traceLists.empty());
641 ASSERT_TRUE(IsTracingOn());
642 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched",
643 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:18432", "OpenRecording failed", "errorCode(1013)"},
644 traceLists));
645 ASSERT_TRUE(traceLists.empty());
646 ASSERT_TRUE(IsTracingOn());
647 }
648
649 /**
650 * @tc.name: RecordingModeTest003
651 * @tc.desc: test close recording mode twice, the record trace contain tag format
652 * @tc.type: FUNC
653 */
654 HWTEST_F(HitraceSystemTest, RecordingModeTest003, TestSize.Level1)
655 {
656 std::vector<std::string> traceLists = {};
657 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched",
658 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:18432", "trace capturing"}, traceLists));
659 ASSERT_TRUE(traceLists.empty());
660 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_finish --record",
661 {"RECORDING_LONG_FINISH_RECORD", "capture done, output files"}, traceLists));
662 ASSERT_FALSE(traceLists.empty());
663 for (const auto& trace : traceLists) {
664 ASSERT_TRUE(IsFileIncludeAllKeyWords(TRACE_FILE_DEFAULT_DIR + trace,
665 {"name: print", "name: sched_wakeup", "name: sched_switch"}));
666 }
667 }
668
669 /**
670 * @tc.name: RecordingModeTest004
671 * @tc.desc: test close recording if close already
672 * @tc.type: FUNC
673 */
674 HWTEST_F(HitraceSystemTest, RecordingModeTest004, TestSize.Level2)
675 {
676 std::vector<std::string> traceLists = {};
677 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_finish --record",
678 {"RECORDING_LONG_FINISH_RECORD", "RecordingOff failed", "errorCode(1012)"}, traceLists));
679 ASSERT_TRUE(traceLists.empty());
680 }
681
682 /**
683 * @tc.name: RecordingModeTest005
684 * @tc.desc: test recording mode file aging
685 * @tc.type: FUNC
686 */
687 HWTEST_F(HitraceSystemTest, RecordingModeTest005, TestSize.Level2)
688 {
689 int testCnt = 30; // 30 : test cnt
690 while (testCnt-- > 0) {
691 ASSERT_TRUE(RunCmd("hitrace --trace_begin --record sched"));
692 ASSERT_TRUE(RunCmd("hitrace --trace_finish --record"));
693 }
694 std::vector<std::string> dirTraceLists = {};
695 GetRecordingTraceFileList(dirTraceLists);
696 if (IsRootVersion()) {
697 ASSERT_GE(dirTraceLists.size(), 30); // 30 : file cnt
698 } else {
699 ASSERT_LE(dirTraceLists.size(), 16); // 16 : max file cnt
700 }
701 }
702
703 /**
704 * @tc.name: RecordingModeTest006
705 * @tc.desc: test recording mode has a higher priority than snapshot mode
706 * @tc.type: FUNC
707 */
708 HWTEST_F(HitraceSystemTest, RecordingModeTest006, TestSize.Level1)
709 {
710 std::vector<std::string> traceLists = {};
711 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --start_bgsrv", {"SNAPSHOT_START", "OpenSnapshot done"}, traceLists));
712 ASSERT_TRUE(traceLists.empty());
713 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched",
714 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:18432", "errorCode(1013)"}, traceLists));
715 ASSERT_TRUE(traceLists.empty());
716 }
717
718 /**
719 * @tc.name: RecordingModeTest007
720 * @tc.desc: test recording mode buffer size customization
721 * @tc.type: FUNC
722 */
723 HWTEST_F(HitraceSystemTest, RecordingModeTest007, TestSize.Level1)
724 {
725 std::vector<std::string> traceLists = {};
726 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched -b 102400",
727 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:102400", "trace capturing"}, traceLists));
728 ASSERT_TRUE(traceLists.empty());
729 ASSERT_EQ(ReadBufferSizeKB(), IsHmKernel() ? "102400" : "102402");
730 }
731
732 /**
733 * @tc.name: RecordingModeTest008
734 * @tc.desc: test recording mode buffer size customization in hm kernel:[256, 1048576]
735 * @tc.type: FUNC
736 */
737 HWTEST_F(HitraceSystemTest, RecordingModeTest008, TestSize.Level1)
738 {
739 if (!IsHmKernel()) {
740 return;
741 }
742 std::vector<std::string> traceLists = {};
743 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched -b 255",
744 {"buffer size must be from 256 KB to 1024 MB", "parsing args failed, exit"}, traceLists));
745 ASSERT_TRUE(traceLists.empty());
746 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched -b 256",
747 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:256", "trace capturing"}, traceLists));
748 ASSERT_TRUE(traceLists.empty());
749 ASSERT_EQ(ReadBufferSizeKB(), "512");
750 }
751
752 /**
753 * @tc.name: RecordingModeTest009
754 * @tc.desc: test recording mode buffer size customization in hm kernel:[256, 1048576]
755 * @tc.type: FUNC
756 */
757 HWTEST_F(HitraceSystemTest, RecordingModeTest009, TestSize.Level1)
758 {
759 if (!IsHmKernel()) {
760 return;
761 }
762 std::vector<std::string> traceLists = {};
763 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched -b 1048577",
764 {"buffer size must be from 256 KB to 1024 MB", "parsing args failed, exit"}, traceLists));
765 ASSERT_TRUE(traceLists.empty());
766 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched -b 1048576",
767 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:1048576", "trace capturing"}, traceLists));
768 ASSERT_TRUE(traceLists.empty());
769 ASSERT_EQ(ReadBufferSizeKB(), "1048576");
770 }
771
772 /**
773 * @tc.name: RecordingModeTest010
774 * @tc.desc: test recording mode buffer size customization in linux kernel:[256, 307200], hm kernel:[256, 1048576]
775 * @tc.type: FUNC
776 */
777 HWTEST_F(HitraceSystemTest, RecordingModeTest010, TestSize.Level1)
778 {
779 if (IsHmKernel()) {
780 return;
781 }
782 std::vector<std::string> traceLists = {};
783 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched -b 255",
784 {"buffer size must be from 256 KB to 300 MB", "parsing args failed, exit"}, traceLists));
785 ASSERT_TRUE(traceLists.empty());
786 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched -b 256",
787 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:256", "trace capturing"}, traceLists));
788 ASSERT_TRUE(traceLists.empty());
789 ASSERT_EQ(ReadBufferSizeKB(), "258");
790 }
791
792 /**
793 * @tc.name: RecordingModeTest011
794 * @tc.desc: test recording mode buffer size customization in linux kernel: [256, 307200]
795 * @tc.type: FUNC
796 */
797 HWTEST_F(HitraceSystemTest, RecordingModeTest011, TestSize.Level1)
798 {
799 if (IsHmKernel()) {
800 return;
801 }
802 std::vector<std::string> traceLists = {};
803 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched -b 307201",
804 {"buffer size must be from 256 KB to 300 MB", "parsing args failed, exit"}, traceLists));
805 ASSERT_TRUE(traceLists.empty());
806 ASSERT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin --record sched -b 307200",
807 {"RECORDING_LONG_BEGIN_RECORD", "tags:sched", "bufferSize:307200", "trace capturing"}, traceLists));
808 ASSERT_TRUE(traceLists.empty());
809 }
810
811 /**
812 * @tc.name: HitraceSystemTestErr001
813 * @tc.desc: when excute hitrace record command failed, -b abc
814 * @tc.type: FUNC
815 */
816 HWTEST_F(HitraceSystemTest, HitraceSystemTestErr001, TestSize.Level2)
817 {
818 std::vector<std::string> traceLists = {};
819 EXPECT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin ace -b abc",
820 {"buffer size is illegal input"}, traceLists));
821 ASSERT_TRUE(traceLists.empty());
822 }
823
824 /**
825 * @tc.name: HitraceSystemTestErr002
826 * @tc.desc: when excute hitrace record command failed, -t abc
827 * @tc.type: FUNC
828 */
829 HWTEST_F(HitraceSystemTest, HitraceSystemTestErr002, TestSize.Level2)
830 {
831 std::vector<std::string> traceLists = {};
832 EXPECT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin ace -t abc",
833 {"the time is illegal input"}, traceLists));
834 ASSERT_TRUE(traceLists.empty());
835 }
836
837 /**
838 * @tc.name: HitraceSystemTestErr003
839 * @tc.desc: when excute hitrace record command failed, -t 0
840 * @tc.type: FUNC
841 */
842 HWTEST_F(HitraceSystemTest, HitraceSystemTestErr003, TestSize.Level2)
843 {
844 std::vector<std::string> traceLists = {};
845 EXPECT_TRUE(CheckTraceCommandOutput("hitrace --trace_begin ace -t 0",
846 {"to be greater than zero"}, traceLists));
847 ASSERT_TRUE(traceLists.empty());
848 }
849
850 /**
851 * @tc.name: HitraceSystemTestErr004
852 * @tc.desc: when excute hitrace record command failed, --abc
853 * @tc.type: FUNC
854 */
855 HWTEST_F(HitraceSystemTest, HitraceSystemTestErr004, TestSize.Level2)
856 {
857 std::vector<std::string> traceLists = {};
858 EXPECT_TRUE(CheckTraceCommandOutput("hitrace --abc", {"parsing args failed"}, traceLists));
859 ASSERT_TRUE(traceLists.empty());
860 }
861
862 /**
863 * @tc.name: HitraceSystemHelpTest
864 * @tc.desc: excute hitrace help command
865 * @tc.type: FUNC
866 */
867 HWTEST_F(HitraceSystemTest, HitraceSystemHelpTest, TestSize.Level2)
868 {
869 std::vector<std::string> traceLists = {};
870 EXPECT_TRUE(CheckTraceCommandOutput("hitrace -h", {"trace_begin", "trace_finish"}, traceLists));
871 ASSERT_TRUE(traceLists.empty());
872 }
873
874 /**
875 * @tc.name: HitraceSystemCompressesTest
876 * @tc.desc: when excute hitrace record command with -z
877 * @tc.type: FUNC
878 */
879 HWTEST_F(HitraceSystemTest, HitraceSystemCompressesTest, TestSize.Level2)
880 {
881 std::vector<std::string> traceLists = {};
882 ASSERT_TRUE(RunCmd("hitrace --trace_begin app"));
883 ASSERT_TRUE(RunCmd("hitrace --trace_dump"));
884 ASSERT_FALSE(CheckTraceCommandOutput("hitrace --trace_finish -z", {"TASK-PID"}, traceLists));
885 ASSERT_TRUE(traceLists.empty());
886 }
887
888 /**
889 * @tc.name: HitraceSystemRawTest
890 * @tc.desc: when excute hitrace command with --raw
891 * @tc.type: FUNC
892 */
893 HWTEST_F(HitraceSystemTest, HitraceSystemRawTest, TestSize.Level2)
894 {
895 std::vector<std::string> traceLists = {};
896 ASSERT_TRUE(CheckTraceCommandOutput("hitrace -t 2 app --raw",
897 {"RECORDING_SHORT_RAW", "capture done, output files:"}, traceLists));
898 ASSERT_FALSE(traceLists.empty());
899 for (size_t i = 0; i < traceLists.size(); i++) {
900 std::string traceFilePath = "/data/log/hitrace/" + traceLists[i];
901 ASSERT_TRUE(access(traceFilePath.c_str(), F_OK) != -1);
902 }
903 }
904 } // namespace
905 } // namespace Hitrace
906 } // namespace HiviewDFX
907 } // namespace OHOS
908