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 /**
291 * @brief in appspawn service, max write
292 *
293 */
294 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_007, TestSize.Level0)
295 {
296 int ret = -1;
297 AppSpawnedProcess *appInfo = nullptr;
298 AppSpawnContent *content = nullptr;
299 const char name[] = "app-test-001";
300 do {
301 char path[PATH_MAX] = {};
302 appInfo = CreateTestAppInfo(name);
303 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
304 appInfo->max = 10; // 10 test max
305 ret = GetTestCGroupFilePath(appInfo, "pids.max", path, true);
306 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
307 content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, path, sizeof(path), MODE_FOR_APP_SPAWN);
308 APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, break);
309 ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, content, appInfo);
310
311 // add success
312 ret = GetTestCGroupFilePath(appInfo, "pids.max", path, false);
313 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
314 ret = -1;
315 FILE *file = fopen(path, "r");
316 APPSPAWN_CHECK(file != nullptr, break, "Open file fail %{public}s errno: %{public}d", path, errno);
317 uint32_t max = 0;
318 ret = -1;
319 while (fscanf_s(file, "%d\n", &max) == 1 && max > 0) {
320 APPSPAWN_LOGV("max %{public}d %{public}d", max, appInfo->max);
321 if (max == appInfo->max) {
322 ret = 0;
323 break;
324 }
325 }
326 fclose(file);
327 } while (0);
328 if (appInfo) {
329 free(appInfo);
330 }
331 AppSpawnDestroyContent(content);
332 LE_StopLoop(LE_GetDefaultLoop());
333 LE_CloseLoop(LE_GetDefaultLoop());
334 ASSERT_EQ(ret, 0);
335 }
336
337 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_008, TestSize.Level0)
338 {
339 int ret = -1;
340 AppSpawnedProcess *appInfo = nullptr;
341 const char name[] = "app-test-001";
342 do {
343 appInfo = CreateTestAppInfo(name);
344 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
345 char path[PATH_MAX] = {};
346 ret = GetCgroupPath(appInfo, path, -1);
347 } while (0);
348 if (appInfo) {
349 free(appInfo);
350 }
351 ASSERT_NE(ret, 0);
352 }
353
354 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_009, TestSize.Level0)
355 {
356 pid_t pids[] = {100, 101, 102};
357 int ret = WriteToFile(nullptr, -1, pids, 3);
358 ASSERT_NE(ret, 0);
359 }
360
361 HWTEST_F(AppSpawnCGroupTest, App_Spawn_CGroup_010, TestSize.Level0)
362 {
363 int ret = -1;
364 AppSpawnedProcess *appInfo = nullptr;
365 AppSpawnContent *content = nullptr;
366 const char name[] = "app-test-001";
367 do {
368 char path[PATH_MAX] = {};
369 appInfo = CreateTestAppInfo(name);
370 APPSPAWN_CHECK(appInfo != nullptr, break, "Failed to create appInfo");
371
372 ret = GetTestCGroupFilePath(appInfo, "cgroup.procs", path, true);
373 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
374 content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, path, sizeof(path), MODE_FOR_APP_SPAWN);
375 APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, break);
376 // spawn prepare process
377 ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, content, appInfo);
378
379 // add success
380 ret = GetTestCGroupFilePath(appInfo, "cgroup.procs", path, false);
381 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
382 // write pid
383 pid_t pids[] = {100, 101, 102, 103};
384 ret = WriteToFile(path, 0, pids, 3);
385
386 } while (0);
387 if (appInfo) {
388 free(appInfo);
389 }
390 AppSpawnDestroyContent(content);
391 LE_StopLoop(LE_GetDefaultLoop());
392 LE_CloseLoop(LE_GetDefaultLoop());
393 ASSERT_EQ(ret, 0);
394 }
395 } // namespace OHOS