• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include <sys/socket.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 #include <cstdlib>
20 #include "init_cmds.h"
21 #include "init_service.h"
22 #include "init_service_manager.h"
23 #include "init_service_socket.h"
24 #include "param_stub.h"
25 #include "init_utils.h"
26 #include "securec.h"
27 #include "init_group_manager.h"
28 #include "trigger_manager.h"
29 #include "bootstage.h"
30 #include "init_hook.h"
31 #include "plugin_adapter.h"
32 
33 using namespace testing::ext;
34 using namespace std;
35 namespace init_ut {
36 class ServiceUnitTest : public testing::Test {
37 public:
SetUpTestCase(void)38     static void SetUpTestCase(void)
39     {
40         string svcPath = "/data/init_ut/test_service";
41         auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(svcPath.c_str(), "wb"), fclose);
42         if (fp == nullptr) {
43             cout << "ServiceUnitTest open : " << svcPath << " failed." << errno << endl;
44         }
45         sync();
46     }
47 
TearDownTestCase(void)48     static void TearDownTestCase(void) {};
SetUp()49     void SetUp() {};
TearDown()50     void TearDown() {};
51 };
52 
53 HWTEST_F(ServiceUnitTest, case01, TestSize.Level1)
54 {
55     const char *jsonStr = "{\"services\":{\"name\":\"test_service\",\"path\":[\"/data/init_ut/test_service\"],"
56         "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
57         "\"gid\":[\"system\"], \"critical\":1}}";
58     cJSON* jobItem = cJSON_Parse(jsonStr);
59     ASSERT_NE(nullptr, jobItem);
60     cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
61     ASSERT_NE(nullptr, serviceItem);
62     Service *service = AddService("test_service");
63     int ret = ParseOneService(serviceItem, service);
64     EXPECT_EQ(ret, 0);
65 
66     ret = ServiceStart(service);
67     EXPECT_EQ(ret, 0);
68 
69     ret = ServiceStop(service);
70     EXPECT_EQ(ret, 0);
71 
72     ReleaseService(service);
73 }
74 
75 HWTEST_F(ServiceUnitTest, case02, TestSize.Level1)
76 {
77     const char *jsonStr = "{\"services\":{\"name\":\"test_service8\",\"path\":[\"/data/init_ut/test_service\"],"
78         "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
79         "\"gid\":[\"system\"],\"caps\":[10, 4294967295, 10000],\"cpucore\":[1]}}";
80     cJSON* jobItem = cJSON_Parse(jsonStr);
81     ASSERT_NE(nullptr, jobItem);
82     cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
83     ASSERT_NE(nullptr, serviceItem);
84     Service *service = AddService("test_service8");
85     ASSERT_NE(nullptr, service);
86     int ret = ParseOneService(serviceItem, service);
87     EXPECT_EQ(ret, 0);
88 
89     int *fds = (int *)malloc(sizeof(int) * 1); // ServiceStop will release fds
90     ASSERT_NE(nullptr, fds);
91     UpdaterServiceFds(service, fds, 1);
92     service->attribute = SERVICE_ATTR_ONDEMAND;
93     ret = ServiceStart(service);
94     EXPECT_EQ(ret, 0);
95     CmdLines *cmdline = (CmdLines *)malloc(sizeof(CmdLines) + sizeof(CmdLine));
96     ASSERT_NE(nullptr, cmdline);
97     cmdline->cmdNum = 1;
98     cmdline->cmds[0].cmdIndex = 0;
99     service->restartArg = cmdline;
100     ServiceSocket tmpSock = { .next = nullptr, .sockFd = 0 };
101     ServiceSocket tmpSock1 = { .next = &tmpSock, .sockFd = 0 };
102     service->socketCfg = &tmpSock1;
103     ServiceReap(service);
104     service->socketCfg = nullptr;
105     service->attribute &= SERVICE_ATTR_NEED_RESTART;
106     service->firstCrashTime = 0;
107     ServiceReap(service);
108     DoCmdByName("reset ", "test_service8");
109     // reset again
110     DoCmdByName("reset ", "test_service8");
111     service->pid = 0xfffffff; // 0xfffffff is not exist pid
112     service->attribute = SERVICE_ATTR_TIMERSTART;
113     ret = ServiceStop(service);
114     EXPECT_NE(ret, 0);
115     ReleaseService(service);
116 }
117 
118 HWTEST_F(ServiceUnitTest, TestServiceStartAbnormal, TestSize.Level1)
119 {
120     const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/data/init_ut/test_service\"],"
121         "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
122         "\"gid\":[\"system\"]}}";
123     cJSON* jobItem = cJSON_Parse(jsonStr);
124     ASSERT_NE(nullptr, jobItem);
125     cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
126     ASSERT_NE(nullptr, serviceItem);
127     Service *service = AddService("test_service1");
128     ASSERT_NE(nullptr, service);
129     int ret = ParseOneService(serviceItem, service);
130     EXPECT_EQ(ret, 0);
131 
132     const char *path = "/data/init_ut/test_service_unused";
133     ret = strncpy_s(service->pathArgs.argv[0], strlen(path) + 1, path, strlen(path));
134     EXPECT_EQ(ret, 0);
135 
136     ret = ServiceStart(service);
137     EXPECT_EQ(ret, -1);
138 
139     service->attribute &= SERVICE_ATTR_INVALID;
140     ret = ServiceStart(service);
141     EXPECT_EQ(ret, -1);
142 
143     service->pid = -1;
144     ret = ServiceStop(service);
145     EXPECT_EQ(ret, 0);
146     ReleaseService(service);
147 }
148 
149 HWTEST_F(ServiceUnitTest, TestServiceReap, TestSize.Level1)
150 {
151     Service *service = AddService("test_service2");
152     ASSERT_NE(nullptr, service);
153     EXPECT_EQ(service->attribute, 0);
154     service->attribute = SERVICE_ATTR_ONDEMAND;
155     ServiceReap(service);
156     service->attribute = 0;
157 
158     service->restartArg = (CmdLines *)calloc(1, sizeof(CmdLines));
159     ASSERT_NE(nullptr, service->restartArg);
160     ServiceReap(service);
161     EXPECT_EQ(service->attribute, 0);
162 
163     const int crashCount = 241;
164     service->crashCnt = crashCount;
165     ServiceReap(service);
166     EXPECT_EQ(service->attribute, 0);
167 
168     service->attribute |= SERVICE_ATTR_ONCE;
169     ServiceReap(service);
170     EXPECT_EQ(service->attribute, SERVICE_ATTR_ONCE);
171     service->attribute = SERVICE_ATTR_CRITICAL;
172     service->crashCount = 1;
173     ServiceReap(service);
174     ReleaseService(service);
175 }
176 
177 HWTEST_F(ServiceUnitTest, TestServiceReapOther, TestSize.Level1)
178 {
179     const char *serviceStr = "{\"services\":{\"name\":\"test_service4\",\"path\":[\"/data/init_ut/test_service\"],"
180         "\"onrestart\":[\"sleep 1\"],\"console\":1,\"writepid\":[\"/dev/test_service\"]}}";
181 
182     cJSON* jobItem = cJSON_Parse(serviceStr);
183     ASSERT_NE(nullptr, jobItem);
184     cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
185     ASSERT_NE(nullptr, serviceItem);
186     Service *service = AddService("test_service4");
187     ASSERT_NE(nullptr, service);
188     int ret = ParseOneService(serviceItem, service);
189     EXPECT_EQ(ret, 0);
190 
191     ServiceReap(service);
192     EXPECT_NE(service->attribute, 0);
193 
194     service->attribute |= SERVICE_ATTR_CRITICAL;
195     ServiceReap(service);
196     EXPECT_NE(service->attribute, 0);
197 
198     service->attribute |= SERVICE_ATTR_NEED_STOP;
199     ServiceReap(service);
200     EXPECT_NE(service->attribute, 0);
201 
202     service->attribute |= SERVICE_ATTR_INVALID;
203     ServiceReap(service);
204     EXPECT_NE(service->attribute, 0);
205 
206     ret = ServiceStop(service);
207     EXPECT_EQ(ret, 0);
208     ReleaseService(service);
209 }
210 
211 HWTEST_F(ServiceUnitTest, TestServiceManagerRelease, TestSize.Level1)
212 {
213     Service *service = nullptr;
214     ReleaseService(service);
215     EXPECT_TRUE(service == nullptr);
216     service = AddService("test_service5");
217     ASSERT_NE(nullptr, service);
218     service->pathArgs.argv = (char **)malloc(sizeof(char *));
219     ASSERT_NE(nullptr, service->pathArgs.argv);
220     service->pathArgs.count = 1;
221     const char *path = "/data/init_ut/test_service_release";
222     service->pathArgs.argv[0] = strdup(path);
223 
224     service->writePidArgs.argv = (char **)malloc(sizeof(char *));
225     ASSERT_NE(nullptr, service->writePidArgs.argv);
226     service->writePidArgs.count = 1;
227     service->writePidArgs.argv[0] = strdup(path);
228 
229     service->servPerm.caps = (unsigned int *)malloc(sizeof(unsigned int));
230     ASSERT_NE(nullptr, service->servPerm.caps);
231     service->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t));
232     ASSERT_NE(nullptr, service->servPerm.gIDArray);
233     service->socketCfg = (ServiceSocket *)malloc(sizeof(ServiceSocket));
234     ASSERT_NE(nullptr, service->socketCfg);
235     service->socketCfg->sockFd = 0;
236     service->socketCfg->next = nullptr;
237     service->fileCfg = (ServiceFile *)malloc(sizeof(ServiceFile));
238     ASSERT_NE(nullptr, service->fileCfg);
239     service->fileCfg->fd = 0;
240     service->fileCfg->next = nullptr;
241     ReleaseService(service);
242     service = nullptr;
243 }
244 
245 HWTEST_F(ServiceUnitTest, TestServiceManagerGetService, TestSize.Level1)
246 {
247     Service *service = GetServiceByPid(1);
248     StopAllServices(1, nullptr, 0, nullptr);
249     EXPECT_TRUE(service == nullptr);
250     const char *jsonStr = "{\"services\":{\"name\":\"test_service2\",\"path\":[\"/data/init_ut/test_service\"],"
251         "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
252         "\"gid\":[\"system\"], \"critical\":[1,2]}}";
253     cJSON* jobItem = cJSON_Parse(jsonStr);
254     ASSERT_NE(nullptr, jobItem);
255     cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
256     ASSERT_NE(nullptr, serviceItem);
257     service = AddService("test_service2");
258     ASSERT_NE(nullptr, service);
259     int ret = ParseOneService(serviceItem, service);
260     EXPECT_NE(ret, 0);
261     const char *jsonStr1 = "{\"services\":{\"name\":\"test_service3\",\"path\":[\"/data/init_ut/test_service\"],"
262         "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
263         "\"gid\":[\"system\"], \"critical\":[\"on\"]}}";
264     jobItem = cJSON_Parse(jsonStr1);
265     ASSERT_NE(nullptr, jobItem);
266     serviceItem = cJSON_GetObjectItem(jobItem, "services");
267     ASSERT_NE(nullptr, serviceItem);
268     service = AddService("test_service3");
269     ASSERT_NE(nullptr, service);
270     ret = ParseOneService(serviceItem, service);
271     EXPECT_NE(ret, 0);
272 }
273 
274 /**
275 * @tc.name: TestServiceBootEventHook
276 * @tc.desc: test bootevent module exec correct
277 * @tc.type: FUNC
278 * @tc.require: issueI5NTX4
279 * @tc.author:
280 */
281 HWTEST_F(ServiceUnitTest, TestServiceBootEventHook, TestSize.Level1)
282 {
283     const char *serviceStr = "{"
284 	    "\"services\": [{"
285             "\"name\" : \"test-service\","
286             "\"path\" : [\"/dev/test_service\"],"
287             "\"start-mode\" : \"condition\","
288             "\"writepid\":[\"/dev/test_service\"],"
289             "\"bootevents\" : \"bootevent2\""
290         "},{"
291             "\"name\" : \"test-service\","
292             "\"path\" : [\"/dev/test_service\"],"
293             "\"start-mode\" : \"condition\","
294             "\"writepid\":[\"/dev/test_service\"],"
295             "\"bootevents\" : \"bootevent.bootevent2\""
296         "},{"
297             "\"name\" : \"test-service2\","
298             "\"path\" : [\"/dev/test_service\"],"
299             "\"console\":1,"
300             "\"start-mode\" : \"boot\","
301             "\"writepid\":[\"/dev/test_service\"],"
302             "\"bootevents\" : [\"bootevent.bootevent1\", \"bootevent.bootevent2\"]"
303         "}]"
304     "}";
305 
306     SERVICE_INFO_CTX serviceInfoContext;
307     serviceInfoContext.serviceName = "test-service2";
308     serviceInfoContext.reserved = "bootevent";
309     HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
310     (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&serviceInfoContext), NULL);
311     cJSON *fileRoot = cJSON_Parse(serviceStr);
312     ASSERT_NE(nullptr, fileRoot);
313     PluginExecCmd("clear", 0, nullptr);
314     ParseAllServices(fileRoot);
315     (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), NULL);
316     serviceInfoContext.reserved = NULL;
317     (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), NULL);
318     const char *initBootevent[] = {"init", "test"};
319     PluginExecCmd("bootevent", ARRAY_LENGTH(initBootevent), initBootevent);
320     const char *initBooteventDup[] = {"init", "test"};
321     PluginExecCmd("bootevent", ARRAY_LENGTH(initBooteventDup), initBooteventDup);
322     const char *initBooteventErr[] = {"init"};
323     PluginExecCmd("bootevent", ARRAY_LENGTH(initBooteventErr), initBooteventErr);
324     SystemWriteParam("bootevent.bootevent1", "true");
325     SystemWriteParam("bootevent.bootevent2", "true");
326     SystemWriteParam("bootevent.bootevent2", "true");
327     SystemWriteParam("persist.init.bootevent.enable", "false");
328     HookMgrExecute(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, NULL, NULL);
329     CloseTriggerWorkSpace();
330     cJSON_Delete(fileRoot);
331 }
332 
333 HWTEST_F(ServiceUnitTest, TestServiceExec, TestSize.Level1)
334 {
335     Service *service = AddService("test_service7");
336     ASSERT_NE(nullptr, service);
337 
338     service->pathArgs.argv = (char **)malloc(sizeof(char *));
339     ASSERT_NE(service->pathArgs.argv, nullptr);
340     service->pathArgs.count = 1;
341     const char *path = "/data/init_ut/test_service_release";
342     service->pathArgs.argv[0] = strdup(path);
343     service->importance = 20;
344     service->servPerm.gIDCnt = -1;
345     service->servPerm.uID = 0;
346     unsigned int *caps = (unsigned int *)calloc(1, sizeof(unsigned int) * 1);
347     ASSERT_NE(nullptr, caps);
348     caps[0] = FULL_CAP;
349     service->servPerm.caps = caps;
350     service->servPerm.capsCnt = 1;
351     IsEnableSandbox();
352     EnterServiceSandbox(service);
353     int ret = ServiceExec(service);
354     EXPECT_EQ(ret, 0);
355 
356     const int invalidImportantValue = 20;
357     ret = SetImportantValue(service, "", invalidImportantValue, 1);
358     EXPECT_EQ(ret, -1);
359     ReleaseService(service);
360 }
361 } // namespace init_ut
362