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