• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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