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