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