1 | //===-- GDBRemoteCommunicationTest.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 "GDBRemoteTestUtils.h" |
9 | #include "llvm/Testing/Support/Error.h" |
10 | |
11 | using namespace lldb_private::process_gdb_remote; |
12 | using namespace lldb_private; |
13 | using namespace lldb; |
14 | typedef GDBRemoteCommunication::PacketResult PacketResult; |
15 | |
16 | namespace { |
17 | |
18 | class TestClient : public GDBRemoteCommunication { |
19 | public: |
20 | TestClient() : GDBRemoteCommunication() {} |
21 | |
22 | PacketResult (StringExtractorGDBRemote &response) { |
23 | return GDBRemoteCommunication::ReadPacket(response, timeout: std::chrono::seconds(1), |
24 | /*sync_on_timeout*/ false); |
25 | } |
26 | }; |
27 | |
28 | class GDBRemoteCommunicationTest : public GDBRemoteTest { |
29 | public: |
30 | void SetUp() override { |
31 | ASSERT_THAT_ERROR(GDBRemoteCommunication::ConnectLocally(client, server), |
32 | llvm::Succeeded()); |
33 | } |
34 | |
35 | protected: |
36 | TestClient client; |
37 | MockServer server; |
38 | |
39 | bool Write(llvm::StringRef packet) { |
40 | ConnectionStatus status; |
41 | return server.WriteAll(src: packet.data(), src_len: packet.size(), status, error_ptr: nullptr) == |
42 | packet.size(); |
43 | } |
44 | }; |
45 | } // end anonymous namespace |
46 | |
47 | // Test that we can decode packets correctly. In particular, verify that |
48 | // checksum calculation works. |
49 | TEST_F(GDBRemoteCommunicationTest, ReadPacket) { |
50 | struct TestCase { |
51 | llvm::StringLiteral Packet; |
52 | llvm::StringLiteral Payload; |
53 | }; |
54 | static constexpr TestCase Tests[] = { |
55 | {.Packet: {"$#00" }, .Payload: {"" }}, |
56 | {.Packet: {"$foobar#79" }, .Payload: {"foobar" }}, |
57 | {.Packet: {"$}]#da" }, .Payload: {"}" }}, // Escaped } |
58 | {.Packet: {"$x*%#c7" }, .Payload: {"xxxxxxxxx" }}, // RLE |
59 | {.Packet: {"+$#00" }, .Payload: {"" }}, // Spurious ACK |
60 | {.Packet: {"-$#00" }, .Payload: {"" }}, // Spurious NAK |
61 | }; |
62 | for (const auto &Test : Tests) { |
63 | SCOPED_TRACE(Test.Packet + " -> " + Test.Payload); |
64 | StringExtractorGDBRemote response; |
65 | ASSERT_TRUE(Write(Test.Packet)); |
66 | ASSERT_EQ(PacketResult::Success, client.ReadPacket(response)); |
67 | ASSERT_EQ(Test.Payload, response.GetStringRef()); |
68 | ASSERT_EQ(PacketResult::Success, server.GetAck()); |
69 | } |
70 | } |
71 | |
72 | // Test that packets with incorrect RLE sequences do not cause a crash and |
73 | // reported as invalid. |
74 | TEST_F(GDBRemoteCommunicationTest, CheckForPacket) { |
75 | using PacketType = GDBRemoteCommunication::PacketType; |
76 | struct TestCase { |
77 | llvm::StringLiteral Packet; |
78 | PacketType Result; |
79 | }; |
80 | static constexpr TestCase Tests[] = { |
81 | {.Packet: {"$#00" }, .Result: PacketType::Standard}, |
82 | {.Packet: {"$xx*#00" }, .Result: PacketType::Invalid}, // '*' without a count |
83 | {.Packet: {"$*#00" }, .Result: PacketType::Invalid}, // '*' without a preceding character |
84 | {.Packet: {"$xx}#00" }, .Result: PacketType::Invalid}, // bare escape character '}' |
85 | {.Packet: {"%#00" }, .Result: PacketType::Notify}, // a correct packet after an invalid |
86 | }; |
87 | for (const auto &Test : Tests) { |
88 | SCOPED_TRACE(Test.Packet); |
89 | StringExtractorGDBRemote response; |
90 | EXPECT_EQ(Test.Result, client.CheckForPacket(Test.Packet.bytes_begin(), |
91 | Test.Packet.size(), response)); |
92 | } |
93 | } |
94 | |