1/*
2 * Copyright (C) 2024 HiHope Open Source Organization.
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 <cerrno>
17#include <cstdio>
18#include <cstdlib>
19#include <string>
20#include <vector>
21#include <fcntl.h>
22#include <unistd.h>
23#include <gtest/gtest.h>
24#include <sys/file.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <sys/xattr.h>
28#include "securec.h"
29
30using namespace testing::ext;
31using namespace std;
32
33static const char *TEST_FILE = "/data/local/tmp/fcntl.txt";
34mode_t MODE_0644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
35
36class FcntlApiTest : public testing::Test {
37public:
38    static void SetUpTestCase();
39    static void TearDownTestCase();
40    void SetUp();
41    void TearDown();
42private:
43};
44void FcntlApiTest::SetUp()
45{
46}
47void FcntlApiTest::TearDown()
48{
49}
50void FcntlApiTest::SetUpTestCase()
51{
52}
53void FcntlApiTest::TearDownTestCase()
54{
55}
56
57/*
58 * @tc.number : SUB_KERNEL_SYSCALL_FCNTL_0100
59 * @tc.name   : FcntlManipulateFdFlagSuccess_0001
60 * @tc.desc   : fcntl get fd flag and set fd flag success.
61 * @tc.size   : MediumTest
62 * @tc.type   : Function
63 * @tc.level  : Level 1
64 */
65HWTEST_F(FcntlApiTest, FcntlFdFlagSuccess_0001, Function | MediumTest | Level1)
66{
67    int ret;
68    int flags = 0;
69    int fd = open(TEST_FILE, O_RDWR | O_CREAT | O_TRUNC, MODE_0644);
70    EXPECT_TRUE(fd > 0);
71
72    ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
73    EXPECT_EQ(ret, 0);
74
75    flags = fcntl(fd, F_GETFD);
76    EXPECT_EQ(flags, FD_CLOEXEC);
77
78    ret = fcntl(fd, F_SETFL, O_NONBLOCK);
79    EXPECT_EQ(ret, 0);
80
81    flags = fcntl(fd, F_GETFL);
82    EXPECT_EQ(flags & O_NONBLOCK, O_NONBLOCK);
83
84    close(fd);
85    remove(TEST_FILE);
86}
87
88/*
89 * @tc.number : SUB_KERNEL_SYSCALL_FCNTL_0200
90 * @tc.name   : FcntlManipulateFileLockSuccess_0002
91 * @tc.desc   : fcntl set file lock success and return unlock by get lock check.
92 * @tc.size   : MediumTest
93 * @tc.type   : Function
94 * @tc.level  : Level 1
95 */
96HWTEST_F(FcntlApiTest, FcntlManipulateFileLockSuccess_0002, Function | MediumTest | Level1)
97{
98    int ret;
99    int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0644);
100    EXPECT_TRUE(fd > 0);
101
102    struct flock lockCheck = { 0 };
103    struct flock lock = {
104        .l_type = F_RDLCK,
105        .l_whence = SEEK_SET,
106        .l_start = 0,
107        .l_len = 0,
108    };
109
110    ret = fcntl(fd, F_SETLK, &lock);
111    EXPECT_EQ(ret, 0);
112
113    ret = fcntl(fd, F_GETLK, &lockCheck);
114    EXPECT_EQ(ret, 0);
115    EXPECT_EQ(lockCheck.l_type, F_UNLCK);
116    EXPECT_EQ(lockCheck.l_whence, lock.l_whence);
117    EXPECT_EQ(lockCheck.l_start, lock.l_start);
118    EXPECT_EQ(lockCheck.l_len, lock.l_len);
119
120    close(fd);
121    remove(TEST_FILE);
122}
123
124/*
125 * @tc.number : SUB_KERNEL_SYSCALL_FCNTL_0300
126 * @tc.name   : FcntlManipulateInvalidFdFail_0003
127 * @tc.desc   : fcntl manipulate invalid fd fail, errno EBADF.
128 * @tc.size   : MediumTest
129 * @tc.type   : Function
130 * @tc.level  : Level 2
131 */
132HWTEST_F(FcntlApiTest, FcntlManipulateInvalidFdFail_0003, Function | MediumTest | Level2)
133{
134    int ret;
135    int invalidFd = -1;
136    errno = 0;
137    ret = fcntl(invalidFd, F_GETFL);
138    EXPECT_EQ(ret, -1);
139    EXPECT_EQ(errno, EBADF);
140}
141
142/*
143 * @tc.number : SUB_KERNEL_SYSCALL_FCNTL_0400
144 * @tc.name   : FcntlSetInvalidLockFail_0004
145 * @tc.desc   : fcntl set invalid nullptr lock fail, errno EFAULT.
146 * @tc.size   : MediumTest
147 * @tc.type   : Function
148 * @tc.level  : Level 2
149 */
150HWTEST_F(FcntlApiTest, FcntlSetInvalidLockFail_0004, Function | MediumTest | Level2)
151{
152    int ret;
153    int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0644);
154    EXPECT_TRUE(fd > 0);
155
156    errno = 0;
157    ret = fcntl(fd, F_SETLKW, nullptr);
158    EXPECT_EQ(ret, -1);
159    EXPECT_EQ(errno, EFAULT);
160
161    close(fd);
162    remove(TEST_FILE);
163}
164
165/*
166 * @tc.number : SUB_KERNEL_SYSCALL_FCNTL_0500
167 * @tc.name   : FcntlDupFdSuccess_0005
168 * @tc.desc   : fcntl duplicate fd success.
169 * @tc.size   : MediumTest
170 * @tc.type   : Function
171 * @tc.level  : Level 1
172 */
173HWTEST_F(FcntlApiTest, FcntlDupFdSuccess_0005, Function | MediumTest | Level1)
174{
175    int ret;
176    int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0644);
177    EXPECT_TRUE(fd > 0);
178
179    ret = fcntl(fd, F_DUPFD, 0);
180    EXPECT_TRUE(ret > 0);
181
182    ret = fcntl(fd, F_DUPFD_CLOEXEC, 0);
183    EXPECT_TRUE(ret > 0);
184
185    close(fd);
186    close(ret);
187    remove(TEST_FILE);
188}
189
190/*
191 * @tc.number : SUB_KERNEL_SYSCALL_FCNTL_0600
192 * @tc.name   : FcntlSetLockSuccess_0006
193 * @tc.desc   : fcntl set lock success.
194 * @tc.size   : MediumTest
195 * @tc.type   : Function
196 * @tc.level  : Level 1
197 */
198HWTEST_F(FcntlApiTest, FcntlSetLockSuccess_0006, Function | MediumTest | Level1)
199{
200    int ret;
201    int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0644);
202    EXPECT_TRUE(fd > 0);
203
204    struct flock lock = {
205        .l_type = F_WRLCK,
206        .l_whence = SEEK_SET,
207        .l_start = 0,
208        .l_len = 0,
209    };
210
211    ret = fcntl(fd, F_SETLK, &lock);
212    EXPECT_EQ(ret, 0);
213
214    close(fd);
215    remove(TEST_FILE);
216}
217
218/*
219 * @tc.number : SUB_KERNEL_SYSCALL_FCNTL_0700
220 * @tc.name   : FcntlOfdSetLockSuccess_0007
221 * @tc.desc   : fcntl ofd set lock success.
222 * @tc.size   : MediumTest
223 * @tc.type   : Function
224 * @tc.level  : Level 1
225 */
226HWTEST_F(FcntlApiTest, FcntlOfdSetLockSuccess_0007, Function | MediumTest | Level1)
227{
228    int ret;
229    int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0644);
230    EXPECT_TRUE(fd > 0);
231
232    struct flock lock = {
233        .l_type = F_WRLCK,
234        .l_whence = SEEK_SET,
235        .l_start = 0,
236        .l_len = 0,
237    };
238
239    ret = fcntl(fd, F_OFD_SETLK, &lock);
240    EXPECT_EQ(ret, 0);
241
242    close(fd);
243    remove(TEST_FILE);
244}
245
246/*
247 * @tc.number : SUB_KERNEL_SYSCALL_FCNTL_0800
248 * @tc.name   : FcntlSetPipeSzSuccess_0008
249 * @tc.desc   : fcntl set pipe get pipe success.
250 * @tc.size   : MediumTest
251 * @tc.type   : Function
252 * @tc.level  : Level 1
253 */
254HWTEST_F(FcntlApiTest, FcntlSetPipeSzSuccess_0008, Function | MediumTest | Level1)
255{
256    int fds[2];
257    int ret = pipe(fds);
258    EXPECT_TRUE(ret == 0);
259
260    ret = fcntl(fds[1], F_SETPIPE_SZ, 1024);
261    EXPECT_GE(ret, 0);
262    ret = fcntl(fds[1], F_GETPIPE_SZ);
263    EXPECT_GE(ret, 0);
264
265    close(fds[0]);
266    close(fds[1]);
267}
268
269/*
270 * @tc.number : SUB_KERNEL_SYSCALL_FCNTL_0900
271 * @tc.name   : FcntlAddAndGetSealsFlagSuccess_0009
272 * @tc.desc   : fcntl add F_SEAL_SEAL/F_SEAL_SHRINK/F_SEAL_WRITE/F_SEAL_GROW flags and get seals success.
273 * @tc.size   : MediumTest
274 * @tc.type   : Function
275 * @tc.level  : Level 1
276 */
277HWTEST_F(FcntlApiTest, FcntlAddAndGetSealsFlagSuccess_0009, Function | MediumTest | Level1)
278{
279    int flags = 0;
280    int fd = open(TEST_FILE, O_RDWR | O_CREAT | O_TRUNC, MODE_0644);
281    EXPECT_TRUE(fd > 0);
282
283    // F_ADD_SEALS F_SEAL_GROW test success
284    flags = fcntl(fd, F_ADD_SEALS, F_SEAL_GROW);
285    EXPECT_EQ(flags & F_SEAL_GROW, F_SEAL_GROW);
286
287    // F_ADD_SEALS F_SEAL_SEAL test success
288    flags = fcntl(fd, F_ADD_SEALS, F_SEAL_SEAL);
289    EXPECT_EQ(flags & F_SEAL_SEAL, F_SEAL_SEAL);
290
291    // F_ADD_SEALS F_SEAL_WRITE test success
292    flags = fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE);
293    EXPECT_EQ(flags & F_SEAL_WRITE, F_SEAL_WRITE);
294
295    // F_ADD_SEALS F_SEAL_SHRINK test success
296    flags = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK);
297    EXPECT_EQ(flags & F_SEAL_SHRINK, F_SEAL_SHRINK);
298
299    // F_GET_SEALS test success
300    int testFlags = F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_SEAL | F_SEAL_WRITE;
301    flags = fcntl(fd, F_GET_SEALS);
302    EXPECT_EQ(flags & testFlags, testFlags);
303
304    close(fd);
305    remove(TEST_FILE);
306}