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
128c1b6bd7SPavel Labath #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__anon7c812b550111::MockDelegate321756630dSRaphael Isemann void HandleAsyncStdout(llvm::StringRef out) override { output += out; }
HandleAsyncMisc__anon7c812b550111::MockDelegate331756630dSRaphael Isemann void HandleAsyncMisc(llvm::StringRef data) override { misc_data += data; }
HandleStopReply__anon7c812b550111::MockDelegate341756630dSRaphael Isemann void HandleStopReply() override { ++stop_reply_called; }
3549178e5eSTodd Fiala
HandleAsyncStructuredDataPacket__anon7c812b550111::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__anon7c812b550111::TestClient42b9c1b51eSKate Stone TestClient() : GDBRemoteClientBase("test.client", "test.client.listener") {
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:
58*379f24ffSJim Ingham // We don't have a process to get the interrupt timeout from, so make one up.
59*379f24ffSJim 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(),
67*379f24ffSJim Ingham "c", g_timeout,
68*379f24ffSJim Ingham response);
698c1b6bd7SPavel Labath }
708c1b6bd7SPavel Labath
WaitForRunEvent()71b9c1b51eSKate Stone void WaitForRunEvent() {
728c1b6bd7SPavel Labath EventSP event_sp;
73d35031e1SPavel Labath listener_sp->GetEventForBroadcasterWithType(
74d35031e1SPavel Labath &client, TestClient::eBroadcastBitRunPacketSent, event_sp, llvm::None);
758c1b6bd7SPavel Labath }
768c1b6bd7SPavel Labath };
778c1b6bd7SPavel Labath
78*379f24ffSJim Ingham std::chrono::seconds GDBRemoteClientBaseTest::g_timeout(10);
79*379f24ffSJim Ingham
808c1b6bd7SPavel Labath } // end anonymous namespace
818c1b6bd7SPavel Labath
TEST_F(GDBRemoteClientBaseTest,SendContinueAndWait)82b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndWait) {
838c1b6bd7SPavel Labath StringExtractorGDBRemote response;
848c1b6bd7SPavel Labath
858c1b6bd7SPavel Labath // Continue. The inferior will stop with a signal.
8693df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
8793df2fbeSPavel Labath ASSERT_EQ(eStateStopped, SendCPacket(response));
888c1b6bd7SPavel Labath ASSERT_EQ("T01", response.GetStringRef());
8993df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
908c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
918c1b6bd7SPavel Labath
928c1b6bd7SPavel Labath // Continue. The inferior will exit.
9393df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("W01"));
9493df2fbeSPavel Labath ASSERT_EQ(eStateExited, SendCPacket(response));
958c1b6bd7SPavel Labath ASSERT_EQ("W01", response.GetStringRef());
9693df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
978c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
988c1b6bd7SPavel Labath
998c1b6bd7SPavel Labath // Continue. The inferior will get killed.
10093df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("X01"));
10193df2fbeSPavel Labath ASSERT_EQ(eStateExited, SendCPacket(response));
1028c1b6bd7SPavel Labath ASSERT_EQ("X01", response.GetStringRef());
10393df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1048c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
1058c1b6bd7SPavel Labath }
1068c1b6bd7SPavel Labath
TEST_F(GDBRemoteClientBaseTest,SendContinueAndAsyncSignal)107b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) {
1088c1b6bd7SPavel Labath StringExtractorGDBRemote continue_response, response;
1098c1b6bd7SPavel Labath
1108c1b6bd7SPavel Labath // SendAsyncSignal should do nothing when we are not running.
111*379f24ffSJim Ingham ASSERT_FALSE(client.SendAsyncSignal(0x47, g_timeout));
1128c1b6bd7SPavel Labath
1138c1b6bd7SPavel Labath // Continue. After the run packet is sent, send an async signal.
114b9c1b51eSKate Stone std::future<StateType> continue_state = std::async(
11593df2fbeSPavel Labath std::launch::async, [&] { return SendCPacket(continue_response); });
11693df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1178c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
11893df2fbeSPavel Labath WaitForRunEvent();
1198c1b6bd7SPavel Labath
120*379f24ffSJim Ingham std::future<bool> async_result = std::async(std::launch::async, [&] {
121*379f24ffSJim Ingham return client.SendAsyncSignal(0x47, g_timeout);
122*379f24ffSJim Ingham });
1238c1b6bd7SPavel Labath
1248c1b6bd7SPavel Labath // First we'll get interrupted.
12593df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1268c1b6bd7SPavel Labath ASSERT_EQ("\x03", response.GetStringRef());
12793df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
1288c1b6bd7SPavel Labath
1298c1b6bd7SPavel Labath // Then we get the signal packet.
13093df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1318c1b6bd7SPavel Labath ASSERT_EQ("C47", response.GetStringRef());
1328c1b6bd7SPavel Labath ASSERT_TRUE(async_result.get());
1338c1b6bd7SPavel Labath
1348c1b6bd7SPavel Labath // And we report back a signal stop.
13593df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T47"));
1368c1b6bd7SPavel Labath ASSERT_EQ(eStateStopped, continue_state.get());
1378c1b6bd7SPavel Labath ASSERT_EQ("T47", continue_response.GetStringRef());
1388c1b6bd7SPavel Labath }
1398c1b6bd7SPavel Labath
TEST_F(GDBRemoteClientBaseTest,SendContinueAndAsyncPacket)140b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket) {
1418c1b6bd7SPavel Labath StringExtractorGDBRemote continue_response, async_response, response;
1428c1b6bd7SPavel Labath
1438c1b6bd7SPavel Labath // Continue. After the run packet is sent, send an async packet.
144b9c1b51eSKate Stone std::future<StateType> continue_state = std::async(
14593df2fbeSPavel Labath std::launch::async, [&] { return SendCPacket(continue_response); });
14693df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1478c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
14893df2fbeSPavel Labath WaitForRunEvent();
1498c1b6bd7SPavel Labath
1508c1b6bd7SPavel Labath // Sending without async enabled should fail.
151*379f24ffSJim Ingham ASSERT_EQ(PacketResult::ErrorSendFailed,
152*379f24ffSJim Ingham client.SendPacketAndWaitForResponse("qTest1", response));
1538c1b6bd7SPavel Labath
1548c1b6bd7SPavel Labath std::future<PacketResult> async_result = std::async(std::launch::async, [&] {
15593df2fbeSPavel Labath return client.SendPacketAndWaitForResponse("qTest2", async_response,
156*379f24ffSJim Ingham g_timeout);
1578c1b6bd7SPavel Labath });
1588c1b6bd7SPavel Labath
1598c1b6bd7SPavel Labath // First we'll get interrupted.
16093df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1618c1b6bd7SPavel Labath ASSERT_EQ("\x03", response.GetStringRef());
16293df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
1638c1b6bd7SPavel Labath
1648c1b6bd7SPavel Labath // Then we get the async packet.
16593df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1668c1b6bd7SPavel Labath ASSERT_EQ("qTest2", response.GetStringRef());
1678c1b6bd7SPavel Labath
1688c1b6bd7SPavel Labath // Send the response and receive it.
16993df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest2"));
1708c1b6bd7SPavel Labath ASSERT_EQ(PacketResult::Success, async_result.get());
1718c1b6bd7SPavel Labath ASSERT_EQ("QTest2", async_response.GetStringRef());
1728c1b6bd7SPavel Labath
1738c1b6bd7SPavel Labath // And we get resumed again.
17493df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1758c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
17693df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
1778c1b6bd7SPavel Labath ASSERT_EQ(eStateStopped, continue_state.get());
1788c1b6bd7SPavel Labath ASSERT_EQ("T01", continue_response.GetStringRef());
1798c1b6bd7SPavel Labath }
1808c1b6bd7SPavel Labath
TEST_F(GDBRemoteClientBaseTest,SendContinueAndInterrupt)181b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt) {
1828c1b6bd7SPavel Labath StringExtractorGDBRemote continue_response, response;
1838c1b6bd7SPavel Labath
1848c1b6bd7SPavel Labath // Interrupt should do nothing when we're not running.
185*379f24ffSJim Ingham ASSERT_FALSE(client.Interrupt(g_timeout));
1868c1b6bd7SPavel Labath
1878c1b6bd7SPavel Labath // Continue. After the run packet is sent, send an interrupt.
188b9c1b51eSKate Stone std::future<StateType> continue_state = std::async(
18993df2fbeSPavel Labath std::launch::async, [&] { return SendCPacket(continue_response); });
19093df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1918c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
19293df2fbeSPavel Labath WaitForRunEvent();
1938c1b6bd7SPavel Labath
194*379f24ffSJim Ingham std::future<bool> async_result = std::async(
195*379f24ffSJim Ingham std::launch::async, [&] { return client.Interrupt(g_timeout); });
1968c1b6bd7SPavel Labath
1978c1b6bd7SPavel Labath // We get interrupted.
19893df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
1998c1b6bd7SPavel Labath ASSERT_EQ("\x03", response.GetStringRef());
20093df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
2018c1b6bd7SPavel Labath
2028c1b6bd7SPavel Labath // And that's it.
2038c1b6bd7SPavel Labath ASSERT_EQ(eStateStopped, continue_state.get());
2048c1b6bd7SPavel Labath ASSERT_EQ("T13", continue_response.GetStringRef());
2058c1b6bd7SPavel Labath ASSERT_TRUE(async_result.get());
2068c1b6bd7SPavel Labath }
2078c1b6bd7SPavel Labath
TEST_F(GDBRemoteClientBaseTest,SendContinueAndLateInterrupt)208b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndLateInterrupt) {
2098c1b6bd7SPavel Labath StringExtractorGDBRemote continue_response, response;
2108c1b6bd7SPavel Labath
2118c1b6bd7SPavel Labath // Continue. After the run packet is sent, send an interrupt.
212b9c1b51eSKate Stone std::future<StateType> continue_state = std::async(
21393df2fbeSPavel Labath std::launch::async, [&] { return SendCPacket(continue_response); });
21493df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2158c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
21693df2fbeSPavel Labath WaitForRunEvent();
2178c1b6bd7SPavel Labath
218*379f24ffSJim Ingham std::future<bool> async_result = std::async(
219*379f24ffSJim Ingham std::launch::async, [&] { return client.Interrupt(g_timeout); });
2208c1b6bd7SPavel Labath
221b9c1b51eSKate Stone // However, the target stops due to a different reason than the original
222b9c1b51eSKate Stone // interrupt.
22393df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2248c1b6bd7SPavel Labath ASSERT_EQ("\x03", response.GetStringRef());
22593df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
2268c1b6bd7SPavel Labath ASSERT_EQ(eStateStopped, continue_state.get());
2278c1b6bd7SPavel Labath ASSERT_EQ("T01", continue_response.GetStringRef());
2288c1b6bd7SPavel Labath ASSERT_TRUE(async_result.get());
2298c1b6bd7SPavel Labath
2308c1b6bd7SPavel Labath // The subsequent continue packet should work normally.
23193df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
23293df2fbeSPavel Labath ASSERT_EQ(eStateStopped, SendCPacket(response));
2338c1b6bd7SPavel Labath ASSERT_EQ("T01", response.GetStringRef());
23493df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2358c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
2368c1b6bd7SPavel Labath }
2378c1b6bd7SPavel Labath
TEST_F(GDBRemoteClientBaseTest,SendContinueAndInterrupt2PacketBug)238b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) {
2398c1b6bd7SPavel Labath StringExtractorGDBRemote continue_response, async_response, response;
2408c1b6bd7SPavel Labath
2418c1b6bd7SPavel Labath // Interrupt should do nothing when we're not running.
242*379f24ffSJim Ingham ASSERT_FALSE(client.Interrupt(g_timeout));
2438c1b6bd7SPavel Labath
2448c1b6bd7SPavel Labath // Continue. After the run packet is sent, send an async signal.
245b9c1b51eSKate Stone std::future<StateType> continue_state = std::async(
24693df2fbeSPavel Labath std::launch::async, [&] { return SendCPacket(continue_response); });
24793df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2488c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
24993df2fbeSPavel Labath WaitForRunEvent();
2508c1b6bd7SPavel Labath
251*379f24ffSJim Ingham std::future<bool> interrupt_result = std::async(
252*379f24ffSJim Ingham std::launch::async, [&] { return client.Interrupt(g_timeout); });
2538c1b6bd7SPavel Labath
2548c1b6bd7SPavel Labath // We get interrupted. We'll send two packets to simulate a buggy stub.
25593df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2568c1b6bd7SPavel Labath ASSERT_EQ("\x03", response.GetStringRef());
25793df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
25893df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
2598c1b6bd7SPavel Labath
2608c1b6bd7SPavel Labath // We should stop.
2618c1b6bd7SPavel Labath ASSERT_EQ(eStateStopped, continue_state.get());
2628c1b6bd7SPavel Labath ASSERT_EQ("T13", continue_response.GetStringRef());
2638c1b6bd7SPavel Labath ASSERT_TRUE(interrupt_result.get());
2648c1b6bd7SPavel Labath
2658c1b6bd7SPavel Labath // Packet stream should remain synchronized.
2668c1b6bd7SPavel Labath std::future<PacketResult> send_result = std::async(std::launch::async, [&] {
267*379f24ffSJim Ingham return client.SendPacketAndWaitForResponse("qTest", async_response);
2688c1b6bd7SPavel Labath });
26993df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2708c1b6bd7SPavel Labath ASSERT_EQ("qTest", response.GetStringRef());
27193df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest"));
2728c1b6bd7SPavel Labath ASSERT_EQ(PacketResult::Success, send_result.get());
2738c1b6bd7SPavel Labath ASSERT_EQ("QTest", async_response.GetStringRef());
2748c1b6bd7SPavel Labath }
2758c1b6bd7SPavel Labath
TEST_F(GDBRemoteClientBaseTest,SendContinueDelegateInterface)276b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateInterface) {
2778c1b6bd7SPavel Labath StringExtractorGDBRemote response;
2788c1b6bd7SPavel Labath
279b9c1b51eSKate Stone // Continue. We'll have the server send a bunch of async packets before it
280b9c1b51eSKate Stone // stops.
28193df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("O4142"));
28293df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("Apro"));
28393df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("O4344"));
28493df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("Afile"));
28593df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
28693df2fbeSPavel Labath ASSERT_EQ(eStateStopped, SendCPacket(response));
2878c1b6bd7SPavel Labath ASSERT_EQ("T01", response.GetStringRef());
28893df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
2898c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
2908c1b6bd7SPavel Labath
29193df2fbeSPavel Labath EXPECT_EQ("ABCD", delegate.output);
29293df2fbeSPavel Labath EXPECT_EQ("profile", delegate.misc_data);
29393df2fbeSPavel Labath EXPECT_EQ(1u, delegate.stop_reply_called);
2948c1b6bd7SPavel Labath }
2958c1b6bd7SPavel Labath
TEST_F(GDBRemoteClientBaseTest,SendContinueDelegateStructuredDataReceipt)296fcdb1af6STodd Fiala TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateStructuredDataReceipt) {
297fcdb1af6STodd Fiala // Build the plain-text version of the JSON data we will have the
298fcdb1af6STodd Fiala // server send.
299fcdb1af6STodd Fiala const std::string json_payload =
300fcdb1af6STodd Fiala "{ \"type\": \"MyFeatureType\", "
301fcdb1af6STodd Fiala " \"elements\": [ \"entry1\", \"entry2\" ] }";
302fcdb1af6STodd Fiala const std::string json_packet = "JSON-async:" + json_payload;
303fcdb1af6STodd Fiala
304fcdb1af6STodd Fiala // Escape it properly for transit.
305fcdb1af6STodd Fiala StreamGDBRemote stream;
306fcdb1af6STodd Fiala stream.PutEscapedBytes(json_packet.c_str(), json_packet.length());
307fcdb1af6STodd Fiala stream.Flush();
308fcdb1af6STodd Fiala
309fcdb1af6STodd Fiala StringExtractorGDBRemote response;
310fcdb1af6STodd Fiala
311fcdb1af6STodd Fiala // Send async structured data packet, then stop.
31293df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket(stream.GetData()));
31393df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
31493df2fbeSPavel Labath ASSERT_EQ(eStateStopped, SendCPacket(response));
315fcdb1af6STodd Fiala ASSERT_EQ("T01", response.GetStringRef());
31693df2fbeSPavel Labath ASSERT_EQ(1ul, delegate.structured_data_packets.size());
317fcdb1af6STodd Fiala
318fcdb1af6STodd Fiala // Verify the packet contents. It should have been unescaped upon packet
319fcdb1af6STodd Fiala // reception.
32093df2fbeSPavel Labath ASSERT_EQ(json_packet, delegate.structured_data_packets[0]);
321fcdb1af6STodd Fiala }
322fcdb1af6STodd Fiala
TEST_F(GDBRemoteClientBaseTest,InterruptNoResponse)323b9c1b51eSKate Stone TEST_F(GDBRemoteClientBaseTest, InterruptNoResponse) {
3248c1b6bd7SPavel Labath StringExtractorGDBRemote continue_response, response;
3258c1b6bd7SPavel Labath
3268c1b6bd7SPavel Labath // Continue. After the run packet is sent, send an interrupt.
327b9c1b51eSKate Stone std::future<StateType> continue_state = std::async(
32893df2fbeSPavel Labath std::launch::async, [&] { return SendCPacket(continue_response); });
32993df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
3308c1b6bd7SPavel Labath ASSERT_EQ("c", response.GetStringRef());
33193df2fbeSPavel Labath WaitForRunEvent();
3328c1b6bd7SPavel Labath
333*379f24ffSJim Ingham std::future<bool> async_result = std::async(
334*379f24ffSJim Ingham std::launch::async, [&] { return client.Interrupt(g_timeout); });
3358c1b6bd7SPavel Labath
3368c1b6bd7SPavel Labath // We get interrupted, but we don't send a stop packet.
33793df2fbeSPavel Labath ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
3388c1b6bd7SPavel Labath ASSERT_EQ("\x03", response.GetStringRef());
3398c1b6bd7SPavel Labath
3408c1b6bd7SPavel Labath // The functions should still terminate (after a timeout).
3418c1b6bd7SPavel Labath ASSERT_TRUE(async_result.get());
3428c1b6bd7SPavel Labath ASSERT_EQ(eStateInvalid, continue_state.get());
3438c1b6bd7SPavel Labath }
3447da84753SPavel Labath
TEST_F(GDBRemoteClientBaseTest,SendPacketAndReceiveResponseWithOutputSupport)3457da84753SPavel Labath TEST_F(GDBRemoteClientBaseTest, SendPacketAndReceiveResponseWithOutputSupport) {
3467da84753SPavel Labath StringExtractorGDBRemote response;
3477da84753SPavel Labath StreamString command_output;
3487da84753SPavel Labath
3497da84753SPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("O"));
3507da84753SPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("O48656c6c6f2c"));
3517da84753SPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("O20"));
3527da84753SPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("O"));
3537da84753SPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("O776f726c64"));
3547da84753SPavel Labath ASSERT_EQ(PacketResult::Success, server.SendPacket("OK"));
3557da84753SPavel Labath
3567da84753SPavel Labath PacketResult result = client.SendPacketAndReceiveResponseWithOutputSupport(
357*379f24ffSJim Ingham "qRcmd,test", response, g_timeout,
3587da84753SPavel Labath [&command_output](llvm::StringRef output) { command_output << output; });
3597da84753SPavel Labath
3607da84753SPavel Labath ASSERT_EQ(PacketResult::Success, result);
3617da84753SPavel Labath ASSERT_EQ("OK", response.GetStringRef());
3627da84753SPavel Labath ASSERT_EQ("Hello, world", command_output.GetString().str());
3637da84753SPavel Labath }
364