1 /*
2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
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 <pthread.h>
23 #include <unistd.h>
24 #include <arpa/inet.h>
25 #include <gtest/gtest.h>
26 #include <netinet/in.h>
27 #include <sys/stat.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
30 #include "securec.h"
31
32 using namespace testing::ext;
33
34 static const int BUFFER_SIZE = 1024;
35 static const int TEST_PORT = 22354;
36 static const char *TEST_LOCAL_IP = "127.0.0.1";
37 static int g_serviceFd = -1;
38
39 class HatsSendmsgTest : public testing::Test {
40 public:
41 static void SetUpTestCase();
42 static void TearDownTestCase();
43 void SetUp();
44 void TearDown();
45 private:
46 };
SetUp()47 void HatsSendmsgTest::SetUp()
48 {
49 int ret;
50 int socketFd = -1;
51 int32_t optVal = 1;
52 struct sockaddr_in serAddr = {
53 .sin_family = AF_INET,
54 .sin_port = htons(TEST_PORT),
55 .sin_addr = {
56 .s_addr = inet_addr(TEST_LOCAL_IP),
57 }
58 };
59
60 socketFd = socket(AF_INET, SOCK_STREAM, 0);
61 EXPECT_TRUE(socketFd > 0);
62
63 ret = setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
64 EXPECT_EQ(ret, 0);
65
66 ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
67 EXPECT_EQ(ret, 0);
68
69 g_serviceFd = socketFd;
70 }
TearDown()71 void HatsSendmsgTest::TearDown()
72 {
73 close(g_serviceFd);
74 g_serviceFd = -1;
75 }
SetUpTestCase()76 void HatsSendmsgTest::SetUpTestCase()
77 {
78 }
TearDownTestCase()79 void HatsSendmsgTest::TearDownTestCase()
80 {
81 }
82
ClientConnect(void * args)83 static void *ClientConnect(void *args)
84 {
85 int ret;
86 ssize_t size;
87 int clientFd = -1;
88 char buffer[BUFFER_SIZE] = { 0 };
89 struct sockaddr_in addr;
90 socklen_t addrlen = sizeof(addr);
91 struct sockaddr_in serAddr = {
92 .sin_family = AF_INET,
93 .sin_port = htons(TEST_PORT),
94 .sin_addr = {
95 .s_addr = inet_addr(TEST_LOCAL_IP),
96 }
97 };
98
99 clientFd = socket(AF_INET, SOCK_STREAM, 0);
100 EXPECT_TRUE(clientFd > 0);
101
102 ret = connect(clientFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in));
103 EXPECT_EQ(ret, 0);
104
105 struct msghdr msg = {0};
106 struct iovec iov = {buffer, sizeof(buffer)};
107 msg.msg_iov = &iov;
108 msg.msg_iovlen = 1;
109 msg.msg_name = reinterpret_cast<struct sockaddr *>(&addr);
110 msg.msg_namelen = addrlen;
111
112 size = recvmsg(clientFd, &msg, 0);
113 EXPECT_TRUE(size >= 0);
114
115 close(clientFd);
116 return nullptr;
117 }
118
119 /*
120 * @tc.number : SUB_KERNEL_SYSCALL_SENDMSG_0100
121 * @tc.name : SendmsgSuccess_0001
122 * @tc.desc : Sendmsg test success.
123 * @tc.size : MediumTest
124 * @tc.type : Function
125 * @tc.level : Level 1
126 */
127 HWTEST_F(HatsSendmsgTest, SendmsgSuccess_0001, Function | MediumTest | Level1)
128 {
129 int ret;
130 ssize_t size;
131 pthread_t thread;
132 int acceptFd = -1;
133 int32_t backLog = 5;
134 struct sockaddr_in dstAddr = { 0 };
135 struct sockaddr_in peerAddr;
136 socklen_t addrLen = sizeof(struct sockaddr_in);
137 socklen_t peerLen = sizeof(struct sockaddr_in);
138
139 ret = listen(g_serviceFd, backLog);
140 EXPECT_EQ(ret, 0);
141
142 pthread_create(&thread, nullptr, ClientConnect, nullptr);
143
144 acceptFd = accept4(g_serviceFd, reinterpret_cast<struct sockaddr *>(&dstAddr), &addrLen, 0);
145 EXPECT_TRUE(acceptFd > 0);
146
147 ret = getpeername(acceptFd, reinterpret_cast<struct sockaddr *>(&peerAddr), &peerLen);
148 EXPECT_EQ(ret, 0);
149
150 EXPECT_STREQ(inet_ntoa(peerAddr.sin_addr), TEST_LOCAL_IP);
151 EXPECT_EQ(peerLen, sizeof(struct sockaddr));
152
153 struct msghdr msg;
154 struct iovec iov;
155 char buffer[BUFFER_SIZE];
156 iov.iov_base = buffer;
157 iov.iov_len = sizeof(buffer);
158 msg.msg_name = nullptr; // 不需要目标地址
159 msg.msg_namelen = 0;
160 msg.msg_iov = &iov;
161 msg.msg_iovlen = 1;
162 msg.msg_control = nullptr;
163 msg.msg_controllen = 0;
164
165 size = sendmsg(acceptFd, &msg, 0);
166 EXPECT_TRUE(size >= 0);
167
168 close(acceptFd);
169 pthread_join(thread, nullptr);
170 }
171
172 /*
173 * @tc.number : SUB_KERNEL_SYSCALL_SENDMSG_0200
174 * @tc.name : SendmsgSuccess_0002
175 * @tc.desc : Sendmsg test success by MSG_MORE.
176 * @tc.size : MediumTest
177 * @tc.type : Function
178 * @tc.level : Level 2
179 */
180 HWTEST_F(HatsSendmsgTest, SendmsgSuccess_0002, Function | MediumTest | Level2)
181 {
182 int ret;
183 ssize_t size;
184 pthread_t thread;
185 int acceptFd = -1;
186 int32_t backLog = 5;
187 struct sockaddr_in dstAddr = { 0 };
188 socklen_t addrLen = sizeof(struct sockaddr_in);
189
190 ret = listen(g_serviceFd, backLog);
191 EXPECT_EQ(ret, 0);
192
193 pthread_create(&thread, nullptr, ClientConnect, nullptr);
194 acceptFd = accept4(g_serviceFd, reinterpret_cast<struct sockaddr *>(&dstAddr), &addrLen, 0);
195 EXPECT_TRUE(acceptFd > 0);
196
197 char buf1[] = "Hello, ";
198 char buf2[] = "world!";
199
200 struct iovec iov[2];
201 iov[0].iov_base = buf1;
202 iov[0].iov_len = sizeof(buf1) - 1;
203 iov[1].iov_base = buf2;
204 iov[1].iov_len = sizeof(buf2) - 1;
205
206 struct msghdr message;
207 memset_s(&message, sizeof(message), 0, sizeof(message));
208 message.msg_iov = iov;
209 message.msg_iovlen = 2;
210
211 size = sendmsg(acceptFd, &message, MSG_MORE);
212 EXPECT_TRUE(size >= 0);
213
214 size = sendmsg(acceptFd, &message, 0);
215 EXPECT_TRUE(size >= 0);
216
217 close(acceptFd);
218 pthread_join(thread, nullptr);
219 }
220
221 /*
222 * @tc.number : SUB_KERNEL_SYSCALL_SENDMSG_0300
223 * @tc.name : SendmsgSuccess_0003
224 * @tc.desc : Sendmsg test success by MSG_NOSIGNAL.
225 * @tc.size : MediumTest
226 * @tc.type : Function
227 * @tc.level : Level 2
228 */
229 HWTEST_F(HatsSendmsgTest, SendmsgSuccess_0003, Function | MediumTest | Level2)
230 {
231 int ret;
232 ssize_t size;
233 pthread_t thread;
234 int acceptFd = -1;
235 int32_t backLog = 5;
236 struct sockaddr_in dstAddr = { 0 };
237 socklen_t addrLen = sizeof(struct sockaddr_in);
238
239 ret = listen(g_serviceFd, backLog);
240 EXPECT_EQ(ret, 0);
241
242 pthread_create(&thread, nullptr, ClientConnect, nullptr);
243 acceptFd = accept4(g_serviceFd, reinterpret_cast<struct sockaddr *>(&dstAddr), &addrLen, 0);
244 EXPECT_TRUE(acceptFd > 0);
245
246 char buf[] = "Hello, world!";
247 struct iovec iov;
248 iov.iov_base = buf;
249 iov.iov_len = sizeof(buf) - 1;
250
251 struct msghdr message;
252 memset_s(&message, sizeof(message), 0, sizeof(message));
253 message.msg_iov = &iov;
254 message.msg_iovlen = 1;
255
256 size = sendmsg(acceptFd, &message, MSG_NOSIGNAL);
257 EXPECT_TRUE(size >= 0);
258
259 close(acceptFd);
260 pthread_join(thread, nullptr);
261 }
262
263 /*
264 * @tc.number : SUB_KERNEL_SYSCALL_SENDMSG_0400
265 * @tc.name : SendmsgSuccess_0004
266 * @tc.desc : Sendmsg test success by MSG_OOB.
267 * @tc.size : MediumTest
268 * @tc.type : Function
269 * @tc.level : Level 2
270 */
271 HWTEST_F(HatsSendmsgTest, SendmsgSuccess_0004, Function | MediumTest | Level2)
272 {
273 int ret;
274 ssize_t size;
275 pthread_t thread;
276 int acceptFd = -1;
277 int32_t backLog = 5;
278 struct sockaddr_in dstAddr = { 0 };
279 socklen_t addrLen = sizeof(struct sockaddr_in);
280
281 ret = listen(g_serviceFd, backLog);
282 EXPECT_EQ(ret, 0);
283
284 pthread_create(&thread, nullptr, ClientConnect, nullptr);
285 acceptFd = accept4(g_serviceFd, reinterpret_cast<struct sockaddr *>(&dstAddr), &addrLen, 0);
286 EXPECT_TRUE(acceptFd > 0);
287
288 char oobData = '!';
289 struct iovec iov;
290 iov.iov_base = &oobData;
291 iov.iov_len = sizeof(oobData);
292
293 struct msghdr message;
294 memset_s(&message, sizeof(message), 0, sizeof(message));
295 message.msg_iov = &iov;
296 message.msg_iovlen = 1;
297
298 size = sendmsg(acceptFd, &message, MSG_OOB);
299 EXPECT_TRUE(size >= 0);
300
301 char normalData[] = "Hello, world!";
302 iov.iov_base = normalData;
303 iov.iov_len = sizeof(normalData) - 1;
304
305 size = sendmsg(acceptFd, &message, 0);
306 EXPECT_TRUE(size >= 0);
307
308 close(acceptFd);
309 pthread_join(thread, nullptr);
310 }