1/*
2 * Copyright (c) 2020-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#include "FileSystemTest.h"
16#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <sys/statvfs.h>
23#include <sys/statfs.h>
24#include <sys/mount.h>
25#include <wchar.h>
26#include <fcntl.h>
27#include <unistd.h>
28#include <dirent.h>
29#include <ftw.h>
30#include <libgen.h>
31#include <glob.h>
32
33#include <gtest/gtest.h>
34
35#include "utils.h"
36#include "log.h"
37#include "KernelConstants.h"
38#include "libfs.h"
39
40using namespace testing::ext;
41
42/**
43 * @tc.number   SUB_KERNEL_FS_OTHER_0100
44 * @tc.name     basic function test : get dirname
45 * @tc.desc     [C- SOFTWARE -0200]
46 */
47HWTEST_F(FileSystemTest, testPath, Function | MediumTest | Level1)
48{
49    int fd = 0;
50    fd = creat(FILE0, 0777);
51    EXPECT_NE(fd, -1) << "> creat faild errno = " << errno;
52    EXPECT_NE(close(fd), -1) << "> close errno = " << errno;
53
54    // get dir
55    char *workDir = dirname((char*)FILE0);
56    ASSERT_NE(workDir, nullptr) << "> dirname errno = " << errno;
57    EXPECT_STREQ(".", workDir);
58    LOG("> workDir = %s", workDir);
59}
60
61/**
62 * @tc.number   SUB_KERNEL_FS_OTHER_0110
63 * @tc.name     basic function test : get current dir name
64 * @tc.desc     [C- SOFTWARE -0200]
65 */
66HWTEST_F(FileSystemTest, testGetCurrentDirName, Function | MediumTest | Level1)
67{
68    int fd = 0;
69    fd = creat(FILE0, 0777);
70    EXPECT_NE(fd, -1) << "> creat faild errno = " << errno;
71    EXPECT_NE(close(fd), -1) << "> close errno = " << errno;
72
73    // get current dir name
74    const char *currentDirStandard = TOP_DIR;
75    char *currentDir = get_current_dir_name();
76    ASSERT_NE(currentDir, nullptr);
77    EXPECT_STREQ(currentDir, currentDirStandard);
78    LOG("> currentDir = %s", currentDir);
79}
80
81/**
82 * @tc.number   SUB_KERNEL_FS_OTHER_0120
83 * @tc.name     basic function test : get basename
84 * @tc.desc     [C- SOFTWARE -0200]
85 */
86HWTEST_F(FileSystemTest, testBasename, Function | MediumTest | Level1)
87{
88    int fd = 0;
89    fd = creat(FILE0, 0777);
90    EXPECT_NE(fd, -1) << "> creat faild errno = " << errno;
91    EXPECT_NE(close(fd), -1) << "> close errno = " << errno;
92
93    // get file name
94    char *desName = basename((char*)FILE0);
95    ASSERT_NE(desName, nullptr) << "> basename errno = " << errno;
96    EXPECT_STREQ(desName, FILE0);
97    LOG("> desName = %s", desName);
98}
99
100int FtwCheckDirTree(const char *path, const struct stat *sb, int flag)
101{
102    const char file0[] = DIR0 "/" DIR0_FILE0;
103    const char file1[] = DIR0 "/" DIR0_DIR1 "/" DIR0_DIR1_FILE0;
104    const char dir0[] = DIR0;
105    const char dir1[] = DIR0 "/" DIR0_DIR0;
106    const char dir2[] = DIR0 "/" DIR0_DIR1;
107    const char dir3[] = DIR0 "/" DIR0_DIR1"/" DIR0_DIR1_DIR0;
108    if (flag == FTW_F) {
109        if (strncmp(path, file0, sizeof(file0)) == 0) {
110            LOG("> File %s", file0);
111        } else if (strncmp(path, file1, sizeof(file1)) == 0) {
112            LOG("> File %s", file1);
113        } else {
114            LOG("> File error %s", path);
115            return -1;
116        }
117    } else if (flag == FTW_D) {
118        if (strncmp(path, dir0, sizeof(dir0)) == 0) {
119            LOG("> Dir  %s", DIR0);
120        } else if (strncmp(path, dir1, sizeof(dir1)) == 0) {
121            LOG("> Dir  %s", dir1);
122        } else if (strncmp(path, dir2, sizeof(dir2)) == 0) {
123            LOG("> Dir  %s", dir2);
124        } else if (strncmp(path, dir3, sizeof(dir3)) == 0) {
125            LOG("> Dir  %s", dir3);
126        } else {
127            LOG("> File error  %s", path);
128            return -1;
129        }
130    }
131    return 0;
132}
133
134/**
135 * @tc.number   SUB_KERNEL_FS_OTHER_0200
136 * @tc.name     basic function test : use ftw check file tree
137 * @tc.desc     [C- SOFTWARE -0200]
138 */
139HWTEST_F(FileSystemTest, testFtw, Function | MediumTest | Level3)
140{
141    CreateTestFolder();
142    EXPECT_EQ(ftw(DIR0, FtwCheckDirTree, 100), 0) << "> ftw error";
143}
144
145int NftwCheckDirTree(const char *path, const struct stat *sb, int flag, struct FTW *s)
146{
147    const char file0[] = DIR0 "/" DIR0_FILE0;
148    const char file1[] = DIR0 "/" DIR0_DIR1 "/" DIR0_DIR1_FILE0;
149    const char dir0[] = DIR0;
150    const char dir1[] = DIR0 "/" DIR0_DIR0;
151    const char dir2[] = DIR0 "/" DIR0_DIR1;
152    const char dir3[] = DIR0 "/" DIR0_DIR1"/" DIR0_DIR1_DIR0;
153    if (flag == FTW_F) {
154        if (strncmp(path, file0, sizeof(file0)) == 0) {
155            LOG("> File %s", file0);
156        } else if (strncmp(path, file1, sizeof(file1)) == 0) {
157            LOG("> File %s", file1);
158        } else {
159            LOG("> File %s", path);
160            return -1;
161        }
162    } else if (flag == FTW_D) {
163        if (strncmp(path, dir0, sizeof(dir0)) == 0) {
164            LOG("> Dir  %s", DIR0);
165        } else if (strncmp(path, dir1, sizeof(dir1)) == 0) {
166            LOG("> Dir  %s", dir1);
167        } else if (strncmp(path, dir2, sizeof(dir2)) == 0) {
168            LOG("> Dir  %s", dir2);
169        } else if (strncmp(path, dir3, sizeof(dir3)) == 0) {
170            LOG("> Dir  %s", dir3);
171        } else {
172            LOG("> File %s", path);
173            return -1;
174        }
175    }
176    return 0;
177}
178
179/**
180 * @tc.number   SUB_KERNEL_FS_OTHER_0210
181 * @tc.name     basic function test : use nftw check file tree
182 * @tc.desc     [C- SOFTWARE -0200]
183 */
184HWTEST_F(FileSystemTest, testNftw, Function | MediumTest | Level3)
185{
186    CreateTestFolder();
187    EXPECT_EQ(nftw(DIR0, NftwCheckDirTree, 100, 0), 0) << "> ftw error";
188}
189
190/**
191 * @tc.number   SUB_KERNEL_FS_OTHER_0300
192 * @tc.name     basic function test : use statvfs and statfs check file system information.
193 * @tc.desc     [C- SOFTWARE -0200]
194 */
195HWTEST_F(FileSystemTest, testStatvfs, Function | MediumTest | Level2)
196{
197    struct statvfs vfsBuf = {0};
198    struct statfs fsBuf = {0};
199
200    statvfs(".", &vfsBuf);
201    LOG("vfsBuf.f_bsize = %lu", vfsBuf.f_bsize);        // File system block size.
202    LOG("vfsBuf.f_frsize = %lu", vfsBuf.f_frsize);      // Fundamental file system block size.
203    LOG("vfsBuf.f_blocks = %lu", vfsBuf.f_blocks);      // Total number of blocks on file system in units of f_frsize.
204    LOG("vfsBuf.f_bfree = %lu", vfsBuf.f_bfree);        // Total number of free blocks.
205    LOG("vfsBuf.f_bavail = %lu", vfsBuf.f_bavail);      // Number of free blocks available to non-privileged process.
206    LOG("vfsBuf.f_files = %lu", vfsBuf.f_files);        // Total number of file serial numbers.
207    LOG("vfsBuf.f_ffree = %lu", vfsBuf.f_ffree);        // Total number of free file serial numbers.
208    LOG("vfsBuf.f_favail = %lu", vfsBuf.f_favail);      // Number of i-nodes available to unprivileged process.
209    LOG("vfsBuf.f_fsid = %lu", vfsBuf.f_fsid);          // File system ID.
210    LOG("vfsBuf.f_flag = %lu", vfsBuf.f_flag);          // Bit mask of f_flag values.
211    LOG("vfsBuf.f_namemax = %lu", vfsBuf.f_namemax);    // Maximum filename length.
212
213    statfs(".", &fsBuf);
214    LOG("fsBuf.f_type = %lu", fsBuf.f_type);            // Type of filesystem.
215    LOG("fsBuf.f_bsize = %lu", fsBuf.f_bsize);          // Optimal transfer block size.
216    LOG("fsBuf.f_blocks = %lu", fsBuf.f_blocks);        // Total data blocks in filesystem.
217    LOG("fsBuf.f_bfree = %lu", fsBuf.f_bfree);          // Total data blocks in filesystem.
218    LOG("fsBuf.f_bavail = %lu", fsBuf.f_bavail);        // Free blocks available to unprivileged user.
219    LOG("fsBuf.f_files = %lu", fsBuf.f_files);          // Total file nodes in filesystem.
220    LOG("fsBuf.f_ffree = %lu", fsBuf.f_ffree);          // Free file nodes in filesystem.
221    LOG("fsBuf.f_fsid.__val[0] = %d", fsBuf.f_fsid.__val[0]);   // Filesystem ID.
222    LOG("fsBuf.f_fsid.__val[1] = %d", fsBuf.f_fsid.__val[1]);   // Filesystem ID.
223    LOG("fsBuf.f_namelen = %ld", fsBuf.f_namelen);      // Maximum length of filenames.
224
225    EXPECT_EQ(vfsBuf.f_bsize, fsBuf.f_bsize);
226    EXPECT_EQ(vfsBuf.f_blocks, fsBuf.f_blocks);
227    EXPECT_EQ(vfsBuf.f_files, fsBuf.f_files);
228    EXPECT_EQ(vfsBuf.f_ffree, fsBuf.f_ffree);
229    EXPECT_EQ(vfsBuf.f_namemax, fsBuf.f_namelen);
230}
231
232/**
233 * @tc.number   SUB_KERNEL_FS_OTHER_0400
234 * @tc.name     basic function test : Use glob function and globfree function for path generation and release
235 * @tc.desc     [C- SOFTWARE -0200]
236 */
237HWTEST_F(FileSystemTest, testGlob, Function | MediumTest | Level3)
238{
239    glob_t buf;
240    CreateTestFolder();
241    EXPECT_EQ(glob(TOP_DIR "/" DIR0 "/*", GLOB_ERR, NULL, &buf), 0) << "> glod errno = " << errno;
242    if (buf.gl_pathc == 3) {
243        EXPECT_STREQ(buf.gl_pathv[0], TOP_DIR "/" DIR0 "/" DIR0_DIR0);
244        EXPECT_STREQ(buf.gl_pathv[1], TOP_DIR "/" DIR0 "/" DIR0_DIR1);
245        EXPECT_STREQ(buf.gl_pathv[2], TOP_DIR "/" DIR0 "/" DIR0_FILE0);
246    } else {
247        ADD_FAILURE();
248    }
249    globfree(&buf);
250}
251