1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include "dfx_test_util.h"
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <fstream>
19800b99b8Sopenharmony_ci#include <iostream>
20800b99b8Sopenharmony_ci#include <sstream>
21800b99b8Sopenharmony_ci#include <unistd.h>
22800b99b8Sopenharmony_ci
23800b99b8Sopenharmony_ci#include "dfx_define.h"
24800b99b8Sopenharmony_ci#include <directory_ex.h>
25800b99b8Sopenharmony_ci#include "file_util.h"
26800b99b8Sopenharmony_ci#include <string_ex.h>
27800b99b8Sopenharmony_ci
28800b99b8Sopenharmony_cinamespace OHOS {
29800b99b8Sopenharmony_cinamespace HiviewDFX {
30800b99b8Sopenharmony_cinamespace {
31800b99b8Sopenharmony_ciconst int BUF_LEN = 128;
32800b99b8Sopenharmony_ci}
33800b99b8Sopenharmony_ci
34800b99b8Sopenharmony_cistd::string ExecuteCommands(const std::string& cmds)
35800b99b8Sopenharmony_ci{
36800b99b8Sopenharmony_ci    if (cmds.empty()) {
37800b99b8Sopenharmony_ci        return "";
38800b99b8Sopenharmony_ci    }
39800b99b8Sopenharmony_ci    FILE *procFileInfo = nullptr;
40800b99b8Sopenharmony_ci    std::string cmdLog = "";
41800b99b8Sopenharmony_ci    procFileInfo = popen(cmds.c_str(), "r");
42800b99b8Sopenharmony_ci    if (procFileInfo == nullptr) {
43800b99b8Sopenharmony_ci        perror("popen execute failed\n");
44800b99b8Sopenharmony_ci        return cmdLog;
45800b99b8Sopenharmony_ci    }
46800b99b8Sopenharmony_ci    char res[BUF_LEN] = { '\0' };
47800b99b8Sopenharmony_ci    while (fgets(res, sizeof(res), procFileInfo) != nullptr) {
48800b99b8Sopenharmony_ci        cmdLog += res;
49800b99b8Sopenharmony_ci    }
50800b99b8Sopenharmony_ci    pclose(procFileInfo);
51800b99b8Sopenharmony_ci    return cmdLog;
52800b99b8Sopenharmony_ci}
53800b99b8Sopenharmony_ci
54800b99b8Sopenharmony_cibool ExecuteCommands(const std::string& cmds, std::vector<std::string>& ress)
55800b99b8Sopenharmony_ci{
56800b99b8Sopenharmony_ci    if (cmds.empty()) {
57800b99b8Sopenharmony_ci        return false;
58800b99b8Sopenharmony_ci    }
59800b99b8Sopenharmony_ci
60800b99b8Sopenharmony_ci    ress.clear();
61800b99b8Sopenharmony_ci    FILE *fp = nullptr;
62800b99b8Sopenharmony_ci    fp = popen(cmds.c_str(), "r");
63800b99b8Sopenharmony_ci    if (fp == nullptr) {
64800b99b8Sopenharmony_ci        perror("popen execute failed\n");
65800b99b8Sopenharmony_ci        return false;
66800b99b8Sopenharmony_ci    }
67800b99b8Sopenharmony_ci
68800b99b8Sopenharmony_ci    char res[BUF_LEN] = { '\0' };
69800b99b8Sopenharmony_ci    while (fgets(res, sizeof(res), fp) != nullptr) {
70800b99b8Sopenharmony_ci        ress.push_back(std::string(res));
71800b99b8Sopenharmony_ci    }
72800b99b8Sopenharmony_ci    pclose(fp);
73800b99b8Sopenharmony_ci    return true;
74800b99b8Sopenharmony_ci}
75800b99b8Sopenharmony_ci
76800b99b8Sopenharmony_ciint GetProcessPid(const std::string& processName)
77800b99b8Sopenharmony_ci{
78800b99b8Sopenharmony_ci    std::string cmd = "pidof " + processName;
79800b99b8Sopenharmony_ci    std::string pidStr = ExecuteCommands(cmd);
80800b99b8Sopenharmony_ci    int32_t pid = 0;
81800b99b8Sopenharmony_ci    std::stringstream pidStream(pidStr);
82800b99b8Sopenharmony_ci    pidStream >> pid;
83800b99b8Sopenharmony_ci    printf("the pid of process(%s) is %s \n", processName.c_str(), pidStr.c_str());
84800b99b8Sopenharmony_ci    return pid;
85800b99b8Sopenharmony_ci}
86800b99b8Sopenharmony_ci
87800b99b8Sopenharmony_ciint LaunchTestHap(const std::string& abilityName, const std::string& bundleName)
88800b99b8Sopenharmony_ci{
89800b99b8Sopenharmony_ci    std::string launchCmd = "/system/bin/aa start -a " + abilityName + " -b " + bundleName;
90800b99b8Sopenharmony_ci    (void)ExecuteCommands(launchCmd);
91800b99b8Sopenharmony_ci    sleep(2); // 2 : sleep 2s
92800b99b8Sopenharmony_ci    return GetProcessPid(bundleName);
93800b99b8Sopenharmony_ci}
94800b99b8Sopenharmony_ci
95800b99b8Sopenharmony_civoid StopTestHap(const std::string& bundleName)
96800b99b8Sopenharmony_ci{
97800b99b8Sopenharmony_ci    std::string stopCmd = "/system/bin/aa force-stop " + bundleName;
98800b99b8Sopenharmony_ci    (void)ExecuteCommands(stopCmd);
99800b99b8Sopenharmony_ci}
100800b99b8Sopenharmony_ci
101800b99b8Sopenharmony_civoid InstallTestHap(const std::string& hapName)
102800b99b8Sopenharmony_ci{
103800b99b8Sopenharmony_ci    std::string installCmd = "bm install -p " + hapName;
104800b99b8Sopenharmony_ci    (void)ExecuteCommands(installCmd);
105800b99b8Sopenharmony_ci}
106800b99b8Sopenharmony_ci
107800b99b8Sopenharmony_civoid UninstallTestHap(const std::string& bundleName)
108800b99b8Sopenharmony_ci{
109800b99b8Sopenharmony_ci    std::string uninstallCmd = "bm uninstall -n " + bundleName;
110800b99b8Sopenharmony_ci    (void)ExecuteCommands(uninstallCmd);
111800b99b8Sopenharmony_ci}
112800b99b8Sopenharmony_ci
113800b99b8Sopenharmony_ciint CountLines(const std::string& fileName)
114800b99b8Sopenharmony_ci{
115800b99b8Sopenharmony_ci    std::ifstream readFile;
116800b99b8Sopenharmony_ci    readFile.open(fileName.c_str(), std::ios::in);
117800b99b8Sopenharmony_ci    if (readFile.fail()) {
118800b99b8Sopenharmony_ci        return 0;
119800b99b8Sopenharmony_ci    } else {
120800b99b8Sopenharmony_ci        int n = 0;
121800b99b8Sopenharmony_ci        std::string tmpuseValue;
122800b99b8Sopenharmony_ci        while (getline(readFile, tmpuseValue, '\n')) {
123800b99b8Sopenharmony_ci            n++;
124800b99b8Sopenharmony_ci        }
125800b99b8Sopenharmony_ci        readFile.close();
126800b99b8Sopenharmony_ci        return n;
127800b99b8Sopenharmony_ci    }
128800b99b8Sopenharmony_ci}
129800b99b8Sopenharmony_ci
130800b99b8Sopenharmony_cibool CheckProcessComm(int pid, const std::string& name)
131800b99b8Sopenharmony_ci{
132800b99b8Sopenharmony_ci    std::string cmd = "cat /proc/" + std::to_string(pid) + "/comm";
133800b99b8Sopenharmony_ci    std::string comm = ExecuteCommands(cmd);
134800b99b8Sopenharmony_ci    size_t pos = comm.find('\n');
135800b99b8Sopenharmony_ci    if (pos != std::string::npos) {
136800b99b8Sopenharmony_ci        comm.erase(pos, 1);
137800b99b8Sopenharmony_ci    }
138800b99b8Sopenharmony_ci    if (!strcmp(comm.c_str(), name.c_str())) {
139800b99b8Sopenharmony_ci        return true;
140800b99b8Sopenharmony_ci    }
141800b99b8Sopenharmony_ci    return false;
142800b99b8Sopenharmony_ci}
143800b99b8Sopenharmony_ci
144800b99b8Sopenharmony_ciint CheckKeyWords(const std::string& filePath, std::string *keywords, int length, int minRegIdx)
145800b99b8Sopenharmony_ci{
146800b99b8Sopenharmony_ci    std::ifstream file;
147800b99b8Sopenharmony_ci    file.open(filePath.c_str(), std::ios::in);
148800b99b8Sopenharmony_ci    long lines = CountLines(filePath);
149800b99b8Sopenharmony_ci    std::vector<std::string> t(lines * 4); // 4 : max string blocks of one line
150800b99b8Sopenharmony_ci    int i = 0;
151800b99b8Sopenharmony_ci    int j = 0;
152800b99b8Sopenharmony_ci    std::string::size_type idx;
153800b99b8Sopenharmony_ci    int count = 0;
154800b99b8Sopenharmony_ci    int maxRegIdx = minRegIdx + REGISTERS_NUM + 1;
155800b99b8Sopenharmony_ci    while (!file.eof()) {
156800b99b8Sopenharmony_ci        file >> t.at(i);
157800b99b8Sopenharmony_ci        idx = t.at(i).find(keywords[j]);
158800b99b8Sopenharmony_ci        if (idx != std::string::npos) {
159800b99b8Sopenharmony_ci            if (minRegIdx != -1 && j > minRegIdx && // -1 : do not check register value
160800b99b8Sopenharmony_ci                j < maxRegIdx && t.at(i).size() < (REGISTER_FORMAT_LENGTH + 3)) { // 3 : register label length
161800b99b8Sopenharmony_ci                count--;
162800b99b8Sopenharmony_ci            }
163800b99b8Sopenharmony_ci            count++;
164800b99b8Sopenharmony_ci            j++;
165800b99b8Sopenharmony_ci            if (j == length) {
166800b99b8Sopenharmony_ci                break;
167800b99b8Sopenharmony_ci            }
168800b99b8Sopenharmony_ci            continue;
169800b99b8Sopenharmony_ci        }
170800b99b8Sopenharmony_ci        i++;
171800b99b8Sopenharmony_ci    }
172800b99b8Sopenharmony_ci    file.close();
173800b99b8Sopenharmony_ci    std::cout << "Matched keywords count: " << count << std::endl;
174800b99b8Sopenharmony_ci    if (j < length) {
175800b99b8Sopenharmony_ci        std::cout << "Not found keyword: " << keywords[j] << std::endl;
176800b99b8Sopenharmony_ci    }
177800b99b8Sopenharmony_ci    return count;
178800b99b8Sopenharmony_ci}
179800b99b8Sopenharmony_ci
180800b99b8Sopenharmony_cibool CheckContent(const std::string& content, const std::string& keyContent, bool checkExist)
181800b99b8Sopenharmony_ci{
182800b99b8Sopenharmony_ci    bool findKeyContent = false;
183800b99b8Sopenharmony_ci    if (content.find(keyContent) != std::string::npos) {
184800b99b8Sopenharmony_ci        findKeyContent = true;
185800b99b8Sopenharmony_ci    }
186800b99b8Sopenharmony_ci
187800b99b8Sopenharmony_ci    if (checkExist && !findKeyContent) {
188800b99b8Sopenharmony_ci        printf("Failed to find: %s in %s\n", keyContent.c_str(), content.c_str());
189800b99b8Sopenharmony_ci        return false;
190800b99b8Sopenharmony_ci    }
191800b99b8Sopenharmony_ci
192800b99b8Sopenharmony_ci    if (!checkExist && findKeyContent) {
193800b99b8Sopenharmony_ci        printf("Find: %s in %s\n", keyContent.c_str(), content.c_str());
194800b99b8Sopenharmony_ci        return false;
195800b99b8Sopenharmony_ci    }
196800b99b8Sopenharmony_ci    return true;
197800b99b8Sopenharmony_ci}
198800b99b8Sopenharmony_ci
199800b99b8Sopenharmony_ciint GetKeywordsNum(const std::string& msg, std::string *keywords, int length)
200800b99b8Sopenharmony_ci{
201800b99b8Sopenharmony_ci    int count = 0;
202800b99b8Sopenharmony_ci    std::string::size_type idx;
203800b99b8Sopenharmony_ci    for (int i = 0; i < length; i++) {
204800b99b8Sopenharmony_ci        idx = msg.find(keywords[i]);
205800b99b8Sopenharmony_ci        if (idx != std::string::npos) {
206800b99b8Sopenharmony_ci            count++;
207800b99b8Sopenharmony_ci        }
208800b99b8Sopenharmony_ci    }
209800b99b8Sopenharmony_ci    return count;
210800b99b8Sopenharmony_ci}
211800b99b8Sopenharmony_ci
212800b99b8Sopenharmony_cistd::string GetCppCrashFileName(const pid_t pid, const std::string& tempPath)
213800b99b8Sopenharmony_ci{
214800b99b8Sopenharmony_ci    std::string filePath = "";
215800b99b8Sopenharmony_ci    if (pid <= 0) {
216800b99b8Sopenharmony_ci        return filePath;
217800b99b8Sopenharmony_ci    }
218800b99b8Sopenharmony_ci    std::string fileNamePrefix = "cppcrash-" + std::to_string(pid);
219800b99b8Sopenharmony_ci    std::vector<std::string> files;
220800b99b8Sopenharmony_ci    OHOS::GetDirFiles(tempPath, files);
221800b99b8Sopenharmony_ci    for (const auto& file : files) {
222800b99b8Sopenharmony_ci        if (file.find(fileNamePrefix) != std::string::npos) {
223800b99b8Sopenharmony_ci            filePath = file;
224800b99b8Sopenharmony_ci            break;
225800b99b8Sopenharmony_ci        }
226800b99b8Sopenharmony_ci    }
227800b99b8Sopenharmony_ci    return filePath;
228800b99b8Sopenharmony_ci}
229800b99b8Sopenharmony_ci
230800b99b8Sopenharmony_ciuint64_t GetSelfMemoryCount()
231800b99b8Sopenharmony_ci{
232800b99b8Sopenharmony_ci    std::string path = "/proc/self/smaps_rollup";
233800b99b8Sopenharmony_ci    std::string content;
234800b99b8Sopenharmony_ci    if (!OHOS::HiviewDFX::LoadStringFromFile(path, content)) {
235800b99b8Sopenharmony_ci        printf("Failed to load path content: %s\n", path.c_str());
236800b99b8Sopenharmony_ci        return 0;
237800b99b8Sopenharmony_ci    }
238800b99b8Sopenharmony_ci
239800b99b8Sopenharmony_ci    std::vector<std::string> result;
240800b99b8Sopenharmony_ci    OHOS::SplitStr(content, "\n", result);
241800b99b8Sopenharmony_ci    auto iter = std::find_if(result.begin(), result.end(),
242800b99b8Sopenharmony_ci        [] (const std::string& str) {
243800b99b8Sopenharmony_ci            return str.find("Pss:") != std::string::npos;
244800b99b8Sopenharmony_ci        });
245800b99b8Sopenharmony_ci    if (iter == result.end()) {
246800b99b8Sopenharmony_ci        perror("Failed to find Pss.\n");
247800b99b8Sopenharmony_ci        return 0;
248800b99b8Sopenharmony_ci    }
249800b99b8Sopenharmony_ci
250800b99b8Sopenharmony_ci    std::string pss = *iter;
251800b99b8Sopenharmony_ci    uint64_t retVal = 0;
252800b99b8Sopenharmony_ci    for (size_t i = 0; i < pss.size(); i++) {
253800b99b8Sopenharmony_ci        if (isdigit(pss[i])) {
254800b99b8Sopenharmony_ci            retVal = atoi(&pss[i]);
255800b99b8Sopenharmony_ci            break;
256800b99b8Sopenharmony_ci        }
257800b99b8Sopenharmony_ci    }
258800b99b8Sopenharmony_ci    return retVal;
259800b99b8Sopenharmony_ci}
260800b99b8Sopenharmony_ci
261800b99b8Sopenharmony_ciuint32_t GetSelfMapsCount()
262800b99b8Sopenharmony_ci{
263800b99b8Sopenharmony_ci    std::string path = std::string(PROC_SELF_MAPS_PATH);
264800b99b8Sopenharmony_ci    std::string content;
265800b99b8Sopenharmony_ci    if (!OHOS::HiviewDFX::LoadStringFromFile(path, content)) {
266800b99b8Sopenharmony_ci        printf("Failed to load path content: %s\n", path.c_str());
267800b99b8Sopenharmony_ci        return 0;
268800b99b8Sopenharmony_ci    }
269800b99b8Sopenharmony_ci
270800b99b8Sopenharmony_ci    std::vector<std::string> result;
271800b99b8Sopenharmony_ci    OHOS::SplitStr(content, "\n", result);
272800b99b8Sopenharmony_ci    return result.size();
273800b99b8Sopenharmony_ci}
274800b99b8Sopenharmony_ci
275800b99b8Sopenharmony_ciuint32_t GetSelfFdCount()
276800b99b8Sopenharmony_ci{
277800b99b8Sopenharmony_ci    std::string path = "/proc/self/fd";
278800b99b8Sopenharmony_ci    std::vector<std::string> content;
279800b99b8Sopenharmony_ci    OHOS::GetDirFiles(path, content);
280800b99b8Sopenharmony_ci    return content.size();
281800b99b8Sopenharmony_ci}
282800b99b8Sopenharmony_ci
283800b99b8Sopenharmony_civoid CheckResourceUsage(uint32_t fdCount, uint32_t mapsCount, uint64_t memCount)
284800b99b8Sopenharmony_ci{
285800b99b8Sopenharmony_ci    // check memory/fd/maps
286800b99b8Sopenharmony_ci    auto curFdCount = GetSelfFdCount();
287800b99b8Sopenharmony_ci    printf("AfterTest Fd New: %u\n", curFdCount);
288800b99b8Sopenharmony_ci    printf("Fd Old: %u\n", fdCount);
289800b99b8Sopenharmony_ci
290800b99b8Sopenharmony_ci    auto curMapsCount = GetSelfMapsCount();
291800b99b8Sopenharmony_ci    printf("AfterTest Maps New: %u\n", curMapsCount);
292800b99b8Sopenharmony_ci    printf("Maps Old: %u\n", mapsCount);
293800b99b8Sopenharmony_ci
294800b99b8Sopenharmony_ci    auto curMemSize = GetSelfMemoryCount();
295800b99b8Sopenharmony_ci    printf("AfterTest Memory New: %lu\n", static_cast<unsigned long>(curMemSize));
296800b99b8Sopenharmony_ci    printf("Memory Old: %lu\n", static_cast<unsigned long>(memCount));
297800b99b8Sopenharmony_ci}
298800b99b8Sopenharmony_ci} // namespace HiviewDFX
299800b99b8Sopenharmony_ci} // namespace OHOS