2015-01-16 08:47:08 +08:00
|
|
|
//===-- SocketTest.cpp ------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-05-29 03:56:43 +08:00
|
|
|
#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0)
|
|
|
|
// Workaround for MSVC standard library bug, which fails to include <thread> when
|
|
|
|
// exceptions are disabled.
|
|
|
|
#include <eh.h>
|
|
|
|
#endif
|
|
|
|
|
2015-01-16 08:47:08 +08:00
|
|
|
#include <thread>
|
|
|
|
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
#include "lldb/Host/Socket.h"
|
|
|
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
2015-03-14 12:19:32 +08:00
|
|
|
class SocketTest : public testing::Test
|
2015-01-16 08:47:08 +08:00
|
|
|
{
|
2015-03-14 12:19:32 +08:00
|
|
|
public:
|
|
|
|
void
|
|
|
|
SetUp() override
|
|
|
|
{
|
|
|
|
#if defined(_MSC_VER)
|
|
|
|
WSADATA data;
|
|
|
|
::WSAStartup(MAKEWORD(2, 2), &data);
|
|
|
|
#endif
|
|
|
|
}
|
2015-01-16 08:47:08 +08:00
|
|
|
|
2015-03-14 12:19:32 +08:00
|
|
|
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<Socket> *a_up, std::unique_ptr<Socket> *b_up)
|
|
|
|
{
|
|
|
|
Predicate<uint16_t> 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.
|
2015-01-16 08:47:08 +08:00
|
|
|
|
2015-03-14 12:19:32 +08:00
|
|
|
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<Socket> 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();
|
|
|
|
}
|
|
|
|
};
|
2015-01-16 08:47:08 +08:00
|
|
|
|
|
|
|
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> socket_a_up;
|
|
|
|
std::unique_ptr<Socket> socket_b_up;
|
|
|
|
CreateConnectedSockets (&socket_a_up, &socket_b_up);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F (SocketTest, GetAddress)
|
|
|
|
{
|
|
|
|
std::unique_ptr<Socket> socket_a_up;
|
|
|
|
std::unique_ptr<Socket> 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 ());
|
|
|
|
}
|