diff options
Diffstat (limited to 'unittests/Host')
-rw-r--r-- | unittests/Host/CMakeLists.txt | 5 | ||||
-rw-r--r-- | unittests/Host/SocketAddressTest.cpp | 77 | ||||
-rw-r--r-- | unittests/Host/SocketTest.cpp | 201 | ||||
-rw-r--r-- | unittests/Host/SymbolsTest.cpp | 30 |
4 files changed, 313 insertions, 0 deletions
diff --git a/unittests/Host/CMakeLists.txt b/unittests/Host/CMakeLists.txt new file mode 100644 index 000000000000..b4739e113f48 --- /dev/null +++ b/unittests/Host/CMakeLists.txt @@ -0,0 +1,5 @@ +add_lldb_unittest(HostTests + SocketAddressTest.cpp + SocketTest.cpp + SymbolsTest.cpp + ) diff --git a/unittests/Host/SocketAddressTest.cpp b/unittests/Host/SocketAddressTest.cpp new file mode 100644 index 000000000000..bd6bda13f449 --- /dev/null +++ b/unittests/Host/SocketAddressTest.cpp @@ -0,0 +1,77 @@ +//===-- SocketAddressTest.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "gtest/gtest.h" + +#include "lldb/Host/SocketAddress.h" + +namespace +{ + class SocketAddressTest: public ::testing::Test + { + }; +} + +using namespace lldb_private; + +TEST_F (SocketAddressTest, Set) +{ + SocketAddress sa; + ASSERT_TRUE (sa.SetToLocalhost (AF_INET, 1138)); + ASSERT_STREQ ("127.0.0.1", sa.GetIPAddress ().c_str ()); + ASSERT_EQ (1138, sa.GetPort ()); + + ASSERT_TRUE (sa.SetToAnyAddress (AF_INET, 0)); + ASSERT_STREQ ("0.0.0.0", sa.GetIPAddress ().c_str ()); + ASSERT_EQ (0, sa.GetPort ()); + + ASSERT_TRUE (sa.SetToLocalhost (AF_INET6, 1139)); +#ifdef _WIN32 + ASSERT_STREQ ("0:0:0:0:0:0:0:1", sa.GetIPAddress ().c_str ()); +#else + ASSERT_STREQ ("::1", sa.GetIPAddress ().c_str ()); +#endif + ASSERT_EQ (1139, sa.GetPort ()); +} + +#ifdef _WIN32 + +// we need to test our inet_ntop implementation for Windows XP +const char* inet_ntop (int af, const void * src, + char * dst, socklen_t size); + +TEST_F (SocketAddressTest, inet_ntop) +{ + const uint8_t address4[4] = {255, 0, 1, 100}; + const uint8_t address6[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 255, 0}; + + char buffer[INET6_ADDRSTRLEN]; + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ ("1:203:405:607:809:a0b:c0d:ff00", inet_ntop (AF_INET6, address6, buffer, sizeof (buffer))); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ ("1:203:405:607:809:a0b:c0d:ff00", inet_ntop (AF_INET6, address6, buffer, 31)); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ (nullptr, inet_ntop (AF_INET6, address6, buffer, 0)); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ (nullptr, inet_ntop (AF_INET6, address6, buffer, 30)); + + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ ("255.0.1.100", inet_ntop (AF_INET, address4, buffer, sizeof (buffer))); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ ("255.0.1.100", inet_ntop (AF_INET, address4, buffer, 12)); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ (nullptr, inet_ntop (AF_INET, address4, buffer, 0)); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ (nullptr, inet_ntop (AF_INET, address4, buffer, 11)); +} + +#endif + + diff --git a/unittests/Host/SocketTest.cpp b/unittests/Host/SocketTest.cpp new file mode 100644 index 000000000000..ebb2f319a9c5 --- /dev/null +++ b/unittests/Host/SocketTest.cpp @@ -0,0 +1,201 @@ +//===-- SocketTest.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#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 + +#include <cstdio> +#include <functional> +#include <thread> + +#include "gtest/gtest.h" + +#include "lldb/Host/Config.h" +#include "lldb/Host/Socket.h" +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Host/common/UDPSocket.h" + +#ifndef LLDB_DISABLE_POSIX +#include "lldb/Host/posix/DomainSocket.h" +#endif + +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->Accept(listen_remote_address, child_processes_inherit, *accept_socket); + } + + template<typename SocketType> + void + CreateConnectedSockets(const char *listen_remote_address, const std::function<std::string(const SocketType&)> &get_connect_addr, std::unique_ptr<SocketType> *a_up, std::unique_ptr<SocketType> *b_up) + { + bool child_processes_inherit = false; + Error error; + std::unique_ptr<SocketType> listen_socket_up(new SocketType(child_processes_inherit, error)); + EXPECT_FALSE(error.Fail()); + error = listen_socket_up->Listen(listen_remote_address, 5); + EXPECT_FALSE(error.Fail()); + 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); + + std::string connect_remote_address = get_connect_addr(*listen_socket_up); + std::unique_ptr<SocketType> connect_socket_up(new SocketType(child_processes_inherit, error)); + EXPECT_FALSE(error.Fail()); + error = connect_socket_up->Connect(connect_remote_address.c_str()); + EXPECT_FALSE(error.Fail()); + EXPECT_TRUE(connect_socket_up->IsValid()); + + a_up->swap(connect_socket_up); + EXPECT_TRUE(error.Success()); + EXPECT_NE(nullptr, a_up->get()); + EXPECT_TRUE((*a_up)->IsValid()); + + accept_thread.join(); + b_up->reset(static_cast<SocketType*>(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 ()); +} + +#ifndef LLDB_DISABLE_POSIX +TEST_F (SocketTest, DomainListenConnectAccept) +{ + char* file_name_str = tempnam(nullptr, nullptr); + EXPECT_NE (nullptr, file_name_str); + const std::string file_name(file_name_str); + free(file_name_str); + + std::unique_ptr<DomainSocket> socket_a_up; + std::unique_ptr<DomainSocket> socket_b_up; + CreateConnectedSockets<DomainSocket>(file_name.c_str(), + [=](const DomainSocket &) + { + return file_name; + }, + &socket_a_up, &socket_b_up); +} +#endif + +TEST_F (SocketTest, TCPListen0ConnectAccept) +{ + std::unique_ptr<TCPSocket> socket_a_up; + std::unique_ptr<TCPSocket> socket_b_up; + CreateConnectedSockets<TCPSocket>("127.0.0.1:0", + [=](const TCPSocket &s) + { + char connect_remote_address[64]; + snprintf(connect_remote_address, sizeof(connect_remote_address), "localhost:%u", s.GetLocalPortNumber()); + return std::string(connect_remote_address); + }, + &socket_a_up, &socket_b_up); +} + +TEST_F (SocketTest, TCPGetAddress) +{ + std::unique_ptr<TCPSocket> socket_a_up; + std::unique_ptr<TCPSocket> socket_b_up; + CreateConnectedSockets<TCPSocket>("127.0.0.1:0", + [=](const TCPSocket &s) + { + char connect_remote_address[64]; + snprintf(connect_remote_address, sizeof(connect_remote_address), "localhost:%u", s.GetLocalPortNumber()); + return std::string(connect_remote_address); + }, + &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 ()); +} + +TEST_F (SocketTest, UDPConnect) +{ + Socket* socket_a; + Socket* socket_b; + + bool child_processes_inherit = false; + auto error = UDPSocket::Connect("127.0.0.1:0", child_processes_inherit, socket_a, socket_b); + + std::unique_ptr<Socket> a_up(socket_a); + std::unique_ptr<Socket> b_up(socket_b); + + EXPECT_TRUE(error.Success ()); + EXPECT_TRUE(a_up->IsValid()); + EXPECT_TRUE(b_up->IsValid()); +} diff --git a/unittests/Host/SymbolsTest.cpp b/unittests/Host/SymbolsTest.cpp new file mode 100644 index 000000000000..cb59b2c56539 --- /dev/null +++ b/unittests/Host/SymbolsTest.cpp @@ -0,0 +1,30 @@ +//===-- SymbolsTest.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "lldb/Host/Symbols.h" +#include "lldb/Core/ModuleSpec.h" + +using namespace lldb_private; + +TEST(SymbolsTest, LocateExecutableSymbolFileForUnknownExecutableAndUnknownSymbolFile) +{ + ModuleSpec module_spec; + FileSpec symbol_file_spec = Symbols::LocateExecutableSymbolFile(module_spec); + EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty()); +} + +TEST(SymbolsTest, LocateExecutableSymbolFileForUnknownExecutableAndMissingSymbolFile) +{ + ModuleSpec module_spec; + // using a GUID here because the symbol file shouldn't actually exist on disk + module_spec.GetSymbolFileSpec().SetFile("4A524676-B24B-4F4E-968A-551D465EBAF1.so", false); + FileSpec symbol_file_spec = Symbols::LocateExecutableSymbolFile(module_spec); + EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty()); +} |