1 /*
2  * Copyright (c) 2024-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 <gtest/gtest.h>
17 
18 #include <cstring>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include "appspawn.h"
24 #include "appspawn_hook.h"
25 #include "appspawn_manager.h"
26 #include "appspawn_modulemgr.h"
27 #include "appspawn_permission.h"
28 #include "appspawn_sandbox.h"
29 #include "appspawn_utils.h"
30 #include "cJSON.h"
31 #include "json_utils.h"
32 #include "securec.h"
33 
34 #include "app_spawn_stub.h"
35 #include "app_spawn_test_helper.h"
36 
37 using namespace testing;
38 using namespace testing::ext;
39 
40 namespace OHOS {
41 class AppSpawnModuleInterfaceTest : 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 
49 /**
50  * @brief module interface
51  *
52  */
53 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_AppSpawnModuleMgrInstall_001, TestSize.Level1)
54 {
55     int ret = AppSpawnModuleMgrInstall(nullptr);
56     EXPECT_NE(0, ret);
57     ret = AppSpawnLoadAutoRunModules(MODULE_MAX);
58     EXPECT_NE(0, ret);
59 
60     ret = AppSpawnLoadAutoRunModules(MODULE_MAX);
61     EXPECT_NE(0, ret);
62     ret = AppSpawnModuleMgrInstall("/");
63     EXPECT_EQ(0, ret);
64     ret = AppSpawnModuleMgrInstall("");
65     EXPECT_EQ(0, ret);
66     ret = AppSpawnModuleMgrInstall("libappspawn_asan");
67     EXPECT_EQ(0, ret);
68 }
69 
70 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_AppSpawnLoadAutoRunModules_001, TestSize.Level1)
71 {
72     int ret = AppSpawnLoadAutoRunModules(MODULE_DEFAULT);
73     EXPECT_EQ(0, ret);
74     ret = AppSpawnLoadAutoRunModules(MODULE_APPSPAWN);
75     EXPECT_EQ(0, ret);
76     ret = AppSpawnLoadAutoRunModules(MODULE_NWEBSPAWN);
77     EXPECT_EQ(0, ret);
78     ret = AppSpawnLoadAutoRunModules(MODULE_COMMON);
79     EXPECT_EQ(0, ret);
80     ret = AppSpawnLoadAutoRunModules(MODULE_MAX);
81     EXPECT_NE(0, ret);
82     ret = AppSpawnLoadAutoRunModules(100);
83     EXPECT_NE(0, ret);
84 }
85 
86 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_AppSpawnModuleMgrUnInstall_001, TestSize.Level1)
87 {
88     AppSpawnModuleMgrUnInstall(MODULE_DEFAULT);
89     AppSpawnModuleMgrUnInstall(MODULE_APPSPAWN);
90     AppSpawnModuleMgrUnInstall(MODULE_NWEBSPAWN);
91     AppSpawnModuleMgrUnInstall(MODULE_COMMON);
92     AppSpawnModuleMgrUnInstall(MODULE_MAX);
93     AppSpawnModuleMgrUnInstall(100);
94 }
95 
96 /**
97  * @brief hook interface
98  *
99  */
TestAppPreload(AppSpawnMgr * content)100 static int TestAppPreload(AppSpawnMgr *content)
101 {
102     return 0;
103 }
104 
105 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_Server_Hook_001, TestSize.Level0)
106 {
107     AppSpawnMgr *mgr = CreateAppSpawnMgr(MODE_FOR_NWEB_SPAWN);
108     EXPECT_EQ(mgr != nullptr, 1);
109 
110     int ret = 0;
111     for (int i = 0; i < STAGE_MAX; i++) {
112         AppSpawnContent *content = reinterpret_cast<AppSpawnContent *>(mgr);
113 
114         for (int k = 0; k <= HOOK_PRIO_LOWEST + 1000; k += 1000) { // 1000
115             ret = AddServerStageHook(static_cast<AppSpawnHookStage>(i), k, TestAppPreload);
116             EXPECT_EQ(ret == 0, (i >= STAGE_SERVER_PRELOAD) && (i <= STAGE_SERVER_EXIT));
117         }
118         ret = AddServerStageHook(static_cast<AppSpawnHookStage>(i), 0, nullptr);
119         EXPECT_EQ(ret == 0, 0);
120 
121         ret = ServerStageHookExecute(static_cast<AppSpawnHookStage>(i), content);
122         EXPECT_EQ(ret == 0, (i >= STAGE_SERVER_PRELOAD) && (i <= STAGE_SERVER_EXIT));
123 
124         ret = ServerStageHookExecute(static_cast<AppSpawnHookStage>(i), nullptr);
125         EXPECT_NE(ret, 0);
126     }
127     DeleteAppSpawnMgr(mgr);
128 }
129 
130 /**
131  * @brief AddAppSpawnHook
132  *
133  */
TestAppSpawn(AppSpawnMgr * content,AppSpawningCtx * property)134 static int TestAppSpawn(AppSpawnMgr *content, AppSpawningCtx *property)
135 {
136     return 0;
137 }
138 
139 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_App_Spawn_Hook_001, TestSize.Level0)
140 {
141     AppSpawnMgr *mgr = CreateAppSpawnMgr(MODE_FOR_NWEB_SPAWN);
142     EXPECT_EQ(mgr != nullptr, 1);
143     AppSpawningCtx *appCtx = CreateAppSpawningCtx();
144     EXPECT_EQ(appCtx != nullptr, 1);
145 
146     int ret = 0;
147     for (int i = 0; i < STAGE_MAX; i++) {
148         AppSpawnClient *client = reinterpret_cast<AppSpawnClient *>(appCtx);
149         AppSpawnContent *content = reinterpret_cast<AppSpawnContent *>(mgr);
150 
151         for (int k = 0; k <= HOOK_PRIO_LOWEST + 1000; k += 1000) { // 1000
152             ret = AddAppSpawnHook(static_cast<AppSpawnHookStage>(i), k, TestAppSpawn);
153             EXPECT_EQ(ret == 0, (i >= STAGE_PARENT_PRE_FORK) && (i <= STAGE_CHILD_PRE_RUN));
154         }
155         ret = AddAppSpawnHook(static_cast<AppSpawnHookStage>(i), 0, nullptr);
156         EXPECT_EQ(ret == 0, 0);
157 
158         if (i == STAGE_CHILD_PRE_RUN || i == STAGE_CHILD_EXECUTE) {
159             printf("App_Spawn_App_Spawn_Hook_001 %d \n", i);
160             continue;
161         }
162         ret = AppSpawnHookExecute(static_cast<AppSpawnHookStage>(i), 0, content, client);
163         EXPECT_EQ(ret == 0, (i >= STAGE_PARENT_PRE_FORK) && (i <= STAGE_CHILD_PRE_RUN));
164 
165         ret = AppSpawnHookExecute(static_cast<AppSpawnHookStage>(i), 0, nullptr, client);
166         EXPECT_NE(ret, 0);
167 
168         ret = AppSpawnHookExecute(static_cast<AppSpawnHookStage>(i), 0, nullptr, nullptr);
169         EXPECT_NE(ret, 0);
170 
171         ret = AppSpawnHookExecute(static_cast<AppSpawnHookStage>(i), 0, content, nullptr);
172         EXPECT_NE(ret, 0);
173     }
174     DeleteAppSpawningCtx(appCtx);
175     DeleteAppSpawnMgr(mgr);
176 }
177 
178 /**
179  * @brief AddProcessMgrHook
180  *
181  */
ReportProcessExitInfo(const AppSpawnMgr * content,const AppSpawnedProcess * appInfo)182 static int ReportProcessExitInfo(const AppSpawnMgr *content, const AppSpawnedProcess *appInfo)
183 {
184     return 0;
185 }
186 
187 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_Process_Hook_001, TestSize.Level0)
188 {
189     AppSpawnMgr *mgr = CreateAppSpawnMgr(MODE_FOR_NWEB_SPAWN);
190     EXPECT_EQ(mgr != nullptr, 1);
191     AppSpawnedProcess *app = AddSpawnedProcess(1000, "test-001", false);
192     EXPECT_EQ(app != nullptr, 1);
193 
194     int ret = 0;
195     for (int i = 0; i < STAGE_MAX; i++) {
196         for (int k = 0; k <= HOOK_PRIO_LOWEST + 1000; k += 1000) { // 1000
197             ret = AddProcessMgrHook(static_cast<AppSpawnHookStage>(i), k, ReportProcessExitInfo);
198             EXPECT_EQ(ret == 0, (i >= STAGE_SERVER_APP_ADD && i <= STAGE_SERVER_APP_UMOUNT));
199         }
200 
201         ret = AddProcessMgrHook(static_cast<AppSpawnHookStage>(i), 0, nullptr);
202         EXPECT_EQ(ret == 0, 0);
203 
204         ret = ProcessMgrHookExecute(static_cast<AppSpawnHookStage>(i), reinterpret_cast<AppSpawnContent *>(mgr), app);
205         EXPECT_EQ(ret == 0, (i >= STAGE_SERVER_APP_ADD && i <= STAGE_SERVER_APP_UMOUNT));
206 
207         ret = ProcessMgrHookExecute(static_cast<AppSpawnHookStage>(i), nullptr, app);
208         EXPECT_NE(ret, 0);
209 
210         ret = ProcessMgrHookExecute(static_cast<AppSpawnHookStage>(i), nullptr, nullptr);
211         EXPECT_NE(ret, 0);
212 
213         ret = ProcessMgrHookExecute(static_cast<AppSpawnHookStage>(i),
214             reinterpret_cast<AppSpawnContent *>(mgr), nullptr);
215         EXPECT_NE(ret, 0);
216     }
217     TerminateSpawnedProcess(app);
218     DeleteAppSpawnMgr(mgr);
219 }
220 
221 /**
222  * @brief RegChildLooper
223  *
224  */
TestChildLoop(AppSpawnContent * content,AppSpawnClient * client)225 static int TestChildLoop(AppSpawnContent *content, AppSpawnClient *client)
226 {
227     return 0;
228 }
229 
230 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_RegChildLooper_001, TestSize.Level0)
231 {
232     AppSpawnMgr *mgr = CreateAppSpawnMgr(MODE_FOR_NWEB_SPAWN);
233     EXPECT_EQ(mgr != nullptr, 1);
234     RegChildLooper(reinterpret_cast<AppSpawnContent *>(mgr), TestChildLoop);
235     RegChildLooper(reinterpret_cast<AppSpawnContent *>(mgr), nullptr);
236     DeleteAppSpawnMgr(mgr);
237     RegChildLooper(nullptr, TestChildLoop);
238 }
239 
240 /**
241  * @brief MakeDirRec
242  * int MakeDirRec(const char *path, mode_t mode, int lastPath);
243  */
244 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_MakeDirRec_001, TestSize.Level0)
245 {
246     int ret = MakeDirRec(nullptr, 0, -1);
247     EXPECT_EQ(ret, -1);
248     ret = MakeDirRec(APPSPAWN_BASE_DIR "/test_appspawn/3", 0, 0);
249     EXPECT_EQ(ret, 0);
250     ret = MakeDirRec(APPSPAWN_BASE_DIR "/test_appspawn/1", 0711, 0); // create file
251     EXPECT_EQ(ret, 0);
252     ret = MakeDirRec(APPSPAWN_BASE_DIR "/test_appspawn/2", 0711, 1); // create path
253     EXPECT_EQ(ret, 0);
254 }
255 
256 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_DiffTime_001, TestSize.Level0)
257 {
258     struct timespec endTime;
259     struct timespec startTime;
260     clock_gettime(CLOCK_MONOTONIC, &startTime);
261     startTime.tv_sec += 1;
262     clock_gettime(CLOCK_MONOTONIC, &endTime);
263     uint64_t diff = DiffTime(&startTime, &endTime);
264     EXPECT_NE(diff, 0);
265     diff = DiffTime(nullptr, &endTime);
266     EXPECT_EQ(diff, 0);
267     diff = DiffTime(&startTime, nullptr);
268     EXPECT_EQ(diff, 0);
269 }
270 
TestSplitStringHandle(const char * str,void * context)271 int TestSplitStringHandle(const char *str, void *context)
272 {
273     static int index = 0;
274     if (index == 3) { // 3 test
275         EXPECT_EQ(strcmp(str, "dddd"), 0);
276     }
277     index++;
278     return 0;
279 }
280 
281 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_StringSplit_001, TestSize.Level0)
282 {
283     const char *testStr = "aaaa|bbbb|cccc  |dddd|   eeee| 1111 | 2222";
284     int ret = StringSplit(testStr, "|", nullptr, TestSplitStringHandle);
285     EXPECT_EQ(ret, 0);
286     ret = StringSplit(testStr, "|", nullptr, nullptr);
287     EXPECT_NE(ret, 0);
288 
289     ret = StringSplit(testStr, nullptr, nullptr, TestSplitStringHandle);
290     EXPECT_NE(ret, 0);
291     ret = StringSplit(nullptr, "|", nullptr, TestSplitStringHandle);
292     EXPECT_NE(ret, 0);
293     ret = StringSplit(nullptr, "|", nullptr, nullptr);
294     EXPECT_NE(ret, 0);
295     ret = StringSplit(nullptr, nullptr, nullptr, nullptr);
296     EXPECT_NE(ret, 0);
297 }
298 
299 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_GetLastStr_001, TestSize.Level0)
300 {
301     const char *testStr = "aaaa|bbbb|cccc  |dddd|   eeee| 1111 | 2222";
302     char *tmp = GetLastStr(testStr, "2222");
303     EXPECT_EQ(tmp != nullptr, 1);
304 
305     tmp = GetLastStr(testStr, nullptr);
306     EXPECT_EQ(tmp != nullptr, 0);
307 
308     tmp = GetLastStr(nullptr, nullptr);
309     EXPECT_EQ(tmp != nullptr, 0);
310     tmp = GetLastStr(nullptr, "2222");
311     EXPECT_EQ(tmp != nullptr, 0);
312 }
313 
314 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_DumpCurrentDir_001, TestSize.Level0)
315 {
316     char path[PATH_MAX] = {};
317     DumpCurrentDir(path, sizeof(path), APPSPAWN_BASE_DIR "/test_appspawn/");
318     DumpCurrentDir(path, sizeof(path), nullptr);
319     DumpCurrentDir(path, 0, nullptr);
320     DumpCurrentDir(path, 0, APPSPAWN_BASE_DIR "/test_appspawn/");
321     DumpCurrentDir(nullptr, sizeof(path), APPSPAWN_BASE_DIR "/test_appspawn/");
322     DumpCurrentDir(nullptr, sizeof(path), nullptr);
323 }
324 
TestParseAppSandboxConfig(const cJSON * root,ParseJsonContext * context)325 static int TestParseAppSandboxConfig(const cJSON *root, ParseJsonContext *context)
326 {
327     return 0;
328 }
329 
330 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_ParseJsonConfig_001, TestSize.Level0)
331 {
332     int ret = 0;
333 #ifdef APPSPAWN_SANDBOX_NEW
334     ret = ParseJsonConfig("etc/sandbox", WEB_SANDBOX_FILE_NAME, TestParseAppSandboxConfig, nullptr);
335     EXPECT_EQ(ret, 0);
336     ret = ParseJsonConfig("etc/sandbox", APP_SANDBOX_FILE_NAME, TestParseAppSandboxConfig, nullptr);
337     EXPECT_EQ(ret, 0);
338 #else
339     ret = ParseJsonConfig("etc/sandbox", APP_SANDBOX_FILE_NAME, TestParseAppSandboxConfig, nullptr);
340     EXPECT_EQ(ret, 0);
341 #endif
342     ret = ParseJsonConfig("etc/sandbox", APP_SANDBOX_FILE_NAME, nullptr, nullptr);
343     EXPECT_NE(ret, 0);
344     ret = ParseJsonConfig("etc/sandbox", nullptr, TestParseAppSandboxConfig, nullptr);
345     EXPECT_NE(ret, 0);
346     ret = ParseJsonConfig("etc/sandbox", nullptr, nullptr, nullptr);
347     EXPECT_NE(ret, 0);
348     ret = ParseJsonConfig(nullptr, APP_SANDBOX_FILE_NAME, TestParseAppSandboxConfig, nullptr);
349     EXPECT_NE(ret, 0);
350     ret = ParseJsonConfig(nullptr, nullptr, TestParseAppSandboxConfig, nullptr);
351     EXPECT_NE(ret, 0);
352     ret = ParseJsonConfig(nullptr, nullptr, nullptr, nullptr);
353     EXPECT_NE(ret, 0);
354 }
355 
356 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_GetJsonObjFromFile_001, TestSize.Level0)
357 {
358     cJSON *json = GetJsonObjFromFile("/etc/sandbox/appdata-sandbox.json");
359     EXPECT_EQ(json != nullptr, 1);
360     cJSON_Delete(json);
361     json = GetJsonObjFromFile(nullptr);
362     EXPECT_EQ(json == nullptr, 1);
363 }
364 
365 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_GetStringFromJsonObj_001, TestSize.Level0)
366 {
367     const std::string buffer = "{ \
368         \"global\": { \
369             \"sandbox-root\": \"/mnt/sandbox/<currentUserId>/app-root\", \
370             \"sandbox-ns-flags\": [ \"pid\", \"net\" ], \
371             \"sandbox-flags\": 100, \
372             \"top-sandbox-switch\": \"ON\" \
373         } \
374     }";
375 
376     cJSON *json = cJSON_Parse(buffer.c_str());
377     EXPECT_EQ(json != nullptr, 1);
378     char *tmp = GetStringFromJsonObj(cJSON_GetObjectItemCaseSensitive(json, "global"), "sandbox-root");
379     EXPECT_EQ(tmp != nullptr, 1);
380     tmp = GetStringFromJsonObj(cJSON_GetObjectItemCaseSensitive(json, "global"), nullptr);
381     EXPECT_EQ(tmp == nullptr, 1);
382     tmp = GetStringFromJsonObj(nullptr, "sandbox-root");
383     EXPECT_EQ(tmp == nullptr, 1);
384     tmp = GetStringFromJsonObj(nullptr, nullptr);
385     EXPECT_EQ(tmp == nullptr, 1);
386     cJSON_Delete(json);
387 }
388 
389 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_GetBoolValueFromJsonObj_001, TestSize.Level0)
390 {
391     const std::string buffer = "{ \
392         \"global\": { \
393             \"sandbox-root\": \"/mnt/sandbox/<currentUserId>/app-root\", \
394             \"sandbox-ns-flags\": [ \"pid\", \"net\" ], \
395             \"sandbox-flags\": 100, \
396             \"top-sandbox-switch\": \"ON\" \
397         } \
398     }";
399 
400     cJSON *json = cJSON_Parse(buffer.c_str());
401     EXPECT_EQ(json != nullptr, 1);
402     bool ret = GetBoolValueFromJsonObj(cJSON_GetObjectItemCaseSensitive(json, "global"), "top-sandbox-switch", false);
403     EXPECT_EQ(ret, true);
404     ret = GetBoolValueFromJsonObj(cJSON_GetObjectItemCaseSensitive(json, "global"), nullptr, false);
405     EXPECT_EQ(ret, 0);
406     ret = GetBoolValueFromJsonObj(nullptr, "top-sandbox-switch", false);
407     EXPECT_EQ(ret, 0);
408     ret = GetBoolValueFromJsonObj(nullptr, nullptr, false);
409     EXPECT_EQ(ret, 0);
410     cJSON_Delete(json);
411 }
412 
413 HWTEST_F(AppSpawnModuleInterfaceTest, App_Spawn_GetIntValueFromJsonObj_001, TestSize.Level0)
414 {
415     const std::string buffer = "{ \
416         \"global\": { \
417             \"sandbox-root\": \"/mnt/sandbox/<currentUserId>/app-root\", \
418             \"sandbox-ns-flags\": [ \"pid\", \"net\" ], \
419             \"sandbox-flags\": 100, \
420             \"top-sandbox-switch\": \"ON\" \
421         } \
422     }";
423     cJSON *json = cJSON_Parse(buffer.c_str());
424     EXPECT_EQ(json != nullptr, 1);
425     int tmp = GetIntValueFromJsonObj(cJSON_GetObjectItemCaseSensitive(json, "global"), "sandbox-flags", 0);
426     EXPECT_EQ(tmp, 100);
427     tmp = GetIntValueFromJsonObj(cJSON_GetObjectItemCaseSensitive(json, "global"), nullptr, 0);
428     EXPECT_EQ(tmp, 0);
429     tmp = GetIntValueFromJsonObj(nullptr, "sandbox-flags", 0);
430     EXPECT_EQ(tmp, 0);
431     tmp = GetIntValueFromJsonObj(nullptr, nullptr, 0);
432     EXPECT_EQ(tmp, 0);
433     cJSON_Delete(json);
434 }
435 }  // namespace OHOS
436