1/*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "hitrace_dump.h"
17#include "common_utils.h"
18
19#include <iostream>
20#include <memory>
21#include <fstream>
22#include <string>
23#include <vector>
24#include <map>
25
26#include <unistd.h>
27#include <cstdio>
28#include <fcntl.h>
29#include "securec.h"
30
31#include "hilog/log.h"
32#include "parameters.h"
33#include <gtest/gtest.h>
34
35using namespace OHOS::HiviewDFX::Hitrace;
36using namespace testing::ext;
37using OHOS::HiviewDFX::HiLog;
38
39namespace {
40
41#undef LOG_DOMAIN
42#define LOG_DOMAIN 0xD002D33
43
44#undef LOG_TAG
45#define LOG_TAG "HitraceTest"
46
47const std::string TAG_PROP = "debug.hitrace.tags.enableflags";
48const std::string DEFAULT_OUTPUT_DIR = "/data/log/hitrace/";
49const std::string LOG_DIR = "/data/log/";
50const int SLEEP_TIME = 10; // sleep 10ms
51
52std::string g_traceRootPath;
53
54void AddPair2Table(std::string outputFileName, int nowSec)
55{
56    std::vector<std::pair<std::string, int>> traceFilesTable = GetTraceFilesTable();
57    traceFilesTable.push_back({outputFileName, nowSec});
58    SetTraceFilesTable(traceFilesTable);
59}
60
61bool CreateFile(std::string outputFileName)
62{
63    std::ofstream ofs;
64    ofs.open(outputFileName, std::ios::out | std::ios::trunc);
65    bool openRes = ofs.is_open();
66    ofs.close();
67    return openRes;
68}
69
70void EraseFile(std::string outputFileName)
71{
72    std::vector<std::pair<std::string, int>> traceFilesTable = GetTraceFilesTable();
73    for (auto iter = traceFilesTable.begin(); iter != traceFilesTable.end();) {
74        if (strcmp(iter->first.c_str(), outputFileName.c_str())) {
75            iter = traceFilesTable.erase(iter);
76            continue;
77        }
78        iter++;
79    }
80    SetTraceFilesTable(traceFilesTable);
81}
82
83bool TraverseFiles(std::vector<std::string> files, std::string outputFileName)
84{
85    int i = 1;
86    bool isExists = false;
87    for (std::vector<std::string>::iterator iter = files.begin(); iter != files.end(); iter++) {
88        isExists |= (strcmp(iter->c_str(), outputFileName.c_str()) == 0);
89        HILOG_INFO(LOG_CORE, "ret.outputFile%{public}d: %{public}s", i++, iter->c_str());
90    }
91    return isExists;
92}
93
94bool RunCmd(const string& cmdstr)
95{
96    FILE *fp = popen(cmdstr.c_str(), "r");
97    if (fp == nullptr) {
98        return false;
99    }
100    pclose(fp);
101    return true;
102}
103
104class HitraceDumpTest : public testing::Test {
105public:
106    static void SetUpTestCase(void);
107    static void TearDownTestCase(void);
108    void SetUp();
109    void TearDown() {}
110};
111
112void HitraceDumpTest::SetUp()
113{
114    CloseTrace();
115}
116
117void HitraceDumpTest::SetUpTestCase()
118{
119    const std::string debugfsDir = "/sys/kernel/debug/tracing/";
120    const std::string tracefsDir = "/sys/kernel/tracing/";
121    if (access((debugfsDir + "trace_marker").c_str(), F_OK) != -1) {
122        g_traceRootPath = debugfsDir;
123    } else if (access((tracefsDir + "trace_marker").c_str(), F_OK) != -1) {
124        g_traceRootPath = tracefsDir;
125    } else {
126        HILOG_ERROR(LOG_CORE, "Error: Finding trace folder failed.");
127    }
128
129    /* Open CMD_MODE */
130}
131
132void HitraceDumpTest::TearDownTestCase()
133{
134    /* Close CMD_MODE */
135}
136
137/**
138 * @tc.name: GetTraceModeTest_001
139 * @tc.desc: test GetTraceMode() service mode
140 * @tc.type: FUNC
141 */
142HWTEST_F(HitraceDumpTest, GetTraceModeTest_001, TestSize.Level0)
143{
144    // check service mode
145    const std::vector<std::string> tagGroups = {"scene_performance"};
146    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
147    TraceMode serviceMode = GetTraceMode();
148    ASSERT_TRUE(serviceMode == TraceMode::SERVICE_MODE);
149
150    // check close mode
151    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
152    TraceMode closeMode = GetTraceMode();
153    ASSERT_TRUE(closeMode == TraceMode::CLOSE);
154}
155
156/**
157 * @tc.name: GetTraceModeTest_002
158 * @tc.desc: test GetTraceMode() cmd mode
159 * @tc.type: FUNC
160 */
161HWTEST_F(HitraceDumpTest, GetTraceModeTest_002, TestSize.Level0)
162{
163    // check cmd mode
164    std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1";
165    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
166    TraceMode cmdMode = GetTraceMode();
167    ASSERT_TRUE(cmdMode == TraceMode::CMD_MODE);
168
169    // check close mode
170    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
171    TraceMode closeMode = GetTraceMode();
172    ASSERT_TRUE(closeMode == TraceMode::CLOSE);
173}
174
175/**
176 * @tc.name: DumpTraceTest_001
177 * @tc.desc: Test DumpTrace(int maxDuration) for valid input.
178 * The no arg version DumpTrace() is implicitly tested in other tests.
179 * @tc.type: FUNC
180 */
181HWTEST_F(HitraceDumpTest, DumpTraceTest_001, TestSize.Level0)
182{
183    const std::vector<std::string> tagGroups = {"default"};
184    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
185
186    int maxDuration = 1;
187    TraceRetInfo ret = DumpTrace(maxDuration);
188    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
189    ASSERT_TRUE(ret.outputFiles.size() > 0);
190    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
191}
192
193/**
194 * @tc.name: DumpTraceTest_002
195 * @tc.desc: Test DumpTrace(int maxDuration) for invalid input.
196 * @tc.type: FUNC
197 */
198HWTEST_F(HitraceDumpTest, DumpTraceTest_002, TestSize.Level0)
199{
200    const std::vector<std::string> tagGroups = {"default"};
201    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
202
203    int maxDuration = -1;
204    TraceRetInfo ret = DumpTrace(maxDuration);
205    ASSERT_TRUE(ret.errorCode == TraceErrorCode::CALL_ERROR);
206    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
207}
208
209/**
210 * @tc.name: DumpTraceTest_003
211 * @tc.desc: Test DumpTrace(int maxDuration, uint64_t happenTime) for valid input.
212 * @tc.type: FUNC
213 */
214HWTEST_F(HitraceDumpTest, DumpTraceTest_003, TestSize.Level0)
215{
216    const std::vector<std::string> tagGroups = {"default"};
217    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
218    sleep(2); // need at least one second of trace in cpu due to the input unit of 1 second to avoid OUT_OF_TIME.
219    uint64_t traceEndTime = static_cast<uint64_t>(std::time(nullptr));
220    TraceRetInfo ret = DumpTrace(0, traceEndTime);
221    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
222    ASSERT_TRUE(ret.outputFiles.size() > 0);
223    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
224
225    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
226    sleep(2);
227    traceEndTime = static_cast<uint64_t>(std::time(nullptr));
228    int maxDuration = 10;
229    ret = DumpTrace(maxDuration, traceEndTime);
230    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
231    ASSERT_TRUE(ret.outputFiles.size() > 0);
232    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
233}
234
235/**
236 * @tc.name: DumpTraceTest_004
237 * @tc.desc: Test DumpTrace(int maxDuration, uint64_t happenTime) for invalid input.
238 * @tc.type: FUNC
239 */
240HWTEST_F(HitraceDumpTest, DumpTraceTest_004, TestSize.Level0)
241{
242    const std::vector<std::string> tagGroups = {"default"};
243
244    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
245    uint64_t traceEndTime = 1;
246    TraceRetInfo ret = DumpTrace(0, traceEndTime);
247    ASSERT_TRUE(ret.errorCode == TraceErrorCode::OUT_OF_TIME);
248    ASSERT_TRUE(ret.outputFiles.empty());
249    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
250
251    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
252    traceEndTime = static_cast<uint64_t>(std::time(nullptr)) + 10; // current time + 10 seconds
253    ret = DumpTrace(0, traceEndTime);
254    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
255    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
256
257    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
258    traceEndTime = 10; // 1970-01-01 08:00:10
259    int maxDuration = -1;
260    ret = DumpTrace(maxDuration, traceEndTime);
261    ASSERT_TRUE(ret.errorCode == TraceErrorCode::CALL_ERROR);
262    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
263
264    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
265    traceEndTime = static_cast<uint64_t>(std::time(nullptr)) + 10; // current time + 10 seconds
266    maxDuration = -1;
267    ret = DumpTrace(maxDuration, traceEndTime);
268    ASSERT_TRUE(ret.errorCode == TraceErrorCode::CALL_ERROR);
269    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
270
271    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
272    traceEndTime = 10;
273    maxDuration = 10;
274    ret = DumpTrace(maxDuration, traceEndTime);
275    ASSERT_TRUE(ret.errorCode == TraceErrorCode::OUT_OF_TIME);
276    ASSERT_TRUE(ret.outputFiles.empty());
277    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
278
279    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
280    traceEndTime = static_cast<uint64_t>(std::time(nullptr)) + 100; // current time + 100 seconds
281    maxDuration = 10;
282    ret = DumpTrace(maxDuration, traceEndTime);
283    ASSERT_TRUE(ret.errorCode == TraceErrorCode::OUT_OF_TIME);
284    ASSERT_TRUE(ret.outputFiles.empty());
285    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
286
287    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
288    traceEndTime = static_cast<uint64_t>(std::time(nullptr)) + 1; // current time + 1 seconds
289    maxDuration = 10;
290    ret = DumpTrace(maxDuration, traceEndTime);
291    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
292    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
293}
294
295/**
296 * @tc.name: DumpTraceTest_005
297 * @tc.desc: Test DumpTrace(int maxDuration, uint64_t happenTime) for OUT_OF_TIME.
298 * @tc.type: FUNC
299 */
300HWTEST_F(HitraceDumpTest, DumpTraceTest_005, TestSize.Level0)
301{
302    const std::vector<std::string> tagGroups = {"default"};
303    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
304    sleep(2);
305    uint64_t traceEndTime = static_cast<uint64_t>(std::time(nullptr)) - 20; // current time - 20 seconds
306    TraceRetInfo ret = DumpTrace(0, traceEndTime);
307    ASSERT_TRUE(ret.errorCode == TraceErrorCode::OUT_OF_TIME);
308    ASSERT_TRUE(ret.outputFiles.empty());
309    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
310
311    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
312    sleep(2);
313    traceEndTime = static_cast<uint64_t>(std::time(nullptr)) - 20; // current time - 20 seconds
314    int maxDuration = 10;
315    ret = DumpTrace(maxDuration, traceEndTime);
316    ASSERT_TRUE(ret.errorCode == TraceErrorCode::OUT_OF_TIME);
317    ASSERT_TRUE(ret.outputFiles.empty());
318    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
319}
320
321/**
322 * @tc.name: DumpForServiceMode_001
323 * @tc.desc: The correct usage of grasping trace in SERVICE_MODE.
324 * @tc.type: FUNC
325 */
326HWTEST_F(HitraceDumpTest, DumpForServiceMode_001, TestSize.Level0)
327{
328    const std::vector<std::string> tagGroups = {"scene_performance"};
329    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
330
331    TraceRetInfo ret = DumpTrace();
332    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
333    ASSERT_TRUE(ret.outputFiles.size() > 0);
334    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
335}
336
337/**
338 * @tc.name: DumpForCmdMode_001
339 * @tc.desc: The correct usage of grasping trace in CMD_MODE.
340 * @tc.type: FUNC
341 */
342HWTEST_F(HitraceDumpTest, DumpForCmdMode_001, TestSize.Level0)
343{
344    std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1";
345    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
346
347    ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
348    sleep(1);
349
350    TraceRetInfo ret = DumpTraceOff();
351    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
352    ASSERT_TRUE(ret.outputFiles.size() > 0);
353
354    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
355}
356
357/**
358 * @tc.name: DumpForCmdMode_002
359 * @tc.desc: Specifies the path of the command in CMD_MODE.
360 * @tc.type: FUNC
361 */
362HWTEST_F(HitraceDumpTest, DumpForCmdMode_002, TestSize.Level0)
363{
364    std::string filePathName = "/data/local/tmp/mytrace.sys";
365    std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1 output:" + filePathName;
366    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
367    ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
368    sleep(1);
369
370    TraceRetInfo ret = DumpTraceOff();
371    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
372
373    ASSERT_TRUE(TraverseFiles(ret.outputFiles, filePathName))
374        << "unspport set outputfile, default generate file in /data/log/hitrace.";
375
376    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
377}
378
379/**
380 * @tc.name: DumpForCmdMode_003
381 * @tc.desc: Invalid args verification in CMD_MODE.
382 * @tc.type: FUNC
383 */
384HWTEST_F(HitraceDumpTest, DumpForCmdMode_003, TestSize.Level0)
385{
386    std::string args = "clockType:boot bufferSize:1024 overwrite:1 ";
387    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
388    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
389
390    args = "tags:hdc clockType:boot bufferSize:1024 overwrite:1 descriptions:123";
391    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::TAG_ERROR);
392
393    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
394}
395
396/**
397 * @tc.name: DumpForCmdMode_004
398 * @tc.desc: The CMD_MODE cannot be interrupted by the SERVICE_MODE.
399 * @tc.type: FUNC
400 */
401HWTEST_F(HitraceDumpTest, DumpForCmdMode_004, TestSize.Level0)
402{
403    std::string args = "tags:memory clockType:boot1 bufferSize:1024 overwrite:0";
404    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
405
406    const std::vector<std::string> tagGroups = {"scene_performance"};
407    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::CALL_ERROR);
408
409    ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
410    sleep(1);
411
412    TraceRetInfo ret = DumpTraceOff();
413    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
414    ASSERT_TRUE(ret.outputFiles.size() > 0);
415
416    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
417
418    args = "tags:memory clockType: bufferSize:1024 overwrite:1";
419    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
420    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
421
422    args = "tags:memory clockType:perf bufferSize:1024 overwrite:1";
423    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
424    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
425}
426
427/**
428 * @tc.name: DumpForCmdMode_005
429 * @tc.desc: Enable the cmd mode in non-close mode.
430 * @tc.type: FUNC
431 */
432HWTEST_F(HitraceDumpTest, DumpForCmdMode_005, TestSize.Level0)
433{
434    const std::vector<std::string> tagGroups = {"scene_performance"};
435    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
436    std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1";
437    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::CALL_ERROR);
438    ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::CALL_ERROR);
439
440    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
441}
442
443/**
444 * @tc.name: DumpForCmdMode_006
445 * @tc.desc: Test the CMD_MODE when there's extra space in args.
446 * @tc.type: FUNC
447 */
448HWTEST_F(HitraceDumpTest, DumpForCmdMode_006, TestSize.Level0)
449{
450    std::string args = "tags: sched clockType: boot bufferSize:1024 overwrite: 1";
451    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
452
453    ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
454    sleep(1);
455
456    TraceRetInfo ret = DumpTraceOff();
457    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
458    ASSERT_TRUE(ret.outputFiles.size() > 0);
459
460    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
461}
462
463/**
464 * @tc.name: DumpForCmdMode_007
465 * @tc.desc: Test the CMD_MODE when set fileLimit in args.
466 * @tc.type: FUNC
467 */
468HWTEST_F(HitraceDumpTest, DumpForCmdMode_007, TestSize.Level0)
469{
470    std::string args = "tags:sched,ace,app,disk,distributeddatamgr,freq,graphic,idle,irq,load,mdfs,mmc,";
471    args += "notification,ohos,pagecache,regulators,sync,ufs,workq,zaudio,zcamera,zimage,zmedia ";
472    args += "clockType: boot bufferSize:1024 overwrite: 1 fileLimit: 2 fileSize: 51200";
473    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
474
475    ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
476    sleep(1);
477
478    TraceRetInfo ret = DumpTraceOff();
479    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
480    ASSERT_TRUE(ret.outputFiles.size() > 0);
481
482    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
483}
484
485/**
486 * @tc.name: DumpForCmdMode_008
487 * @tc.desc: Test the CMD_MODE when there's extra space in args.
488 * @tc.type: FUNC
489 */
490HWTEST_F(HitraceDumpTest, DumpForCmdMode_008, TestSize.Level0)
491{
492    std::string filePathName = "/data/local/tmp/mylongtrace.sys";
493    std::string args = "tags:sched,ace,app,disk,distributeddatamgr,freq,graphic,idle,irq,load,mdfs,mmc,";
494    args += "notification,ohos,pagecache,regulators,sync,ufs,workq,zaudio,zcamera,zimage,zmedia ";
495    args += "clockType: boot bufferSize:1024 overwrite: 1 output:" + filePathName;
496    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
497
498    ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
499    if (remove(filePathName.c_str()) == 0) {
500        HILOG_INFO(LOG_CORE, "Delete mylongtrace.sys success.");
501    } else {
502        HILOG_ERROR(LOG_CORE, "Delete mylongtrace.sys failed.");
503    }
504    sleep(SLEEP_TIME);
505
506    TraceRetInfo ret = DumpTraceOff();
507    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
508    ASSERT_TRUE(ret.outputFiles.size() > 0);
509
510    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
511}
512
513/**
514 * @tc.name: DumpForCmdMode_009
515 * @tc.desc: Test the CMD_MODE when set fileLimit in args.
516 * @tc.type: FUNC
517 */
518HWTEST_F(HitraceDumpTest, DumpForCmdMode_009, TestSize.Level0)
519{
520    std::string args = "tags:sched,ace,app,disk,distributeddatamgr,freq,graphic,idle,irq,load,mdfs,mmc,";
521    args += "notification,ohos,pagecache,regulators,sync,ufs,workq,zaudio,zcamera,zimage,zmedia ";
522    args += "clockType: boot bufferSize:1024 overwrite: 1 fileLimit: 2";
523    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
524
525    ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
526    sleep(1);
527
528    TraceRetInfo ret = DumpTraceOff();
529    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
530    ASSERT_TRUE(ret.outputFiles.size() > 0);
531
532    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
533}
534
535/**
536 * @tc.name: ParammeterCheck_001
537 * @tc.desc: Check parameter after interface call.
538 * @tc.type: FUNC
539 */
540HWTEST_F(HitraceDumpTest, ParammeterCheck_001, TestSize.Level0)
541{
542    const std::vector<std::string> tagGroups = {"scene_performance"};
543    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
544
545    // ckeck Property("debug.hitrace.tags.enableflags")
546    uint64_t openTags = OHOS::system::GetUintParameter<uint64_t>(TAG_PROP, 0);
547    ASSERT_TRUE(openTags > 0);
548
549    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
550
551    // ckeck Property("debug.hitrace.tags.enableflags")
552    uint64_t closeTags = OHOS::system::GetUintParameter<uint64_t>(TAG_PROP, 0);
553    ASSERT_TRUE(closeTags == 0);
554}
555
556/**
557 * @tc.name: DumpForServiceMode_002
558 * @tc.desc: Verify if files can be returned as expected in Service_MODE.
559 * @tc.type: FUNC
560 */
561HWTEST_F(HitraceDumpTest, DumpForServiceMode_002, TestSize.Level0)
562{
563    const std::vector<std::string> tagGroups = {"scene_performance"};
564    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
565    ASSERT_TRUE(access(DEFAULT_OUTPUT_DIR.c_str(), F_OK) == 0) << "/data/log/hitrace not exists.";
566
567    struct timeval now = {0, 0};
568    gettimeofday(&now, nullptr);
569    int nowSec = now.tv_sec;
570    int nowUsec = now.tv_usec;
571    nowSec--;
572    std::string outputFileName = DEFAULT_OUTPUT_DIR + "trace_" + std::to_string(nowSec)
573        + "_" + std::to_string(nowUsec) + ".sys";
574    ASSERT_TRUE(CreateFile(outputFileName)) << "create log file failed.";
575    HILOG_INFO(LOG_CORE, "outputFileName: %{public}s", outputFileName.c_str());
576    AddPair2Table(outputFileName, nowSec);
577
578    TraceRetInfo ret = DumpTrace();
579    // Remove outputFileName in g_hitraceFilesTable
580    EraseFile(outputFileName);
581    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
582    ASSERT_TRUE(TraverseFiles(ret.outputFiles, outputFileName)) << "file created by user is not exists.";
583    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
584}
585
586/**
587 * @tc.name: DumpForServiceMode_003
588 * @tc.desc: Verify if files can be deleted in Service_MODE.
589 * @tc.type: FUNC
590 */
591HWTEST_F(HitraceDumpTest, DumpForServiceMode_003, TestSize.Level0)
592{
593    const std::vector<std::string> tagGroups = {"scene_performance"};
594    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
595    ASSERT_TRUE(access(DEFAULT_OUTPUT_DIR.c_str(), F_OK) == 0) << "/data/log/hitrace not exists.";
596
597    struct timeval now = {0, 0};
598    gettimeofday(&now, nullptr);
599    int nowSec = now.tv_sec;
600    int nowUsec = now.tv_usec;
601    nowSec = nowSec - 1900;
602    std::string outputFileName = DEFAULT_OUTPUT_DIR + "trace_" + std::to_string(nowSec)
603        + "_" + std::to_string(nowUsec) + ".sys";
604    ASSERT_TRUE(CreateFile(outputFileName)) << "create log file failed.";
605    HILOG_INFO(LOG_CORE, "outputFileName: %{public}s", outputFileName.c_str());
606    AddPair2Table(outputFileName, nowSec);
607
608    TraceRetInfo ret = DumpTrace();
609    ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
610    ASSERT_FALSE(TraverseFiles(ret.outputFiles, outputFileName))
611        << "Returned files that should have been deleted half an hour ago.";
612    ASSERT_TRUE(access(outputFileName.c_str(), F_OK) < 0) << "The file was not deleted half an hour ago";
613    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
614}
615
616/**
617 * @tc.name: DumpForServiceMode_004
618 * @tc.desc: Invalid parameter verification in CMD_MODE.
619 * @tc.type: FUNC
620 */
621HWTEST_F(HitraceDumpTest, DumpForServiceMode_004, TestSize.Level0)
622{
623    const std::vector<std::string> tagGroups;
624    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::TAG_ERROR);
625
626    const std::vector<std::string> tagGroups1 = {"scene_performance1"};
627    ASSERT_TRUE(OpenTrace(tagGroups1) == TraceErrorCode::TAG_ERROR);
628    ASSERT_TRUE(DumpTrace().errorCode == TraceErrorCode::CALL_ERROR);
629
630    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
631}
632
633/**
634 * @tc.name: DumpForServiceMode_005
635 * @tc.desc: Enable the service mode in CMD_MODE.
636 * @tc.type: FUNC
637 */
638HWTEST_F(HitraceDumpTest, DumpForServiceMode_005, TestSize.Level0)
639{
640    std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1";
641    ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
642
643    const std::vector<std::string> tagGroups = {"scene_performance"};
644    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::CALL_ERROR);
645
646    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
647
648    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
649
650    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::CALL_ERROR);
651
652    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
653}
654
655/**
656 * @tc.name: DumpForServiceMode_006
657 * @tc.desc: Invalid parameter verification in CMD_MODE.
658 * @tc.type: FUNC
659 */
660HWTEST_F(HitraceDumpTest, DumpForServiceMode_006, TestSize.Level0)
661{
662    const std::vector<std::string> tagGroups = {"scene_performance"};
663    ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
664    ASSERT_TRUE(access(DEFAULT_OUTPUT_DIR.c_str(), F_OK) == 0) << "/data/log/hitrace not exists.";
665
666    SetSysInitParamTags(123);
667    ASSERT_TRUE(SetCheckParam() == false);
668
669    ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
670}
671
672/**
673 * @tc.name: CommonUtils_001
674 * @tc.desc: Test canonicalizeSpecPath(), enter an existing file path.
675 * @tc.type: FUNC
676*/
677HWTEST_F(HitraceDumpTest, CommonUtils_001, TestSize.Level0)
678{
679    // prepare a file
680    std::string filePath = "/data/local/tmp/tmp.txt";
681    if (access(filePath.c_str(), F_OK) != 0) {
682        int fd = open(filePath.c_str(), O_CREAT);
683        close(fd);
684    }
685    ASSERT_TRUE(CanonicalizeSpecPath(filePath.c_str()) == filePath);
686}
687
688/**
689 * @tc.name: CommonUtils_002
690 * @tc.desc: Test canonicalizeSpecPath(), enter a non-existent file path.
691 * @tc.type: FUNC
692*/
693HWTEST_F(HitraceDumpTest, CommonUtils_002, TestSize.Level0)
694{
695    // prepare a file
696    std::string filePath = "/data/local/tmp/tmp1.txt";
697    if (access(filePath.c_str(), F_OK) != 0) {
698        ASSERT_TRUE(CanonicalizeSpecPath(filePath.c_str()) == filePath);
699    }
700}
701
702/**
703 * @tc.name: CommonUtils_003
704 * @tc.desc: Test canonicalizeSpecPath(), enter a non-existent file path with "..".
705 * @tc.type: FUNC
706*/
707HWTEST_F(HitraceDumpTest, CommonUtils_003, TestSize.Level0)
708{
709    // prepare a file
710    std::string filePath = "../tmp2.txt";
711    if (access(filePath.c_str(), F_OK) != 0) {
712        ASSERT_TRUE(CanonicalizeSpecPath(filePath.c_str()) == "");
713    }
714}
715
716/**
717 * @tc.name: CommonUtils_004
718 * @tc.desc: Test MarkClockSync().
719 * @tc.type: FUNC
720*/
721HWTEST_F(HitraceDumpTest, CommonUtils_004, TestSize.Level0)
722{
723    ASSERT_TRUE(MarkClockSync(g_traceRootPath) == true);
724}
725
726/**
727 * @tc.name: CommonUtils_005
728 * @tc.desc: Test ParseTagInfo().
729 * @tc.type: FUNC
730*/
731HWTEST_F(HitraceDumpTest, CommonUtils_005, TestSize.Level0)
732{
733    std::map<std::string, OHOS::HiviewDFX::Hitrace::TagCategory> allTags;
734    std::map<std::string, std::vector<std::string>> tagGroupTable;
735    ASSERT_TRUE(ParseTagInfo(allTags, tagGroupTable) == true);
736    ASSERT_TRUE(allTags.size() > 0);
737    ASSERT_TRUE(tagGroupTable.size() > 0);
738}
739
740/**
741 * @tc.name: CommonUtils_006
742 * @tc.desc: Test ParseTagInfo().
743 * @tc.type: FUNC
744*/
745HWTEST_F(HitraceDumpTest, CommonUtils_006, TestSize.Level0)
746{
747    std::map<std::string, OHOS::HiviewDFX::Hitrace::TagCategory> allTags;
748    std::map<std::string, std::vector<std::string>> tagGroupTable;
749
750    ASSERT_TRUE(RunCmd("mount -o rw,remount /"));
751    ASSERT_TRUE(RunCmd("cp /system/etc/hiview/hitrace_utils.json /system/etc/hiview/hitrace_utils-bak.json"));
752    ASSERT_TRUE(RunCmd("sed -i 's/tag_groups/TestCommonUtils/g' /system/etc/hiview/hitrace_utils.json"));
753    ParseTagInfo(allTags, tagGroupTable);
754    ASSERT_TRUE(RunCmd("sed -i 's/tag_category/TestCommonUtils/g' /system/etc/hiview/hitrace_utils.json"));
755    ParseTagInfo(allTags, tagGroupTable);
756    ASSERT_TRUE(RunCmd("rm /system/etc/hiview/hitrace_utils.json"));
757    ParseTagInfo(allTags, tagGroupTable);
758    ASSERT_TRUE(RunCmd("mv /system/etc/hiview/hitrace_utils-bak.json /system/etc/hiview/hitrace_utils.json"));
759
760    ASSERT_TRUE(IsNumber("scene_performance") == TraceErrorCode::SUCCESS);
761    ASSERT_TRUE(IsNumber("") == false);
762    ASSERT_TRUE(IsNumber("tags:sched clockType:boot bufferSize:1024 overwrite:1") == false);
763    CanonicalizeSpecPath(nullptr);
764    MarkClockSync("/sys/kernel/debug/tracing/test_trace_marker");
765}
766} // namespace
767