1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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 <array>
17 #include <dlfcn.h>
18 #include <fcntl.h>
19 #include <gtest/gtest.h>
20 #include <sys/stat.h>
21 #include <sys/syscall.h>
22 #include <unistd.h>
23
24 #include "logging.h"
25 #include "openssl/sha.h"
26
27 using namespace testing::ext;
28
29 #define HHB(v) (((v) & 0xF0) >> 4)
30 #define LHB(v) ((v) & 0x0F)
31
32 namespace {
33 #if defined(__LP64__)
34 const std::string DEFAULT_SO_PATH("/system/lib64/");
35 #else
36 const std::string DEFAULT_SO_PATH("/system/lib/");
37 #endif
38 const std::string DEFAULT_HIPROFILERD_PATH("/system/bin/hiprofilerd");
39 const std::string DEFAULT_HIPROFILER_PLUGINS_PATH("/system/bin/hiprofiler_plugins");
40 const std::string DEFAULT_HIPROFILERD_NAME("hiprofilerd");
41 const std::string DEFAULT_HIPROFILER_PLUGINS_NAME("hiprofiler_plugins");
42
43 const std::string DEFAULT_HIPROFILER_CMD_PATH("/system/bin/hiprofiler_cmd");
44 const std::string FTRACE_PLUGIN_PATH("/data/local/tmp/libftrace_plugin.z.so");
45 const std::string HIPERF_PLUGIN_PATH("/data/local/tmp/libhiperfplugin.z.so");
46 std::string DEFAULT_PATH("/data/local/tmp/");
47 constexpr uint32_t READ_BUFFER_SIZE = 1024;
48 constexpr int SLEEP_TIME = 3;
49 constexpr int FILE_READ_CHUNK_SIZE = 4096;
50 constexpr char HEX_CHARS[] = "0123456789abcdef";
51 constexpr int LINE_SIZE = 1000;
52
53
54 class HiprofilerCmdTest : public ::testing::Test {
55 public:
SetUpTestCase()56 static void SetUpTestCase() {}
TearDownTestCase()57 static void TearDownTestCase() {}
58
StartServerStub(std::string name)59 void StartServerStub(std::string name)
60 {
61 if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
62 return;
63 }
64 int processNum = fork();
65 if (processNum == 0) {
66 if (DEFAULT_HIPROFILERD_PATH == name) {
67 // start running hiprofilerd
68 execl(name.c_str(), nullptr, nullptr);
69 } else if (DEFAULT_HIPROFILER_PLUGINS_PATH == name) {
70 // start running hiprofiler_plugins
71 execl(name.c_str(), DEFAULT_PATH.c_str(), nullptr);
72 }
73 _exit(1);
74 } else if (DEFAULT_HIPROFILERD_PATH == name) {
75 hiprofilerdPid_ = processNum;
76 } else if (DEFAULT_HIPROFILER_PLUGINS_PATH == name) {
77 hiprofilerPluginsPid_ = processNum;
78 }
79 }
80
StopProcessStub(int processNum)81 void StopProcessStub(int processNum)
82 {
83 std::string stopCmd = "kill " + std::to_string(processNum);
84 std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(stopCmd.c_str(), "r"), pclose);
85 sleep(SLEEP_TIME); // wait process exit
86 }
87
RunCommand(const std::string& cmd, std::string& content)88 bool RunCommand(const std::string& cmd, std::string& content)
89 {
90 std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
91 CHECK_TRUE(pipe, false, "RunCommand: create popen FAILED!");
92 std::array<char, READ_BUFFER_SIZE> buffer;
93 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
94 content += buffer.data();
95 }
96 return true;
97 }
98
ComputeFileSha256(const std::string& path)99 std::string ComputeFileSha256(const std::string& path)
100 {
101 uint8_t out[SHA256_DIGEST_LENGTH];
102 uint8_t buffer[FILE_READ_CHUNK_SIZE];
103 char realPath[PATH_MAX + 1] = {0};
104
105 SHA256_CTX sha;
106 SHA256_Init(&sha);
107
108 size_t nbytes = 0;
109
110 if ((strlen(path.c_str()) >= PATH_MAX) || (realpath(path.c_str(), realPath) == nullptr)) {
111 PROFILER_LOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
112 return "";
113 }
114 FILE* file = fopen(realPath, "rb");
115 if (file == nullptr) {
116 return "";
117 }
118
119 std::unique_ptr<FILE, decltype(fclose)*> fptr(file, fclose);
120 if (fptr == nullptr) {
121 return "";
122 }
123
124 while ((nbytes = fread(buffer, 1, sizeof(buffer), fptr.get())) > 0) {
125 SHA256_Update(&sha, buffer, nbytes);
126 }
127 SHA256_Final(out, &sha);
128
129 std::string result;
130 result.reserve(SHA256_DIGEST_LENGTH + SHA256_DIGEST_LENGTH);
131 for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
132 result.push_back(HEX_CHARS[HHB(out[i])]);
133 result.push_back(HEX_CHARS[LHB(out[i])]);
134 }
135
136 PROFILER_LOG_DEBUG(LOG_CORE, "%s:%s-(%s)", __func__, path.c_str(), result.c_str());
137 return result;
138 }
139
CreateConfigFile(const std::string configFile)140 void CreateConfigFile(const std::string configFile)
141 {
142 // 构建config文件
143 std::string configStr =
144 "request_id: 26\n"
145 "session_config {\n"
146 " buffers {\n"
147 " pages: 1000\n"
148 " }\n"
149 " result_file: \"/data/local/tmp/hiprofiler_data.htrace\"\n"
150 " sample_duration: 10000\n"
151 "}\n"
152 "plugin_configs {\n"
153 " plugin_name: \"ftrace-plugin\"\n"
154 " sample_interval: 2000\n"
155 " config_data: {\n"
156 " ftrace_events: \"sched/sched_switch\"\n"
157 " ftrace_events: \"sched/sched_wakeup\"\n"
158 " ftrace_events: \"sched/sched_wakeup_new\"\n"
159 " ftrace_events: \"sched/sched_waking\"\n"
160 " ftrace_events: \"sched/sched_process_exit\"\n"
161 " ftrace_events: \"sched/sched_process_free\"\n"
162 " buffer_size_kb: 51200\n"
163 " flush_interval_ms: 1000\n"
164 " flush_threshold_kb: 4096\n"
165 " parse_ksyms: true\n"
166 " clock: \"mono\"\n"
167 " trace_period_ms: 200\n"
168 " debug_on: false\n"
169 " }\n"
170 "}\n";
171
172 // 根据构建的config写文件
173 FILE* writeFp = fopen(configFile.c_str(), "w");
174 if (writeFp == nullptr) {
175 const int bufSize = 256;
176 char buf[bufSize] = { 0 };
177 strerror_r(errno, buf, bufSize);
178 PROFILER_LOG_ERROR(LOG_CORE, "CreateConfigFile: fopen() error = %s", buf);
179 return;
180 }
181
182 size_t len = fwrite(const_cast<char*>(configStr.c_str()), 1, configStr.length(), writeFp);
183 if (len < 0) {
184 const int bufSize = 256;
185 char buf[bufSize] = { 0 };
186 strerror_r(errno, buf, bufSize);
187 PROFILER_LOG_ERROR(LOG_CORE, "CreateConfigFile: fwrite() error = %s", buf);
188 if (fclose(writeFp) != 0) {
189 PROFILER_LOG_ERROR(LOG_CORE, "fclose() error");
190 }
191 return;
192 }
193
194 int ret = fflush(writeFp);
195 if (ret == EOF) {
196 const int bufSize = 256;
197 char buf[bufSize] = { 0 };
198 strerror_r(errno, buf, bufSize);
199 PROFILER_LOG_ERROR(LOG_CORE, "CreateConfigFile: fflush() error = %s", buf);
200 if (fclose(writeFp) != 0) {
201 PROFILER_LOG_ERROR(LOG_CORE, "fclose() error");
202 }
203 return;
204 }
205
206 fsync(fileno(writeFp));
207 ret = fclose(writeFp);
208 if (ret != 0) {
209 const int bufSize = 256;
210 char buf[bufSize] = { 0 };
211 strerror_r(errno, buf, bufSize);
212 PROFILER_LOG_ERROR(LOG_CORE, "CreateConfigFile: fclose() error = %s", buf);
213 return;
214 }
215 }
216
CreateCommand(const std::string &outFile, int time) const217 std::string CreateCommand(const std::string &outFile, int time) const
218 {
219 std::string cmdStr =
220 "hiprofiler_cmd \\\n"
221 "-c - \\\n";
222 cmdStr += "-o " + outFile + " \\\n";
223 cmdStr += "-t " + std::to_string(time) + " \\\n";
224 cmdStr += "-k \\\n"
225 "<<CONFIG\n"
226 "request_id: 1\n"
227 "session_config {\n"
228 " buffers {\n"
229 " pages: 1000\n"
230 " }\n"
231 " result_file: \"/data/local/tmp/hiprofiler_data.htrace\"\n"
232 " sample_duration: 1000\n"
233 "}\n"
234 "plugin_configs {\n"
235 " plugin_name: \"ftrace-plugin\"\n"
236 " sample_interval: 1000\n"
237 " is_protobuf_serialize: true\n"
238 " config_data {\n"
239 " ftrace_events: \"sched/sched_switch\"\n"
240 " ftrace_events: \"sched/sched_wakeup\"\n"
241 " ftrace_events: \"sched/sched_wakeup_new\"\n"
242 " ftrace_events: \"sched/sched_waking\"\n"
243 " ftrace_events: \"sched/sched_process_exit\"\n"
244 " ftrace_events: \"sched/sched_process_free\"\n"
245 " hitrace_categories: \"ability\"\n"
246 " hitrace_categories: \"ace\"\n"
247 " buffer_size_kb: 51200\n"
248 " flush_interval_ms: 1000\n"
249 " flush_threshold_kb: 4096\n"
250 " parse_ksyms: true\n"
251 " clock: \"mono\"\n"
252 " trace_period_ms: 200\n"
253 " debug_on: false\n"
254 " }\n"
255 "}\n"
256 "CONFIG\n";
257 return cmdStr;
258 }
259
CreateHiperfCommand(const std::string &outFile, int time) const260 std::string CreateHiperfCommand(const std::string &outFile, int time) const
261 {
262 std::string cmdStr =
263 "hiprofiler_cmd \\\n"
264 "-c - \\\n";
265 cmdStr += "-o " + outFile + " \\\n";
266 cmdStr += "-t " + std::to_string(time) + " \\\n";
267 cmdStr += "-k \\\n"
268 "<<CONFIG\n"
269 "request_id: 1\n"
270 "session_config {\n"
271 " buffers {\n"
272 " pages: 1000\n"
273 " }\n"
274 " result_file: \"/data/local/tmp/hiprofiler_data.htrace\"\n"
275 " sample_duration: 1000\n"
276 "}\n"
277 "plugin_configs {\n"
278 " plugin_name: \"hiperf-plugin\"\n"
279 " sample_interval: 1000\n"
280 " is_protobuf_serialize: true\n"
281 " config_data {\n"
282 " is_root: false\n"
283 " outfile_name: \"/data/local/tmp/perf.data\"\n"
284 " record_args: \"-f 1000 -a --call-stack dwarf\"\n"
285 " }\n"
286 "}\n"
287 "CONFIG\n";
288 return cmdStr;
289 }
290
CreateEncoderCommand(const std::string &outFile, int time) const291 std::string CreateEncoderCommand(const std::string &outFile, int time) const
292 {
293 std::string cmdStr =
294 "hiprofiler_cmd \\\n"
295 "-c - \\\n";
296 cmdStr += "-k \\\n";
297 cmdStr += "-o " + outFile + " \\\n";
298 cmdStr += "-t " + std::to_string(time) + " \\\n"
299 "<<CONFIG\n"
300 "request_id: 1\n"
301 "session_config {\n"
302 " buffers {\n"
303 " pages: 1000\n"
304 " }\n"
305 " result_file: \"/data/local/tmp/hiprofiler_data.htrace\"\n"
306 " sample_duration: 3000\n"
307 "}\n"
308 "plugin_configs {\n"
309 " plugin_name: \"ftrace-plugin\"\n"
310 " sample_interval: 1000\n"
311 " config_data {\n"
312 " ftrace_events: \"sched/sched_switch\"\n"
313 " ftrace_events: \"sched/sched_wakeup\"\n"
314 " ftrace_events: \"sched/sched_wakeup_new\"\n"
315 " ftrace_events: \"sched/sched_waking\"\n"
316 " ftrace_events: \"sched/sched_process_exit\"\n"
317 " ftrace_events: \"sched/sched_process_free\"\n"
318 " hitrace_categories: \"ability\"\n"
319 " hitrace_categories: \"ace\"\n"
320 " buffer_size_kb: 51200\n"
321 " flush_interval_ms: 1000\n"
322 " flush_threshold_kb: 4096\n"
323 " parse_ksyms: true\n"
324 " clock: \"mono\"\n"
325 " trace_period_ms: 200\n"
326 " debug_on: false\n"
327 " }\n"
328 "}\n"
329 "CONFIG\n";
330 return cmdStr;
331 }
332
CreateSplitHtraceCommand(const std::string &outFile, int time) const333 std::string CreateSplitHtraceCommand(const std::string &outFile, int time) const
334 {
335 std::string cmdStr =
336 "hiprofiler_cmd -s -k \\\n"
337 "-c - \\\n";
338 cmdStr += "-o " + outFile + " \\\n";
339 cmdStr += "-t " + std::to_string(time) + " \\\n"
340 "<<CONFIG\n"
341 "request_id: 1\n"
342 "session_config {\n"
343 " buffers {\n"
344 " pages: 16384\n"
345 " }\n"
346 " split_file: true\n"
347 "}\n"
348 "plugin_configs {\n"
349 " plugin_name: \"ftrace-plugin\"\n"
350 " sample_interval: 1000\n"
351 " config_data {\n"
352 " ftrace_events: \"sched/sched_switch\"\n"
353 " ftrace_events: \"sched/sched_wakeup\"\n"
354 " ftrace_events: \"sched/sched_wakeup_new\"\n"
355 " ftrace_events: \"sched/sched_waking\"\n"
356 " ftrace_events: \"sched/sched_process_exit\"\n"
357 " ftrace_events: \"sched/sched_process_free\"\n"
358 " buffer_size_kb: 51200\n"
359 " flush_interval_ms: 1000\n"
360 " flush_threshold_kb: 4096\n"
361 " parse_ksyms: true\n"
362 " clock: \"mono\"\n"
363 " trace_period_ms: 200\n"
364 " debug_on: false\n"
365 " }\n"
366 "}\n"
367 "CONFIG\n";
368 return cmdStr;
369 }
370
CreateSplitHiperfCommand(const std::string &outFile, const std::string &perfFile, const std::string &perfSplitFile, int time) const371 std::string CreateSplitHiperfCommand(const std::string &outFile, const std::string &perfFile,
372 const std::string &perfSplitFile, int time) const
373 {
374 std::string cmdStr =
375 "hiprofiler_cmd -s -k \\\n"
376 "-c - \\\n";
377 cmdStr += "-o " + outFile + " \\\n";
378 cmdStr += "-t " + std::to_string(time) + " \\\n"
379 "<<CONFIG\n"
380 "request_id: 1\n"
381 "session_config {\n"
382 " buffers {\n"
383 " pages: 16384\n"
384 " }\n"
385 " split_file: true\n"
386 "}\n"
387 "plugin_configs {\n"
388 " plugin_name: \"hiperf-plugin\"\n"
389 " config_data {\n"
390 " is_root: false\n"
391 " outfile_name: \"" + perfFile + "\"\n"
392 " record_args: \"-f 1000 -a --cpu-limit 100 -e hw-cpu-cycles,sched:sched_waking --call-stack dwarf --clockid monotonic --offcpu -m 256\"\n"
393 " split_outfile_name: \"" + perfSplitFile + "\"\n"
394 " }\n"
395 "}\n"
396 "CONFIG\n";
397 return cmdStr;
398 }
399
CreateSplitHiebpfCommand(const std::string &outFile, const std::string &ebpfFile, const std::string &ebpfSplitFile, int time) const400 std::string CreateSplitHiebpfCommand(const std::string &outFile, const std::string &ebpfFile,
401 const std::string &ebpfSplitFile, int time) const
402 {
403 std::string cmdStr =
404 "hiprofiler_cmd -s -k \\\n"
405 "-c - \\\n";
406 cmdStr += "-o " + outFile + " \\\n";
407 cmdStr += "-t " + std::to_string(time) + " \\\n"
408 "<<CONFIG\n"
409 "request_id: 1\n"
410 "session_config {\n"
411 " buffers {\n"
412 " pages: 16384\n"
413 " }\n"
414 " split_file: true\n"
415 "}\n"
416 "plugin_configs {\n"
417 " plugin_name: \"hiebpf-plugin\"\n"
418 " config_data {\n"
419 " cmd_line: \"hiebpf --events fs,ptrace,bio --duration 200 --max_stack_depth 10\"\n"
420 " outfile_name: \"" + ebpfFile + "\"\n"
421 " split_outfile_name: \"" + ebpfSplitFile + "\"\n"
422 " }\n"
423 "}\n"
424 "CONFIG\n";
425 return cmdStr;
426 }
427
GetFileSize(const char* filename)428 unsigned long GetFileSize(const char* filename)
429 {
430 struct stat buf;
431
432 if (stat(filename, &buf) < 0) {
433 return 0;
434 }
435 return static_cast<unsigned long>(buf.st_size);
436 }
437
KillProcess(const std::string processName)438 void KillProcess(const std::string processName)
439 {
440 int pid = -1;
441 std::string findpid = "pidof " + processName;
442 PROFILER_LOG_INFO(LOG_CORE, "find pid command : %s", findpid.c_str());
443 std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(findpid.c_str(), "r"), pclose);
444
445 char line[LINE_SIZE];
446 do {
447 if (fgets(line, sizeof(line), pipe.get()) == nullptr) {
448 PROFILER_LOG_INFO(LOG_CORE, "not find processName : %s", processName.c_str());
449 return;
450 } else if (strlen(line) > 0 && isdigit(static_cast<unsigned char>(line[0]))) {
451 pid = atoi(line);
452 PROFILER_LOG_INFO(LOG_CORE, "find processName : %s, pid: %d", processName.c_str(), pid);
453 break;
454 }
455 } while (1);
456
457 if (pid != -1) {
458 StopProcessStub(pid);
459 }
460 }
461 private:
462 int hiprofilerdPid_ = -1;
463 int hiprofilerPluginsPid_ = -1;
464 };
465
466 /**
467 * @tc.name: hiprofiler_cmd
468 * @tc.desc: Test hiprofiler_cmd with -h -q.
469 * @tc.type: FUNC
470 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0110, Function | MediumTest | Level1)471 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0110, Function | MediumTest | Level1)
472 {
473 KillProcess(DEFAULT_HIPROFILERD_NAME);
474 KillProcess(DEFAULT_HIPROFILER_PLUGINS_NAME);
475
476 std::string cmd = DEFAULT_HIPROFILER_CMD_PATH + " -h";
477 std::string content = "";
478 EXPECT_TRUE(RunCommand(cmd, content));
479 std::string destStr = "help";
480 EXPECT_EQ(strncmp(content.c_str(), destStr.c_str(), strlen(destStr.c_str())), 0);
481
482 content = "";
483 cmd = DEFAULT_HIPROFILER_CMD_PATH + " -q";
484 EXPECT_TRUE(RunCommand(cmd, content));
485 destStr = "Service not started";
486 EXPECT_EQ(strncmp(content.c_str(), destStr.c_str(), strlen(destStr.c_str())), 0);
487
488 StartServerStub(DEFAULT_HIPROFILERD_PATH);
489 sleep(1);
490 content = "";
491 EXPECT_TRUE(RunCommand(cmd, content));
492 destStr = "OK";
493 EXPECT_EQ(strncmp(content.c_str(), destStr.c_str(), strlen(destStr.c_str())), 0);
494 StopProcessStub(hiprofilerdPid_);
495 }
496
497 /**
498 * @tc.name: hiprofiler_cmd
499 * @tc.desc: Test hiprofiler_cmd with -c file.
500 * @tc.type: FUNC
501 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0120, Function | MediumTest | Level1)502 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0120, Function | MediumTest | Level1)
503 {
504 KillProcess(DEFAULT_HIPROFILERD_NAME);
505 KillProcess(DEFAULT_HIPROFILER_PLUGINS_NAME);
506
507 // 测试不存在的config文件
508 std::string configTestFile = DEFAULT_PATH + "1234.txt";
509 std::string outFile = DEFAULT_PATH + "trace.htrace";
510 std::string content = "";
511 std::string cmd = DEFAULT_HIPROFILER_CMD_PATH + " -c " + configTestFile + " -o " + outFile + " -t 3";
512 EXPECT_TRUE(RunCommand(cmd, content));
513 std::string destStr = "Read " + configTestFile + " fail";
514 EXPECT_TRUE(content.find(destStr) != std::string::npos);
515
516 // 创建有效的config文件
517 const std::string configFile = DEFAULT_PATH + "ftrace.config";
518 CreateConfigFile(configFile);
519
520 // 测试有效的config文件,不开启hiprofilerd和hiprofiler_plugin进程
521 content = "";
522 cmd = DEFAULT_HIPROFILER_CMD_PATH + " -c " + configFile + " -o " + outFile + " -t 3";
523 EXPECT_TRUE(RunCommand(cmd, content));
524 sleep(SLEEP_TIME);
525 EXPECT_NE(access(outFile.c_str(), F_OK), 0);
526
527 // 开启hiprofilerd和hiprofiler_plugin进程,可以生成trace文件
528 content = "";
529 StartServerStub(DEFAULT_HIPROFILERD_PATH);
530 sleep(1);
531 StartServerStub(DEFAULT_HIPROFILER_PLUGINS_PATH);
532 sleep(1);
533 EXPECT_TRUE(RunCommand(cmd, content));
534 sleep(SLEEP_TIME);
535 EXPECT_EQ(access(outFile.c_str(), F_OK), 0);
536
537 // 删除资源文件和生成的trace文件
538 cmd = "rm " + configFile + " " + outFile;
539 system(cmd.c_str());
540 StopProcessStub(hiprofilerPluginsPid_);
541 StopProcessStub(hiprofilerdPid_);
542 }
543
544 /**
545 * @tc.name: hiprofiler_cmd
546 * @tc.desc: Test hiprofiler_cmd with -c string.
547 * @tc.type: FUNC
548 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0130, Function | MediumTest | Level1)549 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0130, Function | MediumTest | Level1)
550 {
551 std::string cmd = "cp " + DEFAULT_SO_PATH + "libftrace_plugin.z.so " + DEFAULT_PATH;
552 system(cmd.c_str());
553
554 // 开启hiprofilerd和hiprofiler_plugin进程,验证字符串格式的config
555 std::string content = "";
556 StartServerStub(DEFAULT_HIPROFILERD_PATH);
557 sleep(1);
558 StartServerStub(DEFAULT_HIPROFILER_PLUGINS_PATH);
559 sleep(1);
560 std::string outFile = DEFAULT_PATH + "trace.htrace";
561 int time = 3;
562 cmd = CreateCommand(outFile, time);
563 EXPECT_TRUE(RunCommand(cmd, content));
564 sleep(time);
565 EXPECT_EQ(access(outFile.c_str(), F_OK), 0);
566
567 // 删除资源文件和生成的trace文件
568 cmd = "rm " + FTRACE_PLUGIN_PATH + " " + outFile;
569 system(cmd.c_str());
570 StopProcessStub(hiprofilerPluginsPid_);
571 StopProcessStub(hiprofilerdPid_);
572 }
573
574 /**
575 * @tc.name: hiprofiler_cmd
576 * @tc.desc: Test hiprofiler_cmd with -s -l -k.
577 * @tc.type: FUNC
578 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0140, Function | MediumTest | Level1)579 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0140, Function | MediumTest | Level1)
580 {
581 KillProcess(DEFAULT_HIPROFILERD_NAME);
582 KillProcess(DEFAULT_HIPROFILER_PLUGINS_NAME);
583
584 std::string cmd = DEFAULT_HIPROFILER_CMD_PATH + " -s -l -k";
585 std::string content = "";
586 EXPECT_TRUE(RunCommand(cmd, content));
587 std::string destStr = "plugin";
588 EXPECT_TRUE(content.find(destStr) != std::string::npos);
589 }
590
591 /**
592 * @tc.name: hiprofiler_cmd
593 * @tc.desc: Test hiprofiler_cmd with -l -k.
594 * @tc.type: FUNC
595 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0150, Function | MediumTest | Level1)596 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0150, Function | MediumTest | Level1)
597 {
598 KillProcess(DEFAULT_HIPROFILERD_NAME);
599 KillProcess(DEFAULT_HIPROFILER_PLUGINS_NAME);
600
601 std::string cmd = DEFAULT_HIPROFILER_CMD_PATH + " -l -k";
602 std::string content = "";
603 EXPECT_TRUE(RunCommand(cmd, content));
604 }
605
606 /**
607 * @tc.name: hiprofiler_cmd
608 * @tc.desc: Test hiprofiler_cmd with -k.
609 * @tc.type: FUNC
610 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0160, Function | MediumTest | Level1)611 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0160, Function | MediumTest | Level1)
612 {
613 KillProcess(DEFAULT_HIPROFILERD_NAME);
614 KillProcess(DEFAULT_HIPROFILER_PLUGINS_NAME);
615
616 std::string cmd = DEFAULT_HIPROFILER_CMD_PATH + " -k";
617 std::string content = "";
618 EXPECT_TRUE(RunCommand(cmd, content));
619 }
620
621 /**
622 * @tc.name: hiprofiler_cmd
623 * @tc.desc: Test hiprofiler_cmd with proto encoder.
624 * @tc.type: FUNC
625 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0170, Function | MediumTest | Level1)626 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0170, Function | MediumTest | Level1)
627 {
628 std::string cmd = "cp " + DEFAULT_SO_PATH + "libftrace_plugin.z.so " + DEFAULT_PATH;
629 system(cmd.c_str());
630
631 // 开启hiprofilerd和hiprofiler_plugin进程,验证字符串格式的config
632 std::string content = "";
633 StartServerStub(DEFAULT_HIPROFILERD_PATH);
634 sleep(1);
635 StartServerStub(DEFAULT_HIPROFILER_PLUGINS_PATH);
636 sleep(1);
637 std::string outFile = DEFAULT_PATH + "trace_encoder.htrace";
638 int time = 3;
639 cmd = CreateEncoderCommand(outFile, time);
640 EXPECT_TRUE(RunCommand(cmd, content));
641 sleep(time);
642 EXPECT_EQ(access(outFile.c_str(), F_OK), 0);
643
644 // 删除资源文件和生成的trace文件
645 cmd = "rm " + FTRACE_PLUGIN_PATH + " " + outFile;
646 system(cmd.c_str());
647 StopProcessStub(hiprofilerPluginsPid_);
648 StopProcessStub(hiprofilerdPid_);
649 }
650
651 /**
652 * @tc.name: hiprofiler_cmd
653 * @tc.desc: Test hiprofiler_cmd with ctrl+c.
654 * @tc.type: FUNC
655 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0180, Function | MediumTest | Level1)656 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0180, Function | MediumTest | Level1)
657 {
658 std::string content = "";
659 std::string cmd = DEFAULT_HIPROFILER_CMD_PATH + " -s";
660 EXPECT_TRUE(RunCommand(cmd, content));
661 sleep(2); // 2: wait hiprofilerd start
662 pid_t pid = fork();
663 EXPECT_GE(pid, 0);
664 if (pid == 0) {
665 content = "";
666 const int time = 20;
667 std::string outFile = DEFAULT_PATH + "trace.htrace";
668 cmd = CreateCommand(outFile, time);
669 EXPECT_TRUE(RunCommand(cmd, content));
670 EXPECT_EQ(access(outFile.c_str(), F_OK), 0);
671 // 删除生成的trace文件
672 cmd = "rm " + outFile;
673 system(cmd.c_str());
674 _exit(0);
675 } else if (pid > 0) {
676 sleep(1); // 1: wait child process start
677 content = "";
678 cmd = "pidof hiprofiler_cmd";
679 EXPECT_TRUE(RunCommand(cmd, content));
680 ASSERT_STRNE(content.c_str(), "");
681 cmd = "kill -2 " + content;
682 content = "";
683 EXPECT_TRUE(RunCommand(cmd, content));
684 EXPECT_STREQ(content.c_str(), "");
685 // 等待子进程结束
686 waitpid(pid, nullptr, 0);
687 cmd = DEFAULT_HIPROFILER_CMD_PATH + " -k";
688 EXPECT_TRUE(RunCommand(cmd, content));
689 sleep(5); // 5: wait hiprofilerd exit
690 content = "";
691 cmd = "pidof " + DEFAULT_HIPROFILERD_NAME;
692 EXPECT_TRUE(RunCommand(cmd, content));
693 EXPECT_STREQ(content.c_str(), "");
694 }
695 }
696
697 /**
698 * @tc.name: hiprofiler_cmd
699 * @tc.desc: Test hiprofiler_cmd with -c string.
700 * @tc.type: FUNC
701 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0190, Function | MediumTest | Level1)702 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0190, Function | MediumTest | Level1)
703 {
704 std::string cmd = "cp " + DEFAULT_SO_PATH + "libhiperfplugin.z.so " + DEFAULT_PATH;
705 system(cmd.c_str());
706
707 // 开启hiprofilerd和hiprofiler_plugin进程,验证字符串格式的config
708 std::string content = "";
709 StartServerStub(DEFAULT_HIPROFILERD_PATH);
710 sleep(1);
711 StartServerStub(DEFAULT_HIPROFILER_PLUGINS_PATH);
712 sleep(1);
713 std::string outFile = DEFAULT_PATH + "trace.htrace";
714 int time = 10;
715 cmd = CreateHiperfCommand(outFile, time);
716 EXPECT_TRUE(RunCommand(cmd, content));
717 sleep(time);
718 EXPECT_EQ(access(outFile.c_str(), F_OK), 0);
719
720 // 删除资源文件和生成的trace文件
721 cmd = "rm " + HIPERF_PLUGIN_PATH + " " + outFile;
722 system(cmd.c_str());
723 StopProcessStub(hiprofilerPluginsPid_);
724 StopProcessStub(hiprofilerdPid_);
725 }
726 }
727
728 /**
729 * @tc.name: hiprofiler_cmd
730 * @tc.desc: Test hiprofiler_cmd with split Htrace file.
731 * @tc.type: FUNC
732 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0200, Function | MediumTest | Level1)733 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0200, Function | MediumTest | Level1)
734 {
735 std::string outFileName = "split_htrace";
736 std::string outFile = DEFAULT_PATH + outFileName + ".htrace";
737 std::string content = "";
738 int time = 10;
739 std::string cmd = CreateSplitHtraceCommand(outFile, time);
740 EXPECT_TRUE(RunCommand(cmd, content));
741
742 EXPECT_NE(access(outFile.c_str(), F_OK), 0);
743
744 cmd = "ls " + DEFAULT_PATH + outFileName + "*_1.htrace";
745 EXPECT_TRUE(RunCommand(cmd, content));
746 EXPECT_STRNE(content.c_str(), "");
747
748 cmd = "rm " + DEFAULT_PATH + outFileName + "*.htrace";
749 system(cmd.c_str());
750 }
751
752 /**
753 * @tc.name: hiprofiler_cmd
754 * @tc.desc: Test hiprofiler_cmd with split hiperf file.
755 * @tc.type: FUNC
756 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0220, Function | MediumTest | Level1)757 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0220, Function | MediumTest | Level1)
758 {
759 std::string outFileName = "split_hiperf";
760 std::string outFile = DEFAULT_PATH + outFileName + ".htrace";
761 std::string perfFile = "/data/local/tmp/perf.data";
762 std::string perfSplitFile = "/data/local/tmp/split_perf_data.htrace";
763 std::string content = "";
764 int time = 10;
765 std::string cmd = CreateSplitHiperfCommand(outFile, perfFile, perfSplitFile, time);
766 EXPECT_TRUE(RunCommand(cmd, content));
767
768 EXPECT_NE(access(outFile.c_str(), F_OK), 0);
769
770 cmd = "ls " + DEFAULT_PATH + outFileName + "*_1.htrace";
771 EXPECT_TRUE(RunCommand(cmd, content));
772 EXPECT_STRNE(content.c_str(), "");
773
774 EXPECT_EQ(access(perfSplitFile.c_str(), F_OK), 0);
775 if (access(perfFile.c_str(), F_OK) == 0) {
776 const int headerSize = 1024 + 1024; // htrace header + hiperf header
777 auto perfFileSize = GetFileSize(perfFile.c_str());
778 auto perfSplitFileSize = GetFileSize(perfSplitFile.c_str());
779 EXPECT_GT(perfSplitFileSize, perfFileSize + headerSize);
780 }
781
782 cmd = "rm " + DEFAULT_PATH + outFileName + "*.htrace " + perfFile + " " + perfSplitFile;
783 system(cmd.c_str());
784 }
785 /**
786 * @tc.name: hiprofiler_cmd
787 * @tc.desc: Test hiprofiler_cmd with split hiebpf file.
788 * @tc.type: FUNC
789 */
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0230, Function | MediumTest | Level1)790 HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0230, Function | MediumTest | Level1)
791 {
792 #if defined(__LP64__) // just support 64bit
793 std::string outFileName = "split_hiebpf";
794 std::string outFile = DEFAULT_PATH + outFileName + ".htrace";
795 std::string ebpfFile = "/data/local/tmp/ebpf.data";
796 std::string ebpfSplitFile = "/data/local/tmp/split_ebpf_data.htrace";
797 std::string content = "";
798 int time = 10;
799 std::string cmd = CreateSplitHiebpfCommand(outFile, ebpfFile, ebpfSplitFile, time);
800 EXPECT_TRUE(RunCommand(cmd, content));
801
802 EXPECT_NE(access(outFile.c_str(), F_OK), 0);
803
804 cmd = "ls " + DEFAULT_PATH + outFileName + "*_1.htrace";
805 EXPECT_TRUE(RunCommand(cmd, content));
806 EXPECT_STRNE(content.c_str(), "");
807
808 EXPECT_EQ(access(ebpfSplitFile.c_str(), F_OK), 0);
809 if (access(ebpfFile.c_str(), F_OK) == 0) {
810 const int headerSize = 1024 + 1024; // htrace header + hiebpf header
811 auto ebpfFileSize = GetFileSize(ebpfFile.c_str());
812 auto ebpfSplitFileSize = GetFileSize(ebpfSplitFile.c_str());
813 EXPECT_GT(ebpfSplitFileSize, ebpfFileSize + headerSize);
814 }
815
816 cmd = "rm " + DEFAULT_PATH + outFileName + "*.htrace " + ebpfFile + " " + ebpfSplitFile;
817 system(cmd.c_str());
818 #endif
819 }
820