1 /*
2 * Copyright (c) 2022 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 <cinttypes>
17 #include <sys/mount.h>
18 #include "fs_manager/fs_manager.h"
19 #include "init_log.h"
20 #include "init_param.h"
21 #include "param_stub.h"
22 #include "securec.h"
23 #include "systemcapability.h"
24 #include "service_control.h"
25 #include "control_fd.h"
26 #include "loop_event.h"
27 #include "fd_holder.h"
28 #include "fd_holder_internal.h"
29
30 using namespace testing::ext;
31 using namespace std;
32
33 namespace init_ut {
34
35 extern "C" {
36 void CmdDisConnectComplete(const TaskHandle client);
37 void CmdOnSendMessageComplete(const TaskHandle task, const BufferHandle handle);
38 void CmdOnClose(const TaskHandle task);
39 void CmdOnConnectComplete(const TaskHandle client);
40 void CmdOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen);
41 void ProcessPtyRead(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context);
42 void ProcessPtyWrite(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context);
43 int CmdOnIncommingConnect(const LoopHandle loop, const TaskHandle server);
44 CmdAgent *CmdAgentCreate(const char *server);
45 void CmdClientOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen);
46 int SendCmdMessage(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName);
47 int SendMessage(LoopHandle loop, TaskHandle task, const char *message);
48 int *GetFdsFromMsg(size_t *outFdCount, pid_t *requestPid, struct msghdr msghdr);
49 int BuildSendData(char *buffer, size_t size, const char *serviceName, bool hold, bool poll);
50 int CheckSocketPermission(const TaskHandle task);
51 }
52
53 class InnerkitsUnitTest : public testing::Test {
54 public:
SetUpTestCase(void)55 static void SetUpTestCase(void) {};
TearDownTestCase(void)56 static void TearDownTestCase(void) {};
SetUp()57 void SetUp() {};
TearDown()58 void TearDown() {};
59 };
60
CallbackSendMsgProcessTest(const CmdAgent * agent,uint16_t type,const char * cmd,const char * ptyName)61 static int CallbackSendMsgProcessTest(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName)
62 {
63 return 0;
64 }
65
TestCmdServiceProcessDelClient(pid_t pid)66 static int TestCmdServiceProcessDelClient(pid_t pid)
67 {
68 CmdServiceProcessDelClient(pid);
69 return 0;
70 }
71
72 /**
73 * @tc.name: ReadFstabFromFile_unitest
74 * @tc.desc: read fstab from test file.
75 * @tc.type: FUNC
76 * @tc.require:
77 * @tc.author:
78 */
79 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_ReadFstabFromFile001, TestSize.Level1)
80 {
81 Fstab *fstab = nullptr;
82 const std::string fstabFile1 = "/data/fstab.updater1";
83 fstab = ReadFstabFromFile(fstabFile1.c_str(), false);
84 EXPECT_EQ(fstab, nullptr);
85 const std::string fstabFile2 = STARTUP_INIT_UT_PATH"/mount_unitest/ReadFstabFromFile1.fstable";
86 fstab = ReadFstabFromFile(fstabFile2.c_str(), false);
87 EXPECT_NE(fstab, nullptr);
88 ParseFstabPerLine(const_cast<char *>("test"), fstab, true, nullptr);
89 ReleaseFstab(fstab);
90 }
91
92 /**
93 * @tc.name: FindFstabItemForPath_unitest
94 * @tc.desc: read fstab from test file, then find item according to path.
95 * @tc.type: FUNC
96 * @tc.require:
97 * @tc.author:
98 */
99 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_FindFstabItemForPath001, TestSize.Level1)
100 {
101 const std::string fstabFile1 = STARTUP_INIT_UT_PATH"/mount_unitest/ReadFstabFromFile1.fstable";
102 Fstab *fstab = nullptr;
103 fstab = ReadFstabFromFile(fstabFile1.c_str(), false);
104 ASSERT_NE(fstab, nullptr);
105 FstabItem* item = nullptr;
106 const std::string path1 = "";
107 item = FindFstabItemForPath(*fstab, path1.c_str());
108 if (item == nullptr) {
109 SUCCEED();
110 }
111 const std::string path2 = "/data";
112 item = FindFstabItemForPath(*fstab, path2.c_str());
113 if (item != nullptr) {
114 SUCCEED();
115 }
116 const std::string path3 = "/data2";
117 item = FindFstabItemForPath(*fstab, path3.c_str());
118 if (item == nullptr) {
119 SUCCEED();
120 }
121 const std::string path4 = "/data2/test";
122 item = FindFstabItemForPath(*fstab, path4.c_str());
123 if (item != nullptr) {
124 SUCCEED();
125 }
126 ReleaseFstab(fstab);
127 fstab = nullptr;
128 }
129
130 /**
131 * @tc.name: FindFstabItemForMountPoint_unitest
132 * @tc.desc: read fstab from test file, then find item that matches with the mount point.
133 * @tc.type: FUNC
134 * @tc.require:
135 * @tc.author:
136 */
137 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_FindFstabItemForMountPoint001, TestSize.Level1)
138 {
139 const std::string fstabFile1 = STARTUP_INIT_UT_PATH"/mount_unitest/ReadFstabFromFile1.fstable";
140 Fstab *fstab = nullptr;
141 fstab = ReadFstabFromFile(fstabFile1.c_str(), false);
142 ASSERT_NE(fstab, nullptr);
143 FstabItem* item = nullptr;
144 const std::string mp1 = "/data";
145 const std::string mp2 = "/data2";
146 item = FindFstabItemForMountPoint(*fstab, mp2.c_str());
147 if (item == nullptr) {
148 SUCCEED();
149 }
150 const std::string mp3 = "/data";
151 item = FindFstabItemForMountPoint(*fstab, mp3.c_str());
152 if (item != nullptr) {
153 SUCCEED();
154 }
155 ReleaseFstab(fstab);
156 fstab = nullptr;
157 }
158
159 /**
160 * @tc.name: GetMountFlags_unitest
161 * @tc.desc: read fstab from test file, then find the item and get mount flags.
162 * @tc.type: FUNC
163 * @tc.require:
164 * @tc.author:
165 */
166 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_GetMountFlags001, TestSize.Level1)
167 {
168 const std::string fstabFile1 = STARTUP_INIT_UT_PATH"/mount_unitest/ReadFstabFromFile1.fstable";
169 Fstab *fstab = nullptr;
170 fstab = ReadFstabFromFile(fstabFile1.c_str(), true);
171 ASSERT_NE(fstab, nullptr);
172 struct FstabItem* item = nullptr;
173 const std::string mp = "/hos";
174 item = FindFstabItemForMountPoint(*fstab, mp.c_str());
175 if (item == nullptr) {
176 SUCCEED();
177 }
178 const int bufferSize = 512;
179 char fsSpecificOptions[bufferSize] = {0};
180 unsigned long flags = GetMountFlags(item->mountOptions, fsSpecificOptions, bufferSize, item->mountPoint);
181 EXPECT_EQ(flags, static_cast<unsigned long>(MS_NOSUID | MS_NODEV | MS_NOATIME));
182 ReleaseFstab(fstab);
183 fstab = nullptr;
184 }
185
186 /**
187 * @tc.name: GetSlotInfo_unittest
188 * @tc.desc: get the number of slots and get current slot.
189 * @tc.type: FUNC
190 * @tc.require:issueI5NTX2
191 * @tc.author:
192 */
193 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_GetSlotInfo001, TestSize.Level1)
194 {
195 EXPECT_NE(GetBootSlots(), -1);
196 EXPECT_NE(GetCurrentSlot(), -1);
197 }
198
199 /**
200 * @tc.name: LoadFstabFromCommandLine_unittest
201 * @tc.desc: get fstab from command line.
202 * @tc.type: FUNC
203 * @tc.require:issueI5NTX2
204 * @tc.author:
205 */
206 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_LoadFstabFromCommandLine001, TestSize.Level1)
207 {
208 EXPECT_NE(LoadFstabFromCommandLine(), (Fstab *)nullptr);
209 }
210
211 /**
212 * @tc.name: GetBlockDevicePath_unittest
213 * @tc.desc: get block device path according to valid or invalid partition.
214 * @tc.type: FUNC
215 * @tc.require:issueI5NTX2
216 * @tc.author:
217 */
218 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_GetBlockDevicePath001, TestSize.Level1)
219 {
220 char devicePath[MAX_BUFFER_LEN] = {0};
221 EXPECT_EQ(GetBlockDevicePath("/vendor", devicePath, MAX_BUFFER_LEN), 0);
222 EXPECT_EQ(GetBlockDevicePath("/misc", devicePath, MAX_BUFFER_LEN), 0);
223 EXPECT_EQ(GetBlockDevicePath("/invalid", devicePath, MAX_BUFFER_LEN), -1);
224 unlink(BOOT_CMD_LINE);
225 EXPECT_EQ(GetBlockDevicePath("/invalid", devicePath, MAX_BUFFER_LEN), -1);
226 GetCurrentSlot();
227 // restore cmdline
228 PrepareCmdLineData();
229 }
230
231 /**
232 * @tc.name: DoFormat_unittest
233 * @tc.desc: format file system, includes ext4 and f2fs type.
234 * @tc.type: FUNC
235 * @tc.require:
236 * @tc.author:
237 */
238 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_DoFormat001, TestSize.Level1)
239 {
240 EXPECT_NE(DoFormat("/testpath", "ext4"), -1);
241 EXPECT_NE(DoFormat("/testpath", "f2fs"), -1);
242 EXPECT_EQ(DoFormat("/testpath", "notFs"), -1);
243 EXPECT_EQ(DoFormat(nullptr, nullptr), -1);
244 }
245
246 /**
247 * @tc.name: MountAllWithFstabFile_unittest
248 * @tc.desc: mount partitions according to fstab that read from file.
249 * @tc.type: FUNC
250 * @tc.require:issueI5NTX2
251 * @tc.author:
252 */
253 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_MountAllWithFstabFile001, TestSize.Level1)
254 {
255 EXPECT_NE(MountAllWithFstabFile(STARTUP_INIT_UT_PATH"/etc/fstab.required", 0), 1);
256 EXPECT_NE(UmountAllWithFstabFile(STARTUP_INIT_UT_PATH"/etc/fstab.required"), 1);
257 EXPECT_EQ(MountAllWithFstabFile("/testErrorFile", 0), -1);
258 EXPECT_EQ(MountAllWithFstabFile(nullptr, 0), -1);
259 EXPECT_EQ(GetMountStatusForMountPoint(nullptr), -1);
260 FstabItem fstabItem = {};
261 fstabItem.fsType = strdup("notSupport");
262 fstabItem.mountPoint = strdup("");
263 EXPECT_EQ(MountOneItem(nullptr), -1);
264 EXPECT_EQ(MountOneItem(&fstabItem), 0);
265 if (fstabItem.fsType != nullptr) {
266 free(fstabItem.fsType);
267 fstabItem.fsType = nullptr;
268 }
269 if (fstabItem.mountPoint != nullptr) {
270 free(fstabItem.mountPoint);
271 fstabItem.mountPoint = nullptr;
272 }
273 }
274
275 #define SYSCAP_MAX_SIZE 100
276
277 // TestSysCap
278 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_TestSysCap001, TestSize.Level1)
279 {
280 bool ret = HasSystemCapability("test.cap");
281 EXPECT_EQ(ret, false);
282 ret = HasSystemCapability(nullptr);
283 EXPECT_EQ(ret, false);
284 ret = HasSystemCapability("ArkUI.ArkUI.Napi");
285 EXPECT_EQ(ret, true);
286 ret = HasSystemCapability("SystemCapability.ArkUI.ArkUI.Napi");
287 EXPECT_EQ(ret, true);
288 char *wrongName = reinterpret_cast<char *>(malloc(SYSCAP_MAX_SIZE));
289 ASSERT_NE(wrongName, nullptr);
290 EXPECT_EQ(memset_s(wrongName, SYSCAP_MAX_SIZE, 1, SYSCAP_MAX_SIZE), 0);
291 HasSystemCapability(wrongName);
292 free(wrongName);
293 }
294
295 // TestControlService
296 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_ControlService001, TestSize.Level1)
297 {
298 TestSetParamCheckResult("startup.service.ctl.", 0777, 0);
299 ServiceControl("deviceinfoservice", START);
300 SystemWriteParam("startup.service.ctl.deviceinfoservice", "2");
301 ServiceControl("deviceinfoservice", RESTART);
302 ServiceControl("deviceinfoservice", STOP);
303 SystemWriteParam("startup.service.ctl.deviceinfoservice", "0");
304 ServiceControl("param_watcher", RESTART);
305 EXPECT_EQ(ServiceControl(nullptr, RESTART), -1);
306 const char *argv[] = {"testArg"};
307 ServiceControlWithExtra("deviceinfoservice", RESTART, argv, 1);
308 ServiceControlWithExtra(nullptr, RESTART, argv, 1);
309 ServiceControlWithExtra(nullptr, 3, argv, 1); // 3 is action
310 ServiceControlWithExtra("notservie", RESTART, argv, 1);
311 ServiceControlWithExtra("deviceinfoservice", 3, argv, 1); // 3 is action
312 ServiceSetReady("deviceinfoservice");
313 ServiceSetReady(nullptr);
314 ServiceWaitForStatus("deviceinfoservice", SERVICE_READY, 1);
315 ServiceWaitForStatus("deviceinfoservice", SERVICE_READY, -1);
316 ServiceWaitForStatus(nullptr, SERVICE_READY, 1);
317 StartServiceByTimer("deviceinfoservice", 1);
318 StartServiceByTimer("deviceinfoservice", 0);
319 StartServiceByTimer(nullptr, 0);
320 StopServiceTimer("deviceinfoservice");
321 }
322
TestIncommingConnect(const LoopHandle loop,const TaskHandle server)323 static int TestIncommingConnect(const LoopHandle loop, const TaskHandle server)
324 {
325 UNUSED(loop);
326 UNUSED(server);
327 return 0;
328 }
329
330 // TestControlFd
331 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_ControlFd001, TestSize.Level1)
332 {
333 CmdClientInit("/data/testSock1", ACTION_DUMP, "cmd", nullptr);
334 CmdClientInit("/data/testSock1", ACTION_DUMP, "cmd", CallbackSendMsgProcessTest);
335 CmdClientInit(INIT_CONTROL_FD_SOCKET_PATH, ACTION_DUMP, nullptr, nullptr);
336 CmdClientInit(nullptr, ACTION_DUMP, "cmd", nullptr);
337
338 CmdDisConnectComplete(nullptr);
339 CmdOnSendMessageComplete(nullptr, nullptr);
340 CmdOnConnectComplete(nullptr);
341 CmdClientOnRecvMessage(nullptr, nullptr, 0);
342 CmdAgentCreate(nullptr);
343 CmdAgent *agent = CmdAgentCreate(INIT_CONTROL_FD_SOCKET_PATH);
344 EXPECT_NE(agent, nullptr);
345 SendCmdMessage(agent, ACTION_DUMP, "cmd", "test");
346 SendCmdMessage(agent, ACTION_DUMP, "cmd", nullptr);
347 SendMessage(nullptr, nullptr, nullptr);
348 uint32_t events = 0;
349 InitPtyInterface(agent, 0, "cmd", nullptr);
350 InitPtyInterface(agent, 0, "cmd", CallbackSendMsgProcessTest);
351 InitPtyInterface(agent, 0, nullptr, nullptr);
352 InitPtyInterface(nullptr, 0, nullptr, nullptr);
353 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
354 CheckAndCreatFile("/data/init_ut/testInput", mode);
355 int fd = open("/data/init_ut/testInput", O_RDWR);
356 perror("write failed");
357 EXPECT_GT(fd, 0);
358 EXPECT_GT(write(fd, "test", strlen("test")), 0);
359 perror("write failed");
360 lseek(fd, 0, SEEK_SET);
361 ProcessPtyRead(nullptr, fd, &events, (void *)agent);
362 ProcessPtyRead(nullptr, fd, &events, (void *)agent);
363 ProcessPtyRead(nullptr, STDERR_FILENO, &events, nullptr);
364 lseek(fd, 0, SEEK_SET);
365 ProcessPtyWrite(nullptr, fd, &events, (void *)agent);
366 ProcessPtyWrite(nullptr, fd, &events, (void *)agent);
367 ProcessPtyWrite(nullptr, STDERR_FILENO, &events, nullptr);
368 close(fd);
369
370 if (agent) {
371 CmdOnClose(agent->task);
372 }
373 }
374
375 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_ControlFdServer001, TestSize.Level1)
376 {
377 CmdServiceInit(nullptr, nullptr, nullptr);
__anon59c35f230102(uint16_t type, const char *serviceCmd, const void *context) 378 CmdServiceInit("/data/testSock1", [](uint16_t type, const char *serviceCmd, const void *context) {
379 UNUSED(type);
380 UNUSED(serviceCmd);
381 UNUSED(context);
382 }, LE_GetDefaultLoop());
383
384 TaskHandle testServer = nullptr;
385 LE_StreamServerInfo info = {};
386 info.baseInfo.flags = TASK_STREAM | TASK_SERVER | TASK_PIPE | TASK_TEST;
387 info.server = (char *)"/data/testSock1";
388 info.socketId = -1;
389 info.baseInfo.close = nullptr;
390 info.disConnectComplete = nullptr;
391 info.incommingConnect = TestIncommingConnect;
392 info.sendMessageComplete = nullptr;
393 info.recvMessage = nullptr;
394 (void)LE_CreateStreamServer(LE_GetDefaultLoop(), &testServer, &info);
395 CmdOnIncommingConnect(LE_GetDefaultLoop(), testServer);
396
397 CmdOnRecvMessage(testServer, nullptr, 0);
398 CmdMessage *cmdMsg = (CmdMessage *)malloc(sizeof(CmdMessage) + strlen("test"));
399 cmdMsg->type = ACTION_DUMP;
400 cmdMsg->ptyName[0] = '\0';;
401 CmdOnRecvMessage(testServer, (uint8_t *)(&cmdMsg), 0);
402 cmdMsg->type = ACTION_DUMP;
403 cmdMsg->cmd[0] = 'a';
404 cmdMsg->ptyName[0] = 'a';
405 CmdOnRecvMessage(testServer, (uint8_t *)(&cmdMsg), 0);
406 int ret = TestCmdServiceProcessDelClient(0);
407 EXPECT_EQ(ret, 0);
408 ret = TestCmdServiceProcessDelClient(0);
409 EXPECT_EQ(ret, 0);
410 free(cmdMsg);
411 }
412
413 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_HoldFd001, TestSize.Level1)
414 {
415 int ret = CheckSocketPermission(nullptr);
416 EXPECT_EQ(ret, -1);
417 CmdServiceProcessDestroyClient();
418 }
419
420 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_HoldFd002, TestSize.Level1)
421 {
422 int fds1[] = {1, 0};
423 ServiceSaveFd("testServiceName", fds1, ARRAY_LENGTH(fds1));
424 ServiceSaveFd(nullptr, fds1, ARRAY_LENGTH(fds1));
425 ServiceSaveFdWithPoll("testServiceName", fds1, 0);
426 ServiceSaveFdWithPoll(nullptr, fds1, 0);
427 ServiceSaveFdWithPoll("testServiceName", fds1, ARRAY_LENGTH(fds1));
428 EXPECT_EQ(setenv("OHOS_FD_HOLD_testServiceName", "1 0", 0), 0);
429
430 size_t fdCount = 0;
431 int *fds = nullptr;
432 ServiceGetFd("testService", nullptr);
433 ServiceGetFd("testService", &fdCount);
434 char *wrongName = (char *)malloc(MAX_FD_HOLDER_BUFFER + 1);
435 ASSERT_NE(wrongName, nullptr);
436 EXPECT_EQ(memset_s(wrongName, MAX_FD_HOLDER_BUFFER + 1, 1, MAX_FD_HOLDER_BUFFER + 1), 0);
437 ServiceGetFd(wrongName, &fdCount);
438 BuildSendData(wrongName, 1, "testService", 0, 1);
439 BuildSendData(wrongName, 1, "testService", 0, 0);
440 BuildSendData(nullptr, 1, "testService", 0, 0);
441 free(wrongName);
442
443 fds = ServiceGetFd("testServiceName", &fdCount);
444 EXPECT_NE(fds, nullptr);
445 struct msghdr msghdr = {};
446 BuildControlMessage(nullptr, nullptr, 1, 0);
447 BuildControlMessage(&msghdr, nullptr, 1, 0);
448 if (msghdr.msg_control != nullptr) {
449 free(msghdr.msg_control);
450 msghdr.msg_control = nullptr;
451 }
452 BuildControlMessage(&msghdr, fds, -1, 0);
453 if (msghdr.msg_control != nullptr) {
454 free(msghdr.msg_control);
455 msghdr.msg_control = nullptr;
456 }
457 BuildControlMessage(&msghdr, fds, -1, 1);
458 if (msghdr.msg_control != nullptr) {
459 free(msghdr.msg_control);
460 msghdr.msg_control = nullptr;
461 }
462 if (fds != nullptr)
463 {
464 free(fds);
465 fds = nullptr;
466 }
467 }
468
469 HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_HoldFd003, TestSize.Level1)
470 {
471 size_t fdCount = 0;
472 int *fds = nullptr;
473 char buffer[MAX_FD_HOLDER_BUFFER + 1] = {};
474 pid_t requestPid = -1;
475 struct msghdr msghdr = {};
476 GetFdsFromMsg(&fdCount, &requestPid, msghdr);
477 msghdr.msg_flags = MSG_TRUNC;
478 int *ret = nullptr;
479 ret = GetFdsFromMsg(&fdCount, &requestPid, msghdr);
480 EXPECT_EQ(ret, nullptr);
481 struct iovec iovec = {
482 .iov_base = buffer,
483 .iov_len = MAX_FD_HOLDER_BUFFER,
484 };
485 ReceiveFds(0, iovec, &fdCount, false, &requestPid);
486 fds = ReceiveFds(0, iovec, &fdCount, true, &requestPid);
487 if (fds != nullptr)
488 {
489 free(fds);
490 fds = nullptr;
491 }
492 if (msghdr.msg_control != nullptr) {
493 free(msghdr.msg_control);
494 }
495 }
496
497 } // namespace init_ut
498