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