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 <fcntl.h>
21 #include <unistd.h>
22 #include <vector>
23 #include <arpa/inet.h>
24 #include <gtest/gtest.h>
25 #include <netinet/in.h>
26 #include <sys/stat.h>
27 #include <sys/socket.h>
28 #include <sys/types.h>
29 #include <sys/uio.h>
30 #include "securec.h"
31 
32 using namespace testing::ext;
33 
34 class HatsWritevTest : public testing::Test {
35 public:
36 static void SetUpTestCase();
37 static void TearDownTestCase();
38 void SetUp();
39 void TearDown();
40 private:
41 };
SetUp()42 void HatsWritevTest::SetUp()
43 {
44 }
TearDown()45 void HatsWritevTest::TearDown()
46 {
47 }
SetUpTestCase()48 void HatsWritevTest::SetUpTestCase()
49 {
50 }
TearDownTestCase()51 void HatsWritevTest::TearDownTestCase()
52 {
53 }
54 
55 static const char *WRITEV_TEST_FILE = "/data/local/tmp/tryWritev.txt";
56 static const int VEC_LEN = 2;
57 static const char *TEST_DATA = "Hello writev";
58 static const int TEST_DATA_LEN = strlen(TEST_DATA);
59 static const char *TEST_DATA_BUF1 = "Hello ";
60 static const int BUF1_LEN = strlen(TEST_DATA_BUF1);
61 static const char *TEST_DATA_BUF2 = "writev";
62 static const int BUF2_LEN = strlen(TEST_DATA_BUF2);
63 
64 /*
65  * @tc.number : SUB_KERNEL_SYSCALL_WRITEV_0100
66  * @tc.name   : WritevWriteDataToFileSuccess_0001
67  * @tc.desc   : writev writes data to file success.
68  * @tc.size   : MediumTest
69  * @tc.type   : Function
70  * @tc.level  : Level 1
71  */
HWTEST_F(HatsWritevTest, WritevWriteDataToFileSuccess_0001, Function | MediumTest | Level1)72 HWTEST_F(HatsWritevTest, WritevWriteDataToFileSuccess_0001, Function | MediumTest | Level1)
73 {
74     int fd;
75     struct iovec vec[VEC_LEN];
76     int ret;
77     char *iovBuf1 = nullptr;
78     char *iovBuf2 = nullptr;
79     char *readBuf = nullptr;
80     iovBuf1 = new char[BUF1_LEN];
81     memcpy_s(iovBuf1, BUF1_LEN, TEST_DATA_BUF1, BUF1_LEN);
82     iovBuf2 = new char[BUF2_LEN];
83     memcpy_s(iovBuf2, BUF2_LEN, TEST_DATA_BUF2, BUF2_LEN);
84     vec[0].iov_base = iovBuf1;
85     vec[0].iov_len = BUF1_LEN;
86     vec[1].iov_base = iovBuf2;
87     vec[1].iov_len = BUF2_LEN;
88     readBuf = new char[TEST_DATA_LEN + 1];
89 
90     fd = open(WRITEV_TEST_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
91     EXPECT_TRUE(fd >= 3);
92 
93     ret = writev(fd, vec, VEC_LEN);
94     EXPECT_TRUE(ret == TEST_DATA_LEN);
95     close(fd);
96 
97     fd = open(WRITEV_TEST_FILE, O_RDONLY);
98     EXPECT_TRUE(fd >= 3);
99     ret = read(fd, readBuf, TEST_DATA_LEN);
100     EXPECT_TRUE(ret == TEST_DATA_LEN);
101     readBuf[TEST_DATA_LEN] = '\0';
102     ret = strcmp(readBuf, TEST_DATA);
103     EXPECT_TRUE(ret == 0);
104     close(fd);
105     delete[] iovBuf1;
106     delete[] iovBuf2;
107     delete[] readBuf;
108 }
109 
110 /*
111  * @tc.number : SUB_KERNEL_SYSCALL_WRITEV_0200
112  * @tc.name   : WritevWriteToPipeSuccess_0002
113  * @tc.desc   : Writev write data to pipe success.
114  * @tc.size   : MediumTest
115  * @tc.type   : Function
116  * @tc.level  : Level 1
117  */
HWTEST_F(HatsWritevTest, WritevWriteToPipeSuccess_0002, Function | MediumTest | Level1)118 HWTEST_F(HatsWritevTest, WritevWriteToPipeSuccess_0002, Function | MediumTest | Level1)
119 {
120     int pipefd[2];
121     struct iovec vec[VEC_LEN];
122     int ret;
123     char *iovBuf1 = nullptr;
124     char *iovBuf2 = nullptr;
125     char *readBuf = nullptr;
126     iovBuf1 = new char[BUF1_LEN];
127     memcpy_s(iovBuf1, BUF1_LEN, TEST_DATA_BUF1, BUF1_LEN);
128     iovBuf2 = new char[BUF2_LEN];
129     memcpy_s(iovBuf2, BUF2_LEN, TEST_DATA_BUF2, BUF2_LEN);
130     vec[0].iov_base = iovBuf1;
131     vec[0].iov_len = BUF1_LEN;
132     vec[1].iov_base = iovBuf2;
133     vec[1].iov_len = BUF2_LEN;
134     readBuf = new char[TEST_DATA_LEN + 1];
135 
136     ret = pipe(pipefd);
137     EXPECT_TRUE(ret == 0);
138     ret = writev(pipefd[1], vec, VEC_LEN);
139     EXPECT_TRUE(ret == TEST_DATA_LEN);
140 
141     ret = read(pipefd[0], readBuf, TEST_DATA_LEN);
142     EXPECT_TRUE(ret == TEST_DATA_LEN);
143     readBuf[TEST_DATA_LEN] = '\0';
144     ret = strcmp(readBuf, TEST_DATA);
145     EXPECT_TRUE(ret == 0);
146 
147     close(pipefd[0]);
148     close(pipefd[1]);
149     delete[] iovBuf1;
150     delete[] iovBuf2;
151     delete[] readBuf;
152 }
153 
154 
155 /*
156  * @tc.number : SUB_KERNEL_SYSCALL_WRITEV_0300
157  * @tc.name   : WritevInvalidVecLenFail_0003
158  * @tc.desc   : Writv write with invalid iovec length fail.
159  * @tc.size   : MediumTest
160  * @tc.type   : Function
161  * @tc.level  : Level 2
162  */
HWTEST_F(HatsWritevTest, WritevInvalidVecLenFail_0003, Function | MediumTest | Level2)163 HWTEST_F(HatsWritevTest, WritevInvalidVecLenFail_0003, Function | MediumTest | Level2)
164 {
165     int fd;
166     struct iovec vec[VEC_LEN];
167     int ret;
168     int newVecLen;
169     char *iovBuf1 = nullptr;
170     char *iovBuf2 = nullptr;
171     iovBuf1 = new char[BUF1_LEN];
172     ret = memcpy_s(iovBuf1, BUF1_LEN, TEST_DATA_BUF1, BUF1_LEN);
173     iovBuf2 = new char[BUF2_LEN];
174     ret = memcpy_s(iovBuf2, BUF2_LEN, TEST_DATA_BUF2, BUF2_LEN);
175     vec[0].iov_base = iovBuf1;
176     vec[0].iov_len = BUF1_LEN;
177     vec[1].iov_base = iovBuf2;
178     vec[1].iov_len = BUF2_LEN;
179 
180     fd = open(WRITEV_TEST_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
181     EXPECT_TRUE(fd >= 3);
182 
183     newVecLen = -1;
184     errno = 0;
185     ret = writev(fd, vec, newVecLen);
186     EXPECT_TRUE(ret == -1);
187     EXPECT_EQ(errno, EINVAL);
188 
189     close(fd);
190     delete[] iovBuf1;
191     delete[] iovBuf2;
192 }
193 
194 /*
195  * @tc.number : SUB_KERNEL_SYSCALL_WRITEV_0400
196  * @tc.name   : WritevInvalidFdFail_0004
197  * @tc.desc   : writev write data into invalid fd fail.
198  * @tc.size   : MediumTest
199  * @tc.type   : Function
200  * @tc.level  : Level 2
201  */
HWTEST_F(HatsWritevTest, WritevInvalidFdFail_0004, Function | MediumTest | Level2)202 HWTEST_F(HatsWritevTest, WritevInvalidFdFail_0004, Function | MediumTest | Level2)
203 {
204     int fd;
205     struct iovec vec[VEC_LEN];
206     int ret;
207     char *iovBuf1 = nullptr;
208     char *iovBuf2 = nullptr;
209     iovBuf1 = new char[BUF1_LEN];
210     ret = memcpy_s(iovBuf1, BUF1_LEN, TEST_DATA_BUF1, BUF1_LEN);
211     iovBuf2 = new char[BUF2_LEN];
212     ret = memcpy_s(iovBuf2, BUF2_LEN, TEST_DATA_BUF2, BUF2_LEN);
213     vec[0].iov_base = iovBuf1;
214     vec[0].iov_len = BUF1_LEN;
215     vec[1].iov_base = iovBuf2;
216     vec[1].iov_len = BUF2_LEN;
217 
218     fd = -1;
219     errno = 0;
220     ret = writev(fd, vec, VEC_LEN);
221     EXPECT_TRUE(ret == -1);
222     EXPECT_EQ(errno, EBADF);
223 
224     delete[] iovBuf1;
225     delete[] iovBuf2;
226 }
227 
228 /*
229  * @tc.number : SUB_KERNEL_SYSCALL_WRITEV_0500
230  * @tc.name   : WritevFdNotInWriteModeFail_0005
231  * @tc.desc   : writev fd is not in write mode fail.
232  * @tc.size   : MediumTest
233  * @tc.type   : Function
234  * @tc.level  : Level 2
235  */
HWTEST_F(HatsWritevTest, WritevFdNotInWriteModeFail_0005, Function | MediumTest | Level2)236 HWTEST_F(HatsWritevTest, WritevFdNotInWriteModeFail_0005, Function | MediumTest | Level2)
237 {
238     int fd;
239     struct iovec vec[VEC_LEN];
240     int ret;
241     char *iovBuf1 = nullptr;
242     char *iovBuf2 = nullptr;
243     iovBuf1 = new char[BUF1_LEN];
244     ret = memcpy_s(iovBuf1, BUF1_LEN, TEST_DATA_BUF1, BUF1_LEN);
245     iovBuf2 = new char[BUF2_LEN];
246     ret = memcpy_s(iovBuf2, BUF2_LEN, TEST_DATA_BUF2, BUF2_LEN);
247     vec[0].iov_base = iovBuf1;
248     vec[0].iov_len = BUF1_LEN;
249     vec[1].iov_base = iovBuf2;
250     vec[1].iov_len = BUF2_LEN;
251 
252     fd = open(WRITEV_TEST_FILE, O_RDONLY | O_CREAT | O_TRUNC, 0644);
253     EXPECT_TRUE(fd >= 3);
254     errno = 0;
255     ret = writev(fd, vec, VEC_LEN);
256     EXPECT_TRUE(ret == -1);
257     EXPECT_EQ(errno, EBADF);
258     close(fd);
259 
260     fd = open(WRITEV_TEST_FILE, O_APPEND | O_CREAT | O_TRUNC, 0644);
261     EXPECT_TRUE(fd >= 3);
262     errno = 0;
263     ret = writev(fd, vec, VEC_LEN);
264     EXPECT_TRUE(ret == -1);
265     EXPECT_EQ(errno, EBADF);
266     close(fd);
267 
268     delete[] iovBuf1;
269     delete[] iovBuf2;
270 }
271