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 static const int TEST_PORT = 21355;
34 static const int TEST_BAD_PORT = 21354;
35 static const int BAD_SOCKET_FD = -1;
36 static const char *TEST_LOCAL_IP = "127.0.0.1";
37 static int g_serviceFd = -1;
38
39 class HatsConnectTest : 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 HatsConnectTest::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 HatsConnectTest::TearDown()
72 {
73 close(g_serviceFd);
74 g_serviceFd = -1;
75 }
SetUpTestCase()76 void HatsConnectTest::SetUpTestCase()
77 {
78 }
TearDownTestCase()79 void HatsConnectTest::TearDownTestCase()
80 {
81 }
82
83 /*
84 * @tc.number : SUB_KERNEL_SYSCALL_CONNECT_0100
85 * @tc.name : ConnectServiceSuccess_0001
86 * @tc.desc : connect to local service success.
87 * @tc.size : MediumTest
88 * @tc.type : Function
89 * @tc.level : Level 1
90 */
HWTEST_F(HatsConnectTest, ConnectServiceSuccess_0001, Function | MediumTest | Level1)91 HWTEST_F(HatsConnectTest, ConnectServiceSuccess_0001, Function | MediumTest | Level1)
92 {
93 int ret;
94 int socketFd = -1;
95 int32_t backLog = 5;
96 struct sockaddr_in serAddr = {
97 .sin_family = AF_INET,
98 .sin_port = htons(TEST_PORT),
99 .sin_addr = {
100 .s_addr = inet_addr(TEST_LOCAL_IP),
101 }
102 };
103 ret = listen(g_serviceFd, backLog);
104 ASSERT_EQ(ret, 0);
105
106 socketFd = socket(AF_INET, SOCK_STREAM, 0);
107 EXPECT_TRUE(socketFd > 0);
108
109 errno = 0;
110 ret = connect(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in));
111 EXPECT_EQ(ret, 0);
112 EXPECT_EQ(errno, 0);
113 close(socketFd);
114 }
115
116 /*
117 * @tc.number : SUB_KERNEL_SYSCALL_CONNECT_0200
118 * @tc.name : ConnectUseInvalidFdFailed_0002
119 * @tc.desc : connect to service use invalid socket fd failed.
120 * @tc.size : MediumTest
121 * @tc.type : Function
122 * @tc.level : Level 1
123 */
HWTEST_F(HatsConnectTest, ConnectUseInvalidFdFailed_0002, Function | MediumTest | Level1)124 HWTEST_F(HatsConnectTest, ConnectUseInvalidFdFailed_0002, Function | MediumTest | Level1)
125 {
126 int ret;
127 int socketFd = -1;
128 int32_t backLog = 5;
129 struct sockaddr_in serAddr = {
130 .sin_family = AF_INET,
131 .sin_port = htons(TEST_PORT),
132 .sin_addr = {
133 .s_addr = inet_addr(TEST_LOCAL_IP),
134 }
135 };
136 ret = listen(g_serviceFd, backLog);
137 ASSERT_EQ(ret, 0);
138
139 errno = 0;
140 ret = connect(BAD_SOCKET_FD, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in));
141 EXPECT_EQ(ret, -1);
142 EXPECT_EQ(errno, EBADF);
143
144 errno = 0;
145 ret = connect(STDIN_FILENO, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in));
146 EXPECT_EQ(ret, -1);
147 EXPECT_EQ(errno, ENOTSOCK);
148 close(socketFd);
149 }
150
151 /*
152 * @tc.number : SUB_KERNEL_SYSCALL_CONNECT_0300
153 * @tc.name : ConnectUseServiceFdFailed_0003
154 * @tc.desc : client connect use service socket fd, errno EISCONN.
155 * @tc.size : MediumTest
156 * @tc.type : Function
157 * @tc.level : Level 2
158 */
HWTEST_F(HatsConnectTest, ConnectUseServiceFdFailed_0003, Function | MediumTest | Level2)159 HWTEST_F(HatsConnectTest, ConnectUseServiceFdFailed_0003, Function | MediumTest | Level2)
160 {
161 int ret;
162 int32_t backLog = 5;
163 struct sockaddr_in serAddr = {
164 .sin_family = AF_INET,
165 .sin_port = htons(TEST_PORT),
166 .sin_addr = {
167 .s_addr = inet_addr(TEST_LOCAL_IP),
168 }
169 };
170 ret = listen(g_serviceFd, backLog);
171 ASSERT_EQ(ret, 0);
172
173 errno = 0;
174 ret = connect(g_serviceFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in));
175 EXPECT_EQ(ret, -1);
176 EXPECT_EQ(errno, EISCONN);
177 }
178
179 /*
180 * @tc.number : SUB_KERNEL_SYSCALL_CONNECT_0400
181 * @tc.name : ConnectNoListenFdFailed_0004
182 * @tc.desc : connect to socket fd which does not listen, errno ECONNREFUSED.
183 * @tc.size : MediumTest
184 * @tc.type : Function
185 * @tc.level : Level 2
186 */
HWTEST_F(HatsConnectTest, ConnectNoListenFdFailed_0004, Function | MediumTest | Level2)187 HWTEST_F(HatsConnectTest, ConnectNoListenFdFailed_0004, Function | MediumTest | Level2)
188 {
189 int ret;
190 int socketFd = -1;
191 struct sockaddr_in serAddr = {
192 .sin_family = AF_INET,
193 .sin_port = htons(TEST_PORT),
194 .sin_addr = {
195 .s_addr = inet_addr(TEST_LOCAL_IP),
196 }
197 };
198
199 socketFd = socket(AF_INET, SOCK_STREAM, 0);
200 EXPECT_TRUE(socketFd > 0);
201
202 errno = 0;
203 ret = connect(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in));
204 EXPECT_EQ(ret, -1);
205 EXPECT_EQ(errno, ECONNREFUSED);
206 close(socketFd);
207 }
208
209 /*
210 * @tc.number : SUB_KERNEL_SYSCALL_CONNECT_0500
211 * @tc.name : ConnectUseNullAddrFailed_0005
212 * @tc.desc : connect to nullptr addr, errno EFAULT.
213 * @tc.size : MediumTest
214 * @tc.type : Function
215 * @tc.level : Level 2
216 */
HWTEST_F(HatsConnectTest, ConnectUseNullAddrFailed_0005, Function | MediumTest | Level2)217 HWTEST_F(HatsConnectTest, ConnectUseNullAddrFailed_0005, Function | MediumTest | Level2)
218 {
219 int ret;
220 int socketFd = -1;
221 int32_t backLog = 5;
222 ret = listen(g_serviceFd, backLog);
223 ASSERT_EQ(ret, 0);
224
225 socketFd = socket(AF_INET, SOCK_STREAM, 0);
226 EXPECT_TRUE(socketFd > 0);
227
228 errno = 0;
229 ret = connect(socketFd, nullptr, sizeof(struct sockaddr_in));
230 EXPECT_EQ(ret, -1);
231 EXPECT_EQ(errno, EFAULT);
232 close(socketFd);
233 }
234
235 /*
236 * @tc.number : SUB_KERNEL_SYSCALL_CONNECT_0600
237 * @tc.name : ConnectWithErrorPortFailed_0006
238 * @tc.desc : connect to service using error port, errno ECONNREFUSED.
239 * @tc.size : MediumTest
240 * @tc.type : Function
241 * @tc.level : Level 2
242 */
HWTEST_F(HatsConnectTest, ConnectWithErrorPortFailed_0006, Function | MediumTest | Level2)243 HWTEST_F(HatsConnectTest, ConnectWithErrorPortFailed_0006, Function | MediumTest | Level2)
244 {
245 int ret;
246 int socketFd = -1;
247 int32_t backLog = 5;
248 struct sockaddr_in serAddr = {
249 .sin_family = AF_INET,
250 .sin_port = htons(TEST_BAD_PORT),
251 .sin_addr = {
252 .s_addr = inet_addr(TEST_LOCAL_IP),
253 }
254 };
255 ret = listen(g_serviceFd, backLog);
256 ASSERT_EQ(ret, 0);
257
258 socketFd = socket(AF_INET, SOCK_STREAM, 0);
259 EXPECT_TRUE(socketFd > 0);
260
261 errno = 0;
262 ret = connect(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in));
263 EXPECT_EQ(ret, -1);
264 EXPECT_EQ(errno, ECONNREFUSED);
265
266 close(socketFd);
267 }
268
269 /*
270 * @tc.number : SUB_KERNEL_SYSCALL_CONNECT_0700
271 * @tc.name : ConnectTestAddrLen_0007
272 * @tc.desc : connect user addr len >= sizeof(serAddr) success, otherwise errno EINVAL.
273 * @tc.size : MediumTest
274 * @tc.type : Function
275 * @tc.level : Level 2
276 */
HWTEST_F(HatsConnectTest, ConnectTestAddrLen_0007, Function | MediumTest | Level2)277 HWTEST_F(HatsConnectTest, ConnectTestAddrLen_0007, Function | MediumTest | Level2)
278 {
279 int ret;
280 int socketFd = -1;
281 int32_t backLog = 5;
282 struct sockaddr_in serAddr = {
283 .sin_family = AF_INET,
284 .sin_port = htons(TEST_PORT),
285 .sin_addr = {
286 .s_addr = inet_addr(TEST_LOCAL_IP),
287 }
288 };
289 ret = listen(g_serviceFd, backLog);
290 ASSERT_EQ(ret, 0);
291
292 socketFd = socket(AF_INET, SOCK_STREAM, 0);
293 EXPECT_TRUE(socketFd > 0);
294
295 errno = 0;
296 ret = connect(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in) - 1);
297 EXPECT_EQ(ret, -1);
298 EXPECT_EQ(errno, EINVAL);
299
300 errno = 0;
301 ret = connect(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in) + 1);
302 EXPECT_EQ(ret, 0);
303 EXPECT_EQ(errno, 0);
304 close(socketFd);
305 }
306