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