
Summary: This patch refactors the CMake build system's support for building debugserver to allow us to build the majority of debugserver's sources into the debugserverCommon library which can then be reused by unit tests. The first unit test I've written tests debug server's ability to accept incoming connections from LLDB. The test forks the process, and one side creates a listening socket using debugserver's socket API, the other side creates a transmitting socket using LLDB's TCPSocket class. I have no clue where to even start getting this connected into the LLDB Xcode project, so for now these tests are CMake-only. Reviewers: zturner, labath, jasonmolenda Subscribers: lldb-commits, mgorny Differential Revision: https://reviews.llvm.org/D31357 llvm-svn: 300111
134 lines
3.7 KiB
C++
134 lines
3.7 KiB
C++
//===-- RNBSocketTest.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 <arpa/inet.h>
|
|
#include <sys/sysctl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "RNBDefs.h"
|
|
#include "RNBSocket.h"
|
|
#include "lldb/Host/Socket.h"
|
|
#include "lldb/Host/StringConvert.h"
|
|
#include "lldb/Host/common/TCPSocket.h"
|
|
|
|
using namespace lldb_private;
|
|
|
|
std::string hello = "Hello, world!";
|
|
std::string goodbye = "Goodbye!";
|
|
|
|
static void ServerCallbackv4(const void *baton, in_port_t port) {
|
|
auto child_pid = fork();
|
|
if (child_pid == 0) {
|
|
Socket *client_socket;
|
|
char addr_buffer[256];
|
|
sprintf(addr_buffer, "%s:%d", baton, port);
|
|
Error err = Socket::TcpConnect(addr_buffer, false, client_socket);
|
|
if (err.Fail())
|
|
abort();
|
|
char buffer[32];
|
|
size_t read_size = 32;
|
|
err = client_socket->Read((void *)&buffer[0], read_size);
|
|
if (err.Fail())
|
|
abort();
|
|
std::string Recv(&buffer[0], read_size);
|
|
if (Recv != hello)
|
|
abort();
|
|
size_t write_size = goodbye.length();
|
|
err = client_socket->Write(goodbye.c_str(), write_size);
|
|
if (err.Fail())
|
|
abort();
|
|
if (write_size != goodbye.length())
|
|
abort();
|
|
delete client_socket;
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
void TestSocketListen(const char *addr) {
|
|
RNBSocket server_socket;
|
|
auto result =
|
|
server_socket.Listen(addr, 0, ServerCallbackv4, (const void *)addr);
|
|
ASSERT_TRUE(result == rnb_success);
|
|
result = server_socket.Write(hello.c_str(), hello.length());
|
|
ASSERT_TRUE(result == rnb_success);
|
|
std::string bye;
|
|
result = server_socket.Read(bye);
|
|
ASSERT_TRUE(result == rnb_success);
|
|
ASSERT_EQ(bye, goodbye);
|
|
|
|
int exit_status;
|
|
wait(&exit_status);
|
|
ASSERT_EQ(exit_status, 0);
|
|
}
|
|
|
|
TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); }
|
|
|
|
void TestSocketConnect(const char *addr) {
|
|
char addr_wrap[256];
|
|
sprintf(addr_wrap, "%s:0", addr);
|
|
|
|
Socket *server_socket;
|
|
Predicate<uint16_t> port_predicate;
|
|
port_predicate.SetValue(0, eBroadcastNever);
|
|
Error err =
|
|
Socket::TcpListen(addr_wrap, false, server_socket, &port_predicate);
|
|
ASSERT_FALSE(err.Fail());
|
|
|
|
auto port = ((TCPSocket *)server_socket)->GetLocalPortNumber();
|
|
auto child_pid = fork();
|
|
if (child_pid != 0) {
|
|
RNBSocket client_socket;
|
|
auto result = client_socket.Connect(addr, port);
|
|
ASSERT_TRUE(result == rnb_success);
|
|
result = client_socket.Write(hello.c_str(), hello.length());
|
|
ASSERT_TRUE(result == rnb_success);
|
|
std::string bye;
|
|
result = client_socket.Read(bye);
|
|
ASSERT_TRUE(result == rnb_success);
|
|
ASSERT_EQ(bye, goodbye);
|
|
} else {
|
|
Socket *connected_socket;
|
|
err = server_socket->Accept(addr_wrap, false, connected_socket);
|
|
if (err.Fail()) {
|
|
llvm::errs() << err.AsCString();
|
|
abort();
|
|
}
|
|
char buffer[32];
|
|
size_t read_size = 32;
|
|
err = connected_socket->Read((void *)&buffer[0], read_size);
|
|
if (err.Fail()) {
|
|
llvm::errs() << err.AsCString();
|
|
abort();
|
|
}
|
|
std::string Recv(&buffer[0], read_size);
|
|
if (Recv != hello) {
|
|
llvm::errs() << err.AsCString();
|
|
abort();
|
|
}
|
|
size_t write_size = goodbye.length();
|
|
err = connected_socket->Write(goodbye.c_str(), write_size);
|
|
if (err.Fail()) {
|
|
llvm::errs() << err.AsCString();
|
|
abort();
|
|
}
|
|
if (write_size != goodbye.length()) {
|
|
llvm::errs() << err.AsCString();
|
|
abort();
|
|
}
|
|
exit(0);
|
|
}
|
|
int exit_status;
|
|
wait(&exit_status);
|
|
ASSERT_EQ(exit_status, 0);
|
|
}
|
|
|
|
TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); }
|