xref: /llvm-project/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp (revision 41b6d5863fef94bb3a9d184802c5bb6e2759da15)
180814287SRaphael Isemann //===-- GDBRemoteClientBaseTest.cpp ---------------------------------------===//
28c1b6bd7SPavel Labath //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68c1b6bd7SPavel Labath //
78c1b6bd7SPavel Labath //===----------------------------------------------------------------------===//
88c1b6bd7SPavel Labath #include <future>
98c1b6bd7SPavel Labath 
1056d7262bSPavel Labath #include "GDBRemoteTestUtils.h"
118c1b6bd7SPavel Labath 
12*41b6d586SAlex Langford #include "Plugins/Process/Utility/LinuxSignals.h"
138c1b6bd7SPavel Labath #include "Plugins/Process/gdb-remote/GDBRemoteClientBase.h"
148c1b6bd7SPavel Labath #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
15ff5225bfSJonas Devlieghere #include "lldb/Utility/GDBRemote.h"
168c1b6bd7SPavel Labath #include "llvm/ADT/STLExtras.h"
1793df2fbeSPavel Labath #include "llvm/Testing/Support/Error.h"
188c1b6bd7SPavel Labath 
198c1b6bd7SPavel Labath using namespace lldb_private::process_gdb_remote;
208c1b6bd7SPavel Labath using namespace lldb_private;
218c1b6bd7SPavel Labath using namespace lldb;
228c1b6bd7SPavel Labath typedef GDBRemoteCommunication::PacketResult PacketResult;
238c1b6bd7SPavel Labath 
24b9c1b51eSKate Stone namespace {
258c1b6bd7SPavel Labath 
26b9c1b51eSKate Stone struct MockDelegate : public GDBRemoteClientBase::ContinueDelegate {
278c1b6bd7SPavel Labath   std::string output;
288c1b6bd7SPavel Labath   std::string misc_data;
298c1b6bd7SPavel Labath   unsigned stop_reply_called = 0;
30fcdb1af6STodd Fiala   std::vector<std::string> structured_data_packets;
318c1b6bd7SPavel Labath 
HandleAsyncStdout__anonaaf37e580111::MockDelegate321756630dSRaphael Isemann   void HandleAsyncStdout(llvm::StringRef out) override { output += out; }
HandleAsyncMisc__anonaaf37e580111::MockDelegate331756630dSRaphael Isemann   void HandleAsyncMisc(llvm::StringRef data) override { misc_data += data; }
HandleStopReply__anonaaf37e580111::MockDelegate341756630dSRaphael Isemann   void HandleStopReply() override { ++stop_reply_called; }
3549178e5eSTodd Fiala 
HandleAsyncStructuredDataPacket__anonaaf37e580111::MockDelegate361756630dSRaphael Isemann   void HandleAsyncStructuredDataPacket(llvm::StringRef data) override {
37adcd0268SBenjamin Kramer     structured_data_packets.push_back(std::string(data));
3849178e5eSTodd Fiala   }
398c1b6bd7SPavel Labath };
408c1b6bd7SPavel Labath 
41b9c1b51eSKate Stone struct TestClient : public GDBRemoteClientBase {
TestClient__anonaaf37e580111::TestClient42bdb4468dSMichał Górny   TestClient() : GDBRemoteClientBase("test.client") {
43b9c1b51eSKate Stone     m_send_acks = false;
44b9c1b51eSKate Stone   }
458c1b6bd7SPavel Labath };
468c1b6bd7SPavel Labath 
4793df2fbeSPavel Labath class GDBRemoteClientBaseTest : public GDBRemoteTest {
4893df2fbeSPavel Labath public:
SetUp()4993df2fbeSPavel Labath   void SetUp() override {
509e046f02SJonas Devlieghere     ASSERT_THAT_ERROR(GDBRemoteCommunication::ConnectLocally(client, server),
519e046f02SJonas Devlieghere                       llvm::Succeeded());
5293df2fbeSPavel Labath     ASSERT_EQ(TestClient::eBroadcastBitRunPacketSent,
5393df2fbeSPavel Labath               listener_sp->StartListeningForEvents(
5493df2fbeSPavel Labath                   &client, TestClient::eBroadcastBitRunPacketSent));
5593df2fbeSPavel Labath   }
5693df2fbeSPavel Labath 
5793df2fbeSPavel Labath protected:
58379f24ffSJim Ingham   // We don't have a process to get the interrupt timeout from, so make one up.
59379f24ffSJim Ingham   static std::chrono::seconds g_timeout;
608c1b6bd7SPavel Labath   TestClient client;
618c1b6bd7SPavel Labath   MockServer server;
6293df2fbeSPavel Labath   MockDelegate delegate;
6393df2fbeSPavel Labath   ListenerSP listener_sp = Listener::MakeListener("listener");
648c1b6bd7SPavel Labath 
SendCPacket(StringExtractorGDBRemote & response)65b9c1b51eSKate Stone   StateType SendCPacket(StringExtractorGDBRemote &response) {
66b9c1b51eSKate Stone     return client.SendContinuePacketAndWaitForResponse(delegate, LinuxSignals(),
67379f24ffSJim Ingham                                                        "c", g_timeout,
68379f24ffSJim Ingham                                                        response);
698c1b6bd7SPavel Labath   }
708c1b6bd7SPavel Labath 
WaitForRunEvent()71b9c1b51eSKate Stone   void WaitForRunEvent() {
728c1b6bd7SPavel Labath     EventSP event_sp;
73d35031e1SPavel Labath     listener_sp->GetEventForBroadcasterWithType(
74d2a6114fSKazu Hirata         &client, TestClient::eBroadcastBitRunPacketSent, event_sp,
75d2a6114fSKazu Hirata         std::nullopt);
768c1b6bd7SPavel Labath   }
778c1b6bd7SPavel Labath };
788c1b6bd7SPavel Labath 
79379f24ffSJim Ingham std::chrono::seconds GDBRemoteClientBaseTest::g_timeout(10);
80379f24ffSJim Ingham 
818c1b6bd7SPavel Labath } // end anonymous namespace
828c1b6bd7SPavel Labath 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndWait)83b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndWait) {
848c1b6bd7SPavel Labath   StringExtractorGDBRemote response;
858c1b6bd7SPavel Labath 
868c1b6bd7SPavel Labath   // Continue. The inferior will stop with a signal.
8793df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
8893df2fbeSPavel Labath   ASSERT_EQ(eStateStopped, SendCPacket(response));
898c1b6bd7SPavel Labath   ASSERT_EQ("T01", response.GetStringRef());
9093df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
918c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
928c1b6bd7SPavel Labath 
938c1b6bd7SPavel Labath   // Continue. The inferior will exit.
9493df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("W01"));
9593df2fbeSPavel Labath   ASSERT_EQ(eStateExited, SendCPacket(response));
968c1b6bd7SPavel Labath   ASSERT_EQ("W01", response.GetStringRef());
9793df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
988c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
998c1b6bd7SPavel Labath 
1008c1b6bd7SPavel Labath   // Continue. The inferior will get killed.
10193df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("X01"));
10293df2fbeSPavel Labath   ASSERT_EQ(eStateExited, SendCPacket(response));
1038c1b6bd7SPavel Labath   ASSERT_EQ("X01", response.GetStringRef());
10493df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1058c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
1068c1b6bd7SPavel Labath }
1078c1b6bd7SPavel Labath 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndAsyncSignal)108b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) {
1098c1b6bd7SPavel Labath   StringExtractorGDBRemote continue_response, response;
1108c1b6bd7SPavel Labath 
1118c1b6bd7SPavel Labath   // SendAsyncSignal should do nothing when we are not running.
112379f24ffSJim Ingham   ASSERT_FALSE(client.SendAsyncSignal(0x47, g_timeout));
1138c1b6bd7SPavel Labath 
1148c1b6bd7SPavel Labath   // Continue. After the run packet is sent, send an async signal.
115b9c1b51eSKate Stone   std::future<StateType> continue_state = std::async(
11693df2fbeSPavel Labath       std::launch::async, [&] { return SendCPacket(continue_response); });
11793df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1188c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
11993df2fbeSPavel Labath   WaitForRunEvent();
1208c1b6bd7SPavel Labath 
121379f24ffSJim Ingham   std::future<bool> async_result = std::async(std::launch::async, [&] {
122379f24ffSJim Ingham     return client.SendAsyncSignal(0x47, g_timeout);
123379f24ffSJim Ingham   });
1248c1b6bd7SPavel Labath 
1258c1b6bd7SPavel Labath   // First we'll get interrupted.
12693df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1278c1b6bd7SPavel Labath   ASSERT_EQ("\x03", response.GetStringRef());
12893df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
1298c1b6bd7SPavel Labath 
1308c1b6bd7SPavel Labath   // Then we get the signal packet.
13193df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1328c1b6bd7SPavel Labath   ASSERT_EQ("C47", response.GetStringRef());
1338c1b6bd7SPavel Labath   ASSERT_TRUE(async_result.get());
1348c1b6bd7SPavel Labath 
1358c1b6bd7SPavel Labath   // And we report back a signal stop.
13693df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T47"));
1378c1b6bd7SPavel Labath   ASSERT_EQ(eStateStopped, continue_state.get());
1388c1b6bd7SPavel Labath   ASSERT_EQ("T47", continue_response.GetStringRef());
1398c1b6bd7SPavel Labath }
1408c1b6bd7SPavel Labath 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndAsyncPacket)141b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket) {
1428c1b6bd7SPavel Labath   StringExtractorGDBRemote continue_response, async_response, response;
1438c1b6bd7SPavel Labath 
1448c1b6bd7SPavel Labath   // Continue. After the run packet is sent, send an async packet.
145b9c1b51eSKate Stone   std::future<StateType> continue_state = std::async(
14693df2fbeSPavel Labath       std::launch::async, [&] { return SendCPacket(continue_response); });
14793df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1488c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
14993df2fbeSPavel Labath   WaitForRunEvent();
1508c1b6bd7SPavel Labath 
1518c1b6bd7SPavel Labath   // Sending without async enabled should fail.
152379f24ffSJim Ingham   ASSERT_EQ(PacketResult::ErrorSendFailed,
153379f24ffSJim Ingham             client.SendPacketAndWaitForResponse("qTest1", response));
1548c1b6bd7SPavel Labath 
1558c1b6bd7SPavel Labath   std::future<PacketResult> async_result = std::async(std::launch::async, [&] {
15693df2fbeSPavel Labath     return client.SendPacketAndWaitForResponse("qTest2", async_response,
157379f24ffSJim Ingham                                                g_timeout);
1588c1b6bd7SPavel Labath   });
1598c1b6bd7SPavel Labath 
1608c1b6bd7SPavel Labath   // First we'll get interrupted.
16193df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1628c1b6bd7SPavel Labath   ASSERT_EQ("\x03", response.GetStringRef());
16393df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
1648c1b6bd7SPavel Labath 
1658c1b6bd7SPavel Labath   // Then we get the async packet.
16693df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1678c1b6bd7SPavel Labath   ASSERT_EQ("qTest2", response.GetStringRef());
1688c1b6bd7SPavel Labath 
1698c1b6bd7SPavel Labath   // Send the response and receive it.
17093df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest2"));
1718c1b6bd7SPavel Labath   ASSERT_EQ(PacketResult::Success, async_result.get());
1728c1b6bd7SPavel Labath   ASSERT_EQ("QTest2", async_response.GetStringRef());
1738c1b6bd7SPavel Labath 
1748c1b6bd7SPavel Labath   // And we get resumed again.
17593df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1768c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
17793df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
1788c1b6bd7SPavel Labath   ASSERT_EQ(eStateStopped, continue_state.get());
1798c1b6bd7SPavel Labath   ASSERT_EQ("T01", continue_response.GetStringRef());
1808c1b6bd7SPavel Labath }
1818c1b6bd7SPavel Labath 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndInterrupt)182b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt) {
1838c1b6bd7SPavel Labath   StringExtractorGDBRemote continue_response, response;
1848c1b6bd7SPavel Labath 
1858c1b6bd7SPavel Labath   // Interrupt should do nothing when we're not running.
186379f24ffSJim Ingham   ASSERT_FALSE(client.Interrupt(g_timeout));
1878c1b6bd7SPavel Labath 
1888c1b6bd7SPavel Labath   // Continue. After the run packet is sent, send an interrupt.
189b9c1b51eSKate Stone   std::future<StateType> continue_state = std::async(
19093df2fbeSPavel Labath       std::launch::async, [&] { return SendCPacket(continue_response); });
19193df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1928c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
19393df2fbeSPavel Labath   WaitForRunEvent();
1948c1b6bd7SPavel Labath 
195379f24ffSJim Ingham   std::future<bool> async_result = std::async(
196379f24ffSJim Ingham       std::launch::async, [&] { return client.Interrupt(g_timeout); });
1978c1b6bd7SPavel Labath 
1988c1b6bd7SPavel Labath   // We get interrupted.
19993df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2008c1b6bd7SPavel Labath   ASSERT_EQ("\x03", response.GetStringRef());
20193df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
2028c1b6bd7SPavel Labath 
2038c1b6bd7SPavel Labath   // And that's it.
2048c1b6bd7SPavel Labath   ASSERT_EQ(eStateStopped, continue_state.get());
2058c1b6bd7SPavel Labath   ASSERT_EQ("T13", continue_response.GetStringRef());
2068c1b6bd7SPavel Labath   ASSERT_TRUE(async_result.get());
2078c1b6bd7SPavel Labath }
2088c1b6bd7SPavel Labath 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndLateInterrupt)209b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndLateInterrupt) {
2108c1b6bd7SPavel Labath   StringExtractorGDBRemote continue_response, response;
2118c1b6bd7SPavel Labath 
2128c1b6bd7SPavel Labath   // Continue. After the run packet is sent, send an interrupt.
213b9c1b51eSKate Stone   std::future<StateType> continue_state = std::async(
21493df2fbeSPavel Labath       std::launch::async, [&] { return SendCPacket(continue_response); });
21593df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2168c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
21793df2fbeSPavel Labath   WaitForRunEvent();
2188c1b6bd7SPavel Labath 
219379f24ffSJim Ingham   std::future<bool> async_result = std::async(
220379f24ffSJim Ingham       std::launch::async, [&] { return client.Interrupt(g_timeout); });
2218c1b6bd7SPavel Labath 
222b9c1b51eSKate Stone   // However, the target stops due to a different reason than the original
223b9c1b51eSKate Stone   // interrupt.
22493df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2258c1b6bd7SPavel Labath   ASSERT_EQ("\x03", response.GetStringRef());
22693df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
2278c1b6bd7SPavel Labath   ASSERT_EQ(eStateStopped, continue_state.get());
2288c1b6bd7SPavel Labath   ASSERT_EQ("T01", continue_response.GetStringRef());
2298c1b6bd7SPavel Labath   ASSERT_TRUE(async_result.get());
2308c1b6bd7SPavel Labath 
2318c1b6bd7SPavel Labath   // The subsequent continue packet should work normally.
23293df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
23393df2fbeSPavel Labath   ASSERT_EQ(eStateStopped, SendCPacket(response));
2348c1b6bd7SPavel Labath   ASSERT_EQ("T01", response.GetStringRef());
23593df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2368c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
2378c1b6bd7SPavel Labath }
2388c1b6bd7SPavel Labath 
TEST_F(GDBRemoteClientBaseTest,SendContinueAndInterrupt2PacketBug)239b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) {
2408c1b6bd7SPavel Labath   StringExtractorGDBRemote continue_response, async_response, response;
2418c1b6bd7SPavel Labath 
2428c1b6bd7SPavel Labath   // Interrupt should do nothing when we're not running.
243379f24ffSJim Ingham   ASSERT_FALSE(client.Interrupt(g_timeout));
2448c1b6bd7SPavel Labath 
2458c1b6bd7SPavel Labath   // Continue. After the run packet is sent, send an async signal.
246b9c1b51eSKate Stone   std::future<StateType> continue_state = std::async(
24793df2fbeSPavel Labath       std::launch::async, [&] { return SendCPacket(continue_response); });
24893df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2498c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
25093df2fbeSPavel Labath   WaitForRunEvent();
2518c1b6bd7SPavel Labath 
252379f24ffSJim Ingham   std::future<bool> interrupt_result = std::async(
253379f24ffSJim Ingham       std::launch::async, [&] { return client.Interrupt(g_timeout); });
2548c1b6bd7SPavel Labath 
2558c1b6bd7SPavel Labath   // We get interrupted. We'll send two packets to simulate a buggy stub.
25693df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2578c1b6bd7SPavel Labath   ASSERT_EQ("\x03", response.GetStringRef());
25893df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
25993df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
2608c1b6bd7SPavel Labath 
2618c1b6bd7SPavel Labath   // We should stop.
2628c1b6bd7SPavel Labath   ASSERT_EQ(eStateStopped, continue_state.get());
2638c1b6bd7SPavel Labath   ASSERT_EQ("T13", continue_response.GetStringRef());
2648c1b6bd7SPavel Labath   ASSERT_TRUE(interrupt_result.get());
2658c1b6bd7SPavel Labath 
2668c1b6bd7SPavel Labath   // Packet stream should remain synchronized.
2678c1b6bd7SPavel Labath   std::future<PacketResult> send_result = std::async(std::launch::async, [&] {
268379f24ffSJim Ingham     return client.SendPacketAndWaitForResponse("qTest", async_response);
2698c1b6bd7SPavel Labath   });
27093df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2718c1b6bd7SPavel Labath   ASSERT_EQ("qTest", response.GetStringRef());
27293df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest"));
2738c1b6bd7SPavel Labath   ASSERT_EQ(PacketResult::Success, send_result.get());
2748c1b6bd7SPavel Labath   ASSERT_EQ("QTest", async_response.GetStringRef());
2758c1b6bd7SPavel Labath }
2768c1b6bd7SPavel Labath 
TEST_F(GDBRemoteClientBaseTest,SendContinueDelegateInterface)277b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateInterface) {
2788c1b6bd7SPavel Labath   StringExtractorGDBRemote response;
2798c1b6bd7SPavel Labath 
280b9c1b51eSKate Stone   // Continue. We'll have the server send a bunch of async packets before it
281b9c1b51eSKate Stone   // stops.
28293df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("O4142"));
28393df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("Apro"));
28493df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("O4344"));
28593df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("Afile"));
28693df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
28793df2fbeSPavel Labath   ASSERT_EQ(eStateStopped, SendCPacket(response));
2888c1b6bd7SPavel Labath   ASSERT_EQ("T01", response.GetStringRef());
28993df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2908c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
2918c1b6bd7SPavel Labath 
29293df2fbeSPavel Labath   EXPECT_EQ("ABCD", delegate.output);
29393df2fbeSPavel Labath   EXPECT_EQ("profile", delegate.misc_data);
29493df2fbeSPavel Labath   EXPECT_EQ(1u, delegate.stop_reply_called);
2958c1b6bd7SPavel Labath }
2968c1b6bd7SPavel Labath 
TEST_F(GDBRemoteClientBaseTest,SendContinueDelegateStructuredDataReceipt)297fcdb1af6STodd Fiala TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateStructuredDataReceipt) {
298fcdb1af6STodd Fiala   // Build the plain-text version of the JSON data we will have the
299fcdb1af6STodd Fiala   // server send.
300fcdb1af6STodd Fiala   const std::string json_payload =
301fcdb1af6STodd Fiala       "{ \"type\": \"MyFeatureType\", "
302fcdb1af6STodd Fiala       "  \"elements\": [ \"entry1\", \"entry2\" ] }";
303fcdb1af6STodd Fiala   const std::string json_packet = "JSON-async:" + json_payload;
304fcdb1af6STodd Fiala 
305fcdb1af6STodd Fiala   // Escape it properly for transit.
306fcdb1af6STodd Fiala   StreamGDBRemote stream;
307fcdb1af6STodd Fiala   stream.PutEscapedBytes(json_packet.c_str(), json_packet.length());
308fcdb1af6STodd Fiala   stream.Flush();
309fcdb1af6STodd Fiala 
310fcdb1af6STodd Fiala   StringExtractorGDBRemote response;
311fcdb1af6STodd Fiala 
312fcdb1af6STodd Fiala   // Send async structured data packet, then stop.
31393df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket(stream.GetData()));
31493df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
31593df2fbeSPavel Labath   ASSERT_EQ(eStateStopped, SendCPacket(response));
316fcdb1af6STodd Fiala   ASSERT_EQ("T01", response.GetStringRef());
31793df2fbeSPavel Labath   ASSERT_EQ(1ul, delegate.structured_data_packets.size());
318fcdb1af6STodd Fiala 
319fcdb1af6STodd Fiala   // Verify the packet contents.  It should have been unescaped upon packet
320fcdb1af6STodd Fiala   // reception.
32193df2fbeSPavel Labath   ASSERT_EQ(json_packet, delegate.structured_data_packets[0]);
322fcdb1af6STodd Fiala }
323fcdb1af6STodd Fiala 
TEST_F(GDBRemoteClientBaseTest,InterruptNoResponse)324b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, InterruptNoResponse) {
3258c1b6bd7SPavel Labath   StringExtractorGDBRemote continue_response, response;
3268c1b6bd7SPavel Labath 
3278c1b6bd7SPavel Labath   // Continue. After the run packet is sent, send an interrupt.
328b9c1b51eSKate Stone   std::future<StateType> continue_state = std::async(
32993df2fbeSPavel Labath       std::launch::async, [&] { return SendCPacket(continue_response); });
33093df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
3318c1b6bd7SPavel Labath   ASSERT_EQ("c", response.GetStringRef());
33293df2fbeSPavel Labath   WaitForRunEvent();
3338c1b6bd7SPavel Labath 
334379f24ffSJim Ingham   std::future<bool> async_result = std::async(
335379f24ffSJim Ingham       std::launch::async, [&] { return client.Interrupt(g_timeout); });
3368c1b6bd7SPavel Labath 
3378c1b6bd7SPavel Labath   // We get interrupted, but we don't send a stop packet.
33893df2fbeSPavel Labath   ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
3398c1b6bd7SPavel Labath   ASSERT_EQ("\x03", response.GetStringRef());
3408c1b6bd7SPavel Labath 
3418c1b6bd7SPavel Labath   // The functions should still terminate (after a timeout).
3428c1b6bd7SPavel Labath   ASSERT_TRUE(async_result.get());
3438c1b6bd7SPavel Labath   ASSERT_EQ(eStateInvalid, continue_state.get());
3448c1b6bd7SPavel Labath }
3457da84753SPavel Labath 
TEST_F(GDBRemoteClientBaseTest,SendPacketAndReceiveResponseWithOutputSupport)3467da84753SPavel Labath TEST_F(GDBRemoteClientBaseTest, SendPacketAndReceiveResponseWithOutputSupport) {
3477da84753SPavel Labath   StringExtractorGDBRemote response;
3487da84753SPavel Labath   StreamString command_output;
3497da84753SPavel Labath 
3507da84753SPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("O"));
3517da84753SPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("O48656c6c6f2c"));
3527da84753SPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("O20"));
3537da84753SPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("O"));
3547da84753SPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("O776f726c64"));
3557da84753SPavel Labath   ASSERT_EQ(PacketResult::Success, server.SendPacket("OK"));
3567da84753SPavel Labath 
3577da84753SPavel Labath   PacketResult result = client.SendPacketAndReceiveResponseWithOutputSupport(
358379f24ffSJim Ingham       "qRcmd,test", response, g_timeout,
3597da84753SPavel Labath       [&command_output](llvm::StringRef output) { command_output << output; });
3607da84753SPavel Labath 
3617da84753SPavel Labath   ASSERT_EQ(PacketResult::Success, result);
3627da84753SPavel Labath   ASSERT_EQ("OK", response.GetStringRef());
3637da84753SPavel Labath   ASSERT_EQ("Hello, world", command_output.GetString().str());
3647da84753SPavel Labath }
365