1 //===-- GDBRemoteClientBaseTest.cpp ---------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 #include "GDBRemoteTestUtils.h"
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"
19 using namespace lldb_private::process_gdb_remote
;
20 using namespace lldb_private
;
22 typedef GDBRemoteCommunication::PacketResult PacketResult
;
26 struct MockDelegate
: public GDBRemoteClientBase::ContinueDelegate
{
28 std::string misc_data
;
29 unsigned stop_reply_called
= 0;
30 std::vector
<std::string
> structured_data_packets
;
32 void HandleAsyncStdout(llvm::StringRef out
) override
{ output
+= out
; }
33 void HandleAsyncMisc(llvm::StringRef data
) override
{ misc_data
+= data
; }
34 void HandleStopReply() override
{ ++stop_reply_called
; }
36 void HandleAsyncStructuredDataPacket(llvm::StringRef data
) override
{
37 structured_data_packets
.push_back(std::string(data
));
41 struct TestClient
: public GDBRemoteClientBase
{
42 TestClient() : GDBRemoteClientBase("test.client") {
47 class GDBRemoteClientBaseTest
: public GDBRemoteTest
{
49 void SetUp() override
{
50 ASSERT_THAT_ERROR(GDBRemoteCommunication::ConnectLocally(client
, server
),
52 ASSERT_EQ(TestClient::eBroadcastBitRunPacketSent
,
53 listener_sp
->StartListeningForEvents(
54 &client
, TestClient::eBroadcastBitRunPacketSent
));
58 // We don't have a process to get the interrupt timeout from, so make one up.
59 static std::chrono::seconds g_timeout
;
62 MockDelegate delegate
;
63 ListenerSP listener_sp
= Listener::MakeListener("listener");
65 StateType
SendCPacket(StringExtractorGDBRemote
&response
) {
66 return client
.SendContinuePacketAndWaitForResponse(delegate
, LinuxSignals(),
71 void WaitForRunEvent() {
73 listener_sp
->GetEventForBroadcasterWithType(
74 &client
, TestClient::eBroadcastBitRunPacketSent
, event_sp
,
79 std::chrono::seconds
GDBRemoteClientBaseTest::g_timeout(10);
81 } // end anonymous namespace
83 TEST_F(GDBRemoteClientBaseTest
, SendContinueAndWait
) {
84 StringExtractorGDBRemote response
;
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());
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());
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());
108 TEST_F(GDBRemoteClientBaseTest
, SendContinueAndAsyncSignal
) {
109 StringExtractorGDBRemote continue_response
, response
;
111 // SendAsyncSignal should do nothing when we are not running.
112 ASSERT_FALSE(client
.SendAsyncSignal(0x47, g_timeout
));
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());
121 std::future
<bool> async_result
= std::async(std::launch::async
, [&] {
122 return client
.SendAsyncSignal(0x47, g_timeout
);
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"));
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());
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());
141 TEST_F(GDBRemoteClientBaseTest
, SendContinueAndAsyncPacket
) {
142 StringExtractorGDBRemote continue_response
, async_response
, response
;
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());
151 // Sending without async enabled should fail.
152 ASSERT_EQ(PacketResult::ErrorSendFailed
,
153 client
.SendPacketAndWaitForResponse("qTest1", response
));
155 std::future
<PacketResult
> async_result
= std::async(std::launch::async
, [&] {
156 return client
.SendPacketAndWaitForResponse("qTest2", async_response
,
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"));
165 // Then we get the async packet.
166 ASSERT_EQ(PacketResult::Success
, server
.GetPacket(response
));
167 ASSERT_EQ("qTest2", response
.GetStringRef());
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());
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());
182 TEST_F(GDBRemoteClientBaseTest
, SendContinueAndInterrupt
) {
183 StringExtractorGDBRemote continue_response
, response
;
185 // Interrupt should do nothing when we're not running.
186 ASSERT_FALSE(client
.Interrupt(g_timeout
));
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());
195 std::future
<bool> async_result
= std::async(
196 std::launch::async
, [&] { return client
.Interrupt(g_timeout
); });
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"));
204 ASSERT_EQ(eStateStopped
, continue_state
.get());
205 ASSERT_EQ("T13", continue_response
.GetStringRef());
206 ASSERT_TRUE(async_result
.get());
209 TEST_F(GDBRemoteClientBaseTest
, SendContinueAndLateInterrupt
) {
210 StringExtractorGDBRemote continue_response
, response
;
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());
219 std::future
<bool> async_result
= std::async(
220 std::launch::async
, [&] { return client
.Interrupt(g_timeout
); });
222 // However, the target stops due to a different reason than the original
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());
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());
239 TEST_F(GDBRemoteClientBaseTest
, SendContinueAndInterrupt2PacketBug
) {
240 StringExtractorGDBRemote continue_response
, async_response
, response
;
242 // Interrupt should do nothing when we're not running.
243 ASSERT_FALSE(client
.Interrupt(g_timeout
));
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());
252 std::future
<bool> interrupt_result
= std::async(
253 std::launch::async
, [&] { return client
.Interrupt(g_timeout
); });
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"));
262 ASSERT_EQ(eStateStopped
, continue_state
.get());
263 ASSERT_EQ("T13", continue_response
.GetStringRef());
264 ASSERT_TRUE(interrupt_result
.get());
266 // Packet stream should remain synchronized.
267 std::future
<PacketResult
> send_result
= std::async(std::launch::async
, [&] {
268 return client
.SendPacketAndWaitForResponse("qTest", async_response
);
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());
277 TEST_F(GDBRemoteClientBaseTest
, SendContinueDelegateInterface
) {
278 StringExtractorGDBRemote response
;
280 // Continue. We'll have the server send a bunch of async packets before it
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());
292 EXPECT_EQ("ABCD", delegate
.output
);
293 EXPECT_EQ("profile", delegate
.misc_data
);
294 EXPECT_EQ(1u, delegate
.stop_reply_called
);
297 TEST_F(GDBRemoteClientBaseTest
, SendContinueDelegateStructuredDataReceipt
) {
298 // Build the plain-text version of the JSON data we will have the
300 const std::string json_payload
=
301 "{ \"type\": \"MyFeatureType\", "
302 " \"elements\": [ \"entry1\", \"entry2\" ] }";
303 const std::string json_packet
= "JSON-async:" + json_payload
;
305 // Escape it properly for transit.
306 StreamGDBRemote stream
;
307 stream
.PutEscapedBytes(json_packet
.c_str(), json_packet
.length());
310 StringExtractorGDBRemote response
;
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());
319 // Verify the packet contents. It should have been unescaped upon packet
321 ASSERT_EQ(json_packet
, delegate
.structured_data_packets
[0]);
324 TEST_F(GDBRemoteClientBaseTest
, InterruptNoResponse
) {
325 StringExtractorGDBRemote continue_response
, response
;
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());
334 std::future
<bool> async_result
= std::async(
335 std::launch::async
, [&] { return client
.Interrupt(g_timeout
); });
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());
341 // The functions should still terminate (after a timeout).
342 ASSERT_TRUE(async_result
.get());
343 ASSERT_EQ(eStateInvalid
, continue_state
.get());
346 TEST_F(GDBRemoteClientBaseTest
, SendPacketAndReceiveResponseWithOutputSupport
) {
347 StringExtractorGDBRemote response
;
348 StreamString command_output
;
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"));
357 PacketResult result
= client
.SendPacketAndReceiveResponseWithOutputSupport(
358 "qRcmd,test", response
, g_timeout
,
359 [&command_output
](llvm::StringRef output
) { command_output
<< output
; });
361 ASSERT_EQ(PacketResult::Success
, result
);
362 ASSERT_EQ("OK", response
.GetStringRef());
363 ASSERT_EQ("Hello, world", command_output
.GetString().str());