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
27using namespace testing::ext;
28
29#define HHB(v) (((v) & 0xF0) >> 4)
30#define LHB(v)  ((v) & 0x0F)
31
32namespace {
33#if defined(__LP64__)
34const std::string DEFAULT_SO_PATH("/system/lib64/");
35#else
36const std::string DEFAULT_SO_PATH("/system/lib/");
37#endif
38const std::string DEFAULT_HIPROFILERD_PATH("/system/bin/hiprofilerd");
39const std::string DEFAULT_HIPROFILER_PLUGINS_PATH("/system/bin/hiprofiler_plugins");
40const std::string DEFAULT_HIPROFILERD_NAME("hiprofilerd");
41const std::string DEFAULT_HIPROFILER_PLUGINS_NAME("hiprofiler_plugins");
42
43const std::string DEFAULT_HIPROFILER_CMD_PATH("/system/bin/hiprofiler_cmd");
44const std::string FTRACE_PLUGIN_PATH("/data/local/tmp/libftrace_plugin.z.so");
45const std::string HIPERF_PLUGIN_PATH("/data/local/tmp/libhiperfplugin.z.so");
46std::string DEFAULT_PATH("/data/local/tmp/");
47constexpr uint32_t READ_BUFFER_SIZE = 1024;
48constexpr int SLEEP_TIME = 3;
49constexpr int FILE_READ_CHUNK_SIZE = 4096;
50constexpr char HEX_CHARS[] = "0123456789abcdef";
51constexpr int LINE_SIZE = 1000;
52
53
54class HiprofilerCmdTest : public ::testing::Test {
55public:
56    static void SetUpTestCase() {}
57    static void TearDownTestCase() {}
58
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
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
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
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
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
217    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
260    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
291    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
333    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
371    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
400    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
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
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    }
461private:
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 */
471HWTEST_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 */
502HWTEST_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 */
549HWTEST_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 */
579HWTEST_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 */
596HWTEST_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 */
611HWTEST_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 */
626HWTEST_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 */
656HWTEST_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 */
702HWTEST_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 */
733HWTEST_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 */
757HWTEST_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 */
790HWTEST_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