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/statvfs.h>
17#include "init_cmds.h"
18#include "init_param.h"
19#include "init_group_manager.h"
20#include "param_stub.h"
21#include "init_utils.h"
22#include "trigger_manager.h"
23
24using namespace testing::ext;
25using namespace std;
26
27static void DoCmdByName(const char *name, const char *cmdContent)
28{
29    int cmdIndex = 0;
30    (void)GetMatchCmd(name, &cmdIndex);
31    DoCmdByIndex(cmdIndex, cmdContent, nullptr);
32}
33
34namespace init_ut {
35class CmdsUnitTest : public testing::Test {
36public:
37    static void SetUpTestCase(void) {};
38    static void TearDownTestCase(void) {};
39    void SetUp() {};
40    void TearDown() {};
41};
42
43HWTEST_F(CmdsUnitTest, TestCmdExecByName1, TestSize.Level1)
44{
45    DoCmdByName("timer_start ", "media_service|5000");
46    DoCmdByName("timer_start ", "|5000");
47    DoCmdByName("timer_stop ", "media_service");
48    DoCmdByName("exec ", "media_service");
49    DoCmdByName("syncexec ", "/system/bin/toybox");
50    DoCmdByName("load_access_token_id ", "media_service");
51    DoCmdByName("load_access_token_id ", "");
52    DoCmdByName("stopAllServices ", "false");
53    DoCmdByName("stopAllServices ", "true");
54    DoCmdByName("umount ", "/2222222");
55    DoCmdByName("mount ", "/2222222");
56    DoCmdByName("mount ", "ext4 /2222222 /data wait filecrypt=555");
57    DoCmdByName("umount ", "/2222222");
58    DoCmdByName("init_global_key ", "/data");
59    DoCmdByName("init_global_key ", "arg0 arg1");
60    DoCmdByName("init_main_user ", "testUser");
61    DoCmdByName("init_main_user ", nullptr);
62    DoCmdByName("mkswap ", "/data/init_ut");
63    DoCmdByName("swapon ", "/data/init_ut");
64    DoCmdByName("sync ", "");
65    DoCmdByName("restorecon ", "");
66    DoCmdByName("restorecon ", "/data  /data");
67    DoCmdByName("suspend ", "");
68    DoCmdByName("wait ", "1");
69    DoCmdByName("wait ", "aaa 1");
70    DoCmdByName("mksandbox", "/sandbox");
71    DoCmdByName("mount_fstab ", "/2222222");
72    DoCmdByName("umount_fstab ", "/2222222");
73    DoCmdByName("mknode  ", "node1 node1 node1 node1 node1");
74    DoCmdByName("makedev ", "/device1 device2");
75    DoCmdByName("symlink ", "/xxx/xxx/xxx1 /xxx/xxx/xxx2");
76    DoCmdByName("load_param ", "aaa onlyadd");
77    DoCmdByName("load_persist_params ", "");
78    DoCmdByName("load_param ", "");
79    DoCmdByName("setparam ", "bbb 0");
80    DoCmdByName("ifup ", "aaa, bbb");
81    DoCmdByName("insmod ", "a b");
82    DoCmdByName("insmod ", "/data /data");
83}
84
85HWTEST_F(CmdsUnitTest, TestCommonMkdir, TestSize.Level1)
86{
87    auto checkMkdirCmd = [=](const char *mkdirFile, const char *cmdLine) {
88        DoCmdByName("mkdir ", cmdLine);
89        return access(mkdirFile, F_OK);
90    };
91    EXPECT_EQ(checkMkdirCmd("/data/init_ut/test_dir0", "/data/init_ut/test_dir0"), 0);
92    EXPECT_EQ(checkMkdirCmd("/data/init_ut/test_dir1", "/data/init_ut/test_dir1 0755"), 0);
93    EXPECT_EQ(checkMkdirCmd("/data/init_ut/test_dir2", "/data/init_ut/test_dir2 0755 system system"), 0);
94
95    // abnormal
96    EXPECT_NE(checkMkdirCmd("/data/init_ut/test_dir3", ""), 0);
97    EXPECT_NE(checkMkdirCmd("/data/init_ut/test_dir4", "/data/init_ut/test_dir4 0755 system"), 0);
98    EXPECT_EQ(checkMkdirCmd("/data/init_ut/test_dir5", "/data/init_ut/test_dir5 0755 error error"), 0);
99}
100
101HWTEST_F(CmdsUnitTest, TestCommonChown, TestSize.Level1)
102{
103    const char *testFile = "/data/init_ut/test_dir0";
104    DoCmdByName("chown ", "system system /data/init_ut/test_dir0");
105    struct stat info = {};
106    stat(testFile, &info);
107    const unsigned int systemUidGid = 1000;
108    EXPECT_EQ(info.st_uid, systemUidGid);
109    EXPECT_EQ(info.st_gid, systemUidGid);
110
111    // abnormal
112    DoCmdByName("chown ", "error error /data/init_ut/test_dir0");
113    stat(testFile, &info);
114    EXPECT_EQ(info.st_uid, systemUidGid);
115    EXPECT_EQ(info.st_gid, systemUidGid);
116}
117
118HWTEST_F(CmdsUnitTest, TestCommonChmod, TestSize.Level1)
119{
120    const char *testFile = "/data/init_ut/test_dir0/test_file0";
121    const mode_t testMode = S_IRWXU | S_IRWXG | S_IRWXO;
122    int fd = open(testFile, O_CREAT | O_WRONLY, testMode);
123    ASSERT_GE(fd, 0);
124    DoCmdByName("chmod ", "777 /data/init_ut/test_dir0/test_file0");
125    struct stat info;
126    stat(testFile, &info);
127    EXPECT_EQ(testMode, testMode & info.st_mode);
128
129    // abnormal
130    DoCmdByName("chmod ", "999 /data/init_ut/test_dir0/test_file0");
131    stat(testFile, &info);
132    EXPECT_EQ(testMode, testMode & info.st_mode);
133    DoCmdByName("chmod ", "777 /data/init_ut/test_dir0/test_file001");
134
135    close(fd);
136}
137
138HWTEST_F(CmdsUnitTest, TestCommonCopy, TestSize.Level1)
139{
140    const char *testFile1 = "/data/init_ut/test_dir0/test_file_copy1";
141    DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file0 /data/init_ut/test_dir0/test_file_copy1");
142    int fd = open(testFile1, O_RDWR);
143    ASSERT_GE(fd, 0);
144    write(fd, "aaa", strlen("aaa"));
145
146    const char *testFile2 = "/data/init_ut/test_dir0/test_file_copy2";
147    DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy1 /data/init_ut/test_dir0/test_file_copy2");
148    int ret = access(testFile2, F_OK);
149    EXPECT_EQ(ret, 0);
150    close(fd);
151    // abnormal
152    DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy1 /data/init_ut/test_dir0/test_file_copy1");
153    DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy11 /data/init_ut/test_dir0/test_file_copy1");
154    DoCmdByName("copy ", "a");
155
156    DoCmdByName("chmod ", "111 /data/init_ut/test_dir0/test_file_copy1");
157    DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy1 /data/init_ut/test_dir0/test_file_copy2");
158
159    DoCmdByName("chmod ", "777 /data/init_ut/test_dir0/test_file_copy1");
160    DoCmdByName("chmod ", "111 /data/init_ut/test_dir0/test_file_copy2");
161    DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy1 /data/init_ut/test_dir0/test_file_copy2");
162    DoCmdByName("chmod ", "777 /data/init_ut/test_dir0/test_file_copy2");
163}
164
165HWTEST_F(CmdsUnitTest, TestCommonWrite, TestSize.Level1)
166{
167    const char *testFile1 = "/data/init_ut/test_dir0/test_file_write1";
168    int fd = open(testFile1, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
169    ASSERT_GE(fd, 0);
170
171    DoCmdByName("write ", "/data/init_ut/test_dir0/test_file_write1 aaa");
172    const int bufLen = 50;
173    char buffer[bufLen];
174    int length = read(fd, buffer, bufLen - 1);
175    EXPECT_EQ(length, strlen("aaa"));
176    close(fd);
177    // abnormal
178    DoCmdByName("write ", "/data/init_ut/test_dir0/test_file_write2 aaa 2");
179}
180
181HWTEST_F(CmdsUnitTest, TestCommonRm, TestSize.Level1)
182{
183    const char *testFile1 = "/data/init_ut/test_dir0/test_file_write1";
184    DoCmdByName("rm ", testFile1);
185    int ret = access(testFile1, F_OK);
186    EXPECT_NE(ret, 0);
187
188    testFile1 = "/data/init_ut/test_dir1";
189    DoCmdByName("rmdir ", testFile1);
190    ret = access(testFile1, F_OK);
191    EXPECT_NE(ret, 0);
192
193    // abnormal
194    DoCmdByName("rmdir ", testFile1);
195}
196
197HWTEST_F(CmdsUnitTest, TestCommonExport, TestSize.Level1)
198{
199    DoCmdByName("export ", "TEST_INIT 1");
200    EXPECT_STREQ("1", getenv("TEST_INIT"));
201    unsetenv("TEST_INIT");
202    EXPECT_STRNE("1", getenv("TEST_INIT"));
203}
204
205HWTEST_F(CmdsUnitTest, TestCommonMount, TestSize.Level1)
206{
207    DoCmdByName("mount ", "ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/vendor "
208        "/vendor wait rdonly barrier=1");
209    struct statvfs64 vfs {};
210    int ret = statvfs64("/vendor", &vfs);
211    EXPECT_GE(ret, 0);
212    EXPECT_GT(vfs.f_bsize, 0);
213}
214
215HWTEST_F(CmdsUnitTest, TestGetCmdKey, TestSize.Level1)
216{
217    const char *cmd1 = GetCmdKey(0);
218    EXPECT_STREQ(cmd1, "start ");
219}
220
221HWTEST_F(CmdsUnitTest, TestDoCmdByIndex, TestSize.Level1)
222{
223    DoCmdByIndex(1, "/data/init_ut/test_cmd_dir0", nullptr);
224    int ret = access("/data/init_ut/test_cmd_dir0", F_OK);
225    EXPECT_EQ(ret, 0);
226
227    const int execPos = 17;
228    DoCmdByIndex(execPos, "sleep 1", nullptr);
229    DoCmdByIndex(23, "test", nullptr); // 23 is cmd index
230}
231
232HWTEST_F(CmdsUnitTest, TestGetCmdLinesFromJson, TestSize.Level1)
233{
234    const char *jsonStr = "{\"jobs\":[{\"name\":\"init\",\"cmds\":[\"sleep 1\",100,\"test321 123\"]}]}";
235    cJSON* jobItem = cJSON_Parse(jsonStr);
236    ASSERT_NE(nullptr, jobItem);
237    cJSON *cmdsItem = cJSON_GetObjectItem(jobItem, "jobs");
238    ASSERT_NE(nullptr, cmdsItem);
239    ASSERT_TRUE(cJSON_IsArray(cmdsItem));
240
241    cJSON *cmdsItem1 = cJSON_GetArrayItem(cmdsItem, 0);
242    ASSERT_NE(nullptr, cmdsItem1);
243    CmdLines **cmdLines = (CmdLines **)calloc(1, sizeof(CmdLines *));
244    ASSERT_NE(nullptr, cmdLines);
245    int ret = GetCmdLinesFromJson(cmdsItem1, cmdLines);
246    EXPECT_EQ(ret, -1);
247    cJSON *cmdsItem2 = cJSON_GetObjectItem(cmdsItem1, "cmds");
248    ASSERT_NE(nullptr, cmdsItem2);
249    ret = GetCmdLinesFromJson(cmdsItem2, cmdLines);
250    EXPECT_EQ(ret, 0);
251
252    cJSON_Delete(jobItem);
253    if (cmdLines[0] != nullptr) {
254        free(cmdLines[0]);
255        cmdLines[0] = nullptr;
256    }
257    free(cmdLines);
258    cmdLines = nullptr;
259}
260
261HWTEST_F(CmdsUnitTest, TestInitCmdFunc, TestSize.Level1)
262{
263    int ret = GetBootModeFromMisc();
264    EXPECT_EQ(ret, 0);
265    ret = SetFileCryptPolicy(nullptr);
266    EXPECT_NE(ret, 0);
267}
268
269HWTEST_F(CmdsUnitTest, TestBuildStringFromCmdArg, TestSize.Level1)
270{
271    int strNum = 3;
272    struct CmdArgs *ctx = (struct CmdArgs *)calloc(1, sizeof(struct CmdArgs) + sizeof(char *) * (strNum));
273    ctx->argc = strNum;
274    ctx->argv[0] = strdup("123456789012345678901234567890123456789012345678901234567890   \
275            1234567890123456789012345678901234567890123456789012345678901234567");
276    ctx->argv[1] = strdup("test");
277    ctx->argv[2] = nullptr;
278    char *options = BuildStringFromCmdArg(ctx, 0);
279    EXPECT_EQ(options[0], '\0');
280    free(options);
281
282    options = BuildStringFromCmdArg(ctx, 1);
283    EXPECT_STREQ(options, "test");
284    free(options);
285    FreeCmdArg(ctx);
286}
287
288HWTEST_F(CmdsUnitTest, TestInitDiffTime, TestSize.Level1)
289{
290    INIT_TIMING_STAT stat;
291    stat.startTime.tv_sec = 2; // 2 is test sec
292    stat.startTime.tv_nsec = 1000;  // 1000 is test nsec
293
294    stat.endTime.tv_sec = 3;  // 3 is test sec
295    stat.endTime.tv_nsec = 0;
296
297    long long diff = InitDiffTime(&stat);
298    EXPECT_TRUE(diff > 0);
299}
300} // namespace init_ut
301