//===-- SocketTest.cpp ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include #include "gtest/gtest.h" #include "lldb/Host/Socket.h" using namespace lldb_private; class SocketTest : public testing::Test { public: void SetUp() override { #if defined(_MSC_VER) WSADATA data; ::WSAStartup(MAKEWORD(2, 2), &data); #endif } void TearDown() override { #if defined(_MSC_VER) ::WSACleanup(); #endif } protected: static void AcceptThread(Socket *listen_socket, const char *listen_remote_address, bool child_processes_inherit, Socket **accept_socket, Error *error) { *error = listen_socket->BlockingAccept(listen_remote_address, child_processes_inherit, *accept_socket); } void CreateConnectedSockets(std::unique_ptr *a_up, std::unique_ptr *b_up) { Predicate port_predicate; // Used when binding to port zero to wait for the thread // that creates the socket, binds and listens to resolve // the port number. port_predicate.SetValue(0, eBroadcastNever); bool child_processes_inherit = false; Socket *socket = nullptr; const char *listen_remote_address = "localhost:0"; Error error = Socket::TcpListen(listen_remote_address, child_processes_inherit, socket, &port_predicate); std::unique_ptr listen_socket_up(socket); socket = nullptr; EXPECT_FALSE(error.Fail()); EXPECT_NE(nullptr, listen_socket_up.get()); EXPECT_TRUE(listen_socket_up->IsValid()); Error accept_error; Socket *accept_socket; std::thread accept_thread(AcceptThread, listen_socket_up.get(), listen_remote_address, child_processes_inherit, &accept_socket, &accept_error); char connect_remote_address[64]; snprintf(connect_remote_address, sizeof(connect_remote_address), "localhost:%u", port_predicate.GetValue()); error = Socket::TcpConnect(connect_remote_address, child_processes_inherit, socket); a_up->reset(socket); socket = nullptr; EXPECT_TRUE(error.Success()); EXPECT_NE(nullptr, a_up->get()); EXPECT_TRUE((*a_up)->IsValid()); accept_thread.join(); b_up->reset(accept_socket); EXPECT_TRUE(accept_error.Success()); EXPECT_NE(nullptr, b_up->get()); EXPECT_TRUE((*b_up)->IsValid()); listen_socket_up.reset(); } }; TEST_F (SocketTest, DecodeHostAndPort) { std::string host_str; std::string port_str; int32_t port; Error error; EXPECT_TRUE (Socket::DecodeHostAndPort ("localhost:1138", host_str, port_str, port, &error)); EXPECT_STREQ ("localhost", host_str.c_str ()); EXPECT_STREQ ("1138", port_str.c_str ()); EXPECT_EQ (1138, port); EXPECT_TRUE (error.Success ()); EXPECT_FALSE (Socket::DecodeHostAndPort ("google.com:65536", host_str, port_str, port, &error)); EXPECT_TRUE (error.Fail ()); EXPECT_STREQ ("invalid host:port specification: 'google.com:65536'", error.AsCString ()); EXPECT_FALSE (Socket::DecodeHostAndPort ("google.com:-1138", host_str, port_str, port, &error)); EXPECT_TRUE (error.Fail ()); EXPECT_STREQ ("invalid host:port specification: 'google.com:-1138'", error.AsCString ()); EXPECT_TRUE (Socket::DecodeHostAndPort ("12345", host_str, port_str, port, &error)); EXPECT_STREQ ("", host_str.c_str ()); EXPECT_STREQ ("12345", port_str.c_str ()); EXPECT_EQ (12345, port); EXPECT_TRUE (error.Success ()); EXPECT_TRUE (Socket::DecodeHostAndPort ("*:0", host_str, port_str, port, &error)); EXPECT_STREQ ("*", host_str.c_str ()); EXPECT_STREQ ("0", port_str.c_str ()); EXPECT_EQ (0, port); EXPECT_TRUE (error.Success ()); } TEST_F (SocketTest, Listen0ConnectAccept) { std::unique_ptr socket_a_up; std::unique_ptr socket_b_up; CreateConnectedSockets (&socket_a_up, &socket_b_up); } TEST_F (SocketTest, GetAddress) { std::unique_ptr socket_a_up; std::unique_ptr socket_b_up; CreateConnectedSockets (&socket_a_up, &socket_b_up); EXPECT_EQ (socket_a_up->GetLocalPortNumber (), socket_b_up->GetRemotePortNumber ()); EXPECT_EQ (socket_b_up->GetLocalPortNumber (), socket_a_up->GetRemotePortNumber ()); EXPECT_NE (socket_a_up->GetLocalPortNumber (), socket_b_up->GetLocalPortNumber ()); EXPECT_STREQ ("127.0.0.1", socket_a_up->GetRemoteIPAddress ().c_str ()); EXPECT_STREQ ("127.0.0.1", socket_b_up->GetRemoteIPAddress ().c_str ()); }