• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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