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