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 <securec.h> 18 #include <sys/un.h> 19 20 #include "gtest/gtest.h" 21 #include "websocket/client/websocket_client.h" 22 #include "websocket/server/websocket_server.h" 23 24 using namespace OHOS::ArkCompiler::Toolchain; 25 26 namespace panda::test { 27 class WebSocketTest : public testing::Test { 28 public: SetUpTestCase()29 static void SetUpTestCase() 30 { 31 GTEST_LOG_(INFO) << "SetUpTestCase"; 32 } 33 TearDownTestCase()34 static void TearDownTestCase() 35 { 36 GTEST_LOG_(INFO) << "TearDownCase"; 37 } 38 SetUp()39 void SetUp() override 40 { 41 } 42 TearDown()43 void TearDown() override 44 { 45 } 46 47 #if defined(OHOS_PLATFORM) 48 static constexpr char UNIX_DOMAIN_PATH[] = "server.sock"; 49 #endif 50 static constexpr char HELLO_SERVER[] = "hello server"; 51 static constexpr char HELLO_CLIENT[] = "hello client"; 52 static constexpr char SERVER_OK[] = "server ok"; 53 static constexpr char CLIENT_OK[] = "client ok"; 54 static constexpr char QUIT[] = "quit"; 55 static constexpr char PING[] = "ping"; 56 static constexpr int TCP_PORT = 9230; 57 static const std::string LONG_MSG; 58 static const std::string LONG_LONG_MSG; 59 }; 60 61 const std::string WebSocketTest::LONG_MSG = std::string(1000, 'f'); 62 const std::string WebSocketTest::LONG_LONG_MSG = std::string(0xfffff, 'f'); 63 64 HWTEST_F(WebSocketTest, ConnectWebSocketTest, testing::ext::TestSize.Level0) 65 { 66 WebSocketServer serverSocket; 67 bool ret = false; 68 #if defined(OHOS_PLATFORM) 69 int appPid = getpid(); 70 ret = serverSocket.InitUnixWebSocket(UNIX_DOMAIN_PATH + std::to_string(appPid), 5); 71 #else 72 ret = serverSocket.InitTcpWebSocket(TCP_PORT, 5); 73 #endif 74 ASSERT_TRUE(ret); 75 pid_t pid = fork(); 76 if (pid == 0) { 77 // subprocess, handle client connect and recv/send message 78 // note: EXPECT/ASSERT produce errors in subprocess that can not lead to failure of testcase in mainprocess, 79 // so testcase still success finally. 80 WebSocketClient clientSocket; 81 bool retClient = false; 82 #if defined(OHOS_PLATFORM) 83 retClient = clientSocket.InitToolchainWebSocketForSockName(UNIX_DOMAIN_PATH + std::to_string(appPid), 5); 84 #else 85 retClient = clientSocket.InitToolchainWebSocketForPort(TCP_PORT, 5); 86 #endif 87 ASSERT_TRUE(retClient); 88 retClient = clientSocket.ClientSendWSUpgradeReq(); 89 ASSERT_TRUE(retClient); 90 retClient = clientSocket.ClientRecvWSUpgradeRsp(); 91 ASSERT_TRUE(retClient); 92 retClient = clientSocket.SendReply(HELLO_SERVER); 93 EXPECT_TRUE(retClient); 94 std::string recv = clientSocket.Decode(); 95 EXPECT_EQ(strcmp(recv.c_str(), HELLO_CLIENT), 0); 96 if (strcmp(recv.c_str(), HELLO_CLIENT) == 0) { 97 retClient = clientSocket.SendReply(CLIENT_OK); 98 EXPECT_TRUE(retClient); 99 } 100 retClient = clientSocket.SendReply(LONG_MSG); 101 EXPECT_TRUE(retClient); 102 recv = clientSocket.Decode(); 103 EXPECT_EQ(strcmp(recv.c_str(), SERVER_OK), 0); 104 if (strcmp(recv.c_str(), SERVER_OK) == 0) { 105 retClient = clientSocket.SendReply(CLIENT_OK); 106 EXPECT_TRUE(retClient); 107 } 108 retClient = clientSocket.SendReply(LONG_LONG_MSG); 109 EXPECT_TRUE(retClient); 110 recv = clientSocket.Decode(); 111 EXPECT_EQ(strcmp(recv.c_str(), SERVER_OK), 0); 112 if (strcmp(recv.c_str(), SERVER_OK) == 0) { 113 retClient = clientSocket.SendReply(CLIENT_OK); 114 EXPECT_TRUE(retClient); 115 } 116 retClient = clientSocket.SendReply(PING, FrameType::PING); // send a ping frame and wait for pong frame 117 EXPECT_TRUE(retClient); 118 recv = clientSocket.Decode(); // get the pong frame 119 EXPECT_EQ(strcmp(recv.c_str(), ""), 0); // pong frame has no data 120 retClient = clientSocket.SendReply(QUIT); 121 EXPECT_TRUE(retClient); 122 clientSocket.Close(); 123 exit(0); 124 } else if (pid > 0) { 125 // mainprocess, handle server connect and recv/send message 126 ret = serverSocket.AcceptNewConnection(); 127 ASSERT_TRUE(ret); 128 std::string recv = serverSocket.Decode(); 129 EXPECT_EQ(strcmp(recv.c_str(), HELLO_SERVER), 0); 130 serverSocket.SendReply(HELLO_CLIENT); 131 recv = serverSocket.Decode(); 132 EXPECT_EQ(strcmp(recv.c_str(), CLIENT_OK), 0); 133 recv = serverSocket.Decode(); 134 EXPECT_EQ(strcmp(recv.c_str(), LONG_MSG.c_str()), 0); 135 serverSocket.SendReply(SERVER_OK); 136 recv = serverSocket.Decode(); 137 EXPECT_EQ(strcmp(recv.c_str(), CLIENT_OK), 0); 138 recv = serverSocket.Decode(); 139 EXPECT_EQ(strcmp(recv.c_str(), LONG_LONG_MSG.c_str()), 0); 140 serverSocket.SendReply(SERVER_OK); 141 recv = serverSocket.Decode(); 142 EXPECT_EQ(strcmp(recv.c_str(), CLIENT_OK), 0); 143 recv = serverSocket.Decode(); 144 EXPECT_EQ(strcmp(recv.c_str(), PING), 0); // the ping frame has "PING" and send a pong frame 145 recv = serverSocket.Decode(); 146 EXPECT_EQ(strcmp(recv.c_str(), QUIT), 0); 147 serverSocket.Close(); 148 // sleep ensure that linux os core can really release resource 149 sleep(3); 150 } else { 151 std::cerr << "ConnectWebSocketTest::fork failed, error = " 152 << errno << ", desc = " << strerror(errno) << std::endl; 153 } 154 } 155 156 HWTEST_F(WebSocketTest, ReConnectWebSocketTest, testing::ext::TestSize.Level0) 157 { 158 WebSocketServer serverSocket; 159 bool ret = false; 160 #if defined(OHOS_PLATFORM) 161 int appPid = getpid(); 162 ret = serverSocket.InitUnixWebSocket(UNIX_DOMAIN_PATH + std::to_string(appPid), 5); 163 #else 164 ret = serverSocket.InitTcpWebSocket(TCP_PORT, 5); 165 #endif 166 ASSERT_TRUE(ret); 167 for (int i = 0; i < 5; i++) { 168 pid_t pid = fork(); 169 if (pid == 0) { 170 // subprocess, handle client connect and recv/send message 171 // note: EXPECT/ASSERT produce errors in subprocess that can not lead to failure of testcase in mainprocess, 172 // so testcase still success finally. 173 WebSocketClient clientSocket; 174 bool retClient = false; 175 #if defined(OHOS_PLATFORM) 176 retClient = clientSocket.InitToolchainWebSocketForSockName(UNIX_DOMAIN_PATH + std::to_string(appPid), 5); 177 #else 178 retClient = clientSocket.InitToolchainWebSocketForPort(TCP_PORT, 5); 179 #endif 180 ASSERT_TRUE(retClient); 181 retClient = clientSocket.ClientSendWSUpgradeReq(); 182 ASSERT_TRUE(retClient); 183 retClient = clientSocket.ClientRecvWSUpgradeRsp(); 184 ASSERT_TRUE(retClient); 185 retClient = clientSocket.SendReply(HELLO_SERVER + std::to_string(i)); 186 EXPECT_TRUE(retClient); 187 std::string recv = clientSocket.Decode(); 188 EXPECT_EQ(strcmp(recv.c_str(), (HELLO_CLIENT + std::to_string(i)).c_str()), 0); 189 if (strcmp(recv.c_str(), (HELLO_CLIENT + std::to_string(i)).c_str()) == 0) { 190 retClient = clientSocket.SendReply(CLIENT_OK + std::to_string(i)); 191 EXPECT_TRUE(retClient); 192 } 193 clientSocket.Close(); 194 exit(0); 195 } else if (pid > 0) { 196 // mainprocess, handle server connect and recv/send message 197 ret = serverSocket.AcceptNewConnection(); 198 ASSERT_TRUE(ret); 199 std::string recv = serverSocket.Decode(); 200 EXPECT_EQ(strcmp(recv.c_str(), (HELLO_SERVER + std::to_string(i)).c_str()), 0); 201 serverSocket.SendReply(HELLO_CLIENT + std::to_string(i)); 202 recv = serverSocket.Decode(); 203 EXPECT_EQ(strcmp(recv.c_str(), (CLIENT_OK + std::to_string(i)).c_str()), 0); 204 while (serverSocket.IsConnected()) { 205 serverSocket.Decode(); 206 } 207 } else { 208 std::cerr << "ReConnectWebSocketTest::fork failed, error = " 209 << errno << ", desc = " << strerror(errno) << std::endl; 210 } 211 } 212 serverSocket.Close(); 213 } 214 } // namespace panda::test