1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 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 <arpa/inet.h> 17 #include <csignal> 18 #include <securec.h> 19 #include <sys/un.h> 20 21 #include "gtest/gtest.h" 22 #include "client/websocket_client.h" 23 #include "server/websocket_server.h" 24 25 using namespace OHOS::ArkCompiler::Toolchain; 26 27 namespace panda::test { 28 class WebSocketTest : public testing::Test { 29 public: SetUpTestCase()30 static void SetUpTestCase() 31 { 32 GTEST_LOG_(INFO) << "SetUpTestCase"; 33 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { 34 GTEST_LOG_(ERROR) << "Reset SIGPIPE failed."; 35 } 36 } 37 TearDownTestCase()38 static void TearDownTestCase() 39 { 40 GTEST_LOG_(INFO) << "TearDownCase"; 41 } 42 SetUp()43 void SetUp() override 44 { 45 } 46 TearDown()47 void TearDown() override 48 { 49 } 50 51 #if defined(OHOS_PLATFORM) 52 static constexpr char UNIX_DOMAIN_PATH_1[] = "server.sock_1"; 53 static constexpr char UNIX_DOMAIN_PATH_2[] = "server.sock_2"; 54 static constexpr char UNIX_DOMAIN_PATH_3[] = "server.sock_3"; 55 #endif 56 static constexpr char HELLO_SERVER[] = "hello server"; 57 static constexpr char HELLO_CLIENT[] = "hello client"; 58 static constexpr char SERVER_OK[] = "server ok"; 59 static constexpr char CLIENT_OK[] = "client ok"; 60 static constexpr char QUIT[] = "quit"; 61 static constexpr char PING[] = "ping"; 62 static constexpr int TCP_PORT = 9230; 63 static const std::string LONG_MSG; 64 static const std::string LONG_LONG_MSG; 65 }; 66 67 const std::string WebSocketTest::LONG_MSG = std::string(1000, 'f'); 68 const std::string WebSocketTest::LONG_LONG_MSG = std::string(0xfffff, 'f'); 69 70 HWTEST_F(WebSocketTest, ConnectWebSocketTest, testing::ext::TestSize.Level0) 71 { 72 WebSocketServer serverSocket; 73 bool ret = false; 74 #if defined(OHOS_PLATFORM) 75 int appPid = getpid(); 76 ret = serverSocket.InitUnixWebSocket(UNIX_DOMAIN_PATH_1 + std::to_string(appPid), 5); 77 #else 78 ret = serverSocket.InitTcpWebSocket(TCP_PORT, 5); 79 #endif 80 ASSERT_TRUE(ret); 81 pid_t pid = fork(); 82 if (pid == 0) { 83 // subprocess, handle client connect and recv/send message 84 // note: EXPECT/ASSERT produce errors in subprocess that can not lead to failure of testcase in mainprocess, 85 // so testcase still success finally. 86 WebSocketClient clientSocket; 87 bool retClient = false; 88 #if defined(OHOS_PLATFORM) 89 retClient = clientSocket.InitToolchainWebSocketForSockName(UNIX_DOMAIN_PATH_1 + std::to_string(appPid), 5); 90 #else 91 retClient = clientSocket.InitToolchainWebSocketForPort(TCP_PORT, 5); 92 #endif 93 ASSERT_TRUE(retClient); 94 retClient = clientSocket.ClientSendWSUpgradeReq(); 95 ASSERT_TRUE(retClient); 96 retClient = clientSocket.ClientRecvWSUpgradeRsp(); 97 ASSERT_TRUE(retClient); 98 retClient = clientSocket.SendReply(HELLO_SERVER); 99 EXPECT_TRUE(retClient); 100 std::string recv = clientSocket.Decode(); 101 EXPECT_EQ(strcmp(recv.c_str(), HELLO_CLIENT), 0); 102 if (strcmp(recv.c_str(), HELLO_CLIENT) == 0) { 103 retClient = clientSocket.SendReply(CLIENT_OK); 104 EXPECT_TRUE(retClient); 105 } 106 retClient = clientSocket.SendReply(LONG_MSG); 107 EXPECT_TRUE(retClient); 108 recv = clientSocket.Decode(); 109 EXPECT_EQ(strcmp(recv.c_str(), SERVER_OK), 0); 110 if (strcmp(recv.c_str(), SERVER_OK) == 0) { 111 retClient = clientSocket.SendReply(CLIENT_OK); 112 EXPECT_TRUE(retClient); 113 } 114 retClient = clientSocket.SendReply(LONG_LONG_MSG); 115 EXPECT_TRUE(retClient); 116 recv = clientSocket.Decode(); 117 EXPECT_EQ(strcmp(recv.c_str(), SERVER_OK), 0); 118 if (strcmp(recv.c_str(), SERVER_OK) == 0) { 119 retClient = clientSocket.SendReply(CLIENT_OK); 120 EXPECT_TRUE(retClient); 121 } 122 retClient = clientSocket.SendReply(PING, FrameType::PING); // send a ping frame and wait for pong frame 123 EXPECT_TRUE(retClient); 124 recv = clientSocket.Decode(); // get the pong frame 125 EXPECT_EQ(strcmp(recv.c_str(), ""), 0); // pong frame has no data 126 retClient = clientSocket.SendReply(QUIT); 127 EXPECT_TRUE(retClient); 128 clientSocket.Close(); 129 exit(0); 130 } else if (pid > 0) { 131 // mainprocess, handle server connect and recv/send message __anonc7ca8bfe0102() 132 auto openCallBack = []() -> void { 133 GTEST_LOG_(INFO) << "ConnectWebSocketTest connection is open."; 134 }; 135 serverSocket.SetOpenConnectionCallback(openCallBack); 136 137 ret = serverSocket.AcceptNewConnection(); 138 ASSERT_TRUE(ret); 139 std::string recv = serverSocket.Decode(); 140 EXPECT_EQ(strcmp(recv.c_str(), HELLO_SERVER), 0); 141 serverSocket.SendReply(HELLO_CLIENT); 142 recv = serverSocket.Decode(); 143 EXPECT_EQ(strcmp(recv.c_str(), CLIENT_OK), 0); 144 recv = serverSocket.Decode(); 145 EXPECT_EQ(strcmp(recv.c_str(), LONG_MSG.c_str()), 0); 146 serverSocket.SendReply(SERVER_OK); 147 recv = serverSocket.Decode(); 148 EXPECT_EQ(strcmp(recv.c_str(), CLIENT_OK), 0); 149 recv = serverSocket.Decode(); 150 EXPECT_EQ(strcmp(recv.c_str(), LONG_LONG_MSG.c_str()), 0); 151 serverSocket.SendReply(SERVER_OK); 152 recv = serverSocket.Decode(); 153 EXPECT_EQ(strcmp(recv.c_str(), CLIENT_OK), 0); 154 recv = serverSocket.Decode(); 155 EXPECT_EQ(strcmp(recv.c_str(), PING), 0); // the ping frame has "PING" and send a pong frame 156 recv = serverSocket.Decode(); 157 EXPECT_EQ(strcmp(recv.c_str(), QUIT), 0); 158 serverSocket.Close(); 159 // sleep ensure that linux os core can really release resource 160 sleep(3); 161 } else { 162 std::cerr << "ConnectWebSocketTest::fork failed, error = " 163 << errno << ", desc = " << strerror(errno) << std::endl; 164 } 165 } 166 167 HWTEST_F(WebSocketTest, ReConnectWebSocketTest, testing::ext::TestSize.Level0) 168 { 169 WebSocketServer serverSocket; 170 bool ret = false; 171 #if defined(OHOS_PLATFORM) 172 int appPid = getpid(); 173 ret = serverSocket.InitUnixWebSocket(UNIX_DOMAIN_PATH_2 + std::to_string(appPid), 5); 174 #else 175 ret = serverSocket.InitTcpWebSocket(TCP_PORT, 5); 176 #endif 177 ASSERT_TRUE(ret); 178 for (int i = 0; i < 5; i++) { 179 pid_t pid = fork(); 180 if (pid == 0) { 181 // subprocess, handle client connect and recv/send message 182 // note: EXPECT/ASSERT produce errors in subprocess that can not lead to failure of testcase in mainprocess, 183 // so testcase still success finally. 184 WebSocketClient clientSocket; 185 bool retClient = false; 186 #if defined(OHOS_PLATFORM) 187 retClient = clientSocket.InitToolchainWebSocketForSockName(UNIX_DOMAIN_PATH_2 + std::to_string(appPid), 5); 188 #else 189 retClient = clientSocket.InitToolchainWebSocketForPort(TCP_PORT, 5); 190 #endif 191 ASSERT_TRUE(retClient); 192 retClient = clientSocket.ClientSendWSUpgradeReq(); 193 ASSERT_TRUE(retClient); 194 retClient = clientSocket.ClientRecvWSUpgradeRsp(); 195 ASSERT_TRUE(retClient); 196 retClient = clientSocket.SendReply(HELLO_SERVER + std::to_string(i)); 197 EXPECT_TRUE(retClient); 198 std::string recv = clientSocket.Decode(); 199 EXPECT_EQ(strcmp(recv.c_str(), (HELLO_CLIENT + std::to_string(i)).c_str()), 0); 200 if (strcmp(recv.c_str(), (HELLO_CLIENT + std::to_string(i)).c_str()) == 0) { 201 retClient = clientSocket.SendReply(CLIENT_OK + std::to_string(i)); 202 EXPECT_TRUE(retClient); 203 } 204 clientSocket.Close(); 205 exit(0); 206 } else if (pid > 0) { 207 // mainprocess, handle server connect and recv/send message 208 ret = serverSocket.AcceptNewConnection(); 209 ASSERT_TRUE(ret); 210 std::string recv = serverSocket.Decode(); 211 EXPECT_EQ(strcmp(recv.c_str(), (HELLO_SERVER + std::to_string(i)).c_str()), 0); 212 serverSocket.SendReply(HELLO_CLIENT + std::to_string(i)); 213 recv = serverSocket.Decode(); 214 EXPECT_EQ(strcmp(recv.c_str(), (CLIENT_OK + std::to_string(i)).c_str()), 0); 215 while (serverSocket.IsConnected()) { 216 serverSocket.Decode(); 217 } 218 } else { 219 std::cerr << "ReConnectWebSocketTest::fork failed, error = " 220 << errno << ", desc = " << strerror(errno) << std::endl; 221 } 222 } 223 serverSocket.Close(); 224 sleep(3); 225 } 226 227 HWTEST_F(WebSocketTest, ClientAbnormalTest, testing::ext::TestSize.Level0) 228 { 229 WebSocketClient clientSocket; 230 ASSERT_STREQ(clientSocket.GetSocketStateString().c_str(), "closed"); 231 ASSERT_FALSE(clientSocket.ClientSendWSUpgradeReq()); 232 ASSERT_FALSE(clientSocket.ClientRecvWSUpgradeRsp()); 233 ASSERT_FALSE(clientSocket.SendReply(HELLO_SERVER)); 234 } 235 236 HWTEST_F(WebSocketTest, ServerAbnormalTest, testing::ext::TestSize.Level0) 237 { 238 WebSocketServer serverSocket; 239 // No connection established, the function returns directly. 240 serverSocket.Close(); 241 ASSERT_FALSE(serverSocket.AcceptNewConnection()); 242 243 #if defined(OHOS_PLATFORM) 244 int appPid = getpid(); 245 ASSERT_TRUE(serverSocket.InitUnixWebSocket(UNIX_DOMAIN_PATH_3 + std::to_string(appPid), 5)); 246 #else 247 ASSERT_TRUE(serverSocket.InitTcpWebSocket(TCP_PORT, 5)); 248 #endif 249 pid_t pid = fork(); 250 if (pid == 0) { 251 WebSocketClient clientSocket; __anonc7ca8bfe0202() 252 auto closeCallBack = []() -> void { 253 GTEST_LOG_(INFO) << "ServerAbnormalTest client connection is closed."; 254 }; 255 clientSocket.SetCloseConnectionCallback(closeCallBack); 256 257 #if defined(OHOS_PLATFORM) 258 ASSERT_TRUE(clientSocket.InitToolchainWebSocketForSockName(UNIX_DOMAIN_PATH_3 + std::to_string(appPid), 5)); 259 // state is not UNITED, the function returns directly. 260 ASSERT_TRUE(clientSocket.InitToolchainWebSocketForSockName(UNIX_DOMAIN_PATH_3 + std::to_string(appPid), 5)); 261 #else 262 ASSERT_TRUE(clientSocket.InitToolchainWebSocketForPort(TCP_PORT, 5)); 263 // state is not UNITED, the function returns directly. 264 ASSERT_TRUE(clientSocket.InitToolchainWebSocketForPort(TCP_PORT, 5)); 265 #endif 266 ASSERT_TRUE(clientSocket.ClientSendWSUpgradeReq()); 267 ASSERT_FALSE(clientSocket.ClientRecvWSUpgradeRsp()); 268 exit(0); 269 } else if (pid > 0) { __anonc7ca8bfe0302() 270 auto failCallBack = []() -> void { 271 GTEST_LOG_(INFO) << "ServerAbnormalTest server connection is failed."; 272 }; 273 serverSocket.SetFailConnectionCallback(failCallBack); __anonc7ca8bfe0402(const HttpRequest&) 274 auto notValidCallBack = [](const HttpRequest&) -> bool { 275 GTEST_LOG_(INFO) << "ServerAbnormalTest server connection request is not valid."; 276 return false; 277 }; 278 serverSocket.SetValidateConnectionCallback(notValidCallBack); 279 ASSERT_FALSE(serverSocket.AcceptNewConnection()); 280 sleep(3); 281 } else { 282 std::cerr << "ServerAbnormalTest::fork failed, error = " 283 << errno << ", desc = " << strerror(errno) << std::endl; 284 } 285 } 286 } // namespace panda::test