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 
29 using namespace std;
30 using namespace testing::ext;
31 
32 namespace init_ut {
33 static const std::string SRC_FILE_PATH = STARTUP_INIT_UT_PATH"/eng/source/test.txt";
34 static const std::string TARGET_PATH = STARTUP_INIT_UT_PATH"/eng/link_name";
35 static const std::string ENG_ROOT_PATH = STARTUP_INIT_UT_PATH"/eng/";
36 
RemoveDir(const std::string & path)37 static 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 
IsFileExist(const std::string & path)70 static 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 
IsDirExist(const std::string & path)82 static 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 
94 class EngUnitTest : public testing::Test {
95 public:
SetUpTestCase(void)96     static void SetUpTestCase(void) {};
TearDownTestCase(void)97     static void TearDownTestCase(void) {};
SetUp()98     void SetUp() {};
TearDown()99     void TearDown() {};
100 };
101 
102 HWTEST_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 
139 HWTEST_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 
180 HWTEST_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 
188 HWTEST_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 
243 HWTEST_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