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
28 using namespace testing::ext;
29 using namespace std;
30
31 typedef struct {
32 HashNode node;
33 char name[0];
34 } TestHashNode;
35
TestHashNodeCompare(const HashNode * node1,const HashNode * node2)36 static 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
TestHashKeyCompare(const HashNode * node1,const void * key)43 static 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
TestHashNodeFunction(const HashNode * node)49 static 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
TestHashKeyFunction(const void * key)60 static 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
TestHashNodeFree(const HashNode * node,void * context)71 static 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
TestCreateHashNode(const char * value)78 static 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
DoCmdByName(const char * name,const char * cmdContent)93 static 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
100 namespace init_ut {
101 class InitGroupManagerUnitTest : public testing::Test {
102 public:
SetUpTestCase(void)103 static void SetUpTestCase(void) {};
TearDownTestCase(void)104 static void TearDownTestCase(void) {};
SetUp(void)105 void SetUp(void) {};
TearDown(void)106 void TearDown(void) {};
107 };
108
109 HashInfo g_info = {
110 TestHashNodeCompare,
111 TestHashKeyCompare,
112 TestHashNodeFunction,
113 TestHashKeyFunction,
114 TestHashNodeFree,
115 2
116 };
117
118 HWTEST_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);
__anon9672dc4e0202(const HashNode *node, const void *context) 154 OH_HashMapTraverse(handle, [](const HashNode *node, const void *context) {return;}, nullptr);
155 OH_HashMapDestory(handle, nullptr);
156 }
157
158 HWTEST_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);
__anon9672dc4e0302(const HashNode *node, const void *context) 177 OH_HashMapTraverse(handle, [](const HashNode *node, const void *context) {return;}, nullptr);
178 OH_HashMapDestory(handle, nullptr);
179 }
180
181 HWTEST_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
195 HWTEST_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 */
264 HWTEST_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
296 HWTEST_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
337 HWTEST_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
362 HWTEST_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 }
378 HWTEST_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
392 HWTEST_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
400 HWTEST_F(InitGroupManagerUnitTest, TestGetGroupHashMap, TestSize.Level1)
401 {
402 HashMapHandle handle = GetGroupHashMap(NODE_TYPE_GROUPS);
403 EXPECT_TRUE(handle == nullptr);
404 }
405 } // namespace init_ut
406