• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 #include <iostream>
19 #include <memory>
20 #include <fstream>
21 #include <string>
22 #include <vector>
23 
24 #include <unistd.h>
25 #include <cstdio>
26 #include "securec.h"
27 
28 #include "hilog/log.h"
29 #include "parameters.h"
30 #include <gtest/gtest.h>
31 
32 using namespace OHOS::HiviewDFX::Hitrace;
33 using namespace testing::ext;
34 using OHOS::HiviewDFX::HiLog;
35 
36 namespace {
37 
38 constexpr uint64_t HITRACE_TAG = 0xD002D33;
39 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HITRACE_TAG, "HitraceTest"};
40 
41 const std::string TAG_PROP = "debug.hitrace.tags.enableflags";
42 const std::string DEFAULT_OUTPUT_DIR = "/data/log/hitrace/";
43 const std::string LOG_DIR = "/data/log/";
44 
45 std::string g_traceRootPath;
46 
AddPair2Table(std::string outputFileName,int nowSec)47 void AddPair2Table(std::string outputFileName, int nowSec)
48 {
49     std::vector<std::pair<std::string, int>> traceFilesTable = GetTraceFilesTable();
50     traceFilesTable.push_back({outputFileName, nowSec});
51     SetTraceFilesTable(traceFilesTable);
52 }
53 
CreateFile(std::string outputFileName)54 bool CreateFile(std::string outputFileName)
55 {
56     std::ofstream ofs;
57     ofs.open(outputFileName, std::ios::out | std::ios::trunc);
58     bool openRes = ofs.is_open();
59     ofs.close();
60     return openRes;
61 }
62 
EraseFile(std::string outputFileName)63 void EraseFile(std::string outputFileName)
64 {
65     std::vector<std::pair<std::string, int>> traceFilesTable = GetTraceFilesTable();
66     for (auto iter = traceFilesTable.begin(); iter != traceFilesTable.end();) {
67         if (strcmp(iter->first.c_str(), outputFileName.c_str())) {
68             iter = traceFilesTable.erase(iter);
69             continue;
70         }
71         iter++;
72     }
73     SetTraceFilesTable(traceFilesTable);
74 }
75 
TraverseFiles(std::vector<std::string> files,std::string outputFileName)76 bool TraverseFiles(std::vector<std::string> files, std::string outputFileName)
77 {
78     int i = 1;
79     bool isExists = false;
80     for (std::vector<std::string>::iterator iter = files.begin(); iter != files.end(); iter++) {
81         isExists |= (strcmp(iter->c_str(), outputFileName.c_str()) == 0);
82         HiLog::Info(LABEL, "ret.outputFile%{public}d: %{public}s", i++, iter->c_str());
83     }
84     return isExists;
85 }
86 
87 class HitraceDumpTest : public testing::Test {
88 public:
89     static void SetUpTestCase(void);
90     static void TearDownTestCase(void);
SetUp()91     void SetUp() {}
TearDown()92     void TearDown() {}
93 };
94 
SetUpTestCase()95 void HitraceDumpTest::SetUpTestCase()
96 {
97     const std::string debugfsDir = "/sys/kernel/debug/tracing/";
98     const std::string tracefsDir = "/sys/kernel/tracing/";
99     if (access((debugfsDir + "trace_marker").c_str(), F_OK) != -1) {
100         g_traceRootPath = debugfsDir;
101     } else if (access((tracefsDir + "trace_marker").c_str(), F_OK) != -1) {
102         g_traceRootPath = tracefsDir;
103     } else {
104         HiLog::Error(LABEL, "Error: Finding trace folder failed.");
105     }
106 
107     /* Open CMD_MODE */
108 }
109 
TearDownTestCase()110 void HitraceDumpTest::TearDownTestCase()
111 {
112     /* Close CMD_MODE */
113 }
114 
115 /**
116  * @tc.name: GetTraceModeTest_001
117  * @tc.desc: test GetTraceMode() service mode
118  * @tc.type: FUNC
119  */
120 HWTEST_F(HitraceDumpTest, GetTraceModeTest_001, TestSize.Level0)
121 {
122     // check service mode
123     const std::vector<std::string> tagGroups = {"scene_performance"};
124     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
125     TraceMode serviceMode = GetTraceMode();
126     ASSERT_TRUE(serviceMode == TraceMode::SERVICE_MODE);
127 
128     // check close mode
129     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
130     TraceMode closeMode = GetTraceMode();
131     ASSERT_TRUE(closeMode == TraceMode::CLOSE);
132 }
133 
134 /**
135  * @tc.name: GetTraceModeTest_002
136  * @tc.desc: test GetTraceMode() cmd mode
137  * @tc.type: FUNC
138  */
139 HWTEST_F(HitraceDumpTest, GetTraceModeTest_002, TestSize.Level0)
140 {
141     // check cmd mode
142     std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1";
143     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
144     TraceMode cmdMode = GetTraceMode();
145     ASSERT_TRUE(cmdMode == TraceMode::CMD_MODE);
146 
147     // check close mode
148     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
149     TraceMode closeMode = GetTraceMode();
150     ASSERT_TRUE(closeMode == TraceMode::CLOSE);
151 }
152 
153 /**
154  * @tc.name: DumpForServiceMode_001
155  * @tc.desc: The correct usage of grasping trace in SERVICE_MODE.
156  * @tc.type: FUNC
157  */
158 HWTEST_F(HitraceDumpTest, DumpForServiceMode_001, TestSize.Level0)
159 {
160     const std::vector<std::string> tagGroups = {"scene_performance"};
161     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
162 
163     TraceRetInfo ret = DumpTrace();
164     ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
165     ASSERT_TRUE(ret.outputFiles.size() > 0);
166     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
167 }
168 
169 /**
170  * @tc.name: DumpForCmdMode_001
171  * @tc.desc: The correct usage of grasping trace in CMD_MODE.
172  * @tc.type: FUNC
173  */
174 HWTEST_F(HitraceDumpTest, DumpForCmdMode_001, TestSize.Level0)
175 {
176     std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1";
177     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
178 
179     ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
180     sleep(1);
181 
182     TraceRetInfo ret = DumpTraceOff();
183     ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
184     ASSERT_TRUE(ret.outputFiles.size() > 0);
185 
186     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
187 }
188 
189 /**
190  * @tc.name: DumpForCmdMode_002
191  * @tc.desc: Specifies the path of the command in CMD_MODE.
192  * @tc.type: FUNC
193  */
194 HWTEST_F(HitraceDumpTest, DumpForCmdMode_002, TestSize.Level0)
195 {
196     std::string filePathName = "/data/local/tmp/mytrace.sys";
197     std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1 output:" + filePathName;
198     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
199     ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
200     sleep(1);
201 
202     TraceRetInfo ret = DumpTraceOff();
203     ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
204 
205     ASSERT_TRUE(TraverseFiles(ret.outputFiles, filePathName));
206 
207     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
208 }
209 
210 /**
211  * @tc.name: DumpForCmdMode_003
212  * @tc.desc: Invalid args verification in CMD_MODE.
213  * @tc.type: FUNC
214  */
215 HWTEST_F(HitraceDumpTest, DumpForCmdMode_003, TestSize.Level0)
216 {
217     std::string args = "tags:hdcc clockType:boot bufferSize:1024 overwrite:1 ";
218     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::TAG_ERROR);
219 
220     args = "tags:hdcc clockType:boot bufferSize:1024 overwrite:1 descriptions:123";
221     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::TAG_ERROR);
222 
223     ASSERT_TRUE(CloseTrace() == TraceErrorCode::CALL_ERROR);
224 }
225 
226 /**
227  * @tc.name: DumpForCmdMode_004
228  * @tc.desc: The CMD_MODE cannot be interrupted by the SERVICE_MODE.
229  * @tc.type: FUNC
230  */
231 HWTEST_F(HitraceDumpTest, DumpForCmdMode_004, TestSize.Level0)
232 {
233     std::string args = "tags:memory clockType:boot1 bufferSize:1024 overwrite:0";
234     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
235 
236     const std::vector<std::string> tagGroups = {"scene_performance"};
237     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::TRACE_IS_OCCUPIED);
238 
239     ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
240     sleep(1);
241 
242     TraceRetInfo ret = DumpTraceOff();
243     ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
244     ASSERT_TRUE(ret.outputFiles.size() > 0);
245 
246     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
247 
248     args = "tags:memory clockType: bufferSize:1024 overwrite:1";
249     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
250     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
251 
252     args = "tags:memory clockType:perf bufferSize:1024 overwrite:1";
253     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
254     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
255 }
256 
257 /**
258  * @tc.name: DumpForCmdMode_005
259  * @tc.desc: Enable the cmd mode in non-close mode.
260  * @tc.type: FUNC
261  */
262 HWTEST_F(HitraceDumpTest, DumpForCmdMode_005, TestSize.Level0)
263 {
264     const std::vector<std::string> tagGroups = {"scene_performance"};
265     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
266     std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1";
267     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::CALL_ERROR);
268     ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::CALL_ERROR);
269 
270     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
271 }
272 
273 /**
274  * @tc.name: DumpForCmdMode_006
275  * @tc.desc: Test the CMD_MODE when there's extra space in args.
276  * @tc.type: FUNC
277  */
278 HWTEST_F(HitraceDumpTest, DumpForCmdMode_006, TestSize.Level0)
279 {
280     std::string args = "tags: sched clockType: boot bufferSize:1024 overwrite: 1";
281     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
282 
283     ASSERT_TRUE(DumpTraceOn() == TraceErrorCode::SUCCESS);
284     sleep(1);
285 
286     TraceRetInfo ret = DumpTraceOff();
287     ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
288     ASSERT_TRUE(ret.outputFiles.size() > 0);
289 
290     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
291 }
292 
293 /**
294  * @tc.name: ParammeterCheck_001
295  * @tc.desc: Check parameter after interface call.
296  * @tc.type: FUNC
297  */
298 HWTEST_F(HitraceDumpTest, ParammeterCheck_001, TestSize.Level0)
299 {
300     const std::vector<std::string> tagGroups = {"scene_performance"};
301     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
302 
303     // ckeck Property("debug.hitrace.tags.enableflags")
304     uint64_t openTags = OHOS::system::GetUintParameter<uint64_t>(TAG_PROP, 0);
305     ASSERT_TRUE(openTags > 0);
306 
307     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
308 
309     // ckeck Property("debug.hitrace.tags.enableflags")
310     uint64_t closeTags = OHOS::system::GetUintParameter<uint64_t>(TAG_PROP, 0);
311     ASSERT_TRUE(closeTags == 0);
312 }
313 
314 /**
315  * @tc.name: DumpForServiceMode_002
316  * @tc.desc: Verify if files can be returned as expected in Service_MODE.
317  * @tc.type: FUNC
318  */
319 HWTEST_F(HitraceDumpTest, DumpForServiceMode_002, TestSize.Level0)
320 {
321     const std::vector<std::string> tagGroups = {"scene_performance"};
322     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
323     ASSERT_TRUE(access(DEFAULT_OUTPUT_DIR.c_str(), F_OK) == 0) << "/data/log/hitrace not exists.";
324 
325     struct timeval now = {0, 0};
326     gettimeofday(&now, nullptr);
327     int nowSec = now.tv_sec;
328     int nowUsec = now.tv_usec;
329     nowSec--;
330     std::string outputFileName = DEFAULT_OUTPUT_DIR + "trace_" + std::to_string(nowSec)
331         + "_" + std::to_string(nowUsec) + ".sys";
332     ASSERT_TRUE(CreateFile(outputFileName)) << "create log file failed.";
333     HiLog::Info(LABEL, "outputFileName: %{public}s", outputFileName.c_str());
334     AddPair2Table(outputFileName, nowSec);
335 
336     TraceRetInfo ret = DumpTrace();
337     // Remove outputFileName in g_hitraceFilesTable
338     EraseFile(outputFileName);
339     ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
340     ASSERT_TRUE(TraverseFiles(ret.outputFiles, outputFileName)) << "file created by user is not exists.";
341     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
342 }
343 
344 /**
345  * @tc.name: DumpForServiceMode_003
346  * @tc.desc: Verify if files can be deleted in Service_MODE.
347  * @tc.type: FUNC
348  */
349 HWTEST_F(HitraceDumpTest, DumpForServiceMode_003, TestSize.Level0)
350 {
351     const std::vector<std::string> tagGroups = {"scene_performance"};
352     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
353     ASSERT_TRUE(access(DEFAULT_OUTPUT_DIR.c_str(), F_OK) == 0) << "/data/log/hitrace not exists.";
354 
355     struct timeval now = {0, 0};
356     gettimeofday(&now, nullptr);
357     int nowSec = now.tv_sec;
358     int nowUsec = now.tv_usec;
359     nowSec = nowSec - 1900;
360     std::string outputFileName = DEFAULT_OUTPUT_DIR + "trace_" + std::to_string(nowSec)
361         + "_" + std::to_string(nowUsec) + ".sys";
362     ASSERT_TRUE(CreateFile(outputFileName)) << "create log file failed.";
363     HiLog::Info(LABEL, "outputFileName: %{public}s", outputFileName.c_str());
364     AddPair2Table(outputFileName, nowSec);
365 
366     TraceRetInfo ret = DumpTrace();
367     ASSERT_TRUE(ret.errorCode == TraceErrorCode::SUCCESS);
368     ASSERT_FALSE(TraverseFiles(ret.outputFiles, outputFileName))
369         << "Returned files that should have been deleted half an hour ago.";
370     ASSERT_TRUE(access(outputFileName.c_str(), F_OK) < 0) << "The file was not deleted half an hour ago";
371     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
372 }
373 /**
374  * @tc.name: DumpForServiceMode_004
375  * @tc.desc: Invalid parameter verification in CMD_MODE.
376  * @tc.type: FUNC
377  */
378 HWTEST_F(HitraceDumpTest, DumpForServiceMode_004, TestSize.Level0)
379 {
380     const std::vector<std::string> tagGroups;
381     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::TAG_ERROR);
382 
383     const std::vector<std::string> tagGroups1 = {"scene_performance1"};
384     ASSERT_TRUE(OpenTrace(tagGroups1) == TraceErrorCode::TAG_ERROR);
385     ASSERT_TRUE(DumpTrace().errorCode == TraceErrorCode::CALL_ERROR);
386 
387     ASSERT_TRUE(CloseTrace() == TraceErrorCode::CALL_ERROR);
388 }
389 
390 /**
391  * @tc.name: DumpForServiceMode_005
392  * @tc.desc: Enable the service mode in CMD_MODE.
393  * @tc.type: FUNC
394  */
395 HWTEST_F(HitraceDumpTest, DumpForServiceMode_005, TestSize.Level0)
396 {
397     std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1";
398     ASSERT_TRUE(OpenTrace(args) == TraceErrorCode::SUCCESS);
399 
400     const std::vector<std::string> tagGroups = {"scene_performance"};
401     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::TRACE_IS_OCCUPIED);
402 
403     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
404 
405     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::SUCCESS);
406 
407     ASSERT_TRUE(OpenTrace(tagGroups) == TraceErrorCode::CALL_ERROR);
408 
409     ASSERT_TRUE(CloseTrace() == TraceErrorCode::SUCCESS);
410 }
411 } // namespace
412