xref: /llvm-project/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp (revision 41b6d5863fef94bb3a9d184802c5bb6e2759da15)
1 //===-- GDBRemoteClientBaseTest.cpp ---------------------------------------===//
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 #include <future>
9 
10 #include "GDBRemoteTestUtils.h"
11 
12 #include "Plugins/Process/Utility/LinuxSignals.h"
13 #include "Plugins/Process/gdb-remote/GDBRemoteClientBase.h"
14 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
15 #include "lldb/Utility/GDBRemote.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/Testing/Support/Error.h"
18 
19 using namespace lldb_private::process_gdb_remote;
20 using namespace lldb_private;
21 using namespace lldb;
22 typedef GDBRemoteCommunication::PacketResult PacketResult;
23 
24 namespace {
25 
26 struct MockDelegate : public GDBRemoteClientBase::ContinueDelegate {
27   std::string output;
28   std::string misc_data;
29   unsigned stop_reply_called = 0;
30   std::vector<std::string> structured_data_packets;
31 
HandleAsyncStdout__anonaaf37e580111::MockDelegate32   void HandleAsyncStdout(llvm::StringRef out) override { output += out; }
HandleAsyncMisc__anonaaf37e580111::MockDelegate33   void HandleAsyncMisc(llvm::StringRef data) override { misc_data += data; }
HandleStopReply__anonaaf37e580111::MockDelegate34   void HandleStopReply() override { ++stop_reply_called; }
35 
HandleAsyncStructuredDataPacket__anonaaf37e580111::MockDelegate36   void HandleAsyncStructuredDataPacket(llvm::StringRef data) override {
37     structured_data_packets.push_back(std::string(data));
38   }
39 };
40 
41 struct TestClient : public GDBRemoteClientBase {
TestClient__anonaaf37e580111::TestClient42   TestClient() : GDBRemoteClientBase("test.client") {
43     m_send_acks = false;
44   }
45 };
46 
47 class GDBRemoteClientBaseTest : public GDBRemoteTest {
48 public:
SetUp()49   void SetUp() override {
50     ASSERT_THAT_ERROR(GDBRemoteCommunication::ConnectLocally(client, server),
51                       llvm::Succeeded());
52     ASSERT_EQ(TestClient::eBroadcastBitRunPacketSent,
53               listener_sp->StartListeningForEvents(
54                   &client, TestClient::eBroadcastBitRunPacketSent));
55   }
56 
57 protected:
58   // We don't have a process to get the interrupt timeout from, so make one up.
59   static std::chrono::seconds g_timeout;
60   TestClient client;
61   MockServer server;
62   MockDelegate delegate;
63   ListenerSP listener_sp = Listener::MakeListener("listener");
64 
SendCPacket(StringExtractorGDBRemote & response)65   StateType SendCPacket(StringExtractorGDBRemote &response) {
66     return client.SendContinuePacketAndWaitForResponse(delegate, LinuxSignals(),
67                                                        "c", g_timeout,
68                                                        response);
69   }
70 
WaitForRunEvent()71   void WaitForRunEvent() {
72     EventSP event_sp;
73     listener_sp->GetEventForBroadcasterWithType(
74         &client, TestClient::eBroadcastBitRunPacketSent, event_sp,
75         std::nullopt);
76   }
77 };
78 
79 std::chrono::seconds GDBRemoteClientBaseTest::g_timeout(10);
80 
81 } // end anonymous namespace
82 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndWait)83 TEST_F(GDBRemoteClientBaseTest, SendContinueAndWait) {
84   StringExtractorGDBRemote response;
85 
86   // Continue. The inferior will stop with a signal.
87   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
88   ASSERT_EQ(eStateStopped, SendCPacket(response));
89   ASSERT_EQ("T01", response.GetStringRef());
90   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
91   ASSERT_EQ("c", response.GetStringRef());
92 
93   // Continue. The inferior will exit.
94   ASSERT_EQ(PacketResult::Success, server.SendPacket("W01"));
95   ASSERT_EQ(eStateExited, SendCPacket(response));
96   ASSERT_EQ("W01", response.GetStringRef());
97   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
98   ASSERT_EQ("c", response.GetStringRef());
99 
100   // Continue. The inferior will get killed.
101   ASSERT_EQ(PacketResult::Success, server.SendPacket("X01"));
102   ASSERT_EQ(eStateExited, SendCPacket(response));
103   ASSERT_EQ("X01", response.GetStringRef());
104   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
105   ASSERT_EQ("c", response.GetStringRef());
106 }
107 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndAsyncSignal)108 TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) {
109   StringExtractorGDBRemote continue_response, response;
110 
111   // SendAsyncSignal should do nothing when we are not running.
112   ASSERT_FALSE(client.SendAsyncSignal(0x47, g_timeout));
113 
114   // Continue. After the run packet is sent, send an async signal.
115   std::future<StateType> continue_state = std::async(
116       std::launch::async, [&] { return SendCPacket(continue_response); });
117   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
118   ASSERT_EQ("c", response.GetStringRef());
119   WaitForRunEvent();
120 
121   std::future<bool> async_result = std::async(std::launch::async, [&] {
122     return client.SendAsyncSignal(0x47, g_timeout);
123   });
124 
125   // First we'll get interrupted.
126   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
127   ASSERT_EQ("\x03", response.GetStringRef());
128   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
129 
130   // Then we get the signal packet.
131   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
132   ASSERT_EQ("C47", response.GetStringRef());
133   ASSERT_TRUE(async_result.get());
134 
135   // And we report back a signal stop.
136   ASSERT_EQ(PacketResult::Success, server.SendPacket("T47"));
137   ASSERT_EQ(eStateStopped, continue_state.get());
138   ASSERT_EQ("T47", continue_response.GetStringRef());
139 }
140 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndAsyncPacket)141 TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket) {
142   StringExtractorGDBRemote continue_response, async_response, response;
143 
144   // Continue. After the run packet is sent, send an async packet.
145   std::future<StateType> continue_state = std::async(
146       std::launch::async, [&] { return SendCPacket(continue_response); });
147   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
148   ASSERT_EQ("c", response.GetStringRef());
149   WaitForRunEvent();
150 
151   // Sending without async enabled should fail.
152   ASSERT_EQ(PacketResult::ErrorSendFailed,
153             client.SendPacketAndWaitForResponse("qTest1", response));
154 
155   std::future<PacketResult> async_result = std::async(std::launch::async, [&] {
156     return client.SendPacketAndWaitForResponse("qTest2", async_response,
157                                                g_timeout);
158   });
159 
160   // First we'll get interrupted.
161   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
162   ASSERT_EQ("\x03", response.GetStringRef());
163   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
164 
165   // Then we get the async packet.
166   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
167   ASSERT_EQ("qTest2", response.GetStringRef());
168 
169   // Send the response and receive it.
170   ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest2"));
171   ASSERT_EQ(PacketResult::Success, async_result.get());
172   ASSERT_EQ("QTest2", async_response.GetStringRef());
173 
174   // And we get resumed again.
175   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
176   ASSERT_EQ("c", response.GetStringRef());
177   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
178   ASSERT_EQ(eStateStopped, continue_state.get());
179   ASSERT_EQ("T01", continue_response.GetStringRef());
180 }
181 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndInterrupt)182 TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt) {
183   StringExtractorGDBRemote continue_response, response;
184 
185   // Interrupt should do nothing when we're not running.
186   ASSERT_FALSE(client.Interrupt(g_timeout));
187 
188   // Continue. After the run packet is sent, send an interrupt.
189   std::future<StateType> continue_state = std::async(
190       std::launch::async, [&] { return SendCPacket(continue_response); });
191   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
192   ASSERT_EQ("c", response.GetStringRef());
193   WaitForRunEvent();
194 
195   std::future<bool> async_result = std::async(
196       std::launch::async, [&] { return client.Interrupt(g_timeout); });
197 
198   // We get interrupted.
199   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
200   ASSERT_EQ("\x03", response.GetStringRef());
201   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
202 
203   // And that's it.
204   ASSERT_EQ(eStateStopped, continue_state.get());
205   ASSERT_EQ("T13", continue_response.GetStringRef());
206   ASSERT_TRUE(async_result.get());
207 }
208 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndLateInterrupt)209 TEST_F(GDBRemoteClientBaseTest, SendContinueAndLateInterrupt) {
210   StringExtractorGDBRemote continue_response, response;
211 
212   // Continue. After the run packet is sent, send an interrupt.
213   std::future<StateType> continue_state = std::async(
214       std::launch::async, [&] { return SendCPacket(continue_response); });
215   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
216   ASSERT_EQ("c", response.GetStringRef());
217   WaitForRunEvent();
218 
219   std::future<bool> async_result = std::async(
220       std::launch::async, [&] { return client.Interrupt(g_timeout); });
221 
222   // However, the target stops due to a different reason than the original
223   // interrupt.
224   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
225   ASSERT_EQ("\x03", response.GetStringRef());
226   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
227   ASSERT_EQ(eStateStopped, continue_state.get());
228   ASSERT_EQ("T01", continue_response.GetStringRef());
229   ASSERT_TRUE(async_result.get());
230 
231   // The subsequent continue packet should work normally.
232   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
233   ASSERT_EQ(eStateStopped, SendCPacket(response));
234   ASSERT_EQ("T01", response.GetStringRef());
235   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
236   ASSERT_EQ("c", response.GetStringRef());
237 }
238 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndInterrupt2PacketBug)239 TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) {
240   StringExtractorGDBRemote continue_response, async_response, response;
241 
242   // Interrupt should do nothing when we're not running.
243   ASSERT_FALSE(client.Interrupt(g_timeout));
244 
245   // Continue. After the run packet is sent, send an async signal.
246   std::future<StateType> continue_state = std::async(
247       std::launch::async, [&] { return SendCPacket(continue_response); });
248   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
249   ASSERT_EQ("c", response.GetStringRef());
250   WaitForRunEvent();
251 
252   std::future<bool> interrupt_result = std::async(
253       std::launch::async, [&] { return client.Interrupt(g_timeout); });
254 
255   // We get interrupted. We'll send two packets to simulate a buggy stub.
256   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
257   ASSERT_EQ("\x03", response.GetStringRef());
258   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
259   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
260 
261   // We should stop.
262   ASSERT_EQ(eStateStopped, continue_state.get());
263   ASSERT_EQ("T13", continue_response.GetStringRef());
264   ASSERT_TRUE(interrupt_result.get());
265 
266   // Packet stream should remain synchronized.
267   std::future<PacketResult> send_result = std::async(std::launch::async, [&] {
268     return client.SendPacketAndWaitForResponse("qTest", async_response);
269   });
270   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
271   ASSERT_EQ("qTest", response.GetStringRef());
272   ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest"));
273   ASSERT_EQ(PacketResult::Success, send_result.get());
274   ASSERT_EQ("QTest", async_response.GetStringRef());
275 }
276 
TEST_F(GDBRemoteClientBaseTest,SendContinueDelegateInterface)277 TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateInterface) {
278   StringExtractorGDBRemote response;
279 
280   // Continue. We'll have the server send a bunch of async packets before it
281   // stops.
282   ASSERT_EQ(PacketResult::Success, server.SendPacket("O4142"));
283   ASSERT_EQ(PacketResult::Success, server.SendPacket("Apro"));
284   ASSERT_EQ(PacketResult::Success, server.SendPacket("O4344"));
285   ASSERT_EQ(PacketResult::Success, server.SendPacket("Afile"));
286   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
287   ASSERT_EQ(eStateStopped, SendCPacket(response));
288   ASSERT_EQ("T01", response.GetStringRef());
289   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
290   ASSERT_EQ("c", response.GetStringRef());
291 
292   EXPECT_EQ("ABCD", delegate.output);
293   EXPECT_EQ("profile", delegate.misc_data);
294   EXPECT_EQ(1u, delegate.stop_reply_called);
295 }
296 
TEST_F(GDBRemoteClientBaseTest,SendContinueDelegateStructuredDataReceipt)297 TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateStructuredDataReceipt) {
298   // Build the plain-text version of the JSON data we will have the
299   // server send.
300   const std::string json_payload =
301       "{ \"type\": \"MyFeatureType\", "
302       "  \"elements\": [ \"entry1\", \"entry2\" ] }";
303   const std::string json_packet = "JSON-async:" + json_payload;
304 
305   // Escape it properly for transit.
306   StreamGDBRemote stream;
307   stream.PutEscapedBytes(json_packet.c_str(), json_packet.length());
308   stream.Flush();
309 
310   StringExtractorGDBRemote response;
311 
312   // Send async structured data packet, then stop.
313   ASSERT_EQ(PacketResult::Success, server.SendPacket(stream.GetData()));
314   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
315   ASSERT_EQ(eStateStopped, SendCPacket(response));
316   ASSERT_EQ("T01", response.GetStringRef());
317   ASSERT_EQ(1ul, delegate.structured_data_packets.size());
318 
319   // Verify the packet contents.  It should have been unescaped upon packet
320   // reception.
321   ASSERT_EQ(json_packet, delegate.structured_data_packets[0]);
322 }
323 
TEST_F(GDBRemoteClientBaseTest,InterruptNoResponse)324 TEST_F(GDBRemoteClientBaseTest, InterruptNoResponse) {
325   StringExtractorGDBRemote continue_response, response;
326 
327   // Continue. After the run packet is sent, send an interrupt.
328   std::future<StateType> continue_state = std::async(
329       std::launch::async, [&] { return SendCPacket(continue_response); });
330   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
331   ASSERT_EQ("c", response.GetStringRef());
332   WaitForRunEvent();
333 
334   std::future<bool> async_result = std::async(
335       std::launch::async, [&] { return client.Interrupt(g_timeout); });
336 
337   // We get interrupted, but we don't send a stop packet.
338   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
339   ASSERT_EQ("\x03", response.GetStringRef());
340 
341   // The functions should still terminate (after a timeout).
342   ASSERT_TRUE(async_result.get());
343   ASSERT_EQ(eStateInvalid, continue_state.get());
344 }
345 
TEST_F(GDBRemoteClientBaseTest,SendPacketAndReceiveResponseWithOutputSupport)346 TEST_F(GDBRemoteClientBaseTest, SendPacketAndReceiveResponseWithOutputSupport) {
347   StringExtractorGDBRemote response;
348   StreamString command_output;
349 
350   ASSERT_EQ(PacketResult::Success, server.SendPacket("O"));
351   ASSERT_EQ(PacketResult::Success, server.SendPacket("O48656c6c6f2c"));
352   ASSERT_EQ(PacketResult::Success, server.SendPacket("O20"));
353   ASSERT_EQ(PacketResult::Success, server.SendPacket("O"));
354   ASSERT_EQ(PacketResult::Success, server.SendPacket("O776f726c64"));
355   ASSERT_EQ(PacketResult::Success, server.SendPacket("OK"));
356 
357   PacketResult result = client.SendPacketAndReceiveResponseWithOutputSupport(
358       "qRcmd,test", response, g_timeout,
359       [&command_output](llvm::StringRef output) { command_output << output; });
360 
361   ASSERT_EQ(PacketResult::Success, result);
362   ASSERT_EQ("OK", response.GetStringRef());
363   ASSERT_EQ("Hello, world", command_output.GetString().str());
364 }
365