1 /*
2 * Copyright (c) 2024 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 <cerrno>
17 #include <cstdlib>
18 #include <cstring>
19 #include <memory>
20 #include <string>
21 #include <unistd.h>
22 #include <gtest/gtest.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25
26 #include "appspawn_modulemgr.h"
27 #include "appspawn_server.h"
28 #include "appspawn_manager.h"
29 #include "app_spawn_stub.h"
30 #include "app_spawn_test_helper.h"
31 #include "json_utils.h"
32 #include "parameter.h"
33 #include "securec.h"
34
35 using namespace testing;
36 using namespace testing::ext;
37 using namespace OHOS;
38
39 namespace OHOS {
40 static AppSpawnTestHelper g_testHelper;
41 class AppSpawnCGroupTest : public testing::Test {
42 public:
SetUpTestCase()43 static void SetUpTestCase() {}
TearDownTestCase()44 static void TearDownTestCase() {}
SetUp()45 void SetUp() {}
TearDown()46 void TearDown() {}
47 };
48
CreateTestAppInfo(const char * name)49 static AppSpawnedProcess *CreateTestAppInfo(const char *name)
50 {
51 AppSpawnedProcess *appInfo = reinterpret_cast<AppSpawnedProcess *>(
52 malloc(sizeof(AppSpawnedProcess) + strlen(name) + 1));
53 APPSPAWN_CHECK(appInfo != nullptr, return nullptr, "Failed to create appInfo");
54 appInfo->pid = 33; // 33
55 appInfo->uid = 200000 * 200 + 21; // 200000 200 21
56 appInfo->max = 0;
57 appInfo->exitStatus = 0;
58 int ret = strcpy_s(appInfo->name, strlen(name) + 1, name);
59 APPSPAWN_CHECK(ret == 0,
60 free(appInfo); return nullptr, "Failed to strcpy process name");
61 OH_ListInit(&appInfo->node);
62 return appInfo;
63 }
64
GetTestCGroupFilePath(const AppSpawnedProcess * appInfo,const char * fileName,char * path,bool create)65 static int GetTestCGroupFilePath(const AppSpawnedProcess *appInfo, const char *fileName, char *path, bool create)
66 {
67 int ret = GetCgroupPath(appInfo, path, PATH_MAX);
68 APPSPAWN_CHECK(ret == 0, return errno, "Failed to get real path errno: %{public}d", errno);
69 (void)CreateSandboxDir(path, 0755); // 0755 default mode
70 ret = strcat_s(path, PATH_MAX, fileName);
71 APPSPAWN_CHECK(ret == 0, return errno, "Failed to strcat_s errno: %{public}d", errno);
72 if (create) {
73 FILE *file = fopen(path, "w");
74 APPSPAWN_CHECK(file != nullptr, return errno, "Create file fail %{public}s errno: %{public}d", path, errno);
75 fclose(file);
76 }
77 return 0;
78 }
79
80 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_001, TestSize.Level0)
81 {
82 int ret = -1;
83 AppSpawnedProcess *appInfo = nullptr;
84 const char name[] = "app-test-001";
85 do {
86 appInfo = CreateTestAppInfo(name);
87 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
88 char path[PATH_MAX] = {};
89 ret = GetCgroupPath(appInfo, path, sizeof(path));
90 APPSPAWN_CHECK(ret == 0, break, "Failed to get real path errno: %{public}d", errno);
91 APPSPAWN_CHECK(strstr(path, "200") != nullptr && strstr(path, "33") != nullptr && strstr(path, name) != nullptr,
92 break, "Invalid path: %s", path);
93 ret = 0;
94 } while (0);
95 if (appInfo) {
96 free(appInfo);
97 }
98 ASSERT_EQ(ret, 0);
99 }
100
101 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_002, TestSize.Level0)
102 {
103 int ret = -1;
104 AppSpawnedProcess *appInfo = nullptr;
105 AppSpawnContent *content = nullptr;
106 FILE *file = nullptr;
107 const char name[] = "app-test-001";
108 do {
109 char path[PATH_MAX] = {};
110 appInfo = CreateTestAppInfo(name);
111 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
112
113 ret = GetTestCGroupFilePath(appInfo, "cgroup.procs", path, true);
114 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
115 content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, path, sizeof(path), MODE_FOR_APP_SPAWN);
116 APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, break);
117 // spawn prepare process
118 ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, content, appInfo);
119
120 // add success
121 ret = GetTestCGroupFilePath(appInfo, "cgroup.procs", path, false);
122 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
123 // write pid
124 pid_t pids[] = {100, 101, 102};
125 ret = WriteToFile(path, 0, pids, 3);
126 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
127
128 ret = -1;
129 file = fopen(path, "r");
130 APPSPAWN_CHECK(file != nullptr, break, "Open file fail %{public}s errno: %{public}d", path, errno);
131 pid_t pid = 0;
132 ret = -1;
133 while (fscanf_s(file, "%d\n", &pid) == 1 && pid > 0) {
134 APPSPAWN_LOGV("pid %{public}d %{public}d", pid, appInfo->pid);
135 if (pid == appInfo->pid) {
136 ret = 0;
137 break;
138 }
139 }
140 APPSPAWN_CHECK(ret == 0, break, "Error no pid write to path errno: %{public}d", errno);
141
142 } while (0);
143 if (appInfo) {
144 free(appInfo);
145 }
146 if (file) {
147 fclose(file);
148 }
149 AppSpawnDestroyContent(content);
150 LE_StopLoop(LE_GetDefaultLoop());
151 LE_CloseLoop(LE_GetDefaultLoop());
152 ASSERT_EQ(ret, 0);
153 }
154
155 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_003, TestSize.Level0)
156 {
157 int ret = -1;
158 AppSpawnedProcess *appInfo = nullptr;
159 AppSpawnContent *content = nullptr;
160 const char name[] = "app-test-001";
161 do {
162 char path[PATH_MAX] = {};
163 appInfo = CreateTestAppInfo(name);
164 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
165
166 content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, path, sizeof(path), MODE_FOR_APP_SPAWN);
167 APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, break);
168 ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, content, appInfo);
169 ret = 0;
170 } while (0);
171 if (appInfo) {
172 free(appInfo);
173 }
174 AppSpawnDestroyContent(content);
175 LE_StopLoop(LE_GetDefaultLoop());
176 LE_CloseLoop(LE_GetDefaultLoop());
177 ASSERT_EQ(ret, 0);
178 }
179
180 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_004, TestSize.Level0)
181 {
182 int ret = -1;
183 AppSpawnedProcess *appInfo = nullptr;
184 AppSpawnContent *content = nullptr;
185 FILE *file = nullptr;
186 const char name[] = "app-test-001";
187 do {
188 char path[PATH_MAX] = {};
189 appInfo = CreateTestAppInfo(name);
190 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
191 appInfo->pid = 44; // 44 test pid
192
193 content = AppSpawnCreateContent(NWEBSPAWN_SOCKET_NAME, path, sizeof(path), MODE_FOR_NWEB_SPAWN);
194 APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, break);
195 ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, content, appInfo);
196 // add success
197 ret = GetCgroupPath(appInfo, path, sizeof(path));
198 APPSPAWN_CHECK(ret == 0, break, "Failed to get real path errno: %{public}d", errno);
199 ret = strcat_s(path, sizeof(path), "cgroup.procs");
200 APPSPAWN_CHECK(ret == 0, break, "Failed to strcat_s errno: %{public}d", errno);
201 // do not write for nwebspawn, so no file
202 file = fopen(path, "r");
203 APPSPAWN_CHECK(file == nullptr, break, "Find file %{public}s ", path);
204 } while (0);
205 if (appInfo) {
206 free(appInfo);
207 }
208 if (file) {
209 fclose(file);
210 }
211 AppSpawnDestroyContent(content);
212 LE_StopLoop(LE_GetDefaultLoop());
213 LE_CloseLoop(LE_GetDefaultLoop());
214 ASSERT_EQ(ret, 0);
215 }
216
217 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_005, TestSize.Level0)
218 {
219 int ret = -1;
220 AppSpawnedProcess *appInfo = nullptr;
221 AppSpawnContent *content = nullptr;
222 const char name[] = "app-test-001";
223 do {
224 char path[PATH_MAX] = {};
225 appInfo = CreateTestAppInfo(name);
226 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
227
228 content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, path, sizeof(path), MODE_FOR_NWEB_SPAWN);
229 APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, break);
230 ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, content, appInfo);
231 ret = 0;
232 } while (0);
233 if (appInfo) {
234 free(appInfo);
235 }
236 AppSpawnDestroyContent(content);
237 LE_StopLoop(LE_GetDefaultLoop());
238 LE_CloseLoop(LE_GetDefaultLoop());
239 ASSERT_EQ(ret, 0);
240 }
241
242 /**
243 * @brief in appspawn service, add and delete app
244 *
245 */
246 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_006, TestSize.Level0)
247 {
248 int ret = -1;
249 AppSpawnedProcess *appInfo = nullptr;
250 AppSpawnContent *content = nullptr;
251 const char name[] = "app-test-001";
252 do {
253 char path[PATH_MAX] = {};
254 appInfo = CreateTestAppInfo(name);
255 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
256
257 ret = GetTestCGroupFilePath(appInfo, "cgroup.procs", path, true);
258 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
259 content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, path, sizeof(path), MODE_FOR_APP_SPAWN);
260 APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, break);
261 ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, content, appInfo);
262
263 // add success
264 ret = GetTestCGroupFilePath(appInfo, "cgroup.procs", path, false);
265 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
266 // write pid
267 pid_t pids[] = {100, 101, 102};
268 ret = WriteToFile(path, 0, pids, 3);
269 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
270
271 AppSpawnedProcess *appInfo2 = CreateTestAppInfo(name);
272 APPSPAWN_CHECK(appInfo2 != nullptr, break, "Failed to create appInfo");
273 OH_ListAddTail(&GetAppSpawnMgr()->appQueue, &appInfo2->node);
274 appInfo2->pid = 102;
275 ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, content, appInfo2);
276 // died
277 ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, content, appInfo);
278 OH_ListRemove(&appInfo2->node);
279 free(appInfo2);
280 } while (0);
281 if (appInfo) {
282 free(appInfo);
283 }
284 AppSpawnDestroyContent(content);
285 LE_StopLoop(LE_GetDefaultLoop());
286 LE_CloseLoop(LE_GetDefaultLoop());
287 ASSERT_EQ(ret, 0);
288 }
289
290 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_007, TestSize.Level0)
291 {
292 int ret = -1;
293 AppSpawnedProcess *appInfo = nullptr;
294 const char name[] = "app-test-001";
295 do {
296 appInfo = CreateTestAppInfo(name);
297 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
298 char path[PATH_MAX] = {};
299 ret = GetCgroupPath(appInfo, path, -1);
300 } while (0);
301 if (appInfo) {
302 free(appInfo);
303 }
304 ASSERT_NE(ret, 0);
305 }
306
307 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_008, TestSize.Level0)
308 {
309 pid_t pids[] = {100, 101, 102};
310 int ret = WriteToFile(nullptr, -1, pids, 3);
311 ASSERT_NE(ret, 0);
312 }
313
314 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_009, TestSize.Level0)
315 {
316 int ret = -1;
317 AppSpawnedProcess *appInfo = nullptr;
318 AppSpawnContent *content = nullptr;
319 const char name[] = "app-test-001";
320 do {
321 char path[PATH_MAX] = {};
322 appInfo = CreateTestAppInfo(name);
323 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
324
325 ret = GetTestCGroupFilePath(appInfo, "cgroup.procs", path, true);
326 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
327 content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, path, sizeof(path), MODE_FOR_APP_SPAWN);
328 APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, break);
329 // spawn prepare process
330 ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, content, appInfo);
331
332 // add success
333 ret = GetTestCGroupFilePath(appInfo, "cgroup.procs", path, false);
334 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
335 // write pid
336 pid_t pids[] = {100, 101, 102, 103};
337 ret = WriteToFile(path, 0, pids, 3);
338
339 } while (0);
340 if (appInfo) {
341 free(appInfo);
342 }
343 AppSpawnDestroyContent(content);
344 LE_StopLoop(LE_GetDefaultLoop());
345 LE_CloseLoop(LE_GetDefaultLoop());
346 ASSERT_EQ(ret, 0);
347 }
348
349 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_010, TestSize.Level0)
350 {
351 int ret = ProcessMgrRemoveApp(nullptr, nullptr);
352 ASSERT_EQ(ret, -1);
353 AppSpawnMgr *mgr = CreateAppSpawnMgr(MODE_FOR_APP_SPAWN);
354 ret = ProcessMgrRemoveApp(mgr, nullptr);
355 DeleteAppSpawnMgr(mgr);
356 ASSERT_EQ(ret, -1);
357 }
358
359 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_011, TestSize.Level0)
360 {
361 int ret = ProcessMgrAddApp(nullptr, nullptr);
362 ASSERT_EQ(ret, -1);
363 AppSpawnMgr *mgr = CreateAppSpawnMgr(MODE_FOR_APP_SPAWN);
364 ret = ProcessMgrAddApp(mgr, nullptr);
365 DeleteAppSpawnMgr(mgr);
366 ASSERT_EQ(ret, -1);
367 }
368 } // namespace OHOS