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
33class CopyFileRangeApiTest : public testing::Test {
34public:
35    static void SetUpTestCase();
36    static void TearDownTestCase();
37    void SetUp();
38    void TearDown();
39private:
40};
41void CopyFileRangeApiTest::SetUp()
42{
43}
44void CopyFileRangeApiTest::TearDown()
45{
46}
47void CopyFileRangeApiTest::SetUpTestCase()
48{
49}
50void CopyFileRangeApiTest::TearDownTestCase()
51{
52}
53
54static const int MAX_LEN = 128;
55static const char *TEST_FILE = "/data/local/tmp/CopyFileRange.txt";
56static const char *TEST_SRC_FILE = "/data/local/tmp/CopyFileRangeSource.txt";
57static const char *TEST_DES_FILE = "/data/local/tmp/CopyFileRangeDestination.txt";
58static const char *TEST_SRC_DIR = "/data/local/tmp/CopyFileRangeSource";
59static const char *TEST_DES_DIR = "/data/local/tmp/CopyFileRangeDestination";
60static const char *TEST_DATA = "Hello, world!";
61mode_t MODE_0644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
62mode_t MODE_0755 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
63
64/*
65 * @tc.number : SUB_KERNEL_SYSCALL_COPYFILERANGE_0100
66 * @tc.name   : CopyFileRangeCopyValidFdContentSuccess_0001
67 * @tc.desc   : copy_file_range copy TEST_DATA  in fdOut with specify length from fdIn success.
68 * @tc.size   : MediumTest
69 * @tc.type   : Function
70 * @tc.level  : Level 1
71 */
72HWTEST_F(CopyFileRangeApiTest, CopyFileRangeCopyValidFdContentSuccess_0001, Function | MediumTest | Level1)
73{
74    ssize_t size;
75    loff_t offIn = 0;
76    loff_t offOut = 0;
77    int ret = 0;
78    char buffer[MAX_LEN];
79    int fdIn = open(TEST_SRC_FILE, O_RDWR | O_CREAT | O_TRUNC, MODE_0644);
80    EXPECT_TRUE(fdIn > 0);
81    ret = write(fdIn, TEST_DATA, strlen(TEST_DATA));
82    EXPECT_EQ(ret, strlen(TEST_DATA));
83    int fdOut = open(TEST_DES_FILE, O_RDWR | O_CREAT | O_TRUNC, MODE_0644);
84    EXPECT_TRUE(fdOut > 0);
85
86    size = copy_file_range(fdIn, &offIn, fdOut, &offOut, strlen(TEST_DATA), 0);
87    EXPECT_EQ(size, strlen(TEST_DATA));
88    ret = read(fdOut, buffer, strlen(TEST_DATA));
89    EXPECT_EQ(size, strlen(TEST_DATA));
90    EXPECT_STREQ(buffer, TEST_DATA);
91
92    close(fdIn);
93    close(fdOut);
94    remove(TEST_SRC_FILE);
95    remove(TEST_DES_FILE);
96}
97
98/*
99 * @tc.number : SUB_KERNEL_SYSCALL_COPYFILERANGE_0200
100 * @tc.name   : CopyFileRangeCopyInvalidFdContentFail_0002
101 * @tc.desc   : copy_file_range copy from invalid fd or copy into invalid fd fail, errno EBADF.
102 * @tc.size   : MediumTest
103 * @tc.type   : Function
104 * @tc.level  : Level 2
105 */
106HWTEST_F(CopyFileRangeApiTest, CopyFileRangeCopyInvalidFdContentFail_0002, Function | MediumTest | Level2)
107{
108    ssize_t size;
109    loff_t offIn = 0;
110    loff_t offOut = 0;
111    int invalidFd = -1;
112    int fd = open(TEST_FILE, O_RDWR | O_CREAT | O_TRUNC, MODE_0644);
113    EXPECT_TRUE(fd > 0);
114
115    errno = 0;
116    size = copy_file_range(invalidFd, &offIn, fd, &offOut, strlen(TEST_DATA), 0);
117    EXPECT_EQ(size, -1);
118    EXPECT_EQ(errno, EBADF);
119
120    errno = 0;
121    size = copy_file_range(fd, &offIn, invalidFd, &offOut, strlen(TEST_DATA), 0);
122    EXPECT_EQ(size, -1);
123    EXPECT_EQ(errno, EBADF);
124
125    close(fd);
126    remove(TEST_FILE);
127}
128
129/*
130 * @tc.number : SUB_KERNEL_SYSCALL_COPYFILERANGE_0300
131 * @tc.name   : CopyFileRangeCopyInvalidFlagFail_0003
132 * @tc.desc   : copy_file_range copy with invalid flag fail, errno EINVAL.
133 * @tc.size   : MediumTest
134 * @tc.type   : Function
135 * @tc.level  : Level 2
136 */
137HWTEST_F(CopyFileRangeApiTest, CopyFileRangeCopyInvalidFlagFail_0003, Function | MediumTest | Level2)
138{
139    ssize_t size;
140    loff_t offIn = 0;
141    loff_t offOut = 0;
142    int fdIn = open(TEST_SRC_FILE, O_RDWR | O_CREAT | O_TRUNC, MODE_0644);
143    EXPECT_TRUE(fdIn > 0);
144    int fdOut = open(TEST_DES_FILE, O_RDWR | O_CREAT | O_TRUNC, MODE_0644);
145    EXPECT_TRUE(fdOut > 0);
146
147    errno = 0;
148    size = copy_file_range(fdIn, &offIn, fdOut, &offOut, strlen(TEST_DATA), 1);
149    EXPECT_EQ(size, -1);
150    EXPECT_EQ(errno, EINVAL);
151
152    close(fdIn);
153    close(fdOut);
154    remove(TEST_SRC_FILE);
155    remove(TEST_DES_FILE);
156}
157
158/*
159 * @tc.number : SUB_KERNEL_SYSCALL_COPYFILERANGE_0400
160 * @tc.name   : CopyFileRangeCopyFdNoPermissionFail_0004
161 * @tc.desc   : copy_file_range copy TEST_DATA without correct permission in fdOut or fdIn fail, errno EBADF.
162 * @tc.size   : MediumTest
163 * @tc.type   : Function
164 * @tc.level  : Level 2
165 */
166HWTEST_F(CopyFileRangeApiTest, CopyFileRangeCopyFdNoPermissionFail_0004, Function | MediumTest | Level2)
167{
168    ssize_t size;
169    loff_t offIn = 0;
170    loff_t offOut = 0;
171    int result = 0;
172    int fdIn = open(TEST_SRC_FILE, O_WRONLY | O_CREAT, MODE_0644);
173    EXPECT_TRUE(fdIn > 0);
174    result = write(fdIn, TEST_DATA, strlen(TEST_DATA));
175    EXPECT_EQ(result, strlen(TEST_DATA));
176    int fdOut = open(TEST_DES_FILE, O_RDONLY | O_CREAT, MODE_0644);
177    EXPECT_TRUE(fdOut > 0);
178    int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0644);
179    EXPECT_TRUE(fd > 0);
180
181    errno = 0;
182    size = copy_file_range(fdIn, &offIn, fd, &offOut, strlen(TEST_DATA), 0);
183    EXPECT_EQ(size, -1);
184    EXPECT_EQ(errno, EBADF);
185
186    errno = 0;
187    size = copy_file_range(fd, &offIn, fdOut, &offOut, strlen(TEST_DATA), 0);
188    EXPECT_EQ(size, -1);
189    EXPECT_EQ(errno, EBADF);
190
191    close(fd);
192    close(fdIn);
193    close(fdOut);
194    remove(TEST_FILE);
195    remove(TEST_SRC_FILE);
196    remove(TEST_DES_FILE);
197}
198
199/*
200 * @tc.number : SUB_KERNEL_SYSCALL_COPYFILERANGE_0500
201 * @tc.name   : CopyFileRangeCopyOverOffsetContentFail_0005
202 * @tc.desc   : copy_file_range copy TEST_DATA  in fdOut with over offset length from fdIn .
203 * @tc.size   : MediumTest
204 * @tc.type   : Function
205 * @tc.level  : Level 2
206 */
207HWTEST_F(CopyFileRangeApiTest, CopyFileRangeCopyOverOffsetContentFail_0005, Function | MediumTest | Level2)
208{
209    int ret;
210    ssize_t size;
211    loff_t offIn = 0;
212    loff_t offOut = 0;
213    if (access(TEST_SRC_DIR, F_OK) != 0) {
214        ret = mkdir(TEST_SRC_DIR, MODE_0755);
215        EXPECT_EQ(ret, 0);
216    }
217    int fdIn = open(TEST_SRC_DIR, O_RDONLY | O_DIRECTORY);
218    EXPECT_NE(fdIn, -1);
219    if (access(TEST_DES_DIR, F_OK) != 0) {
220        ret = mkdir(TEST_DES_DIR, MODE_0755);
221        EXPECT_EQ(ret, 0);
222    }
223    int fdOut = open(TEST_DES_DIR, O_RDONLY | O_DIRECTORY);
224    EXPECT_NE(fdOut, -1);
225
226    errno = 0;
227    size = copy_file_range(fdIn, &offIn, fdOut, &offOut, strlen(TEST_DATA), 0);
228    EXPECT_EQ(size, -1);
229    EXPECT_EQ(errno, EISDIR);
230
231    close(fdIn);
232    close(fdOut);
233    remove(TEST_SRC_DIR);
234    remove(TEST_DES_DIR);
235}