diff options
Diffstat (limited to 'lldb/unittests/Process/gdb-remote')
4 files changed, 482 insertions, 506 deletions
diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp index 6b56e5c..6039794 100644 --- a/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp +++ b/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp @@ -8,7 +8,8 @@ //===----------------------------------------------------------------------===// #if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> when +// Workaround for MSVC standard library bug, which fails to include <thread> +// when // exceptions are disabled. #include <eh.h> #endif @@ -28,338 +29,320 @@ using namespace lldb_private; using namespace lldb; typedef GDBRemoteCommunication::PacketResult PacketResult; -namespace -{ - -struct MockDelegate : public GDBRemoteClientBase::ContinueDelegate -{ - std::string output; - std::string misc_data; - unsigned stop_reply_called = 0; - - void - HandleAsyncStdout(llvm::StringRef out) - { - output += out; - } - void - HandleAsyncMisc(llvm::StringRef data) - { - misc_data += data; - } - void - HandleStopReply() - { - ++stop_reply_called; - } - - bool - HandleAsyncStructuredData(const StructuredData::ObjectSP - &object_sp) - { - // TODO work in a test here after I fix the gtest breakage. - return true; - } +namespace { +struct MockDelegate : public GDBRemoteClientBase::ContinueDelegate { + std::string output; + std::string misc_data; + unsigned stop_reply_called = 0; + + void HandleAsyncStdout(llvm::StringRef out) { output += out; } + void HandleAsyncMisc(llvm::StringRef data) { misc_data += data; } + void HandleStopReply() { ++stop_reply_called; } + + bool HandleAsyncStructuredData(const StructuredData::ObjectSP &object_sp) { + // TODO work in a test here after I fix the gtest breakage. + return true; + } }; -struct TestClient : public GDBRemoteClientBase -{ - TestClient() : GDBRemoteClientBase("test.client", "test.client.listener") { m_send_acks = false; } +struct TestClient : public GDBRemoteClientBase { + TestClient() : GDBRemoteClientBase("test.client", "test.client.listener") { + m_send_acks = false; + } }; -struct ContinueFixture -{ - MockDelegate delegate; - TestClient client; - MockServer server; - ListenerSP listener_sp; - - ContinueFixture(); - - StateType - SendCPacket(StringExtractorGDBRemote &response) - { - return client.SendContinuePacketAndWaitForResponse(delegate, LinuxSignals(), "c", response); - } - - void - WaitForRunEvent() - { - EventSP event_sp; - listener_sp->WaitForEventForBroadcasterWithType(std::chrono::microseconds(0), &client, - TestClient::eBroadcastBitRunPacketSent, event_sp); - } +struct ContinueFixture { + MockDelegate delegate; + TestClient client; + MockServer server; + ListenerSP listener_sp; + + ContinueFixture(); + + StateType SendCPacket(StringExtractorGDBRemote &response) { + return client.SendContinuePacketAndWaitForResponse(delegate, LinuxSignals(), + "c", response); + } + + void WaitForRunEvent() { + EventSP event_sp; + listener_sp->WaitForEventForBroadcasterWithType( + std::chrono::microseconds(0), &client, + TestClient::eBroadcastBitRunPacketSent, event_sp); + } }; -ContinueFixture::ContinueFixture() : listener_sp(Listener::MakeListener("listener")) -{ - Connect(client, server); - listener_sp->StartListeningForEvents(&client, TestClient::eBroadcastBitRunPacketSent); +ContinueFixture::ContinueFixture() + : listener_sp(Listener::MakeListener("listener")) { + Connect(client, server); + listener_sp->StartListeningForEvents(&client, + TestClient::eBroadcastBitRunPacketSent); } } // end anonymous namespace -class GDBRemoteClientBaseTest : public GDBRemoteTest -{ -}; - -TEST_F(GDBRemoteClientBaseTest, SendContinueAndWait) -{ - StringExtractorGDBRemote response; - ContinueFixture fix; - if (HasFailure()) - return; - - // Continue. The inferior will stop with a signal. - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); - ASSERT_EQ(eStateStopped, fix.SendCPacket(response)); - ASSERT_EQ("T01", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - - // Continue. The inferior will exit. - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("W01")); - ASSERT_EQ(eStateExited, fix.SendCPacket(response)); - ASSERT_EQ("W01", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - - // Continue. The inferior will get killed. - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("X01")); - ASSERT_EQ(eStateExited, fix.SendCPacket(response)); - ASSERT_EQ("X01", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); +class GDBRemoteClientBaseTest : public GDBRemoteTest {}; + +TEST_F(GDBRemoteClientBaseTest, SendContinueAndWait) { + StringExtractorGDBRemote response; + ContinueFixture fix; + if (HasFailure()) + return; + + // Continue. The inferior will stop with a signal. + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); + ASSERT_EQ(eStateStopped, fix.SendCPacket(response)); + ASSERT_EQ("T01", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + + // Continue. The inferior will exit. + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("W01")); + ASSERT_EQ(eStateExited, fix.SendCPacket(response)); + ASSERT_EQ("W01", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + + // Continue. The inferior will get killed. + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("X01")); + ASSERT_EQ(eStateExited, fix.SendCPacket(response)); + ASSERT_EQ("X01", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); } -TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) -{ - StringExtractorGDBRemote continue_response, response; - ContinueFixture fix; - if (HasFailure()) - return; - - // SendAsyncSignal should do nothing when we are not running. - ASSERT_FALSE(fix.client.SendAsyncSignal(0x47)); - - // Continue. After the run packet is sent, send an async signal. - std::future<StateType> continue_state = - std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); }); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - fix.WaitForRunEvent(); - - std::future<bool> async_result = std::async(std::launch::async, [&] { return fix.client.SendAsyncSignal(0x47); }); - - // First we'll get interrupted. - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("\x03", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); - - // Then we get the signal packet. - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("C47", response.GetStringRef()); - ASSERT_TRUE(async_result.get()); - - // And we report back a signal stop. - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T47")); - ASSERT_EQ(eStateStopped, continue_state.get()); - ASSERT_EQ("T47", continue_response.GetStringRef()); +TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) { + StringExtractorGDBRemote continue_response, response; + ContinueFixture fix; + if (HasFailure()) + return; + + // SendAsyncSignal should do nothing when we are not running. + ASSERT_FALSE(fix.client.SendAsyncSignal(0x47)); + + // Continue. After the run packet is sent, send an async signal. + std::future<StateType> continue_state = std::async( + std::launch::async, [&] { return fix.SendCPacket(continue_response); }); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + fix.WaitForRunEvent(); + + std::future<bool> async_result = std::async( + std::launch::async, [&] { return fix.client.SendAsyncSignal(0x47); }); + + // First we'll get interrupted. + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("\x03", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); + + // Then we get the signal packet. + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("C47", response.GetStringRef()); + ASSERT_TRUE(async_result.get()); + + // And we report back a signal stop. + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T47")); + ASSERT_EQ(eStateStopped, continue_state.get()); + ASSERT_EQ("T47", continue_response.GetStringRef()); } -TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket) -{ - StringExtractorGDBRemote continue_response, async_response, response; - const bool send_async = true; - ContinueFixture fix; - if (HasFailure()) - return; - - // Continue. After the run packet is sent, send an async packet. - std::future<StateType> continue_state = - std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); }); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - fix.WaitForRunEvent(); - - // Sending without async enabled should fail. - ASSERT_EQ(PacketResult::ErrorSendFailed, fix.client.SendPacketAndWaitForResponse("qTest1", response, !send_async)); - - std::future<PacketResult> async_result = std::async(std::launch::async, [&] { - return fix.client.SendPacketAndWaitForResponse("qTest2", async_response, send_async); - }); - - // First we'll get interrupted. - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("\x03", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); - - // Then we get the async packet. - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("qTest2", response.GetStringRef()); - - // Send the response and receive it. - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("QTest2")); - ASSERT_EQ(PacketResult::Success, async_result.get()); - ASSERT_EQ("QTest2", async_response.GetStringRef()); - - // And we get resumed again. - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); - ASSERT_EQ(eStateStopped, continue_state.get()); - ASSERT_EQ("T01", continue_response.GetStringRef()); +TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket) { + StringExtractorGDBRemote continue_response, async_response, response; + const bool send_async = true; + ContinueFixture fix; + if (HasFailure()) + return; + + // Continue. After the run packet is sent, send an async packet. + std::future<StateType> continue_state = std::async( + std::launch::async, [&] { return fix.SendCPacket(continue_response); }); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + fix.WaitForRunEvent(); + + // Sending without async enabled should fail. + ASSERT_EQ( + PacketResult::ErrorSendFailed, + fix.client.SendPacketAndWaitForResponse("qTest1", response, !send_async)); + + std::future<PacketResult> async_result = std::async(std::launch::async, [&] { + return fix.client.SendPacketAndWaitForResponse("qTest2", async_response, + send_async); + }); + + // First we'll get interrupted. + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("\x03", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); + + // Then we get the async packet. + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("qTest2", response.GetStringRef()); + + // Send the response and receive it. + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("QTest2")); + ASSERT_EQ(PacketResult::Success, async_result.get()); + ASSERT_EQ("QTest2", async_response.GetStringRef()); + + // And we get resumed again. + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); + ASSERT_EQ(eStateStopped, continue_state.get()); + ASSERT_EQ("T01", continue_response.GetStringRef()); } -TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt) -{ - StringExtractorGDBRemote continue_response, response; - ContinueFixture fix; - if (HasFailure()) - return; - - // Interrupt should do nothing when we're not running. - ASSERT_FALSE(fix.client.Interrupt()); - - // Continue. After the run packet is sent, send an interrupt. - std::future<StateType> continue_state = - std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); }); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - fix.WaitForRunEvent(); - - std::future<bool> async_result = std::async(std::launch::async, [&] { return fix.client.Interrupt(); }); - - // We get interrupted. - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("\x03", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); - - // And that's it. - ASSERT_EQ(eStateStopped, continue_state.get()); - ASSERT_EQ("T13", continue_response.GetStringRef()); - ASSERT_TRUE(async_result.get()); +TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt) { + StringExtractorGDBRemote continue_response, response; + ContinueFixture fix; + if (HasFailure()) + return; + + // Interrupt should do nothing when we're not running. + ASSERT_FALSE(fix.client.Interrupt()); + + // Continue. After the run packet is sent, send an interrupt. + std::future<StateType> continue_state = std::async( + std::launch::async, [&] { return fix.SendCPacket(continue_response); }); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + fix.WaitForRunEvent(); + + std::future<bool> async_result = + std::async(std::launch::async, [&] { return fix.client.Interrupt(); }); + + // We get interrupted. + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("\x03", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); + + // And that's it. + ASSERT_EQ(eStateStopped, continue_state.get()); + ASSERT_EQ("T13", continue_response.GetStringRef()); + ASSERT_TRUE(async_result.get()); } -TEST_F(GDBRemoteClientBaseTest, SendContinueAndLateInterrupt) -{ - StringExtractorGDBRemote continue_response, response; - ContinueFixture fix; - if (HasFailure()) - return; - - // Continue. After the run packet is sent, send an interrupt. - std::future<StateType> continue_state = - std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); }); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - fix.WaitForRunEvent(); - - std::future<bool> async_result = std::async(std::launch::async, [&] { return fix.client.Interrupt(); }); - - // However, the target stops due to a different reason than the original interrupt. - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("\x03", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); - ASSERT_EQ(eStateStopped, continue_state.get()); - ASSERT_EQ("T01", continue_response.GetStringRef()); - ASSERT_TRUE(async_result.get()); - - // The subsequent continue packet should work normally. - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); - ASSERT_EQ(eStateStopped, fix.SendCPacket(response)); - ASSERT_EQ("T01", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); +TEST_F(GDBRemoteClientBaseTest, SendContinueAndLateInterrupt) { + StringExtractorGDBRemote continue_response, response; + ContinueFixture fix; + if (HasFailure()) + return; + + // Continue. After the run packet is sent, send an interrupt. + std::future<StateType> continue_state = std::async( + std::launch::async, [&] { return fix.SendCPacket(continue_response); }); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + fix.WaitForRunEvent(); + + std::future<bool> async_result = + std::async(std::launch::async, [&] { return fix.client.Interrupt(); }); + + // However, the target stops due to a different reason than the original + // interrupt. + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("\x03", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); + ASSERT_EQ(eStateStopped, continue_state.get()); + ASSERT_EQ("T01", continue_response.GetStringRef()); + ASSERT_TRUE(async_result.get()); + + // The subsequent continue packet should work normally. + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); + ASSERT_EQ(eStateStopped, fix.SendCPacket(response)); + ASSERT_EQ("T01", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); } -TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) -{ - StringExtractorGDBRemote continue_response, async_response, response; - const bool send_async = true; - ContinueFixture fix; - if (HasFailure()) - return; - - // Interrupt should do nothing when we're not running. - ASSERT_FALSE(fix.client.Interrupt()); - - // Continue. After the run packet is sent, send an async signal. - std::future<StateType> continue_state = - std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); }); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - fix.WaitForRunEvent(); - - std::future<bool> interrupt_result = std::async(std::launch::async, [&] { return fix.client.Interrupt(); }); - - // We get interrupted. We'll send two packets to simulate a buggy stub. - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("\x03", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); - - // We should stop. - ASSERT_EQ(eStateStopped, continue_state.get()); - ASSERT_EQ("T13", continue_response.GetStringRef()); - ASSERT_TRUE(interrupt_result.get()); - - // Packet stream should remain synchronized. - std::future<PacketResult> send_result = std::async(std::launch::async, [&] { - return fix.client.SendPacketAndWaitForResponse("qTest", async_response, !send_async); - }); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("qTest", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("QTest")); - ASSERT_EQ(PacketResult::Success, send_result.get()); - ASSERT_EQ("QTest", async_response.GetStringRef()); +TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) { + StringExtractorGDBRemote continue_response, async_response, response; + const bool send_async = true; + ContinueFixture fix; + if (HasFailure()) + return; + + // Interrupt should do nothing when we're not running. + ASSERT_FALSE(fix.client.Interrupt()); + + // Continue. After the run packet is sent, send an async signal. + std::future<StateType> continue_state = std::async( + std::launch::async, [&] { return fix.SendCPacket(continue_response); }); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + fix.WaitForRunEvent(); + + std::future<bool> interrupt_result = + std::async(std::launch::async, [&] { return fix.client.Interrupt(); }); + + // We get interrupted. We'll send two packets to simulate a buggy stub. + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("\x03", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T13")); + + // We should stop. + ASSERT_EQ(eStateStopped, continue_state.get()); + ASSERT_EQ("T13", continue_response.GetStringRef()); + ASSERT_TRUE(interrupt_result.get()); + + // Packet stream should remain synchronized. + std::future<PacketResult> send_result = std::async(std::launch::async, [&] { + return fix.client.SendPacketAndWaitForResponse("qTest", async_response, + !send_async); + }); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("qTest", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("QTest")); + ASSERT_EQ(PacketResult::Success, send_result.get()); + ASSERT_EQ("QTest", async_response.GetStringRef()); } -TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateInterface) -{ - StringExtractorGDBRemote response; - ContinueFixture fix; - if (HasFailure()) - return; - - // Continue. We'll have the server send a bunch of async packets before it stops. - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("O4142")); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("Apro")); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("O4344")); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("Afile")); - ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); - ASSERT_EQ(eStateStopped, fix.SendCPacket(response)); - ASSERT_EQ("T01", response.GetStringRef()); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - - EXPECT_EQ("ABCD", fix.delegate.output); - EXPECT_EQ("profile", fix.delegate.misc_data); - EXPECT_EQ(1u, fix.delegate.stop_reply_called); +TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateInterface) { + StringExtractorGDBRemote response; + ContinueFixture fix; + if (HasFailure()) + return; + + // Continue. We'll have the server send a bunch of async packets before it + // stops. + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("O4142")); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("Apro")); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("O4344")); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("Afile")); + ASSERT_EQ(PacketResult::Success, fix.server.SendPacket("T01")); + ASSERT_EQ(eStateStopped, fix.SendCPacket(response)); + ASSERT_EQ("T01", response.GetStringRef()); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + + EXPECT_EQ("ABCD", fix.delegate.output); + EXPECT_EQ("profile", fix.delegate.misc_data); + EXPECT_EQ(1u, fix.delegate.stop_reply_called); } -TEST_F(GDBRemoteClientBaseTest, InterruptNoResponse) -{ - StringExtractorGDBRemote continue_response, response; - ContinueFixture fix; - if (HasFailure()) - return; - - // Continue. After the run packet is sent, send an interrupt. - std::future<StateType> continue_state = - std::async(std::launch::async, [&] { return fix.SendCPacket(continue_response); }); - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("c", response.GetStringRef()); - fix.WaitForRunEvent(); - - std::future<bool> async_result = std::async(std::launch::async, [&] { return fix.client.Interrupt(); }); - - // We get interrupted, but we don't send a stop packet. - ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); - ASSERT_EQ("\x03", response.GetStringRef()); - - // The functions should still terminate (after a timeout). - ASSERT_TRUE(async_result.get()); - ASSERT_EQ(eStateInvalid, continue_state.get()); +TEST_F(GDBRemoteClientBaseTest, InterruptNoResponse) { + StringExtractorGDBRemote continue_response, response; + ContinueFixture fix; + if (HasFailure()) + return; + + // Continue. After the run packet is sent, send an interrupt. + std::future<StateType> continue_state = std::async( + std::launch::async, [&] { return fix.SendCPacket(continue_response); }); + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("c", response.GetStringRef()); + fix.WaitForRunEvent(); + + std::future<bool> async_result = + std::async(std::launch::async, [&] { return fix.client.Interrupt(); }); + + // We get interrupted, but we don't send a stop packet. + ASSERT_EQ(PacketResult::Success, fix.server.GetPacket(response)); + ASSERT_EQ("\x03", response.GetStringRef()); + + // The functions should still terminate (after a timeout). + ASSERT_TRUE(async_result.get()); + ASSERT_EQ(eStateInvalid, continue_state.get()); } diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp index 0b1f60d..d74ac66 100644 --- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -8,7 +8,8 @@ //===----------------------------------------------------------------------===// #if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> when +// Workaround for MSVC standard library bug, which fails to include <thread> +// when // exceptions are disabled. #include <eh.h> #endif @@ -26,159 +27,162 @@ using namespace lldb_private::process_gdb_remote; using namespace lldb_private; using namespace lldb; -namespace -{ +namespace { typedef GDBRemoteCommunication::PacketResult PacketResult; -struct TestClient : public GDBRemoteCommunicationClient -{ - TestClient() { m_send_acks = false; } +struct TestClient : public GDBRemoteCommunicationClient { + TestClient() { m_send_acks = false; } }; -void -Handle_QThreadSuffixSupported(MockServer &server, bool supported) -{ - StringExtractorGDBRemote request; - ASSERT_EQ(PacketResult::Success, server.GetPacket(request)); - ASSERT_EQ("QThreadSuffixSupported", request.GetStringRef()); - if (supported) - ASSERT_EQ(PacketResult::Success, server.SendOKResponse()); - else - ASSERT_EQ(PacketResult::Success, server.SendUnimplementedResponse(nullptr)); +void Handle_QThreadSuffixSupported(MockServer &server, bool supported) { + StringExtractorGDBRemote request; + ASSERT_EQ(PacketResult::Success, server.GetPacket(request)); + ASSERT_EQ("QThreadSuffixSupported", request.GetStringRef()); + if (supported) + ASSERT_EQ(PacketResult::Success, server.SendOKResponse()); + else + ASSERT_EQ(PacketResult::Success, server.SendUnimplementedResponse(nullptr)); } -void -HandlePacket(MockServer &server, llvm::StringRef expected, llvm::StringRef response) -{ - StringExtractorGDBRemote request; - ASSERT_EQ(PacketResult::Success, server.GetPacket(request)); - ASSERT_EQ(expected, request.GetStringRef()); - ASSERT_EQ(PacketResult::Success, server.SendPacket(response)); +void HandlePacket(MockServer &server, llvm::StringRef expected, + llvm::StringRef response) { + StringExtractorGDBRemote request; + ASSERT_EQ(PacketResult::Success, server.GetPacket(request)); + ASSERT_EQ(expected, request.GetStringRef()); + ASSERT_EQ(PacketResult::Success, server.SendPacket(response)); } -uint8_t all_registers[] = {'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'}; +uint8_t all_registers[] = {'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'}; std::string all_registers_hex = "404142434445464748494a4b4c4d4e4f"; uint8_t one_register[] = {'A', 'B', 'C', 'D'}; std::string one_register_hex = "41424344"; } // end anonymous namespace -class GDBRemoteCommunicationClientTest : public GDBRemoteTest -{ -}; +class GDBRemoteCommunicationClientTest : public GDBRemoteTest {}; -TEST_F(GDBRemoteCommunicationClientTest, WriteRegister) -{ - TestClient client; - MockServer server; - Connect(client, server); - if (HasFailure()) - return; +TEST_F(GDBRemoteCommunicationClientTest, WriteRegister) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; - const lldb::tid_t tid = 0x47; - const uint32_t reg_num = 4; - std::future<bool> write_result = - std::async(std::launch::async, [&] { return client.WriteRegister(tid, reg_num, one_register); }); + const lldb::tid_t tid = 0x47; + const uint32_t reg_num = 4; + std::future<bool> write_result = std::async(std::launch::async, [&] { + return client.WriteRegister(tid, reg_num, one_register); + }); - Handle_QThreadSuffixSupported(server, true); + Handle_QThreadSuffixSupported(server, true); - HandlePacket(server, "P4=" + one_register_hex + ";thread:0047;", "OK"); - ASSERT_TRUE(write_result.get()); + HandlePacket(server, "P4=" + one_register_hex + ";thread:0047;", "OK"); + ASSERT_TRUE(write_result.get()); - write_result = std::async(std::launch::async, [&] { return client.WriteAllRegisters(tid, all_registers); }); + write_result = std::async(std::launch::async, [&] { + return client.WriteAllRegisters(tid, all_registers); + }); - HandlePacket(server, "G" + all_registers_hex + ";thread:0047;", "OK"); - ASSERT_TRUE(write_result.get()); + HandlePacket(server, "G" + all_registers_hex + ";thread:0047;", "OK"); + ASSERT_TRUE(write_result.get()); } -TEST_F(GDBRemoteCommunicationClientTest, WriteRegisterNoSuffix) -{ - TestClient client; - MockServer server; - Connect(client, server); - if (HasFailure()) - return; - - const lldb::tid_t tid = 0x47; - const uint32_t reg_num = 4; - std::future<bool> write_result = - std::async(std::launch::async, [&] { return client.WriteRegister(tid, reg_num, one_register); }); - - Handle_QThreadSuffixSupported(server, false); - HandlePacket(server, "Hg47", "OK"); - HandlePacket(server, "P4=" + one_register_hex, "OK"); - ASSERT_TRUE(write_result.get()); - - write_result = std::async(std::launch::async, [&] { return client.WriteAllRegisters(tid, all_registers); }); - - HandlePacket(server, "G" + all_registers_hex, "OK"); - ASSERT_TRUE(write_result.get()); +TEST_F(GDBRemoteCommunicationClientTest, WriteRegisterNoSuffix) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + const lldb::tid_t tid = 0x47; + const uint32_t reg_num = 4; + std::future<bool> write_result = std::async(std::launch::async, [&] { + return client.WriteRegister(tid, reg_num, one_register); + }); + + Handle_QThreadSuffixSupported(server, false); + HandlePacket(server, "Hg47", "OK"); + HandlePacket(server, "P4=" + one_register_hex, "OK"); + ASSERT_TRUE(write_result.get()); + + write_result = std::async(std::launch::async, [&] { + return client.WriteAllRegisters(tid, all_registers); + }); + + HandlePacket(server, "G" + all_registers_hex, "OK"); + ASSERT_TRUE(write_result.get()); } -TEST_F(GDBRemoteCommunicationClientTest, ReadRegister) -{ - TestClient client; - MockServer server; - Connect(client, server); - if (HasFailure()) - return; - - const lldb::tid_t tid = 0x47; - const uint32_t reg_num = 4; - std::future<bool> async_result = std::async(std::launch::async, [&] { return client.GetpPacketSupported(tid); }); - Handle_QThreadSuffixSupported(server, true); - HandlePacket(server, "p0;thread:0047;", one_register_hex); - ASSERT_TRUE(async_result.get()); - - std::future<DataBufferSP> read_result = - std::async(std::launch::async, [&] { return client.ReadRegister(tid, reg_num); }); - HandlePacket(server, "p4;thread:0047;", "41424344"); - auto buffer_sp = read_result.get(); - ASSERT_TRUE(bool(buffer_sp)); - ASSERT_EQ(0, memcmp(buffer_sp->GetBytes(), one_register, sizeof one_register)); - - read_result = std::async(std::launch::async, [&] { return client.ReadAllRegisters(tid); }); - HandlePacket(server, "g;thread:0047;", all_registers_hex); - buffer_sp = read_result.get(); - ASSERT_TRUE(bool(buffer_sp)); - ASSERT_EQ(0, memcmp(buffer_sp->GetBytes(), all_registers, sizeof all_registers)); +TEST_F(GDBRemoteCommunicationClientTest, ReadRegister) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + const lldb::tid_t tid = 0x47; + const uint32_t reg_num = 4; + std::future<bool> async_result = std::async( + std::launch::async, [&] { return client.GetpPacketSupported(tid); }); + Handle_QThreadSuffixSupported(server, true); + HandlePacket(server, "p0;thread:0047;", one_register_hex); + ASSERT_TRUE(async_result.get()); + + std::future<DataBufferSP> read_result = std::async( + std::launch::async, [&] { return client.ReadRegister(tid, reg_num); }); + HandlePacket(server, "p4;thread:0047;", "41424344"); + auto buffer_sp = read_result.get(); + ASSERT_TRUE(bool(buffer_sp)); + ASSERT_EQ(0, + memcmp(buffer_sp->GetBytes(), one_register, sizeof one_register)); + + read_result = std::async(std::launch::async, + [&] { return client.ReadAllRegisters(tid); }); + HandlePacket(server, "g;thread:0047;", all_registers_hex); + buffer_sp = read_result.get(); + ASSERT_TRUE(bool(buffer_sp)); + ASSERT_EQ(0, + memcmp(buffer_sp->GetBytes(), all_registers, sizeof all_registers)); } -TEST_F(GDBRemoteCommunicationClientTest, SaveRestoreRegistersNoSuffix) -{ - TestClient client; - MockServer server; - Connect(client, server); - if (HasFailure()) - return; - - const lldb::tid_t tid = 0x47; - uint32_t save_id; - std::future<bool> async_result = - std::async(std::launch::async, [&] { return client.SaveRegisterState(tid, save_id); }); - Handle_QThreadSuffixSupported(server, false); - HandlePacket(server, "Hg47", "OK"); - HandlePacket(server, "QSaveRegisterState", "1"); - ASSERT_TRUE(async_result.get()); - EXPECT_EQ(1u, save_id); - - async_result = std::async(std::launch::async, [&] { return client.RestoreRegisterState(tid, save_id); }); - HandlePacket(server, "QRestoreRegisterState:1", "OK"); - ASSERT_TRUE(async_result.get()); +TEST_F(GDBRemoteCommunicationClientTest, SaveRestoreRegistersNoSuffix) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + const lldb::tid_t tid = 0x47; + uint32_t save_id; + std::future<bool> async_result = std::async(std::launch::async, [&] { + return client.SaveRegisterState(tid, save_id); + }); + Handle_QThreadSuffixSupported(server, false); + HandlePacket(server, "Hg47", "OK"); + HandlePacket(server, "QSaveRegisterState", "1"); + ASSERT_TRUE(async_result.get()); + EXPECT_EQ(1u, save_id); + + async_result = std::async(std::launch::async, [&] { + return client.RestoreRegisterState(tid, save_id); + }); + HandlePacket(server, "QRestoreRegisterState:1", "OK"); + ASSERT_TRUE(async_result.get()); } -TEST_F(GDBRemoteCommunicationClientTest, SyncThreadState) -{ - TestClient client; - MockServer server; - Connect(client, server); - if (HasFailure()) - return; - - const lldb::tid_t tid = 0x47; - std::future<bool> async_result = std::async(std::launch::async, [&] { return client.SyncThreadState(tid); }); - HandlePacket(server, "qSyncThreadStateSupported", "OK"); - HandlePacket(server, "QSyncThreadState:0047;", "OK"); - ASSERT_TRUE(async_result.get()); +TEST_F(GDBRemoteCommunicationClientTest, SyncThreadState) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + const lldb::tid_t tid = 0x47; + std::future<bool> async_result = std::async( + std::launch::async, [&] { return client.SyncThreadState(tid); }); + HandlePacket(server, "qSyncThreadStateSupported", "OK"); + HandlePacket(server, "QSyncThreadState:0047;", "OK"); + ASSERT_TRUE(async_result.get()); } diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp index 3aee52e..58cc9f5 100644 --- a/lldb/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp +++ b/lldb/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp @@ -8,7 +8,8 @@ //===----------------------------------------------------------------------===// #if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> when +// Workaround for MSVC standard library bug, which fails to include <thread> +// when // exceptions are disabled. #include <eh.h> #endif @@ -20,53 +21,48 @@ #include <future> -namespace lldb_private -{ -namespace process_gdb_remote -{ +namespace lldb_private { +namespace process_gdb_remote { -void -GDBRemoteTest::SetUpTestCase() -{ +void GDBRemoteTest::SetUpTestCase() { #if defined(_MSC_VER) - WSADATA data; - ::WSAStartup(MAKEWORD(2, 2), &data); + WSADATA data; + ::WSAStartup(MAKEWORD(2, 2), &data); #endif } -void -GDBRemoteTest::TearDownTestCase() -{ +void GDBRemoteTest::TearDownTestCase() { #if defined(_MSC_VER) - ::WSACleanup(); + ::WSACleanup(); #endif } -void -Connect(GDBRemoteCommunication &client, GDBRemoteCommunication &server) -{ - bool child_processes_inherit = false; - Error error; - TCPSocket listen_socket(child_processes_inherit, error); - ASSERT_FALSE(error.Fail()); - error = listen_socket.Listen("127.0.0.1:0", 5); - ASSERT_FALSE(error.Fail()); +void Connect(GDBRemoteCommunication &client, GDBRemoteCommunication &server) { + bool child_processes_inherit = false; + Error error; + TCPSocket listen_socket(child_processes_inherit, error); + ASSERT_FALSE(error.Fail()); + error = listen_socket.Listen("127.0.0.1:0", 5); + ASSERT_FALSE(error.Fail()); - Socket *accept_socket; - std::future<Error> accept_error = std::async(std::launch::async, [&] { - return listen_socket.Accept("127.0.0.1:0", child_processes_inherit, accept_socket); - }); + Socket *accept_socket; + std::future<Error> accept_error = std::async(std::launch::async, [&] { + return listen_socket.Accept("127.0.0.1:0", child_processes_inherit, + accept_socket); + }); - char connect_remote_address[64]; - snprintf(connect_remote_address, sizeof(connect_remote_address), "connect://localhost:%u", - listen_socket.GetLocalPortNumber()); + char connect_remote_address[64]; + snprintf(connect_remote_address, sizeof(connect_remote_address), + "connect://localhost:%u", listen_socket.GetLocalPortNumber()); - std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor()); - ASSERT_EQ(conn_ap->Connect(connect_remote_address, nullptr), lldb::eConnectionStatusSuccess); + std::unique_ptr<ConnectionFileDescriptor> conn_ap( + new ConnectionFileDescriptor()); + ASSERT_EQ(conn_ap->Connect(connect_remote_address, nullptr), + lldb::eConnectionStatusSuccess); - client.SetConnection(conn_ap.release()); - ASSERT_TRUE(accept_error.get().Success()); - server.SetConnection(new ConnectionFileDescriptor(accept_socket)); + client.SetConnection(conn_ap.release()); + ASSERT_TRUE(accept_error.get().Success()); + server.SetConnection(new ConnectionFileDescriptor(accept_socket)); } } // namespace process_gdb_remote diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteTestUtils.h b/lldb/unittests/Process/gdb-remote/GDBRemoteTestUtils.h index 6ceeccf..2aad2ae 100644 --- a/lldb/unittests/Process/gdb-remote/GDBRemoteTestUtils.h +++ b/lldb/unittests/Process/gdb-remote/GDBRemoteTestUtils.h @@ -9,47 +9,40 @@ #ifndef lldb_unittests_Process_gdb_remote_GDBRemoteTestUtils_h #define lldb_unittests_Process_gdb_remote_GDBRemoteTestUtils_h -#include "gtest/gtest.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h" +#include "gtest/gtest.h" -namespace lldb_private -{ -namespace process_gdb_remote -{ +namespace lldb_private { +namespace process_gdb_remote { -class GDBRemoteTest : public testing::Test -{ +class GDBRemoteTest : public testing::Test { public: - static void - SetUpTestCase(); + static void SetUpTestCase(); - static void - TearDownTestCase(); + static void TearDownTestCase(); }; -void -Connect(GDBRemoteCommunication &client, GDBRemoteCommunication &server); - -struct MockServer : public GDBRemoteCommunicationServer -{ - MockServer() : GDBRemoteCommunicationServer("mock-server", "mock-server.listener") { m_send_acks = false; } - - PacketResult - SendPacket(llvm::StringRef payload) - { - return GDBRemoteCommunicationServer::SendPacketNoLock(payload); - } - - PacketResult - GetPacket(StringExtractorGDBRemote &response) - { - const unsigned timeout_usec = 1000000; // 1s - const bool sync_on_timeout = false; - return WaitForPacketWithTimeoutMicroSecondsNoLock(response, timeout_usec, sync_on_timeout); - } - - using GDBRemoteCommunicationServer::SendOKResponse; - using GDBRemoteCommunicationServer::SendUnimplementedResponse; +void Connect(GDBRemoteCommunication &client, GDBRemoteCommunication &server); + +struct MockServer : public GDBRemoteCommunicationServer { + MockServer() + : GDBRemoteCommunicationServer("mock-server", "mock-server.listener") { + m_send_acks = false; + } + + PacketResult SendPacket(llvm::StringRef payload) { + return GDBRemoteCommunicationServer::SendPacketNoLock(payload); + } + + PacketResult GetPacket(StringExtractorGDBRemote &response) { + const unsigned timeout_usec = 1000000; // 1s + const bool sync_on_timeout = false; + return WaitForPacketWithTimeoutMicroSecondsNoLock(response, timeout_usec, + sync_on_timeout); + } + + using GDBRemoteCommunicationServer::SendOKResponse; + using GDBRemoteCommunicationServer::SendUnimplementedResponse; }; } // namespace process_gdb_remote |