1/*
2 * Copyright (c) 2023 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 <iostream>
17#include <unistd.h>
18#include <fcntl.h>
19#include <sys/stat.h>
20#include <sys/types.h>
21#include <dirent.h>
22
23#include "init_eng.h"
24#include "init_utils.h"
25#include "param_stub.h"
26#include "bootstage.h"
27#include "securec.h"
28
29using namespace std;
30using namespace testing::ext;
31
32namespace init_ut {
33static const std::string SRC_FILE_PATH = STARTUP_INIT_UT_PATH"/eng/source/test.txt";
34static const std::string TARGET_PATH = STARTUP_INIT_UT_PATH"/eng/link_name";
35static const std::string ENG_ROOT_PATH = STARTUP_INIT_UT_PATH"/eng/";
36
37static bool RemoveDir(const std::string &path)
38{
39    if (path.empty()) {
40        return false;
41    }
42    std::string strPath = path;
43    if (strPath.at(strPath.length() - 1) != '/') {
44        strPath.append("/");
45    }
46    DIR *d = opendir(strPath.c_str());
47    if (d != nullptr) {
48        struct dirent *dt = nullptr;
49        dt = readdir(d);
50        while (dt != nullptr) {
51            if (strcmp(dt->d_name, "..") == 0 || strcmp(dt->d_name, ".") == 0) {
52                dt = readdir(d);
53                continue;
54            }
55            struct stat st {};
56            auto file_name = strPath + std::string(dt->d_name);
57            stat(file_name.c_str(), &st);
58            if (S_ISDIR(st.st_mode)) {
59                RemoveDir(file_name);
60            } else {
61                remove(file_name.c_str());
62            }
63            dt = readdir(d);
64        }
65        closedir(d);
66    }
67    return rmdir(strPath.c_str()) == 0 ? true : false;
68}
69
70static bool IsFileExist(const std::string &path)
71{
72    if (path.empty()) {
73        return false;
74    }
75    struct stat st {};
76    if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
77        return true;
78    }
79    return false;
80}
81
82static bool IsDirExist(const std::string &path)
83{
84    if (path.empty()) {
85        return false;
86    }
87    struct stat st {};
88    if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
89        return true;
90    }
91    return false;
92}
93
94class EngUnitTest : public testing::Test {
95public:
96    static void SetUpTestCase(void) {};
97    static void TearDownTestCase(void) {};
98    void SetUp() {};
99    void TearDown() {};
100};
101
102HWTEST_F(EngUnitTest, TestFilesOverlay, TestSize.Level1)
103{
104    bool isDel = false;
105    bool isExist = IsDirExist(ENG_ROOT_PATH.c_str());
106    if (isExist) {
107        isDel = RemoveDir(ENG_ROOT_PATH.c_str());
108        EXPECT_EQ(isDel, true);
109    }
110    isExist = IsDirExist(TARGET_PATH.c_str());
111    if (isExist) {
112        isDel = RemoveDir(TARGET_PATH.c_str());
113        EXPECT_EQ(isDel, true);
114    }
115    DebugFilesOverlay(ENG_ROOT_PATH.c_str(), TARGET_PATH.c_str());
116
117    CreateTestFile(SRC_FILE_PATH.c_str(), "test");
118    isExist = IsFileExist(SRC_FILE_PATH.c_str());
119    EXPECT_EQ(isExist, true);
120
121    DebugFilesOverlay(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str());
122    isExist = IsFileExistWithType(SRC_FILE_PATH.c_str(), TYPE_REG);
123    EXPECT_EQ(isExist, true);
124
125
126    if (IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK)) {
127        if (unlink(TARGET_PATH.c_str()) < 0) {
128            EXPECT_TRUE(false);
129        }
130    }
131    int ret = symlink(ENG_ROOT_PATH.c_str(), TARGET_PATH.c_str());
132    EXPECT_EQ(ret, 0);
133    isExist = IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK);
134    EXPECT_EQ(isExist, true);
135    DebugFilesOverlay(TARGET_PATH.c_str(), ENG_ROOT_PATH.c_str());
136    EXPECT_EQ(ret, 0);
137}
138
139HWTEST_F(EngUnitTest, TestBindMountFile, TestSize.Level1)
140{
141    BindMountFile("data/init_ut", "");
142    BindMountFile("data", "target");
143    BindMountFile("/data/init_ut//", "/");
144    BindMountFile("/data/init_ut", "/");
145    BindMountFile("/data", "/");
146    BindMountFile("/data/", "/");
147
148    bool isExist = false;
149    if (!IsFileExist(SRC_FILE_PATH.c_str())) {
150        CreateTestFile(SRC_FILE_PATH.c_str(), "test reg file mount");
151        isExist = IsFileExist(SRC_FILE_PATH.c_str());
152        EXPECT_EQ(isExist, true);
153        BindMountFile(SRC_FILE_PATH.c_str(), "/");
154    }
155    BindMountFile(SRC_FILE_PATH.c_str(), "/");
156
157    if (IsFileExist(SRC_FILE_PATH.c_str())) {
158        RemoveDir(STARTUP_INIT_UT_PATH"/eng/source");
159        isExist = IsFileExist(SRC_FILE_PATH.c_str());
160        EXPECT_EQ(isExist, false);
161    }
162    if (IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK)) {
163        if (unlink(TARGET_PATH.c_str()) < 0) {
164            EXPECT_TRUE(false);
165        }
166    }
167
168    bool isLinkFile = IsFileExist(TARGET_PATH.c_str());
169    EXPECT_EQ(isLinkFile, false);
170    BindMountFile(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str());
171
172    int ret = symlink(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str());
173    EXPECT_EQ(ret, 0);
174    isLinkFile = IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK);
175    EXPECT_EQ(isLinkFile, true);
176    BindMountFile(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str());
177    BindMountFile(TARGET_PATH.c_str(), SRC_FILE_PATH.c_str());
178}
179
180HWTEST_F(EngUnitTest, TestMountCmd, TestSize.Level1)
181{
182    char mountCmd[MOUNT_CMD_MAX_LEN] = {};
183    MountEngPartitions();
184    BuildMountCmd(mountCmd, MOUNT_CMD_MAX_LEN, "/eng/source", "/eng/target", "ext4");
185    BuildMountCmd(mountCmd, 0, "/eng/source", "/eng/target", "ext4");
186}
187
188HWTEST_F(EngUnitTest, TestFileType, TestSize.Level1)
189{
190    std::string targetFile = "/data/init_ut/eng/target_file";
191    std::string linkName = "/data/init_ut/eng/link_name_test";
192    bool isExist = false;
193
194    if (!IsFileExist(SRC_FILE_PATH.c_str())) {
195        CreateTestFile(SRC_FILE_PATH.c_str(), "test");
196        isExist = IsFileExist(SRC_FILE_PATH.c_str());
197        EXPECT_EQ(isExist, true);
198    }
199
200    EXPECT_EQ(IsFileExistWithType(SRC_FILE_PATH.c_str(), TYPE_REG), true);
201    EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_DIR), true);
202
203    EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_LINK), false);
204    EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_REG), false);
205    EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_ANY), true);
206    EXPECT_EQ(IsFileExistWithType(SRC_FILE_PATH.c_str(), TYPE_DIR), false);
207
208    if (IsFileExist(targetFile)) {
209        if (unlink(targetFile.c_str()) < 0) {
210            std::cout << "Failed to unlink file " << targetFile << " err = " << errno << std::endl;
211            EXPECT_TRUE(false);
212        }
213    }
214    int fd = open(targetFile.c_str(), O_CREAT | O_CLOEXEC | O_WRONLY, 0644);
215    if (fd < 0) {
216        std::cout << "Failed to create file " << targetFile << " err = " << errno << std::endl;
217        EXPECT_TRUE(false);
218    } else {
219        std::string buffer = "hello";
220        write(fd, buffer.c_str(), buffer.size());
221        close(fd); // avoid leak
222    }
223
224    if (IsFileExist(linkName)) {
225        if (unlink(linkName.c_str()) < 0) {
226            std::cout << "Failed to unlink file " << linkName << " err = " << errno << std::endl;
227            EXPECT_TRUE(false);
228        }
229    }
230
231    int ret = symlink(targetFile.c_str(), linkName.c_str());
232    EXPECT_EQ(ret, 0);
233    bool isFileExist = IsFileExistWithType(linkName.c_str(), TYPE_LINK);
234    EXPECT_EQ(isFileExist, true);
235
236    isFileExist = IsFileExistWithType("/eng/target", TYPE_LINK);
237    EXPECT_EQ(isFileExist, false);
238
239    isFileExist = IsFileExistWithType("/eng/target", TYPE_REG);
240    EXPECT_EQ(isFileExist, false);
241}
242
243HWTEST_F(EngUnitTest, TestHook, TestSize.Level1)
244{
245    HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
246    PrepareCmdLineData();
247    HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
248    const char *cmdLine = "ohos.boot.root_package=off ";
249    CreateTestFile(BOOT_CMD_LINE, cmdLine);
250    HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
251}
252} // namespace init_ut
253