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