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 31using namespace testing::ext; 32 33class HatsAccept4Test : public testing::Test { 34public: 35 static void SetUpTestCase(); 36 static void TearDownTestCase(); 37 void SetUp(); 38 void TearDown(); 39private: 40}; 41void HatsAccept4Test::SetUp() 42{ 43} 44void HatsAccept4Test::TearDown() 45{ 46} 47void HatsAccept4Test::SetUpTestCase() 48{ 49} 50void HatsAccept4Test::TearDownTestCase() 51{ 52} 53 54static const int BAD_SOCKET_FD = -1; 55static const int TEST_PORT = 21357; 56static const char *TEST_LOCAL_IP = "127.0.0.1"; 57 58enum AcceptType { 59 GET_NONE = 0, 60 GET_CLIENT_SOCKET_ADDR_TEST, 61 GET_CLIENT_SOCKET_ADDR_LEN_TEST, 62}; 63 64static 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 93static 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 */ 120HWTEST_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 */ 151HWTEST_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 */ 181HWTEST_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 */ 211HWTEST_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 */ 229HWTEST_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