diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
| commit | f73363f1dd94996356cefbf24388f561891acf0b (patch) | |
| tree | e3c31248bdb36eaec5fd833490d4278162dba2a0 /unittests/tools/lldb-server/tests/TestClient.cpp | |
| parent | 160ee69dd7ae18978f4068116777639ea98dc951 (diff) | |
Notes
Diffstat (limited to 'unittests/tools/lldb-server/tests/TestClient.cpp')
| -rw-r--r-- | unittests/tools/lldb-server/tests/TestClient.cpp | 156 |
1 files changed, 73 insertions, 83 deletions
diff --git a/unittests/tools/lldb-server/tests/TestClient.cpp b/unittests/tools/lldb-server/tests/TestClient.cpp index 4653c2df1ce9..3dd5be2c6e8e 100644 --- a/unittests/tools/lldb-server/tests/TestClient.cpp +++ b/unittests/tools/lldb-server/tests/TestClient.cpp @@ -11,8 +11,8 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Host/common/TCPSocket.h" #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" -#include "lldb/Interpreter/Args.h" #include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Utility/Args.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Path.h" #include "llvm/Testing/Support/Error.h" @@ -25,25 +25,30 @@ using namespace lldb; using namespace lldb_private; using namespace llvm; - -namespace llgs_tests { +using namespace llgs_tests; TestClient::TestClient(std::unique_ptr<Connection> Conn) { SetConnection(Conn.release()); - - SendAck(); // Send this as a handshake. + SetPacketTimeout(std::chrono::seconds(10)); } TestClient::~TestClient() { if (!IsConnected()) return; - std::string response; - // Debugserver (non-conformingly?) sends a reply to the k packet instead of - // simply closing the connection. - PacketResult result = - IsDebugServer() ? PacketResult::Success : PacketResult::ErrorDisconnected; - EXPECT_THAT_ERROR(SendMessage("k", response, result), Succeeded()); + EXPECT_THAT_ERROR(SendMessage("k"), Succeeded()); +} + +Error TestClient::initializeConnection() { + if (SendAck() == 0) + return make_error<StringError>("Sending initial ACK failed.", + inconvertibleErrorCode()); + + if (Error E = SendMessage("QStartNoAckMode")) + return E; + + m_send_acks = false; + return Error::success(); } Expected<std::unique_ptr<TestClient>> TestClient::launch(StringRef Log) { @@ -91,10 +96,12 @@ Expected<std::unique_ptr<TestClient>> TestClient::launchCustom(StringRef Log, Ar ProcessLaunchInfo Info; Info.SetArchitecture(arch_spec); Info.SetArguments(args, true); - - StringList Env; - Host::GetEnvironment(Env); - Info.GetEnvironmentEntries() = Args(Env); + Info.GetEnvironment() = Host::GetEnvironment(); + // TODO: Use this callback to detect botched launches. If lldb-server does not + // start, we can print a nice error message here instead of hanging in + // Accept(). + Info.SetMonitorProcessCallback(&ProcessLaunchInfo::NoOpMonitorCallback, + false); status = Host::LaunchProcess(Info); if (status.Fail()) @@ -105,8 +112,11 @@ Expected<std::unique_ptr<TestClient>> TestClient::launchCustom(StringRef Log, Ar auto Conn = llvm::make_unique<ConnectionFileDescriptor>(accept_socket); auto Client = std::unique_ptr<TestClient>(new TestClient(std::move(Conn))); + if (Error E = Client->initializeConnection()) + return std::move(E); + if (!InferiorArgs.empty()) { - if (Error E = Client->QueryProcessInfo()) + if (Error E = Client->queryProcess()) return std::move(E); } @@ -114,14 +124,9 @@ Expected<std::unique_ptr<TestClient>> TestClient::launchCustom(StringRef Log, Ar } Error TestClient::SetInferior(llvm::ArrayRef<std::string> inferior_args) { - StringList env; - Host::GetEnvironment(env); - for (size_t i = 0; i < env.GetSize(); ++i) { - if (SendEnvironmentPacket(env[i].c_str()) != 0) { - return make_error<StringError>( - formatv("Failed to set environment variable: {0}", env[i]).str(), - inconvertibleErrorCode()); - } + if (SendEnvironment(Host::GetEnvironment()) != 0) { + return make_error<StringError>("Failed to set launch environment", + inconvertibleErrorCode()); } std::stringstream command; command << "A"; @@ -136,7 +141,7 @@ Error TestClient::SetInferior(llvm::ArrayRef<std::string> inferior_args) { return E; if (Error E = SendMessage("qLaunchSuccess")) return E; - if (Error E = QueryProcessInfo()) + if (Error E = queryProcess()) return E; return Error::success(); } @@ -155,19 +160,12 @@ Error TestClient::ContinueThread(unsigned long thread_id) { return Continue(formatv("vCont;c:{0:x-}", thread_id).str()); } -const ProcessInfo &TestClient::GetProcessInfo() { return *m_process_info; } - -Optional<JThreadsInfo> TestClient::GetJThreadsInfo() { - std::string response; - if (SendMessage("jThreadsInfo", response)) - return llvm::None; - auto creation = JThreadsInfo::Create(response, m_process_info->GetEndian()); - if (auto create_error = creation.takeError()) { - GTEST_LOG_(ERROR) << toString(std::move(create_error)); - return llvm::None; - } +const llgs_tests::ProcessInfo &TestClient::GetProcessInfo() { + return *m_process_info; +} - return std::move(*creation); +Expected<JThreadsInfo> TestClient::GetJThreadsInfo() { + return SendMessage<JThreadsInfo>("jThreadsInfo", m_register_infos); } const StopReply &TestClient::GetLatestStopReply() { @@ -183,13 +181,9 @@ Error TestClient::SendMessage(StringRef message) { Error TestClient::SendMessage(StringRef message, std::string &response_string) { if (Error E = SendMessage(message, response_string, PacketResult::Success)) return E; - if (response_string[0] == 'E') { - return make_error<StringError>( - formatv("Error `{0}` while sending message: {1}", response_string, - message) - .str(), - inconvertibleErrorCode()); - } + StringExtractorGDBRemote Extractor(response_string); + if (Extractor.IsErrorResponse()) + return Extractor.GetStatus().ToError(); return Error::success(); } @@ -209,69 +203,65 @@ Error TestClient::SendMessage(StringRef message, std::string &response_string, } unsigned int TestClient::GetPcRegisterId() { - if (m_pc_register != UINT_MAX) - return m_pc_register; - - for (unsigned int register_id = 0;; register_id++) { - std::string message = formatv("qRegisterInfo{0:x-}", register_id).str(); - std::string response; - if (SendMessage(message, response)) { - GTEST_LOG_(ERROR) << "Unable to query register ID for PC register."; - return UINT_MAX; - } + assert(m_pc_register != LLDB_INVALID_REGNUM); + return m_pc_register; +} - auto elements_or_error = SplitUniquePairList("GetPcRegisterId", response); - if (auto split_error = elements_or_error.takeError()) { - GTEST_LOG_(ERROR) << "GetPcRegisterId: Error splitting response: " - << response; - return UINT_MAX; - } +Error TestClient::qProcessInfo() { + m_process_info = None; + auto InfoOr = SendMessage<ProcessInfo>("qProcessInfo"); + if (!InfoOr) + return InfoOr.takeError(); + m_process_info = std::move(*InfoOr); + return Error::success(); +} - auto elements = *elements_or_error; - if (elements["alt-name"] == "pc" || elements["generic"] == "pc") { - m_pc_register = register_id; +Error TestClient::qRegisterInfos() { + for (unsigned int Reg = 0;; ++Reg) { + std::string Message = formatv("qRegisterInfo{0:x-}", Reg).str(); + Expected<RegisterInfo> InfoOr = SendMessage<RegisterInfoParser>(Message); + if (!InfoOr) { + consumeError(InfoOr.takeError()); break; } + m_register_infos.emplace_back(std::move(*InfoOr)); + if (m_register_infos[Reg].kinds[eRegisterKindGeneric] == + LLDB_REGNUM_GENERIC_PC) + m_pc_register = Reg; } - - return m_pc_register; + if (m_pc_register == LLDB_INVALID_REGNUM) + return make_parsing_error("qRegisterInfo: generic"); + return Error::success(); } -llvm::Error TestClient::QueryProcessInfo() { - std::string response; - if (Error E = SendMessage("qProcessInfo", response)) +Error TestClient::queryProcess() { + if (Error E = qProcessInfo()) + return E; + if (Error E = qRegisterInfos()) return E; - auto create_or_error = ProcessInfo::Create(response); - if (!create_or_error) - return create_or_error.takeError(); - m_process_info = *create_or_error; return Error::success(); } Error TestClient::Continue(StringRef message) { assert(m_process_info.hasValue()); - std::string response; - if (Error E = SendMessage(message, response)) - return E; - auto creation = StopReply::create(response, m_process_info->GetEndian()); - if (Error E = creation.takeError()) - return E; + auto StopReplyOr = SendMessage<StopReply>( + message, m_process_info->GetEndian(), m_register_infos); + if (!StopReplyOr) + return StopReplyOr.takeError(); - m_stop_reply = std::move(*creation); + m_stop_reply = std::move(*StopReplyOr); if (!isa<StopReplyStop>(m_stop_reply)) { StringExtractorGDBRemote R; PacketResult result = ReadPacket(R, GetPacketTimeout(), false); if (result != PacketResult::ErrorDisconnected) { return make_error<StringError>( - formatv("Expected connection close after receiving {0}. Got {1}/{2} " + formatv("Expected connection close after sending {0}. Got {1}/{2} " "instead.", - response, result, R.GetStringRef()) + message, result, R.GetStringRef()) .str(), inconvertibleErrorCode()); } } return Error::success(); } - -} // namespace llgs_tests |
