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
TestBuildMountCmd(char * buffer,size_t len,const char * mp,const char * dev,const char * fstype)94 static int TestBuildMountCmd(char *buffer, size_t len, const char *mp, const char *dev, const char *fstype)
95 {
96 BuildMountCmd(buffer, len, mp, dev, fstype);
97 return 0;
98 }
99
100 class EngUnitTest : public testing::Test {
101 public:
SetUpTestCase(void)102 static void SetUpTestCase(void) {};
TearDownTestCase(void)103 static void TearDownTestCase(void) {};
SetUp()104 void SetUp() {};
TearDown()105 void TearDown() {};
106 };
107
108 HWTEST_F(EngUnitTest, TestFilesOverlay, TestSize.Level1)
109 {
110 bool isDel = false;
111 bool isExist = IsDirExist(ENG_ROOT_PATH.c_str());
112 if (isExist) {
113 isDel = RemoveDir(ENG_ROOT_PATH.c_str());
114 EXPECT_EQ(isDel, true);
115 }
116 isExist = IsDirExist(TARGET_PATH.c_str());
117 if (isExist) {
118 isDel = RemoveDir(TARGET_PATH.c_str());
119 EXPECT_EQ(isDel, true);
120 }
121 DebugFilesOverlay(ENG_ROOT_PATH.c_str(), TARGET_PATH.c_str());
122
123 CreateTestFile(SRC_FILE_PATH.c_str(), "test");
124 isExist = IsFileExist(SRC_FILE_PATH.c_str());
125 EXPECT_EQ(isExist, true);
126
127 DebugFilesOverlay(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str());
128 isExist = IsFileExistWithType(SRC_FILE_PATH.c_str(), TYPE_REG);
129 EXPECT_EQ(isExist, true);
130
131
132 if (IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK)) {
133 if (unlink(TARGET_PATH.c_str()) < 0) {
134 EXPECT_TRUE(false);
135 }
136 }
137 int ret = symlink(ENG_ROOT_PATH.c_str(), TARGET_PATH.c_str());
138 EXPECT_EQ(ret, 0);
139 isExist = IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK);
140 EXPECT_EQ(isExist, true);
141 DebugFilesOverlay(TARGET_PATH.c_str(), ENG_ROOT_PATH.c_str());
142 EXPECT_EQ(ret, 0);
143 }
144
145 HWTEST_F(EngUnitTest, TestBindMountFile, TestSize.Level1)
146 {
147 BindMountFile("data/init_ut", "");
148 BindMountFile("data", "target");
149 BindMountFile("/data/init_ut//", "/");
150 BindMountFile("/data/init_ut", "/");
151 BindMountFile("/data", "/");
152 BindMountFile("/data/", "/");
153
154 bool isExist = false;
155 if (!IsFileExist(SRC_FILE_PATH.c_str())) {
156 CreateTestFile(SRC_FILE_PATH.c_str(), "test reg file mount");
157 isExist = IsFileExist(SRC_FILE_PATH.c_str());
158 EXPECT_EQ(isExist, true);
159 BindMountFile(SRC_FILE_PATH.c_str(), "/");
160 }
161 BindMountFile(SRC_FILE_PATH.c_str(), "/");
162
163 if (IsFileExist(SRC_FILE_PATH.c_str())) {
164 RemoveDir(STARTUP_INIT_UT_PATH"/eng/source");
165 isExist = IsFileExist(SRC_FILE_PATH.c_str());
166 EXPECT_EQ(isExist, false);
167 }
168 if (IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK)) {
169 if (unlink(TARGET_PATH.c_str()) < 0) {
170 EXPECT_TRUE(false);
171 }
172 }
173
174 bool isLinkFile = IsFileExist(TARGET_PATH.c_str());
175 EXPECT_EQ(isLinkFile, false);
176 BindMountFile(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str());
177
178 int ret = symlink(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str());
179 EXPECT_EQ(ret, 0);
180 isLinkFile = IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK);
181 EXPECT_EQ(isLinkFile, true);
182 BindMountFile(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str());
183 BindMountFile(TARGET_PATH.c_str(), SRC_FILE_PATH.c_str());
184 }
185
186 HWTEST_F(EngUnitTest, TestMountCmd, TestSize.Level1)
187 {
188 char mountCmd[MOUNT_CMD_MAX_LEN] = {};
189 MountEngPartitions();
190 int ret = TestBuildMountCmd(mountCmd, MOUNT_CMD_MAX_LEN, "/eng/source", "/eng/target", "ext4");
191 EXPECT_EQ(ret, 0);
192 ret = TestBuildMountCmd(mountCmd, 0, "/eng/source", "/eng/target", "ext4");
193 EXPECT_EQ(ret, 0);
194 }
195
196 HWTEST_F(EngUnitTest, TestFileType, TestSize.Level1)
197 {
198 std::string targetFile = "/data/init_ut/eng/target_file";
199 std::string linkName = "/data/init_ut/eng/link_name_test";
200 bool isExist = false;
201
202 if (!IsFileExist(SRC_FILE_PATH.c_str())) {
203 CreateTestFile(SRC_FILE_PATH.c_str(), "test");
204 isExist = IsFileExist(SRC_FILE_PATH.c_str());
205 EXPECT_EQ(isExist, true);
206 }
207
208 EXPECT_EQ(IsFileExistWithType(SRC_FILE_PATH.c_str(), TYPE_REG), true);
209 EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_DIR), true);
210
211 EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_LINK), false);
212 EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_REG), false);
213 EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_ANY), true);
214 EXPECT_EQ(IsFileExistWithType(SRC_FILE_PATH.c_str(), TYPE_DIR), false);
215
216 if (IsFileExist(targetFile)) {
217 if (unlink(targetFile.c_str()) < 0) {
218 std::cout << "Failed to unlink file " << targetFile << " err = " << errno << std::endl;
219 EXPECT_TRUE(false);
220 }
221 }
222 int fd = open(targetFile.c_str(), O_CREAT | O_CLOEXEC | O_WRONLY, 0644);
223 if (fd < 0) {
224 std::cout << "Failed to create file " << targetFile << " err = " << errno << std::endl;
225 EXPECT_TRUE(false);
226 } else {
227 std::string buffer = "hello";
228 write(fd, buffer.c_str(), buffer.size());
229 close(fd); // avoid leak
230 }
231
232 if (IsFileExist(linkName)) {
233 if (unlink(linkName.c_str()) < 0) {
234 std::cout << "Failed to unlink file " << linkName << " err = " << errno << std::endl;
235 EXPECT_TRUE(false);
236 }
237 }
238
239 int ret = symlink(targetFile.c_str(), linkName.c_str());
240 EXPECT_EQ(ret, 0);
241 bool isFileExist = IsFileExistWithType(linkName.c_str(), TYPE_LINK);
242 EXPECT_EQ(isFileExist, true);
243
244 isFileExist = IsFileExistWithType("/eng/target", TYPE_LINK);
245 EXPECT_EQ(isFileExist, false);
246
247 isFileExist = IsFileExistWithType("/eng/target", TYPE_REG);
248 EXPECT_EQ(isFileExist, false);
249 }
250
251 HWTEST_F(EngUnitTest, TestHook, TestSize.Level1)
252 {
253 int ret = HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
254 EXPECT_NE(ret, -1);
255 PrepareCmdLineData();
256 ret = HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
257 EXPECT_NE(ret, -1);
258 const char *cmdLine = "ohos.boot.root_package=off ";
259 CreateTestFile(BOOT_CMD_LINE, cmdLine);
260 ret = HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
261 EXPECT_NE(ret, -1);
262 }
263 } // namespace init_ut
264