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 | #if LLDB_SERVER_IS_DEBUGSERVER |
24 | #define LLGS_TEST(x) DISABLED_ ## x |
25 | #define DS_TEST(x) x |
26 | #else |
27 | #define LLGS_TEST(x) x |
28 | #define DS_TEST(x) DISABLED_ ## x |
29 | #endif |
30 | |
31 | namespace llgs_tests { |
32 | class TestClient |
33 | : public lldb_private::process_gdb_remote::GDBRemoteCommunicationClient { |
34 | public: |
35 | static bool IsDebugServer() { return LLDB_SERVER_IS_DEBUGSERVER; } |
36 | static bool IsLldbServer() { return !IsDebugServer(); } |
37 | |
38 | /// Launches the server, connects it to the client and returns the client. If |
39 | /// Log is non-empty, the server will write it's log to this file. |
40 | static llvm::Expected<std::unique_ptr<TestClient>> launch(llvm::StringRef Log); |
41 | |
42 | /// Launches the server, while specifying the inferior on its command line. |
43 | /// When the client connects, it already has a process ready. |
44 | static llvm::Expected<std::unique_ptr<TestClient>> |
45 | launch(llvm::StringRef Log, llvm::ArrayRef<llvm::StringRef> InferiorArgs); |
46 | |
47 | /// Allows user to pass additional arguments to the server. Be careful when |
48 | /// using this for generic tests, as the two stubs have different |
49 | /// command-line interfaces. |
50 | static llvm::Expected<std::unique_ptr<TestClient>> |
51 | launchCustom(llvm::StringRef Log, bool disable_stdio, |
52 | llvm::ArrayRef<llvm::StringRef> ServerArgs, |
53 | llvm::ArrayRef<llvm::StringRef> InferiorArgs); |
54 | |
55 | ~TestClient() override; |
56 | llvm::Error SetInferior(llvm::ArrayRef<std::string> inferior_args); |
57 | llvm::Error ListThreadsInStopReply(); |
58 | llvm::Error SetBreakpoint(unsigned long address); |
59 | llvm::Error ContinueAll(); |
60 | llvm::Error ContinueThread(unsigned long thread_id); |
61 | const ProcessInfo &GetProcessInfo(); |
62 | llvm::Expected<JThreadsInfo> GetJThreadsInfo(); |
63 | const StopReply &GetLatestStopReply(); |
64 | template <typename T> llvm::Expected<const T &> GetLatestStopReplyAs() { |
65 | assert(m_stop_reply); |
66 | if (const auto *Reply = llvm::dyn_cast<T>(m_stop_reply.get())) |
67 | return *Reply; |
68 | return llvm::make_error<llvm::StringError>( |
69 | Args: llvm::formatv(Fmt: "Unexpected Stop Reply {0}" , Vals: m_stop_reply->getKind()), |
70 | Args: llvm::inconvertibleErrorCode()); |
71 | } |
72 | llvm::Error SendMessage(llvm::StringRef message); |
73 | llvm::Error SendMessage(llvm::StringRef message, |
74 | std::string &response_string); |
75 | llvm::Error SendMessage(llvm::StringRef message, std::string &response_string, |
76 | PacketResult expected_result); |
77 | |
78 | template <typename P, typename... CreateArgs> |
79 | llvm::Expected<typename P::result_type> SendMessage(llvm::StringRef Message, |
80 | CreateArgs &&... Args); |
81 | unsigned int GetPcRegisterId(); |
82 | |
83 | private: |
84 | TestClient(std::unique_ptr<lldb_private::Connection> Conn); |
85 | |
86 | llvm::Error initializeConnection(); |
87 | llvm::Error qProcessInfo(); |
88 | llvm::Error qRegisterInfos(); |
89 | llvm::Error queryProcess(); |
90 | llvm::Error Continue(llvm::StringRef message); |
91 | std::string FormatFailedResult( |
92 | const std::string &message, |
93 | lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult |
94 | result); |
95 | |
96 | std::optional<ProcessInfo> m_process_info; |
97 | std::unique_ptr<StopReply> m_stop_reply; |
98 | std::vector<lldb_private::RegisterInfo> m_register_infos; |
99 | unsigned int m_pc_register = LLDB_INVALID_REGNUM; |
100 | }; |
101 | |
102 | template <typename P, typename... CreateArgs> |
103 | llvm::Expected<typename P::result_type> |
104 | TestClient::SendMessage(llvm::StringRef Message, CreateArgs &&... Args) { |
105 | std::string ResponseText; |
106 | if (llvm::Error E = SendMessage(message: Message, response_string&: ResponseText)) |
107 | return std::move(E); |
108 | return P::create(ResponseText, std::forward<CreateArgs>(Args)...); |
109 | } |
110 | |
111 | } // namespace llgs_tests |
112 | |
113 | #endif // LLDB_UNITTESTS_TOOLS_LLDB_SERVER_TESTS_TESTCLIENT_H |
114 | |