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 "directory_ex.h"
17 #include <gtest/gtest.h>
18 #include <fcntl.h>
19 #include <algorithm>
20 #include <iostream>
21 #include <fstream>
22 #include <unistd.h>
23 #include <vector>
24
25 using namespace testing::ext;
26 using namespace std;
27
28 namespace OHOS {
29 namespace {
30 class UtilsDirectoryTest : public testing::Test {
31 public :
32 static void SetUpTestCase(void);
33 static void TearDownTestCase(void);
34 void SetUp();
35 void TearDown();
36 };
37
SetUpTestCase(void)38 void UtilsDirectoryTest::SetUpTestCase(void)
39 {
40 }
41
TearDownTestCase(void)42 void UtilsDirectoryTest::TearDownTestCase(void)
43 {
44 }
45
SetUp(void)46 void UtilsDirectoryTest::SetUp(void)
47 {
48 }
49
TearDown(void)50 void UtilsDirectoryTest::TearDown(void)
51 {
52 }
53
54 /*
55 * @tc.name: testGetCurrentProcFullFileName001
56 * @tc.desc: get the directory of directorytest
57 */
58 HWTEST_F(UtilsDirectoryTest, testGetCurrentProcFullFileName001, TestSize.Level0)
59 {
60 string strBaseName = "/data/test/UtilsDirectoryTest";
61 string strFilename = GetCurrentProcFullFileName();
62 EXPECT_EQ(strFilename, strBaseName);
63 }
64
65 /*
66 * @tc.name: testGetCurrentProcPath001
67 * @tc.desc: get the path of directorytest
68 */
69 HWTEST_F(UtilsDirectoryTest, testGetCurrentProcPath001, TestSize.Level0)
70 {
71 string strPathName = "/data/test/";
72 string strCurPathName = GetCurrentProcPath();
73 EXPECT_EQ(strCurPathName, strPathName);
74 }
75
76 /*
77 * @tc.name: testExtractFilePath001
78 * @tc.desc: get the filename of the path
79 */
80 HWTEST_F(UtilsDirectoryTest, testExtractFilePath001, TestSize.Level0)
81 {
82 string strFilePath = "/data/test/";
83 string strPath = ExtractFilePath(GetCurrentProcFullFileName());
84 EXPECT_EQ(strFilePath, strPath);
85 }
86
87 /*
88 * @tc.name: testExtractFileName001
89 * @tc.desc: get the filename of the path
90 */
91 HWTEST_F(UtilsDirectoryTest, testExtractFileName001, TestSize.Level0)
92 {
93 string strBaseName = "UtilsDirectoryTest";
94 string strName = ExtractFileName(GetCurrentProcFullFileName());
95 EXPECT_EQ(strBaseName, strName);
96 }
97
98 /*
99 * @tc.name: testExtractFileExt001
100 * @tc.desc: get the filename of the path
101 */
102 HWTEST_F(UtilsDirectoryTest, testExtractFileExt001, TestSize.Level0)
103 {
104 string strBaseName = "test/test.txt";
105 string strTypeName = ExtractFileExt(strBaseName);
106 EXPECT_EQ(strTypeName, "txt");
107 }
108
109 /*
110 * @tc.name: testExtractFileExt002
111 * @tc.desc: get the filename of the path and test whether the filename contains "."
112 */
113 HWTEST_F(UtilsDirectoryTest, testExtractFileExt002, TestSize.Level0)
114 {
115 string strBaseName = "test/test_txt";
116 string strTypeName = ExtractFileExt(strBaseName);
117 EXPECT_EQ(strTypeName, "");
118 }
119
120 /*
121 * @tc.name: testExcludeTrailingPathDelimiter001
122 * @tc.desc: directory unit test
123 */
124 HWTEST_F(UtilsDirectoryTest, testExcludeTrailingPathDelimiter001, TestSize.Level0)
125 {
126 string strResult = "data/test/UtilsDirectoryTest";
127 string strName = ExcludeTrailingPathDelimiter("data/test/UtilsDirectoryTest/");
128 EXPECT_EQ(strResult, strName);
129 }
130
131 /*
132 * @tc.name: testIncludeTrailingPathDelimiter001
133 * @tc.desc: directory unit test
134 */
135 HWTEST_F(UtilsDirectoryTest, testIncludeTrailingPathDelimiter001, TestSize.Level0)
136 {
137 string strResult = "data/test/UtilsDirectoryTest/";
138 string strName = IncludeTrailingPathDelimiter("data/test/UtilsDirectoryTest");
139 EXPECT_EQ(strResult, strName);
140 }
141
142 /*
143 * @tc.name: testIncludeTrailingPathDelimiter002
144 * @tc.desc: directory unit test
145 */
146 HWTEST_F(UtilsDirectoryTest, testIncludeTrailingPathDelimiter002, TestSize.Level0)
147 {
148 string strResult = "/";
149 string strName = IncludeTrailingPathDelimiter("");
150 EXPECT_EQ(strResult, strName);
151 }
152
153 /*
154 * @tc.name: testGetDirFiles001
155 * @tc.desc: test GetDirFiles works on multi-level directory
156 */
157 HWTEST_F(UtilsDirectoryTest, testGetDirFiles001, TestSize.Level0)
158 {
159 string parentPath = "/data/test_dir";
160
161 ForceCreateDirectory(parentPath);
162
163 string dirs[6] = {
164 "/data/test_dir/level1_1",
165 "/data/test_dir/level1_2",
166 "/data/test_dir/level1_2/level2_1",
167 "/data/test_dir/level1_2/level2_2",
168 "/data/test_dir/level1_2/level2_2/level3_1",
169 "/data/test_dir/level1_3",
170 };
171
172 string resultfiles[9] = {
173 "/data/test_dir/level1_1/test_file",
174 "/data/test_dir/level1_2/level2_2/level3_1/test_file_1",
175 "/data/test_dir/level1_2/level2_2/level3_1/test_file_2",
176 "/data/test_dir/level1_2/level2_2/test_file_1",
177 "/data/test_dir/level1_2/level2_2/test_file_2",
178 "/data/test_dir/level1_2/level2_2/test_file_3",
179 "/data/test_dir/level1_2/level2_2/test_file_4",
180 "/data/test_dir/level1_2/test_file",
181 "/data/test_dir/level1_3/test_file",
182 };
183
184 for (auto &path : dirs) {
185 ForceCreateDirectory(path);
186 }
187
188 for (auto &filepath : resultfiles) {
189 ofstream(filepath, fstream::out);
190 }
191
192 vector<string> files;
193
194 GetDirFiles(parentPath, files);
195
196 for (auto &filepath : resultfiles) {
197 auto pos = find(files.begin(), files.end(), filepath);
198 EXPECT_NE(pos, files.end());
199 }
200
201 ForceRemoveDirectory(parentPath);
202 }
203
204 /*
205 * @tc.name: testGetDirFiles002
206 * @tc.desc: test GetDirFiles works on deeply nested directory and handles very long path
207 */
208 HWTEST_F(UtilsDirectoryTest, testGetDirFiles002, TestSize.Level0)
209 {
210 string parentPath = "/data/test_dir/";
211 string veryLongPath = "/data/test_dir/";
212
213 int length = 10000;
214
215 for (int i = 0; i < length; i++) {
216 veryLongPath += "0";
217 veryLongPath += "/";
218 }
219
220 EXPECT_EQ(mkdir("/data/test_dir", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH), 0);
221 chdir(parentPath.c_str());
222
223 for (int i = 0; i < length; i++) {
224 EXPECT_EQ(mkdir("./0", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH), 0);
225 EXPECT_EQ(chdir("./0"), 0);
226 }
227
228 ofstream file("./test_file");
229 file.close();
230 EXPECT_EQ(chdir("/data/test"), 0);
231
232 auto files = vector<string>();
233
234 GetDirFiles(parentPath, files);
235
236 EXPECT_EQ(files.size(), 1);
237 EXPECT_EQ((veryLongPath + "test_file").length(), files[0].length());
238 EXPECT_EQ(veryLongPath + "test_file", files[0]);
239
240 ForceRemoveDirectory(parentPath);
241 }
242
243 /*
244 * @tc.name: testGetDirFiles003
245 * @tc.desc: test GetDirFiles works on symlink
246 */
247 HWTEST_F(UtilsDirectoryTest, testGetDirFiles003, TestSize.Level0)
248 {
249 // create a test dir
250 string originalDataPath = "/data/original";
251 EXPECT_EQ(ForceCreateDirectory(originalDataPath), true);
252
253 string originalFilePath = "/data/original/original_file";
254 string originalDirectoryPath = "/data/original/original_directory";
255
256 ofstream(originalFilePath, fstream::out);
257
258 ForceCreateDirectory(originalDirectoryPath);
259
260 string testDataDir = "/data/test_dir";
261
262 EXPECT_EQ(ForceCreateDirectory(testDataDir), true);
263
264 // test symlink to directory outside the target directory
265 string linktodir = IncludeTrailingPathDelimiter(testDataDir) + "symlink_dir";
266
267 EXPECT_EQ(symlink(originalDirectoryPath.c_str(), linktodir.c_str()), 0);
268
269 vector<string> dirResult;
270 GetDirFiles(testDataDir, dirResult);
271
272 EXPECT_EQ(dirResult.size(), 1);
273 EXPECT_EQ(dirResult[0], linktodir);
274
275 EXPECT_EQ(ForceRemoveDirectory(linktodir), true);
276
277 // test symlink to file outside the target directory
278 string linktofile = IncludeTrailingPathDelimiter(testDataDir) + "symlink_file";
279 EXPECT_EQ(symlink(originalFilePath.c_str(), linktofile.c_str()), 0);
280
281 vector<string> fileResult;
282 GetDirFiles(testDataDir, fileResult);
283 EXPECT_EQ(fileResult.size(), 1);
284 EXPECT_EQ(fileResult[0], linktofile);
285
286 EXPECT_EQ(RemoveFile(linktofile), true);
287
288 // test symlink of files in the same directory
289 string sourceFile = IncludeTrailingPathDelimiter(testDataDir) + "source";
290 string symlinkFile = IncludeTrailingPathDelimiter(testDataDir) + "symlink_file";
291
292 ofstream(sourceFile, fstream::out);
293 EXPECT_EQ(symlink(sourceFile.c_str(), symlinkFile.c_str()), 0);
294
295 vector<string> internalFiles;
296 GetDirFiles(testDataDir, internalFiles);
297
298 EXPECT_NE(find(internalFiles.begin(), internalFiles.end(), sourceFile), internalFiles.end());
299 EXPECT_NE(find(internalFiles.begin(), internalFiles.end(), symlinkFile), internalFiles.end());
300
301 EXPECT_EQ(RemoveFile(sourceFile), true);
302 EXPECT_EQ(RemoveFile(symlinkFile), true);
303
304 ForceRemoveDirectory(originalDataPath);
305 ForceRemoveDirectory(testDataDir);
306 }
307
308 /*
309 * @tc.name: testForceCreateDirectory001
310 * @tc.desc: directory unit test
311 */
312 HWTEST_F(UtilsDirectoryTest, testForceCreateDirectory001, TestSize.Level0)
313 {
314 string dirpath = "/data/test_dir/test2/test3";
315 bool ret = ForceCreateDirectory(dirpath);
316 EXPECT_EQ(ret, true);
317 ret = IsEmptyFolder(dirpath);
318 EXPECT_EQ(ret, true);
319 }
320
321 /*
322 * @tc.name: testForceRemoveDirectory001
323 * @tc.desc: directory unit test
324 */
325 HWTEST_F(UtilsDirectoryTest, testForceRemoveDirectory001, TestSize.Level0)
326 {
327 string dirpath = "/data/test_dir";
328 bool ret = ForceRemoveDirectory(dirpath);
329 EXPECT_EQ(ret, true);
330 }
331
332 /*
333 * @tc.name: testForceRemoveDirectory002
334 * @tc.desc: test whether the folder exists
335 */
336 HWTEST_F(UtilsDirectoryTest, testForceRemoveDirectory002, TestSize.Level0)
337 {
338 string dirpath = "/data/test/utils_directory_tmp/";
339 bool ret = ForceRemoveDirectory(dirpath);
340 EXPECT_EQ(ret, false);
341 }
342
343
344 /*
345 * @tc.name: testForceRemoveDirectory003
346 * @tc.desc: test whether it works when the full path is over than 255.
347 */
348 HWTEST_F(UtilsDirectoryTest, testForceRemoveDirectory003, TestSize.Level0)
349 {
350 string dirpath = "/data/test/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/"
351 "tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/"
352 "tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/"
353 "tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp/tmp";
354 bool ret = ForceCreateDirectory(dirpath);
355 EXPECT_EQ(ret, true);
356 string rootpath = "/data/test/tmp";
357 ret = ForceRemoveDirectory(rootpath);
358 EXPECT_EQ(ret, true);
359 }
360
361 /*
362 * @tc.name: testRemoveFile001
363 * @tc.desc: directory unit test
364 */
365 HWTEST_F(UtilsDirectoryTest, testRemoveFile001, TestSize.Level0)
366 {
367 string dirpath = "/data/test_dir";
368 bool ret = ForceCreateDirectory(dirpath);
369 EXPECT_EQ(ret, true);
370 string filename = dirpath + "/test.txt";
371 FILE *fp = fopen(filename.c_str(), "w");
372 if (NULL != fp) {
373 fclose(fp);
374 ret = RemoveFile(filename);
375 EXPECT_EQ(ret, true);
376 }
377 ret = ForceRemoveDirectory(dirpath);
378 EXPECT_EQ(ret, true);
379 }
380
381 /*
382 * @tc.name: testRemoveFile002
383 * @tc.desc: Remove soft link file.
384 */
385 HWTEST_F(UtilsDirectoryTest, testRemoveFile002, TestSize.Level0)
386 {
387 string dirpath = "/data/test_dir";
388 bool ret = ForceCreateDirectory(dirpath);
389 EXPECT_EQ(ret, true);
390
391 string targetname = "/data/test_target.txt";
392 FILE *fp = fopen(targetname.c_str(), "w");
393 if (NULL != fp) {
394 fclose(fp);
395 }
396
397 // symlink to a directory
398 string linkpath = "/data/test_symlink_dir";
399 int res = symlink(dirpath.c_str(), linkpath.c_str());
400 EXPECT_EQ(res, 0);
401
402 ret = ForceRemoveDirectory(linkpath);
403 EXPECT_EQ(ret, true);
404
405 // Target dir is not removed.
406 ret = faccessat(AT_FDCWD, dirpath.c_str(), F_OK, AT_SYMLINK_NOFOLLOW);
407 EXPECT_EQ(ret, 0);
408
409 // symlink to a file
410 string filename = dirpath + "/test.txt";
411 res = symlink(targetname.c_str(), filename.c_str());
412 EXPECT_EQ(res, 0);
413
414 ret = ForceRemoveDirectory(dirpath);
415 EXPECT_EQ(ret, true);
416
417 // Target file is not removed.
418 ret = faccessat(AT_FDCWD, targetname.c_str(), F_OK, AT_SYMLINK_NOFOLLOW);
419 EXPECT_EQ(ret, 0);
420
421 ret = RemoveFile(targetname);
422 EXPECT_EQ(ret, true);
423 }
424
425 /*
426 * @tc.name: testRemoveFile003
427 * @tc.desc: Remove dangling soft link file.
428 */
429 HWTEST_F(UtilsDirectoryTest, testRemoveFile003, TestSize.Level0)
430 {
431 string dirpath = "/data/test_dir";
432 bool ret = ForceCreateDirectory(dirpath);
433 EXPECT_EQ(ret, true);
434
435 // symlink to a file
436 string targetname = "/data/nonexisted.txt";
437 string filename = dirpath + "/test.txt";
438 int res = symlink(targetname.c_str(), filename.c_str());
439 EXPECT_EQ(res, 0);
440
441 ret = ForceRemoveDirectory(dirpath);
442 EXPECT_EQ(ret, true);
443
444 ret = RemoveFile(targetname);
445 EXPECT_EQ(ret, true);
446 }
447
448 /*
449 * @tc.name: testGetFolderSize001
450 * @tc.desc: directory unit test
451 */
452 HWTEST_F(UtilsDirectoryTest, testGetFolderSize001, TestSize.Level0)
453 {
454 string dirpath = "/data/test_folder/";
455 bool ret = ForceCreateDirectory(dirpath);
456 EXPECT_EQ(ret, true);
457 ofstream out(dirpath + "test.txt");
458 if (out.is_open()) {
459 out << "This is a line.\n";
460 out << "This is another line.\n";
461 out.close();
462 }
463 uint64_t resultsize = GetFolderSize(dirpath);
464 uint64_t resultcomp = 38;
465 EXPECT_EQ(resultsize, resultcomp);
466
467 mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
468 ret = ChangeModeFile(dirpath + "test.txt", mode);
469 EXPECT_EQ(ret, true);
470
471 mode = S_IRUSR | S_IRGRP | S_IROTH;
472 ret = ChangeModeDirectory(dirpath, mode);
473 EXPECT_EQ(ret, true);
474
475 ret = ForceRemoveDirectory(dirpath);
476 EXPECT_EQ(ret, true);
477 }
478
479 /*
480 * @tc.name: testChangeModeFile001
481 * @tc.desc: test whether the folder exists
482 */
483 HWTEST_F(UtilsDirectoryTest, testChangeModeFile001, TestSize.Level0)
484 {
485 string dirpath = "/data/test/utils_directory_tmp/";
486 mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
487 bool ret = ChangeModeFile(dirpath + "test.txt", mode);
488 EXPECT_EQ(ret, false);
489 }
490
491 /*
492 * @tc.name: testChangeModeDirectory001
493 * @tc.desc: test whether the folder is empty and get the size of the folder
494 */
495 HWTEST_F(UtilsDirectoryTest, testChangeModeDirectory001, TestSize.Level0)
496 {
497 string dirpath = "";
498 mode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
499 bool ret = ChangeModeDirectory(dirpath, mode);
500 EXPECT_EQ(ret, false);
501
502 uint64_t resultsize = GetFolderSize(dirpath);
503 uint64_t resultcomp = 0;
504 EXPECT_EQ(resultsize, resultcomp);
505 }
506
507 /*
508 * @tc.name: testPathToRealPath001
509 * @tc.desc: directory unit test
510 */
511 HWTEST_F(UtilsDirectoryTest, testPathToRealPath001, TestSize.Level0)
512 {
513 string path = "/data/test";
514 string realpath;
515 bool ret = PathToRealPath(path, realpath);
516 EXPECT_EQ(ret, true);
517 EXPECT_EQ(path, realpath);
518 }
519
520 /*
521 * @tc.name: testPathToRealPath002
522 * @tc.desc: directory unit test
523 */
524 HWTEST_F(UtilsDirectoryTest, testPathToRealPath002, TestSize.Level0)
525 {
526 string path = "/data/../data/test";
527 string realpath;
528 bool ret = PathToRealPath(path, realpath);
529 EXPECT_EQ(ret, true);
530 EXPECT_EQ("/data/test", realpath);
531 }
532
533 /*
534 * @tc.name: testPathToRealPath003
535 * @tc.desc: directory unit test
536 */
537 HWTEST_F(UtilsDirectoryTest, testPathToRealPath003, TestSize.Level0)
538 {
539 string path = "./";
540 string realpath;
541 bool ret = PathToRealPath(path, realpath);
542 EXPECT_EQ(ret, true);
543 EXPECT_EQ("/data/test", realpath);
544 }
545
546 /*
547 * @tc.name: testPathToRealPath004
548 * @tc.desc: directory unit test
549 */
550 HWTEST_F(UtilsDirectoryTest, testPathToRealPath004, TestSize.Level0)
551 {
552 string path = "";
553 string realpath;
554 bool ret = PathToRealPath(path, realpath);
555 EXPECT_EQ(ret, false);
556 }
557
558 /*
559 * @tc.name: testPathToRealPath005
560 * @tc.desc: directory unit test
561 */
562 HWTEST_F(UtilsDirectoryTest, testPathToRealPath005, TestSize.Level0)
563 {
564 string path = "/data/test/data/test/data/test/data/test/data/test/data/ \
565 test/data/test/data/test/data/test/data/test/data/test/data/test/data/ \
566 test/data/test/data/test/data/test/data/test/data/test/data/test/data/ \
567 test/data/test/data/test/data/test/data/test/data/test/data/test/data/ \
568 test/data/test/data/test/data/test";
569 string realpath;
570 bool ret = PathToRealPath(path, realpath);
571 EXPECT_EQ(ret, false);
572 }
573
574 /*
575 * @tc.name: testPathToRealPath006
576 * @tc.desc: test whether the folder exists
577 */
578 HWTEST_F(UtilsDirectoryTest, testPathToRealPath006, TestSize.Level0)
579 {
580 string path(PATH_MAX, 'x');
581 string realpath;
582 bool ret = PathToRealPath(path, realpath);
583 EXPECT_EQ(ret, false);
584 }
585 } // namespace
586 } // namespace OHOS
587