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