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 <cstring>
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <gtest/gtest.h>
20 #include <sys/types.h>
21 #include <sys/uio.h>
22 #include "securec.h"
23
24 using namespace testing::ext;
25 using namespace std;
26
27 class PreadvApiTest : public testing::Test {
28 public:
29 static void SetUpTestCase();
30 static void TearDownTestCase();
31 void SetUp();
32 void TearDown();
33
34 private:
35 };
36
37 static const char* TEST_DATA = "Hello, world!";
38 static const size_t TEST_LEN = strlen(TEST_DATA);
39 static const int MAX_LEN = 128;
40 static const char* TEST_FILE = "/data/local/tmp/test_file.txt";
41 static const char* EMPTY_FILE = "/data/local/tmp/empty_file.txt";
42
SetUpTestCase()43 void PreadvApiTest::SetUpTestCase()
44 {
45 }
46
TearDownTestCase()47 void PreadvApiTest::TearDownTestCase()
48 {
49 }
50
SetUp()51 void PreadvApiTest::SetUp()
52 {
53 int fd = open(TEST_FILE, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
54 write(fd, TEST_DATA, TEST_LEN);
55 close(fd);
56 }
57
TearDown()58 void PreadvApiTest::TearDown()
59 {
60 unlink(TEST_FILE);
61 }
62
63 /*
64 * @tc.number : SUB_KERNEL_SYSCALL_PREADV_0100
65 * @tc.name : PreadvReadSuccess_0001
66 * @tc.desc : Test basic read functionality of preadv.
67 * @tc.size : MediumTest
68 * @tc.type : Function
69 * @tc.level : Level 1
70 */
HWTEST_F(PreadvApiTest, PreadvReadSuccess_0001, Function | MediumTest | Level1)71 HWTEST_F(PreadvApiTest, PreadvReadSuccess_0001, Function | MediumTest | Level1)
72 {
73 ssize_t size;
74 int midLen = TEST_LEN / 2;
75 char buffer[MAX_LEN] = { 0 };
76 struct iovec iov[2] = {
77 {
78 .iov_base = buffer,
79 .iov_len = TEST_LEN,
80 }, {
81 .iov_base = &buffer[TEST_LEN],
82 .iov_len = TEST_LEN,
83 }
84 };
85
86 int fd = open(TEST_FILE, O_RDONLY);
87
88 // preadv from file start
89 size = preadv(fd, iov, 2, 0);
90 EXPECT_EQ(size, TEST_LEN);
91 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), TEST_DATA);
92
93 // preadv from file middle
94 memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
95 size = preadv(fd, iov, 1, midLen);
96 EXPECT_EQ(size, TEST_LEN - midLen);
97 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), &TEST_DATA[midLen]);
98
99 // preadv from file end
100 memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
101 size = preadv(fd, iov, 1, TEST_LEN);
102 EXPECT_EQ(size, 0);
103
104 close(fd);
105 }
106
107 /*
108 * @tc.number : SUB_KERNEL_SYSCALL_PREADV_0200
109 * @tc.name : PreadvInvalidFdFailed_0002
110 * @tc.desc : Test using an invalid file descriptor with preadv.
111 * @tc.size : MediumTest
112 * @tc.type : Function
113 * @tc.level : Level 2
114 */
HWTEST_F(PreadvApiTest, PreadvInvalidFdFailed_0002, Function | MediumTest | Level2)115 HWTEST_F(PreadvApiTest, PreadvInvalidFdFailed_0002, Function | MediumTest | Level2)
116 {
117 ssize_t size;
118 char buffer[MAX_LEN] = { 0 };
119 struct iovec iov = {
120 .iov_base = buffer,
121 .iov_len = sizeof(buffer),
122 };
123 errno = 0;
124 size = preadv(-1, &iov, 1, 0);
125 EXPECT_EQ(size, -1);
126 EXPECT_EQ(errno, EBADF);
127 }
128
129 /*
130 * @tc.number : SUB_KERNEL_SYSCALL_PREADV_0300
131 * @tc.name : PreadvReadFromEmptyFileSuccess_0003
132 * @tc.desc : Test reading from an empty file with preadv.
133 * @tc.size : MediumTest
134 * @tc.type : Function
135 * @tc.level : Level 1
136 */
HWTEST_F(PreadvApiTest, PreadvReadFromEmptyFileSuccess_0003, Function | MediumTest | Level1)137 HWTEST_F(PreadvApiTest, PreadvReadFromEmptyFileSuccess_0003, Function | MediumTest | Level1)
138 {
139 ssize_t size;
140 char buffer[MAX_LEN] = { 0 };
141 struct iovec iov = {
142 .iov_base = buffer,
143 .iov_len = sizeof(buffer),
144 };
145 int fd = open(EMPTY_FILE, O_CREAT | O_RDWR, 0644);
146 size = preadv(fd, &iov, 1, 0);
147 EXPECT_EQ(size, 0);
148 close(fd);
149 unlink(EMPTY_FILE);
150 }
151
152 /*
153 * @tc.number : SUB_KERNEL_SYSCALL_PREADV_0400
154 * @tc.name : PreadvReadContinuousSuccess_0004
155 * @tc.desc : Test reading from a file with preadv continuously.
156 * @tc.size : MediumTest
157 * @tc.type : Function
158 * @tc.level : Level 1
159 */
HWTEST_F(PreadvApiTest, PreadvReadContinuousSuccess_0004, Function | MediumTest | Level1)160 HWTEST_F(PreadvApiTest, PreadvReadContinuousSuccess_0004, Function | MediumTest | Level1)
161 {
162 ssize_t size;
163 const char *context = "this is a test file.";
164 char buffer[MAX_LEN] = { 0 };
165 struct iovec iov[2] = {
166 {
167 .iov_base = buffer,
168 .iov_len = TEST_LEN,
169 }, {
170 .iov_base = &buffer[MAX_LEN / 2],
171 .iov_len = strlen(context),
172 }
173 };
174
175 int fd = open(TEST_FILE, O_RDWR | O_APPEND, 0644);
176 write(fd, context, strlen(context));
177
178 // preadv context to 2 iovec
179 size = preadv(fd, iov, 2, 0);
180 EXPECT_EQ(size, TEST_LEN + strlen(context));
181 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), TEST_DATA);
182 EXPECT_STREQ(static_cast<char *>(iov[1].iov_base), context);
183
184 close(fd);
185 }
186
187 /*
188 * @tc.number : SUB_KERNEL_SYSCALL_PREADV2_0500
189 * @tc.name : Preadv2ReadSuccess_0002
190 * @tc.desc : preadv2 read file success.
191 * @tc.size : MediumTest
192 * @tc.type : Function
193 * @tc.level : Level 1
194 */
HWTEST_F(PreadvApiTest, Preadv2ReadSuccess_0002, Function | MediumTest | Level1)195 HWTEST_F(PreadvApiTest, Preadv2ReadSuccess_0002, Function | MediumTest | Level1)
196 {
197 ssize_t size;
198 int midLen = TEST_LEN / 2;
199 char buffer[MAX_LEN] = { 0 };
200 struct iovec iov[2] = {
201 {
202 .iov_base = buffer,
203 .iov_len = TEST_LEN,
204 }, {
205 .iov_base = &buffer[TEST_LEN],
206 .iov_len = TEST_LEN,
207 }
208 };
209
210 int fd = open(TEST_FILE, O_RDONLY);
211
212 // preadv from file start
213 size = preadv(fd, iov, 2, 0);
214 EXPECT_EQ(size, TEST_LEN);
215 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), TEST_DATA);
216
217 // preadv from file middle
218 memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
219 size = preadv2(fd, iov, 1, midLen, 0);
220 EXPECT_EQ(size, TEST_LEN - midLen);
221 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), &TEST_DATA[midLen]);
222
223 // preadv from file end
224 memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
225 size = preadv2(fd, iov, 1, TEST_LEN, 0);
226 EXPECT_EQ(size, 0);
227
228 close(fd);
229 }
230