1 /*
2  * Copyright (C) 2021 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 "dbinder_service_test_helper.h"
17 #include <sys/time.h>
18 #include <csignal>
19 #include <unistd.h>
20 #include <vector>
21 #include <string>
22 #include <fstream>
23 #include <iostream>
24 #include <cstdlib>
25 #include <securec.h>
26 #include "ipc_types.h"
27 #include "hilog/log.h"
28 #include "log_tags.h"
29 
30 using namespace OHOS;
31 using namespace OHOS::HiviewDFX;
32 
33 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_TEST, "DbinderTestHelper" };
34 
GetPidByName(std::string taskName)35 pid_t GetPidByName(std::string taskName)
36 {
37     DIR *dir = nullptr;
38     struct dirent *ptr = nullptr;
39     FILE *fp = nullptr;
40     char filepath[PATH_LENGTH];
41     char curTaskName[PATH_LENGTH];
42     char buf[BUF_SIZE];
43     pid_t pid = INVALID_PID;
44 
45     dir = opendir("/proc");
46     if (dir == nullptr) {
47         return pid;
48     }
49     while ((ptr = readdir(dir)) != nullptr) {
50         if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
51             continue;
52         }
53         if (DT_DIR != ptr->d_type) {
54             continue;
55         }
56 
57         if (sprintf_s(filepath, sizeof(filepath), "/proc/%s/status", ptr->d_name) <= EOK) {
58             DBINDER_LOGI(LOG_LABEL, "sprintf_s fail");
59             closedir(dir);
60             return INVALID_PID;
61         }
62 
63         fp = fopen(filepath, "r");
64         if (fp != nullptr) {
65             if (fgets(buf, BUF_SIZE - 1, fp) == nullptr) {
66                 fclose(fp);
67                 continue;
68             }
69             (void)memset_s(curTaskName, sizeof(curTaskName), 0, sizeof(curTaskName));
70             if (sscanf_s(buf, "%*s %s", curTaskName, sizeof(curTaskName)) <= EOK) {
71                 DBINDER_LOGI(LOG_LABEL, "sscanf fail");
72             }
73 
74             if (!strcmp(taskName.c_str(), curTaskName)) {
75                 if (sscanf_s(ptr->d_name, "%d", &pid) <= EOK) {
76                     DBINDER_LOGI(LOG_LABEL, "sscanf fail");
77                 }
78             }
79             fclose(fp);
80         }
81     }
82     closedir(dir);
83     return pid;
84 }
85 
GetChildPids(std::vector<pid_t> & childPids)86 int GetChildPids(std::vector<pid_t> &childPids)
87 {
88     pid_t current = getpid();
89     DBINDER_LOGI(LOG_LABEL, "current pid %{public}d", current);
90     const std::string TASK_PATH = "/proc/" + std::to_string(current) + "/task";
91     DIR *dir = nullptr;
92     struct dirent *ptr = nullptr;
93 
94     dir = opendir(TASK_PATH.c_str());
95     if (dir != nullptr) {
96         while ((ptr = readdir(dir)) != nullptr) {
97             if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
98                 continue;
99             }
100             if (DT_DIR != ptr->d_type) {
101                 continue;
102             }
103 
104             pid_t child = std::stoi(ptr->d_name);
105             if (child == current) {
106                 continue;
107             }
108             childPids.push_back(child);
109             DBINDER_LOGI(LOG_LABEL, "child pid %{public}d", child);
110         }
111         closedir(dir);
112     }
113 
114     return ERR_NONE;
115 }
116 
StartExecutable(std::string name,std::string args)117 pid_t StartExecutable(std::string name, std::string args)
118 {
119     const char *ldLibraryPath = getenv("LD_LIBRARY_PATH");
120     if (ldLibraryPath != nullptr) {
121         unsetenv("LD_LIBRARY_PATH");
122     }
123     pid_t pid = GetPidByName(name);
124     if (pid != INVALID_PID) {
125         DBINDER_LOGI(LOG_LABEL, "test.service is already started, do nothing");
126         return pid;
127     }
128 
129     std::string cmd1 = "chmod +x /data/" + name;
130     int res = system(cmd1.c_str());
131     DBINDER_LOGI(LOG_LABEL, "%{public}s res = %d, errno = %{public}d", cmd1.c_str(), res, errno);
132 
133     std::string cmd2 = "/data/" + name + " " + args + "&";
134     res = system(cmd2.c_str());
135     DBINDER_LOGI(LOG_LABEL, "%{public}s res = %{public}d", cmd2.c_str(), res);
136 
137     if (ldLibraryPath != nullptr) {
138         setenv("LD_LIBRARY_PATH", ldLibraryPath, 1);
139     }
140     res = 0;
141     while (pid == INVALID_PID && res < 10) { // 10:try-time to wait for exe start
142         pid = GetPidByName(name);
143         DBINDER_LOGI(LOG_LABEL, "StartExecutable pid = %{public}d && name = %{public}s", pid, name.c_str());
144         usleep(100 * 1000); // 100:time-length 1000:time-unit
145         res++;
146     }
147 
148     DBINDER_LOGI(LOG_LABEL, "start %{public}s done", name.c_str());
149     return GetPidByName(name);
150 }
151 
StopExecutable(pid_t pid)152 void StopExecutable(pid_t pid)
153 {
154     kill(pid, SIGKILL);
155 }
156 
StopExecutable(std::string name)157 void StopExecutable(std::string name)
158 {
159     pid_t pid = GetPidByName(name);
160     DBINDER_LOGI(LOG_LABEL, "StopExecutable %{public}s pid = %{public}d, prepare to kill it", name.c_str(), pid);
161 
162     if (pid != INVALID_PID) {
163         DBINDER_LOGI(LOG_LABEL, "%{public}s pid = %{public}d, kill it", name.c_str(), pid);
164         kill(pid, SIGKILL);
165     }
166 }
167 
StartDBinderServiceSARegistry(void)168 int StartDBinderServiceSARegistry(void)
169 {
170     pid_t registryPid = GetPidByName(SYSTEM_ABILITY_MANAGER_NAME);
171     if (registryPid != -1) {
172         DBINDER_LOGI(LOG_LABEL, "SYSTEM_ABILITY_MANAGER_NAME Already Started pid=%{public}d", registryPid);
173         return registryPid;
174     }
175     StartExecutable(SYSTEM_ABILITY_MANAGER_NAME);
176     usleep(200 * 1000); // 100:200-length 1000:time-unit
177     DBINDER_LOGI(LOG_LABEL, "Start SYSTEM_ABILITY_MANAGER_NAME done");
178     return ERR_NONE;
179 }
180 
StopDBinderServiceSARegistry(void)181 void StopDBinderServiceSARegistry(void)
182 {
183     StopExecutable(SYSTEM_ABILITY_MANAGER_NAME);
184 }
185 
StartDBinderServiceTestService(void)186 void StartDBinderServiceTestService(void)
187 {
188     pid_t pid = StartExecutable(DBINDER_TEST_SERVICE_NAME);
189     DBINDER_LOGE(LOG_LABEL, "DBINDER_TEST_SERVICE_NAME pid : %{public}d", pid);
190 
191     pid = StartExecutable(DBINDER_TEST_SERVICE_NAME_SECOND);
192     DBINDER_LOGE(LOG_LABEL, "DBINDER_TEST_SERVICE_NAME_SECOND pid : %{public}d", pid);
193 }
194 
StopDBinderServiceTestService(void)195 void StopDBinderServiceTestService(void)
196 {
197     StopExecutable(DBINDER_TEST_SERVICE_NAME);
198     DBINDER_LOGE(LOG_LABEL, "Stop DBINDER_TEST_SERVICE_NAME");
199 
200     StopExecutable(DBINDER_TEST_SERVICE_NAME_SECOND);
201     DBINDER_LOGE(LOG_LABEL, "Stop DBINDER_TEST_SERVICE_NAME_SECOND");
202 }
203 
SetCurrentTestCase(int caseNum)204 int SetCurrentTestCase(int caseNum)
205 {
206     if (caseNum > DBINDER_TEST_START && caseNum < DBINDER_TEST_END) {
207         printf("SetCurrentTestCase to : %d\n", caseNum);
208         return g_currentTestCase = caseNum;
209     }
210     printf("SetCurrentTestCase to : %d\n", DBINDER_TEST_INIT);
211     return DBINDER_TEST_INIT;
212 }
213 
GetCurrentTestCase(void)214 int GetCurrentTestCase(void)
215 {
216     if (g_currentTestCase > DBINDER_TEST_START && g_currentTestCase < DBINDER_TEST_END) {
217         printf("GetCurrentTestCase is : %d\n", g_currentTestCase);
218         return g_currentTestCase;
219     }
220     printf("GetCurrentTestCase is : %d\n", DBINDER_TEST_INIT);
221     return DBINDER_TEST_INIT;
222 }
223 
GetCurrentTime(void)224 int64_t GetCurrentTime(void)
225 {
226     struct timeval timeInterval = {};
227     gettimeofday(&timeInterval, nullptr);
228     return timeInterval.tv_sec * SECOND_TO_MS + timeInterval.tv_usec / SECOND_TO_MS;
229 }
230 
GetSpeed(int64_t timeInterval,int size,int times)231 float GetSpeed(int64_t timeInterval, int size, int times)
232 {
233     if (timeInterval == 0) {
234         return 0;
235     }
236     float dataSize { times * size };
237     float costTime { timeInterval };
238     float speed = dataSize / costTime;
239     return speed * SECOND_TO_MS / KB_TO_B;
240 }
241