xref: /llvm-project/lldb/unittests/tools/lldb-server/tests/TestClient.h (revision 5d2b3378758b42391e90b1adf936537a66b038b6)
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