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