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