1 //===-- TestClient.h --------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_UNITTESTS_TOOLS_LLDB_SERVER_TESTS_TESTCLIENT_H 10 #define LLDB_UNITTESTS_TOOLS_LLDB_SERVER_TESTS_TESTCLIENT_H 11 12 #include "MessageObjects.h" 13 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" 14 #include "lldb/Host/ProcessLaunchInfo.h" 15 #include "lldb/Utility/ArchSpec.h" 16 #include "lldb/Utility/Connection.h" 17 #include "llvm/Support/Casting.h" 18 #include "llvm/Support/FormatVariadic.h" 19 #include <memory> 20 #include <optional> 21 #include <string> 22 23 #ifdef SendMessage 24 #undef SendMessage 25 #endif 26 27 #if LLDB_SERVER_IS_DEBUGSERVER 28 #define LLGS_TEST(x) DISABLED_ ## x 29 #define DS_TEST(x) x 30 #else 31 #define LLGS_TEST(x) x 32 #define DS_TEST(x) DISABLED_ ## x 33 #endif 34 35 namespace llgs_tests { 36 class TestClient 37 : public lldb_private::process_gdb_remote::GDBRemoteCommunicationClient { 38 public: 39 static bool IsDebugServer() { return LLDB_SERVER_IS_DEBUGSERVER; } 40 static bool IsLldbServer() { return !IsDebugServer(); } 41 42 /// Launches the server, connects it to the client and returns the client. If 43 /// Log is non-empty, the server will write it's log to this file. 44 static llvm::Expected<std::unique_ptr<TestClient>> launch(llvm::StringRef Log); 45 46 /// Launches the server, while specifying the inferior on its command line. 47 /// When the client connects, it already has a process ready. 48 static llvm::Expected<std::unique_ptr<TestClient>> 49 launch(llvm::StringRef Log, llvm::ArrayRef<llvm::StringRef> InferiorArgs); 50 51 /// Allows user to pass additional arguments to the server. Be careful when 52 /// using this for generic tests, as the two stubs have different 53 /// command-line interfaces. 54 static llvm::Expected<std::unique_ptr<TestClient>> 55 launchCustom(llvm::StringRef Log, bool disable_stdio, 56 llvm::ArrayRef<llvm::StringRef> ServerArgs, 57 llvm::ArrayRef<llvm::StringRef> InferiorArgs); 58 59 ~TestClient() override; 60 llvm::Error SetInferior(llvm::ArrayRef<std::string> inferior_args); 61 llvm::Error ListThreadsInStopReply(); 62 llvm::Error SetBreakpoint(unsigned long address); 63 llvm::Error ContinueAll(); 64 llvm::Error ContinueThread(unsigned long thread_id); 65 const ProcessInfo &GetProcessInfo(); 66 llvm::Expected<JThreadsInfo> GetJThreadsInfo(); 67 const StopReply &GetLatestStopReply(); 68 template <typename T> llvm::Expected<const T &> GetLatestStopReplyAs() { 69 assert(m_stop_reply); 70 if (const auto *Reply = llvm::dyn_cast<T>(m_stop_reply.get())) 71 return *Reply; 72 return llvm::make_error<llvm::StringError>( 73 llvm::formatv("Unexpected Stop Reply {0}", m_stop_reply->getKind()), 74 llvm::inconvertibleErrorCode()); 75 } 76 llvm::Error SendMessage(llvm::StringRef message); 77 llvm::Error SendMessage(llvm::StringRef message, 78 std::string &response_string); 79 llvm::Error SendMessage(llvm::StringRef message, std::string &response_string, 80 PacketResult expected_result); 81 82 template <typename P, typename... CreateArgs> 83 llvm::Expected<typename P::result_type> SendMessage(llvm::StringRef Message, 84 CreateArgs &&... Args); 85 unsigned int GetPcRegisterId(); 86 87 private: 88 TestClient(std::unique_ptr<lldb_private::Connection> Conn); 89 90 llvm::Error initializeConnection(); 91 llvm::Error qProcessInfo(); 92 llvm::Error qRegisterInfos(); 93 llvm::Error queryProcess(); 94 llvm::Error Continue(llvm::StringRef message); 95 std::string FormatFailedResult( 96 const std::string &message, 97 lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult 98 result); 99 100 std::optional<ProcessInfo> m_process_info; 101 std::unique_ptr<StopReply> m_stop_reply; 102 std::vector<lldb_private::RegisterInfo> m_register_infos; 103 unsigned int m_pc_register = LLDB_INVALID_REGNUM; 104 }; 105 106 template <typename P, typename... CreateArgs> 107 llvm::Expected<typename P::result_type> 108 TestClient::SendMessage(llvm::StringRef Message, CreateArgs &&... Args) { 109 std::string ResponseText; 110 if (llvm::Error E = SendMessage(Message, ResponseText)) 111 return std::move(E); 112 return P::create(ResponseText, std::forward<CreateArgs>(Args)...); 113 } 114 115 } // namespace llgs_tests 116 117 #endif // LLDB_UNITTESTS_TOOLS_LLDB_SERVER_TESTS_TESTCLIENT_H 118