1/* 2 * Copyright (c) 2021 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#include <cstdlib> 16#include "init_cmds.h" 17#include "init_group_manager.h" 18#include "init_hashmap.h" 19#include "init_param.h" 20#include "init_service_manager.h" 21#include "init_utils.h" 22#include "init_unittest.h" 23#include "le_timer.h" 24#include "param_stub.h" 25#include "securec.h" 26#include "control_fd.h" 27 28using namespace testing::ext; 29using namespace std; 30 31typedef struct { 32 HashNode node; 33 char name[0]; 34} TestHashNode; 35 36static int TestHashNodeCompare(const HashNode *node1, const HashNode *node2) 37{ 38 TestHashNode *testNode1 = HASHMAP_ENTRY(node1, TestHashNode, node); 39 TestHashNode *testNode2 = HASHMAP_ENTRY(node2, TestHashNode, node); 40 return strcmp(testNode1->name, testNode2->name); 41} 42 43static int TestHashKeyCompare(const HashNode *node1, const void *key) 44{ 45 TestHashNode *testNode1 = HASHMAP_ENTRY(node1, TestHashNode, node); 46 return strcmp(testNode1->name, reinterpret_cast<char *>(const_cast<void *>(key))); 47} 48 49static int TestHashNodeFunction(const HashNode *node) 50{ 51 TestHashNode *testNode = HASHMAP_ENTRY(node, TestHashNode, node); 52 int code = 0; 53 size_t nameLen = strlen(testNode->name); 54 for (size_t i = 0; i < nameLen; i++) { 55 code += testNode->name[i] - 'A'; 56 } 57 return code; 58} 59 60static int TestHashKeyFunction(const void *key) 61{ 62 int code = 0; 63 const char *buff = static_cast<const char *>(key); 64 size_t buffLen = strlen(buff); 65 for (size_t i = 0; i < buffLen; i++) { 66 code += buff[i] - 'A'; 67 } 68 return code; 69} 70 71static void TestHashNodeFree(const HashNode *node, void *context) 72{ 73 TestHashNode *testNode = HASHMAP_ENTRY(node, TestHashNode, node); 74 printf("TestHashNodeFree %s\n", testNode->name); 75 free(testNode); 76} 77 78static TestHashNode *TestCreateHashNode(const char *value) 79{ 80 TestHashNode *node = reinterpret_cast<TestHashNode *>(malloc(sizeof(TestHashNode) + strlen(value) + 1)); 81 if (node == nullptr) { 82 return nullptr; 83 } 84 int ret = strcpy_s(node->name, strlen(value) + 1, value); 85 if (ret != 0) { 86 free(node); 87 return nullptr; 88 } 89 HASHMAPInitNode(&node->node); 90 return node; 91} 92 93static void DoCmdByName(const char *name, const char *cmdContent) 94{ 95 int cmdIndex = 0; 96 (void)GetMatchCmd(name, &cmdIndex); 97 DoCmdByIndex(cmdIndex, cmdContent, nullptr); 98} 99 100namespace init_ut { 101class InitGroupManagerUnitTest : public testing::Test { 102public: 103 static void SetUpTestCase(void) {}; 104 static void TearDownTestCase(void) {}; 105 void SetUp(void) {}; 106 void TearDown(void) {}; 107}; 108 109HashInfo g_info = { 110 TestHashNodeCompare, 111 TestHashKeyCompare, 112 TestHashNodeFunction, 113 TestHashKeyFunction, 114 TestHashNodeFree, 115 2 116}; 117 118HWTEST_F(InitGroupManagerUnitTest, TestHashMap001, TestSize.Level1) 119{ 120 HashMapHandle handle; 121 OH_HashMapCreate(&handle, &g_info); 122 const char *str1 = "Test hash map node 1"; 123 const char *str2 = "Test hash map node 2"; 124 const char *str3 = "Test hash map node 3"; 125 TestHashNode *node1 = TestCreateHashNode(str1); 126 TestHashNode *node2 = TestCreateHashNode(str2); 127 OH_HashMapAdd(handle, &node1->node); 128 OH_HashMapAdd(handle, &node2->node); 129 HashNode *node = OH_HashMapGet(handle, (const void *)str1); 130 EXPECT_NE(node != nullptr, 0); 131 if (node) { 132 TestHashNode *tmp = HASHMAP_ENTRY(node, TestHashNode, node); 133 EXPECT_EQ(strcmp(tmp->name, str1), 0); 134 } 135 node = OH_HashMapGet(handle, (const void *)str2); 136 EXPECT_NE(node != nullptr, 0); 137 if (node) { 138 TestHashNode *tmp = HASHMAP_ENTRY(node, TestHashNode, node); 139 EXPECT_EQ(strcmp(tmp->name, str2), 0); 140 } 141 TestHashNode *node3 = TestCreateHashNode(str3); 142 OH_HashMapAdd(handle, &node3->node); 143 node3 = TestCreateHashNode("Test hash map node 4"); 144 OH_HashMapAdd(handle, &node3->node); 145 node3 = TestCreateHashNode("Test hash map node 5"); 146 OH_HashMapAdd(handle, &node3->node); 147 node = OH_HashMapGet(handle, (const void *)str3); 148 EXPECT_NE(node != nullptr, 0); 149 if (node) { 150 TestHashNode *tmp = HASHMAP_ENTRY(node, TestHashNode, node); 151 EXPECT_EQ(strcmp(tmp->name, str3), 0); 152 } 153 OH_HashMapIsEmpty(handle); 154 OH_HashMapTraverse(handle, [](const HashNode *node, const void *context) {return;}, nullptr); 155 OH_HashMapDestory(handle, nullptr); 156} 157 158HWTEST_F(InitGroupManagerUnitTest, TestHashMap002, TestSize.Level1) 159{ 160 HashMapHandle handle; 161 OH_HashMapCreate(&handle, &g_info); 162 TestHashNode *node4 = TestCreateHashNode("pre-init"); 163 OH_HashMapAdd(handle, &node4->node); 164 OH_HashMapRemove(handle, "pre-init"); 165 TestHashNodeFree(&node4->node, nullptr); 166 167 const char *act = "load_persist_props_action"; 168 TestHashNode *node5 = TestCreateHashNode(act); 169 OH_HashMapAdd(handle, &node5->node); 170 HashNode *node = OH_HashMapGet(handle, (const void *)act); 171 EXPECT_NE(node != nullptr, 0); 172 if (node) { 173 TestHashNode *tmp = HASHMAP_ENTRY(node, TestHashNode, node); 174 EXPECT_EQ(strcmp(tmp->name, act), 0); 175 } 176 OH_HashMapIsEmpty(handle); 177 OH_HashMapTraverse(handle, [](const HashNode *node, const void *context) {return;}, nullptr); 178 OH_HashMapDestory(handle, nullptr); 179} 180 181HWTEST_F(InitGroupManagerUnitTest, TestInitGroupMgrInit, TestSize.Level1) 182{ 183 InitServiceSpace(); 184 InitWorkspace *workspace = GetInitWorkspace(); 185 EXPECT_EQ(workspace->groupMode, GROUP_BOOT); 186 workspace->groupMode = GROUP_BOOT; 187 if (strcpy_s(workspace->groupModeStr, GROUP_NAME_MAX_LENGTH, "device.boot.group") != EOK) { 188 EXPECT_EQ(1, 0); 189 } 190 // test read cfgfile 191 int ret = InitParseGroupCfg(); 192 EXPECT_EQ(ret, 0); 193} 194 195HWTEST_F(InitGroupManagerUnitTest, TestAddService, TestSize.Level1) 196{ 197 const char *serviceStr = "{" 198 "\"services\": [{" 199 "\"name\" : \"test-service\"," 200 "\"path\" : [\"/dev/test_service\"]," 201 "\"start-mode\" : \"condition\"," 202 "\"end-mode\" : \"after-exec\"," 203 "\"console\":1," 204 "\"writepid\":[\"/dev/test_service\"]," 205 "\"jobs\" : {" 206 "\"on-boot\" : \"boot:bootjob1\"," 207 "\"on-start\" : \"service:startjob\"," 208 "\"on-stop\" : \"service:stopjob\"," 209 "\"on-restart\" : \"service:restartjob\"" 210 "}" 211 "},{" 212 "\"name\" : \"test-service2\"," 213 "\"path\" : [\"/dev/test_service\"]," 214 "\"console\":1," 215 "\"start-mode\" : \"boot\"," 216 "\"writepid\":[\"/dev/test_service\"]," 217 "\"jobs\" : {" 218 "\"on-boot\" : \"boot:bootjob1\"," 219 "\"on-start\" : \"service:startjob\"," 220 "\"on-stop\" : \"service:stopjob\"," 221 "\"on-restart\" : \"service:restartjob\"" 222 "}" 223 "}]" 224 "}"; 225 226 cJSON *fileRoot = cJSON_Parse(serviceStr); 227 ASSERT_NE(nullptr, fileRoot); 228 ConfigContext context = { INIT_CONTEXT_MAIN }; 229 ParseAllServices(fileRoot, &context); 230 cJSON_Delete(fileRoot); 231 232 Service *service = GetServiceByName("test-service"); 233 ServiceStartTimer(service, 1); 234 ServiceStopTimer(service); 235 ASSERT_NE(service != nullptr, 0); 236 EXPECT_EQ(service->startMode, START_MODE_CONDITION); 237 ReleaseService(service); 238 service = GetServiceByName("test-service2"); 239 ASSERT_NE(service != nullptr, 0); 240 EXPECT_EQ(service->startMode, START_MODE_BOOT); 241 ReleaseService(service); 242} 243 244/** 245 * @brief 246 * 247 248 "socket" : [{ 249 "name" : "ueventd", 250 "family" : "AF_INET", // AF_INET,AF_INET6,AF_UNIX(AF_LOCAL),AF_NETLINK 251 "type" : : "SOCK_STREAM", // SOCK_STREAM,SOCK_DGRAM,SOCK_RAW,SOCK_PACKET,SOCK_SEQPACKET 252 "protocol" : "IPPROTO_TCP", // IPPROTO_TCP,IPPTOTO_UDP,IPPROTO_SCTP,PPROTO_TIPC 253 "permissions" : "0660", 254 "uid" : "system", 255 "gid" : "system", 256 "option" : { 257 "passcred" : "true", 258 "rcvbufforce" : "", 259 "cloexec" : "", 260 "nonblock : "" 261 } 262 }], 263 */ 264HWTEST_F(InitGroupManagerUnitTest, TestAddServiceDeny, TestSize.Level1) 265{ 266 const char *serviceStr = "{" 267 "\"services\": [{" 268 "\"name\" : \"test-service5\"," 269 "\"path\" : [\"/dev/test_service\"]," 270 "\"start-mode\" : \"by-condition\"," 271 "\"end-mode\" : \"ready\"," 272 "\"console\":1," 273 "\"writepid\":[\"/dev/test_service\"]," 274 "\"jobs\" : {" 275 "\"on-boot\" : \"boot:bootjob1\"," 276 "\"on-start\" : \"service:startjob\"," 277 "\"on-stop\" : \"service:stopjob\"," 278 "\"on-restart\" : \"service:restartjob\"" 279 "}" 280 "}]" 281 "}"; 282 InitWorkspace *workspace = GetInitWorkspace(); 283 workspace->groupMode = GROUP_CHARGE; 284 285 cJSON *fileRoot = cJSON_Parse(serviceStr); 286 ASSERT_NE(nullptr, fileRoot); 287 ConfigContext context = { INIT_CONTEXT_MAIN }; 288 ParseAllServices(fileRoot, &context); 289 cJSON_Delete(fileRoot); 290 291 Service *service = GetServiceByName("test-service5"); 292 ASSERT_EQ(service, nullptr); 293 workspace->groupMode = GROUP_BOOT; 294} 295 296HWTEST_F(InitGroupManagerUnitTest, TestAddService2, TestSize.Level1) 297{ 298 const char *serviceStr = "{" 299 "\"services\": [{" 300 "\"name\" : \"test-service6\"," 301 "\"path\" : [\"/dev/test_service\"]," 302 "\"console\":1," 303 "\"writepid\":[\"/dev/test_service\"]," 304 "\"jobs\" : {" 305 "\"on-boot\" : \"boot:bootjob1\"," 306 "\"on-start\" : \"service:startjob\"," 307 "\"on-stop\" : \"service:stopjob\"," 308 "\"on-restart\" : \"service:restartjob\"" 309 "}" 310 "}]" 311 "}"; 312 313 InitWorkspace *workspace = GetInitWorkspace(); 314 workspace->groupMode = GROUP_CHARGE; 315 316 InitGroupNode *node = AddGroupNode(NODE_TYPE_SERVICES, "test-service6"); 317 ASSERT_NE(nullptr, node); 318 319 cJSON *fileRoot = cJSON_Parse(serviceStr); 320 ASSERT_NE(nullptr, fileRoot); 321 ConfigContext context = { INIT_CONTEXT_MAIN }; 322 ParseAllServices(fileRoot, &context); 323 cJSON_Delete(fileRoot); 324 char cmdStr[] = "all#bootevent"; 325 char cmdStr1[] = "parameter_service"; 326 ProcessControlFd(ACTION_DUMP, "all", nullptr); 327 ProcessControlFd(ACTION_DUMP, cmdStr, nullptr); 328 ProcessControlFd(ACTION_DUMP, cmdStr1, nullptr); 329 ProcessControlFd(ACTION_SANDBOX, cmdStr, nullptr); 330 ProcessControlFd(ACTION_MODULEMGR, cmdStr, nullptr); 331 ProcessControlFd(ACTION_MAX, cmdStr, nullptr); 332 Service *service = GetServiceByName("test-service6"); 333 ASSERT_NE(service, nullptr); 334 workspace->groupMode = GROUP_BOOT; 335} 336 337HWTEST_F(InitGroupManagerUnitTest, TestParseServiceCpucore, TestSize.Level1) 338{ 339 const char *jsonStr = "{\"services\":{\"name\":\"test_service22\",\"path\":[\"/data/init_ut/test_service\"]," 340 "\"importance\":-20,\"uid\":\"root\",\"writepid\":[\"/dev/test_service\"],\"console\":1," 341 "\"gid\":[\"root\"], \"cpucore\":[5, 2, 4, 1, 2, 0, 1], \"critical\":[1]}}"; 342 cJSON* jobItem = cJSON_Parse(jsonStr); 343 ASSERT_NE(nullptr, jobItem); 344 cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services"); 345 ASSERT_NE(nullptr, serviceItem); 346 Service *service = AddService("test_service22"); 347 const int invalidImportantValue = 20; 348 SetImportantValue(service, "", invalidImportantValue, 1); 349 if (service != nullptr) { 350 int ret = ParseOneService(serviceItem, service); 351 GetAccessToken(); 352 DoCmdByName("timer_start ", "test_service22|5000"); 353 DoCmdByName("timer_start ", "test_service22|aa"); 354 DoCmdByName("timer_start ", ""); 355 EXPECT_EQ(ret, 0); 356 StartServiceByName("test_service22|path"); 357 ReleaseService(service); 358 } 359 cJSON_Delete(jobItem); 360} 361 362HWTEST_F(InitGroupManagerUnitTest, TestUpdaterServiceFds, TestSize.Level1) 363{ 364 Service *service = AddService("test_service8"); 365 ASSERT_NE(nullptr, service); 366 int fds[1] = { -1 }; // ServiceStop will release fds 367 UpdaterServiceFds(nullptr, nullptr, 0); 368 UpdaterServiceFds(service, fds, 1); 369 UpdaterServiceFds(service, fds, 0); 370 UpdaterServiceFds(service, fds, 1); 371 UpdaterServiceFds(service, nullptr, 1); 372 UpdaterServiceFds(service, fds, 1); 373 int ret = UpdaterServiceFds(service, nullptr, 2); // 2 is fd num 374 ASSERT_NE(ret, 0); 375 service->attribute = SERVICE_ATTR_TIMERSTART; 376 ServiceStartTimer(service, 0); 377} 378HWTEST_F(InitGroupManagerUnitTest, TestProcessWatchEvent, TestSize.Level1) 379{ 380 Service *service = AddService("test_service9"); 381 ASSERT_NE(nullptr, service); 382 ServiceSocket servercfg = {.next = nullptr, .sockFd = 0}; 383 service->socketCfg = &servercfg; 384 ServiceWatcher watcher; 385 int ret = AddSocketWatcher(&watcher, service, 0); 386 ASSERT_EQ(ret, 0); 387 uint32_t event; 388 ((WatcherTask *)watcher)->processEvent((WatcherHandle)watcher, 0, &event, service); 389 service->socketCfg = nullptr; 390} 391 392HWTEST_F(InitGroupManagerUnitTest, TestCheckNodeValid, TestSize.Level1) 393{ 394 int ret = CheckNodeValid(NODE_TYPE_MAX, "charger"); 395 EXPECT_EQ(ret, -1); 396 ret = CheckNodeValid(NODE_TYPE_PLUGINS, "charger"); 397 EXPECT_EQ(ret, -1); 398} 399 400HWTEST_F(InitGroupManagerUnitTest, TestGetGroupHashMap, TestSize.Level1) 401{ 402 HashMapHandle handle = GetGroupHashMap(NODE_TYPE_GROUPS); 403 EXPECT_TRUE(handle == nullptr); 404} 405} // namespace init_ut 406