156 lines · cpp
1//===-- RNBSocketTest.cpp -------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "gtest/gtest.h"10 11#include <arpa/inet.h>12#include <sys/sysctl.h>13#include <unistd.h>14 15#include "RNBDefs.h"16#include "RNBSocket.h"17#include "lldb/Host/Socket.h"18#include "lldb/Host/common/TCPSocket.h"19#include "llvm/Testing/Support/Error.h"20 21using namespace lldb_private;22 23std::string hello = "Hello, world!";24std::string goodbye = "Goodbye!";25 26static void ServerCallbackv4(const void *baton, in_port_t port) {27 auto child_pid = fork();28 if (child_pid == 0) {29 std::string addr_buffer =30 llvm::formatv("{0}:{1}", (const char *)baton, port).str();31 llvm::Expected<std::unique_ptr<Socket>> socket_or_err =32 Socket::TcpConnect(addr_buffer);33 ASSERT_THAT_EXPECTED(socket_or_err, llvm::Succeeded());34 Socket *client_socket = socket_or_err->get();35 36 char buffer[32];37 size_t read_size = 32;38 Status err = client_socket->Read((void *)&buffer[0], read_size);39 if (err.Fail())40 abort();41 std::string Recv(&buffer[0], read_size);42 if (Recv != hello)43 abort();44 size_t write_size = goodbye.length();45 err = client_socket->Write(goodbye.c_str(), write_size);46 if (err.Fail())47 abort();48 if (write_size != goodbye.length())49 abort();50 delete client_socket;51 exit(0);52 }53}54 55void TestSocketListen(const char *addr) {56 // Skip IPv6 tests if there isn't a valid interafce57 auto addresses = lldb_private::SocketAddress::GetAddressInfo(58 addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);59 if (addresses.size() == 0)60 return;61 62 const char *fmt = addresses.front().GetFamily() == AF_INET6 ? "[{0}]" : "{0}";63 std::string addr_wrap = llvm::formatv(fmt, addr).str();64 65 RNBSocket server_socket;66 auto result = server_socket.Listen(addr, 0, ServerCallbackv4,67 (const void *)addr_wrap.c_str());68 ASSERT_TRUE(result == rnb_success);69 result = server_socket.Write(hello.c_str(), hello.length());70 ASSERT_TRUE(result == rnb_success);71 std::string bye;72 result = server_socket.Read(bye);73 ASSERT_TRUE(result == rnb_success);74 ASSERT_EQ(bye, goodbye);75 76 int exit_status;77 wait(&exit_status);78 ASSERT_EQ(exit_status, 0);79}80 81TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); }82 83TEST(RNBSocket, LoopBackListenIPv6) { TestSocketListen("::1"); }84 85TEST(RNBSocket, AnyListen) { TestSocketListen("*"); }86 87void TestSocketConnect(const char *addr) {88 // Skip IPv6 tests if there isn't a valid interafce89 auto addresses = lldb_private::SocketAddress::GetAddressInfo(90 addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);91 if (addresses.size() == 0)92 return;93 94 const char *fmt =95 addresses.front().GetFamily() == AF_INET6 ? "[{0}]:0" : "{0}:0";96 std::string addr_wrap = llvm::formatv(fmt, addr).str();97 98 Socket *server_socket;99 llvm::Expected<std::unique_ptr<Socket>> socket_or_err =100 Socket::TcpListen(addr_wrap, false);101 ASSERT_THAT_EXPECTED(socket_or_err, llvm::Succeeded());102 server_socket = socket_or_err->get();103 104 auto port = ((TCPSocket *)server_socket)->GetLocalPortNumber();105 auto child_pid = fork();106 if (child_pid != 0) {107 RNBSocket client_socket;108 auto result = client_socket.Connect(addr, port);109 ASSERT_TRUE(result == rnb_success);110 result = client_socket.Write(hello.c_str(), hello.length());111 ASSERT_TRUE(result == rnb_success);112 std::string bye;113 result = client_socket.Read(bye);114 ASSERT_TRUE(result == rnb_success);115 ASSERT_EQ(bye, goodbye);116 } else {117 Socket *connected_socket;118 Status err =119 server_socket->Accept(std::chrono::seconds(10), connected_socket);120 if (err.Fail()) {121 llvm::errs() << err.AsCString();122 abort();123 }124 char buffer[32];125 size_t read_size = 32;126 err = connected_socket->Read((void *)&buffer[0], read_size);127 if (err.Fail()) {128 llvm::errs() << err.AsCString();129 abort();130 }131 std::string Recv(&buffer[0], read_size);132 if (Recv != hello) {133 llvm::errs() << err.AsCString();134 abort();135 }136 size_t write_size = goodbye.length();137 err = connected_socket->Write(goodbye.c_str(), write_size);138 if (err.Fail()) {139 llvm::errs() << err.AsCString();140 abort();141 }142 if (write_size != goodbye.length()) {143 llvm::errs() << err.AsCString();144 abort();145 }146 exit(0);147 }148 int exit_status;149 wait(&exit_status);150 ASSERT_EQ(exit_status, 0);151}152 153TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); }154 155TEST(RNBSocket, LoopBackConnectIPv6) { TestSocketConnect("::1"); }156