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 | Args: llvm::formatv(Fmt: "Unexpected Stop Reply {0}" , Vals: m_stop_reply->getKind()), |
74 | Args: 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: Message, response_string&: 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 | |