Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,17 @@
add_lldb_unittest(ProcessGdbRemoteTests
GDBRemoteClientBaseTest.cpp
GDBRemoteCommunicationClientTest.cpp
GDBRemoteTestUtils.cpp
LINK_LIBS
lldbCore
lldbHost
lldbPluginPlatformMacOSX
lldbPluginProcessUtility
lldbPluginProcessGDBRemote
LLVMTestingSupport
LINK_COMPONENTS
Support
)

View File

@@ -0,0 +1,341 @@
//===-- GDBRemoteClientBaseTest.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <future>
#include "GDBRemoteTestUtils.h"
#include "Plugins/Process/Utility/LinuxSignals.h"
#include "Plugins/Process/gdb-remote/GDBRemoteClientBase.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
#include "lldb/Utility/StreamGDBRemote.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Testing/Support/Error.h"
using namespace lldb_private::process_gdb_remote;
using namespace lldb_private;
using namespace lldb;
typedef GDBRemoteCommunication::PacketResult PacketResult;
namespace {
struct MockDelegate : public GDBRemoteClientBase::ContinueDelegate {
std::string output;
std::string misc_data;
unsigned stop_reply_called = 0;
std::vector<std::string> structured_data_packets;
void HandleAsyncStdout(llvm::StringRef out) { output += out; }
void HandleAsyncMisc(llvm::StringRef data) { misc_data += data; }
void HandleStopReply() { ++stop_reply_called; }
void HandleAsyncStructuredDataPacket(llvm::StringRef data) {
structured_data_packets.push_back(data);
}
};
struct TestClient : public GDBRemoteClientBase {
TestClient() : GDBRemoteClientBase("test.client", "test.client.listener") {
m_send_acks = false;
}
};
class GDBRemoteClientBaseTest : public GDBRemoteTest {
public:
void SetUp() override {
ASSERT_THAT_ERROR(Connect(client, server), llvm::Succeeded());
ASSERT_EQ(TestClient::eBroadcastBitRunPacketSent,
listener_sp->StartListeningForEvents(
&client, TestClient::eBroadcastBitRunPacketSent));
}
protected:
TestClient client;
MockServer server;
MockDelegate delegate;
ListenerSP listener_sp = Listener::MakeListener("listener");
StateType SendCPacket(StringExtractorGDBRemote &response) {
return client.SendContinuePacketAndWaitForResponse(delegate, LinuxSignals(),
"c", response);
}
void WaitForRunEvent() {
EventSP event_sp;
listener_sp->GetEventForBroadcasterWithType(
&client, TestClient::eBroadcastBitRunPacketSent, event_sp, llvm::None);
}
};
} // end anonymous namespace
TEST_F(GDBRemoteClientBaseTest, SendContinueAndWait) {
StringExtractorGDBRemote response;
// Continue. The inferior will stop with a signal.
ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
ASSERT_EQ(eStateStopped, SendCPacket(response));
ASSERT_EQ("T01", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
// Continue. The inferior will exit.
ASSERT_EQ(PacketResult::Success, server.SendPacket("W01"));
ASSERT_EQ(eStateExited, SendCPacket(response));
ASSERT_EQ("W01", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
// Continue. The inferior will get killed.
ASSERT_EQ(PacketResult::Success, server.SendPacket("X01"));
ASSERT_EQ(eStateExited, SendCPacket(response));
ASSERT_EQ("X01", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
}
TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) {
StringExtractorGDBRemote continue_response, response;
// SendAsyncSignal should do nothing when we are not running.
ASSERT_FALSE(client.SendAsyncSignal(0x47));
// Continue. After the run packet is sent, send an async signal.
std::future<StateType> continue_state = std::async(
std::launch::async, [&] { return SendCPacket(continue_response); });
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
WaitForRunEvent();
std::future<bool> async_result = std::async(
std::launch::async, [&] { return client.SendAsyncSignal(0x47); });
// First we'll get interrupted.
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("\x03", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
// Then we get the signal packet.
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("C47", response.GetStringRef());
ASSERT_TRUE(async_result.get());
// And we report back a signal stop.
ASSERT_EQ(PacketResult::Success, server.SendPacket("T47"));
ASSERT_EQ(eStateStopped, continue_state.get());
ASSERT_EQ("T47", continue_response.GetStringRef());
}
TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket) {
StringExtractorGDBRemote continue_response, async_response, response;
const bool send_async = true;
// Continue. After the run packet is sent, send an async packet.
std::future<StateType> continue_state = std::async(
std::launch::async, [&] { return SendCPacket(continue_response); });
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
WaitForRunEvent();
// Sending without async enabled should fail.
ASSERT_EQ(
PacketResult::ErrorSendFailed,
client.SendPacketAndWaitForResponse("qTest1", response, !send_async));
std::future<PacketResult> async_result = std::async(std::launch::async, [&] {
return client.SendPacketAndWaitForResponse("qTest2", async_response,
send_async);
});
// First we'll get interrupted.
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("\x03", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
// Then we get the async packet.
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("qTest2", response.GetStringRef());
// Send the response and receive it.
ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest2"));
ASSERT_EQ(PacketResult::Success, async_result.get());
ASSERT_EQ("QTest2", async_response.GetStringRef());
// And we get resumed again.
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
ASSERT_EQ(eStateStopped, continue_state.get());
ASSERT_EQ("T01", continue_response.GetStringRef());
}
TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt) {
StringExtractorGDBRemote continue_response, response;
// Interrupt should do nothing when we're not running.
ASSERT_FALSE(client.Interrupt());
// Continue. After the run packet is sent, send an interrupt.
std::future<StateType> continue_state = std::async(
std::launch::async, [&] { return SendCPacket(continue_response); });
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
WaitForRunEvent();
std::future<bool> async_result =
std::async(std::launch::async, [&] { return client.Interrupt(); });
// We get interrupted.
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("\x03", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
// And that's it.
ASSERT_EQ(eStateStopped, continue_state.get());
ASSERT_EQ("T13", continue_response.GetStringRef());
ASSERT_TRUE(async_result.get());
}
TEST_F(GDBRemoteClientBaseTest, SendContinueAndLateInterrupt) {
StringExtractorGDBRemote continue_response, response;
// Continue. After the run packet is sent, send an interrupt.
std::future<StateType> continue_state = std::async(
std::launch::async, [&] { return SendCPacket(continue_response); });
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
WaitForRunEvent();
std::future<bool> async_result =
std::async(std::launch::async, [&] { return client.Interrupt(); });
// However, the target stops due to a different reason than the original
// interrupt.
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("\x03", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
ASSERT_EQ(eStateStopped, continue_state.get());
ASSERT_EQ("T01", continue_response.GetStringRef());
ASSERT_TRUE(async_result.get());
// The subsequent continue packet should work normally.
ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
ASSERT_EQ(eStateStopped, SendCPacket(response));
ASSERT_EQ("T01", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
}
TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) {
StringExtractorGDBRemote continue_response, async_response, response;
const bool send_async = true;
// Interrupt should do nothing when we're not running.
ASSERT_FALSE(client.Interrupt());
// Continue. After the run packet is sent, send an async signal.
std::future<StateType> continue_state = std::async(
std::launch::async, [&] { return SendCPacket(continue_response); });
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
WaitForRunEvent();
std::future<bool> interrupt_result =
std::async(std::launch::async, [&] { return client.Interrupt(); });
// We get interrupted. We'll send two packets to simulate a buggy stub.
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("\x03", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
// We should stop.
ASSERT_EQ(eStateStopped, continue_state.get());
ASSERT_EQ("T13", continue_response.GetStringRef());
ASSERT_TRUE(interrupt_result.get());
// Packet stream should remain synchronized.
std::future<PacketResult> send_result = std::async(std::launch::async, [&] {
return client.SendPacketAndWaitForResponse("qTest", async_response,
!send_async);
});
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("qTest", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest"));
ASSERT_EQ(PacketResult::Success, send_result.get());
ASSERT_EQ("QTest", async_response.GetStringRef());
}
TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateInterface) {
StringExtractorGDBRemote response;
// Continue. We'll have the server send a bunch of async packets before it
// stops.
ASSERT_EQ(PacketResult::Success, server.SendPacket("O4142"));
ASSERT_EQ(PacketResult::Success, server.SendPacket("Apro"));
ASSERT_EQ(PacketResult::Success, server.SendPacket("O4344"));
ASSERT_EQ(PacketResult::Success, server.SendPacket("Afile"));
ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
ASSERT_EQ(eStateStopped, SendCPacket(response));
ASSERT_EQ("T01", response.GetStringRef());
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
EXPECT_EQ("ABCD", delegate.output);
EXPECT_EQ("profile", delegate.misc_data);
EXPECT_EQ(1u, delegate.stop_reply_called);
}
TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateStructuredDataReceipt) {
// Build the plain-text version of the JSON data we will have the
// server send.
const std::string json_payload =
"{ \"type\": \"MyFeatureType\", "
" \"elements\": [ \"entry1\", \"entry2\" ] }";
const std::string json_packet = "JSON-async:" + json_payload;
// Escape it properly for transit.
StreamGDBRemote stream;
stream.PutEscapedBytes(json_packet.c_str(), json_packet.length());
stream.Flush();
StringExtractorGDBRemote response;
// Send async structured data packet, then stop.
ASSERT_EQ(PacketResult::Success, server.SendPacket(stream.GetData()));
ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
ASSERT_EQ(eStateStopped, SendCPacket(response));
ASSERT_EQ("T01", response.GetStringRef());
ASSERT_EQ(1ul, delegate.structured_data_packets.size());
// Verify the packet contents. It should have been unescaped upon packet
// reception.
ASSERT_EQ(json_packet, delegate.structured_data_packets[0]);
}
TEST_F(GDBRemoteClientBaseTest, InterruptNoResponse) {
StringExtractorGDBRemote continue_response, response;
// Continue. After the run packet is sent, send an interrupt.
std::future<StateType> continue_state = std::async(
std::launch::async, [&] { return SendCPacket(continue_response); });
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("c", response.GetStringRef());
WaitForRunEvent();
std::future<bool> async_result =
std::async(std::launch::async, [&] { return client.Interrupt(); });
// We get interrupted, but we don't send a stop packet.
ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
ASSERT_EQ("\x03", response.GetStringRef());
// The functions should still terminate (after a timeout).
ASSERT_TRUE(async_result.get());
ASSERT_EQ(eStateInvalid, continue_state.get());
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
//===-- GDBRemoteTestUtils.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "GDBRemoteTestUtils.h"
#include "lldb/Host/common/TCPSocket.h"
#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
#include <future>
namespace lldb_private {
namespace process_gdb_remote {
void GDBRemoteTest::SetUpTestCase() {
#if defined(_MSC_VER)
WSADATA data;
::WSAStartup(MAKEWORD(2, 2), &data);
#endif
}
void GDBRemoteTest::TearDownTestCase() {
#if defined(_MSC_VER)
::WSACleanup();
#endif
}
llvm::Error GDBRemoteTest::Connect(GDBRemoteCommunication &client,
GDBRemoteCommunication &server) {
bool child_processes_inherit = false;
TCPSocket listen_socket(true, child_processes_inherit);
if (llvm::Error error = listen_socket.Listen("127.0.0.1:0", 5).ToError())
return error;
Socket *accept_socket;
std::future<Status> accept_status = std::async(
std::launch::async, [&] { return listen_socket.Accept(accept_socket); });
llvm::SmallString<32> remote_addr;
llvm::raw_svector_ostream(remote_addr)
<< "connect://localhost:" << listen_socket.GetLocalPortNumber();
std::unique_ptr<ConnectionFileDescriptor> conn_up(
new ConnectionFileDescriptor());
if (conn_up->Connect(remote_addr, nullptr) != lldb::eConnectionStatusSuccess)
return llvm::make_error<llvm::StringError>("Unable to connect",
llvm::inconvertibleErrorCode());
client.SetConnection(conn_up.release());
if (llvm::Error error = accept_status.get().ToError())
return error;
server.SetConnection(new ConnectionFileDescriptor(accept_socket));
return llvm::Error::success();
}
} // namespace process_gdb_remote
} // namespace lldb_private

View File

@@ -0,0 +1,52 @@
//===-- GDBRemoteTestUtils.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef lldb_unittests_Process_gdb_remote_GDBRemoteTestUtils_h
#define lldb_unittests_Process_gdb_remote_GDBRemoteTestUtils_h
#include "gtest/gtest.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
namespace lldb_private {
namespace process_gdb_remote {
class GDBRemoteTest : public testing::Test {
public:
static void SetUpTestCase();
static void TearDownTestCase();
protected:
llvm::Error Connect(GDBRemoteCommunication &client,
GDBRemoteCommunication &server);
};
struct MockServer : public GDBRemoteCommunicationServer {
MockServer()
: GDBRemoteCommunicationServer("mock-server", "mock-server.listener") {
m_send_acks = false;
}
PacketResult SendPacket(llvm::StringRef payload) {
return GDBRemoteCommunicationServer::SendPacketNoLock(payload);
}
PacketResult GetPacket(StringExtractorGDBRemote &response) {
const bool sync_on_timeout = false;
return WaitForPacketNoLock(response, std::chrono::seconds(1),
sync_on_timeout);
}
using GDBRemoteCommunicationServer::SendOKResponse;
using GDBRemoteCommunicationServer::SendUnimplementedResponse;
};
} // namespace process_gdb_remote
} // namespace lldb_private
#endif // lldb_unittests_Process_gdb_remote_GDBRemoteTestUtils_h