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 "securec.h"
30
31 using namespace testing::ext;
32
33 class HatsAccept4Test : public testing::Test {
34 public:
35 static void SetUpTestCase();
36 static void TearDownTestCase();
37 void SetUp();
38 void TearDown();
39 private:
40 };
SetUp()41 void HatsAccept4Test::SetUp()
42 {
43 }
TearDown()44 void HatsAccept4Test::TearDown()
45 {
46 }
SetUpTestCase()47 void HatsAccept4Test::SetUpTestCase()
48 {
49 }
TearDownTestCase()50 void HatsAccept4Test::TearDownTestCase()
51 {
52 }
53
54 static const int BAD_SOCKET_FD = -1;
55 static const int TEST_PORT = 21357;
56 static const char *TEST_LOCAL_IP = "127.0.0.1";
57
58 enum AcceptType {
59 GET_NONE = 0,
60 GET_CLIENT_SOCKET_ADDR_TEST,
61 GET_CLIENT_SOCKET_ADDR_LEN_TEST,
62 };
63
SocketServiceStart(int * fd)64 static void SocketServiceStart(int *fd)
65 {
66 int ret;
67 int socketFd = -1;
68 int32_t backLog = 2;
69 int32_t optVal = 1;
70 struct sockaddr_in serAddr = {
71 .sin_family = AF_INET,
72 .sin_port = htons(TEST_PORT),
73 .sin_addr = {
74 .s_addr = inet_addr(TEST_LOCAL_IP),
75 }
76 };
77
78 socketFd = socket(AF_INET, SOCK_STREAM, 0);
79 ASSERT_TRUE(socketFd > 0);
80
81 ret = setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
82 ASSERT_TRUE(ret == 0);
83
84 ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
85 ASSERT_TRUE(ret == 0);
86
87 ret = listen(socketFd, backLog);
88 ASSERT_EQ(ret, 0);
89
90 *fd = socketFd;
91 }
92
ClientConnect(void * arg)93 static void *ClientConnect(void *arg)
94 {
95 int ret;
96 int socketFd = -1;
97 struct sockaddr_in serAddr = {
98 .sin_family = AF_INET,
99 .sin_port = htons(TEST_PORT),
100 .sin_addr = {
101 .s_addr = inet_addr(TEST_LOCAL_IP),
102 }
103 };
104 socketFd = socket(AF_INET, SOCK_STREAM, 0);
105 EXPECT_TRUE(socketFd > 0);
106 ret = connect(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in));
107 EXPECT_EQ(ret, 0);
108 close(socketFd);
109 return nullptr;
110 }
111
112 /*
113 * @tc.number : SUB_KERNEL_SYSCALL_ACCEPT4_0100
114 * @tc.name : Accept4ValidSockfdSuccess_0001
115 * @tc.desc : accept4 valid sockfd success.
116 * @tc.size : MediumTest
117 * @tc.type : Function
118 * @tc.level : Level 1
119 */
120 HWTEST_F(HatsAccept4Test, Accept4ValidSockfdSuccess_0001, Function | MediumTest | Level1)
121 {
122 int pid = -1;
123 int socketFd = -1;
124 int acceptFd = -1;
125 int status = 0;
126 struct sockaddr_in cliAddr;
127 socklen_t addrlen = sizeof(struct sockaddr_in);
128 SocketServiceStart(&socketFd);
129 ASSERT_TRUE(socketFd > 0);
130 if ((pid = fork()) == 0) {
131 ClientConnect(nullptr);
132 exit(0);
133 }
134 acceptFd = accept4(socketFd, reinterpret_cast<struct sockaddr *>(&cliAddr), &addrlen, 0);
135 EXPECT_TRUE(acceptFd > 0);
136
137 close(acceptFd);
138 close(socketFd);
139 waitpid(pid, &status, 0);
140 EXPECT_TRUE(status == 0);
141 }
142
143 /*
144 * @tc.number : SUB_KERNEL_SYSCALL_ACCEPT4_0200
145 * @tc.name : Accept4GetClientAddrSuccess_0002
146 * @tc.desc : accept4 get client addr success.
147 * @tc.size : MediumTest
148 * @tc.type : Function
149 * @tc.level : Level 1
150 */
151 HWTEST_F(HatsAccept4Test, Accept4GetClientAddrSuccess_0002, Function | MediumTest | Level1)
152 {
153 int pid = -1;
154 int acceptFd = -1;
155 int socketFd = -1;
156 int status = 0;
157 struct sockaddr_in cliAddr = { 0 };
158 socklen_t addrlen = sizeof(struct sockaddr_in);
159 SocketServiceStart(&socketFd);
160 ASSERT_TRUE(socketFd > 0);
161 if ((pid = fork()) == 0) {
162 ClientConnect(nullptr);
163 exit(0);
164 }
165 acceptFd = accept4(socketFd, reinterpret_cast<struct sockaddr *>(&cliAddr), &addrlen, 0);
166 EXPECT_STREQ(inet_ntoa(cliAddr.sin_addr), TEST_LOCAL_IP);
167 close(acceptFd);
168 close(socketFd);
169 waitpid(pid, &status, 0);
170 EXPECT_TRUE(status == 0);
171 }
172
173 /*
174 * @tc.number : SUB_KERNEL_SYSCALL_ACCEPT4_0300
175 * @tc.name : Accept4GetClientAddrSuccess_0003
176 * @tc.desc : accept4 get client addr len success.
177 * @tc.size : MediumTest
178 * @tc.type : Function
179 * @tc.level : Level 1
180 */
181 HWTEST_F(HatsAccept4Test, Accept4GetClientAddrSuccess_0003, Function | MediumTest | Level1)
182 {
183 int pid = -1;
184 int acceptFd = -1;
185 int socketFd = -1;
186 int status = 0;
187 struct sockaddr_in cliAddr = { 0 };
188 socklen_t addrlen = sizeof(struct sockaddr_in);
189 SocketServiceStart(&socketFd);
190 ASSERT_TRUE(socketFd > 0);
191 if ((pid = fork()) == 0) {
192 ClientConnect(nullptr);
193 exit(0);
194 }
195 acceptFd = accept4(socketFd, reinterpret_cast<struct sockaddr *>(&cliAddr), &addrlen, 0);
196 EXPECT_EQ(addrlen, sizeof(struct sockaddr));
197 close(acceptFd);
198 close(socketFd);
199 waitpid(pid, &status, 0);
200 EXPECT_TRUE(status == 0);
201 }
202
203 /*
204 * @tc.number : SUB_KERNEL_SYSCALL_ACCEPT4_0400
205 * @tc.name : Accept4InvalidFd_0004
206 * @tc.desc : accept4 use invalid socket fd, return -1, and set errno.
207 * @tc.size : MediumTest
208 * @tc.type : Function
209 * @tc.level : Level 2
210 */
211 HWTEST_F(HatsAccept4Test, Accept4InvalidFd_0004, Function | MediumTest | Level2)
212 {
213 int ret = accept4(BAD_SOCKET_FD, nullptr, nullptr, 0);
214 EXPECT_EQ(ret, -1);
215 EXPECT_EQ(errno, EBADF);
216 ret = accept4(STDIN_FILENO, nullptr, nullptr, 0);
217 EXPECT_EQ(ret, -1);
218 EXPECT_EQ(errno, ENOTSOCK);
219 }
220
221 /*
222 * @tc.number : SUB_KERNEL_SYSCALL_ACCEPT4_0500
223 * @tc.name : Accept4FlagTestSuccess_0005
224 * @tc.desc : accept4 flag SOCK_NONBLOCK and SOCK_CLOEXEC test success.
225 * @tc.size : MediumTest
226 * @tc.type : Function
227 * @tc.level : Level 1
228 */
229 HWTEST_F(HatsAccept4Test, Accept4FlagTestSuccess_0005, Function | MediumTest | Level1)
230 {
231 int socketFd = -1;
232 int acceptFd = -1;
233 pthread_t thread;
234 struct sockaddr_in cliAddr;
235 socklen_t addrlen = sizeof(struct sockaddr_in);
236 SocketServiceStart(&socketFd);
237 ASSERT_TRUE(socketFd > 0);
238
239 pthread_create(&thread, nullptr, ClientConnect, nullptr);
240 acceptFd = accept4(socketFd, reinterpret_cast<struct sockaddr *>(&cliAddr), &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
241 EXPECT_TRUE(acceptFd > 0);
242
243 close(acceptFd);
244 close(socketFd);
245 pthread_join(thread, nullptr);
246 }
247