1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "dfx_test_util.h"
17
18#include <fstream>
19#include <iostream>
20#include <sstream>
21#include <unistd.h>
22
23#include "dfx_define.h"
24#include <directory_ex.h>
25#include "file_util.h"
26#include <string_ex.h>
27
28namespace OHOS {
29namespace HiviewDFX {
30namespace {
31const int BUF_LEN = 128;
32}
33
34std::string ExecuteCommands(const std::string& cmds)
35{
36    if (cmds.empty()) {
37        return "";
38    }
39    FILE *procFileInfo = nullptr;
40    std::string cmdLog = "";
41    procFileInfo = popen(cmds.c_str(), "r");
42    if (procFileInfo == nullptr) {
43        perror("popen execute failed\n");
44        return cmdLog;
45    }
46    char res[BUF_LEN] = { '\0' };
47    while (fgets(res, sizeof(res), procFileInfo) != nullptr) {
48        cmdLog += res;
49    }
50    pclose(procFileInfo);
51    return cmdLog;
52}
53
54bool ExecuteCommands(const std::string& cmds, std::vector<std::string>& ress)
55{
56    if (cmds.empty()) {
57        return false;
58    }
59
60    ress.clear();
61    FILE *fp = nullptr;
62    fp = popen(cmds.c_str(), "r");
63    if (fp == nullptr) {
64        perror("popen execute failed\n");
65        return false;
66    }
67
68    char res[BUF_LEN] = { '\0' };
69    while (fgets(res, sizeof(res), fp) != nullptr) {
70        ress.push_back(std::string(res));
71    }
72    pclose(fp);
73    return true;
74}
75
76int GetProcessPid(const std::string& processName)
77{
78    std::string cmd = "pidof " + processName;
79    std::string pidStr = ExecuteCommands(cmd);
80    int32_t pid = 0;
81    std::stringstream pidStream(pidStr);
82    pidStream >> pid;
83    printf("the pid of process(%s) is %s \n", processName.c_str(), pidStr.c_str());
84    return pid;
85}
86
87int LaunchTestHap(const std::string& abilityName, const std::string& bundleName)
88{
89    std::string launchCmd = "/system/bin/aa start -a " + abilityName + " -b " + bundleName;
90    (void)ExecuteCommands(launchCmd);
91    sleep(2); // 2 : sleep 2s
92    return GetProcessPid(bundleName);
93}
94
95void StopTestHap(const std::string& bundleName)
96{
97    std::string stopCmd = "/system/bin/aa force-stop " + bundleName;
98    (void)ExecuteCommands(stopCmd);
99}
100
101void InstallTestHap(const std::string& hapName)
102{
103    std::string installCmd = "bm install -p " + hapName;
104    (void)ExecuteCommands(installCmd);
105}
106
107void UninstallTestHap(const std::string& bundleName)
108{
109    std::string uninstallCmd = "bm uninstall -n " + bundleName;
110    (void)ExecuteCommands(uninstallCmd);
111}
112
113int CountLines(const std::string& fileName)
114{
115    std::ifstream readFile;
116    readFile.open(fileName.c_str(), std::ios::in);
117    if (readFile.fail()) {
118        return 0;
119    } else {
120        int n = 0;
121        std::string tmpuseValue;
122        while (getline(readFile, tmpuseValue, '\n')) {
123            n++;
124        }
125        readFile.close();
126        return n;
127    }
128}
129
130bool CheckProcessComm(int pid, const std::string& name)
131{
132    std::string cmd = "cat /proc/" + std::to_string(pid) + "/comm";
133    std::string comm = ExecuteCommands(cmd);
134    size_t pos = comm.find('\n');
135    if (pos != std::string::npos) {
136        comm.erase(pos, 1);
137    }
138    if (!strcmp(comm.c_str(), name.c_str())) {
139        return true;
140    }
141    return false;
142}
143
144int CheckKeyWords(const std::string& filePath, std::string *keywords, int length, int minRegIdx)
145{
146    std::ifstream file;
147    file.open(filePath.c_str(), std::ios::in);
148    long lines = CountLines(filePath);
149    std::vector<std::string> t(lines * 4); // 4 : max string blocks of one line
150    int i = 0;
151    int j = 0;
152    std::string::size_type idx;
153    int count = 0;
154    int maxRegIdx = minRegIdx + REGISTERS_NUM + 1;
155    while (!file.eof()) {
156        file >> t.at(i);
157        idx = t.at(i).find(keywords[j]);
158        if (idx != std::string::npos) {
159            if (minRegIdx != -1 && j > minRegIdx && // -1 : do not check register value
160                j < maxRegIdx && t.at(i).size() < (REGISTER_FORMAT_LENGTH + 3)) { // 3 : register label length
161                count--;
162            }
163            count++;
164            j++;
165            if (j == length) {
166                break;
167            }
168            continue;
169        }
170        i++;
171    }
172    file.close();
173    std::cout << "Matched keywords count: " << count << std::endl;
174    if (j < length) {
175        std::cout << "Not found keyword: " << keywords[j] << std::endl;
176    }
177    return count;
178}
179
180bool CheckContent(const std::string& content, const std::string& keyContent, bool checkExist)
181{
182    bool findKeyContent = false;
183    if (content.find(keyContent) != std::string::npos) {
184        findKeyContent = true;
185    }
186
187    if (checkExist && !findKeyContent) {
188        printf("Failed to find: %s in %s\n", keyContent.c_str(), content.c_str());
189        return false;
190    }
191
192    if (!checkExist && findKeyContent) {
193        printf("Find: %s in %s\n", keyContent.c_str(), content.c_str());
194        return false;
195    }
196    return true;
197}
198
199int GetKeywordsNum(const std::string& msg, std::string *keywords, int length)
200{
201    int count = 0;
202    std::string::size_type idx;
203    for (int i = 0; i < length; i++) {
204        idx = msg.find(keywords[i]);
205        if (idx != std::string::npos) {
206            count++;
207        }
208    }
209    return count;
210}
211
212std::string GetCppCrashFileName(const pid_t pid, const std::string& tempPath)
213{
214    std::string filePath = "";
215    if (pid <= 0) {
216        return filePath;
217    }
218    std::string fileNamePrefix = "cppcrash-" + std::to_string(pid);
219    std::vector<std::string> files;
220    OHOS::GetDirFiles(tempPath, files);
221    for (const auto& file : files) {
222        if (file.find(fileNamePrefix) != std::string::npos) {
223            filePath = file;
224            break;
225        }
226    }
227    return filePath;
228}
229
230uint64_t GetSelfMemoryCount()
231{
232    std::string path = "/proc/self/smaps_rollup";
233    std::string content;
234    if (!OHOS::HiviewDFX::LoadStringFromFile(path, content)) {
235        printf("Failed to load path content: %s\n", path.c_str());
236        return 0;
237    }
238
239    std::vector<std::string> result;
240    OHOS::SplitStr(content, "\n", result);
241    auto iter = std::find_if(result.begin(), result.end(),
242        [] (const std::string& str) {
243            return str.find("Pss:") != std::string::npos;
244        });
245    if (iter == result.end()) {
246        perror("Failed to find Pss.\n");
247        return 0;
248    }
249
250    std::string pss = *iter;
251    uint64_t retVal = 0;
252    for (size_t i = 0; i < pss.size(); i++) {
253        if (isdigit(pss[i])) {
254            retVal = atoi(&pss[i]);
255            break;
256        }
257    }
258    return retVal;
259}
260
261uint32_t GetSelfMapsCount()
262{
263    std::string path = std::string(PROC_SELF_MAPS_PATH);
264    std::string content;
265    if (!OHOS::HiviewDFX::LoadStringFromFile(path, content)) {
266        printf("Failed to load path content: %s\n", path.c_str());
267        return 0;
268    }
269
270    std::vector<std::string> result;
271    OHOS::SplitStr(content, "\n", result);
272    return result.size();
273}
274
275uint32_t GetSelfFdCount()
276{
277    std::string path = "/proc/self/fd";
278    std::vector<std::string> content;
279    OHOS::GetDirFiles(path, content);
280    return content.size();
281}
282
283void CheckResourceUsage(uint32_t fdCount, uint32_t mapsCount, uint64_t memCount)
284{
285    // check memory/fd/maps
286    auto curFdCount = GetSelfFdCount();
287    printf("AfterTest Fd New: %u\n", curFdCount);
288    printf("Fd Old: %u\n", fdCount);
289
290    auto curMapsCount = GetSelfMapsCount();
291    printf("AfterTest Maps New: %u\n", curMapsCount);
292    printf("Maps Old: %u\n", mapsCount);
293
294    auto curMemSize = GetSelfMemoryCount();
295    printf("AfterTest Memory New: %lu\n", static_cast<unsigned long>(curMemSize));
296    printf("Memory Old: %lu\n", static_cast<unsigned long>(memCount));
297}
298} // namespace HiviewDFX
299} // namespace OHOS