258 lines · cpp
1//===-- ProcessEventDataTest.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Plugins/Platform/MacOSX/PlatformMacOSX.h"10#include "Plugins/Platform/MacOSX/PlatformRemoteMacOSX.h"11#include "TestingSupport/TestUtilities.h"12#include "lldb/Core/Debugger.h"13#include "lldb/Host/FileSystem.h"14#include "lldb/Host/HostInfo.h"15#include "lldb/Target/Process.h"16#include "lldb/Target/StopInfo.h"17#include "lldb/Target/Thread.h"18#include "lldb/Utility/ArchSpec.h"19#include "lldb/Utility/Event.h"20#include "gtest/gtest.h"21 22using namespace lldb_private;23using namespace lldb;24 25namespace {26class ProcessEventDataTest : public ::testing::Test {27public:28 void SetUp() override {29 FileSystem::Initialize();30 HostInfo::Initialize();31 PlatformMacOSX::Initialize();32 std::call_once(TestUtilities::g_debugger_initialize_flag,33 []() { Debugger::Initialize(nullptr); });34 }35 void TearDown() override {36 PlatformMacOSX::Terminate();37 HostInfo::Terminate();38 FileSystem::Terminate();39 }40};41 42class DummyProcess : public Process {43public:44 DummyProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)45 : Process(target_sp, listener_sp) {}46 47 bool CanDebug(lldb::TargetSP target, bool plugin_specified_by_name) override {48 return true;49 }50 Status DoDestroy() override { return {}; }51 void RefreshStateAfterStop() override {}52 size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,53 Status &error) override {54 return 0;55 }56 bool DoUpdateThreadList(ThreadList &old_thread_list,57 ThreadList &new_thread_list) override {58 return false;59 }60 llvm::StringRef GetPluginName() override { return "Dummy"; }61 62 ProcessModID &GetModIDNonConstRef() { return m_mod_id; }63};64 65class DummyThread : public Thread {66public:67 using Thread::Thread;68 69 ~DummyThread() override { DestroyThread(); }70 71 void RefreshStateAfterStop() override {}72 73 lldb::RegisterContextSP GetRegisterContext() override { return nullptr; }74 75 lldb::RegisterContextSP76 CreateRegisterContextForFrame(StackFrame *frame) override {77 return nullptr;78 }79 80 bool CalculateStopInfo() override { return false; }81};82 83class DummyStopInfo : public StopInfo {84public:85 DummyStopInfo(Thread &thread, uint64_t value) : StopInfo(thread, value) {}86 87 bool ShouldStop(Event *event_ptr) override { return m_should_stop; }88 89 StopReason GetStopReason() const override { return m_stop_reason; }90 91 bool m_should_stop = true;92 StopReason m_stop_reason = eStopReasonBreakpoint;93};94 95class DummyProcessEventData : public Process::ProcessEventData {96public:97 DummyProcessEventData(ProcessSP &process_sp, StateType state)98 : ProcessEventData(process_sp, state) {}99 bool ShouldStop(Event *event_ptr, bool &found_valid_stopinfo) override {100 m_should_stop_hit_count++;101 return false;102 }103 104 int m_should_stop_hit_count = 0;105};106} // namespace107 108typedef std::shared_ptr<Process::ProcessEventData> ProcessEventDataSP;109typedef std::shared_ptr<Event> EventSP;110 111TargetSP CreateTarget(DebuggerSP &debugger_sp, ArchSpec &arch) {112 PlatformSP platform_sp;113 TargetSP target_sp;114 debugger_sp->GetTargetList().CreateTarget(115 *debugger_sp, "", arch, eLoadDependentsNo, platform_sp, target_sp);116 117 return target_sp;118}119 120ThreadSP CreateThread(ProcessSP &process_sp, bool should_stop,121 bool has_valid_stopinfo) {122 ThreadSP thread_sp = std::make_shared<DummyThread>(*process_sp.get(), 0);123 if (thread_sp == nullptr) {124 return nullptr;125 }126 127 if (has_valid_stopinfo) {128 StopInfoSP stopinfo_sp =129 std::make_shared<DummyStopInfo>(*thread_sp.get(), 0);130 static_cast<DummyStopInfo *>(stopinfo_sp.get())->m_should_stop =131 should_stop;132 if (stopinfo_sp == nullptr) {133 return nullptr;134 }135 136 thread_sp->SetStopInfo(stopinfo_sp);137 }138 139 process_sp->GetThreadList().AddThread(thread_sp);140 141 return thread_sp;142}143 144// Disable this test till I figure out why changing how events are sent145// to Secondary Listeners (44d9692e6a657ec46e98e4912ac56417da67cfee)146// caused this test to fail. It is testing responses to events that are147// not delivered in the way Process events are meant to be delivered, it148// bypasses the private event queue, and I'm not sure is testing real149// behaviors.150#if 0151TEST_F(ProcessEventDataTest, DoOnRemoval) {152 ArchSpec arch("x86_64-apple-macosx-");153 154 Platform::SetHostPlatform(PlatformRemoteMacOSX::CreateInstance(true, &arch));155 156 DebuggerSP debugger_sp = Debugger::CreateInstance();157 ASSERT_TRUE(debugger_sp);158 159 TargetSP target_sp = CreateTarget(debugger_sp, arch);160 ASSERT_TRUE(target_sp);161 162 ListenerSP listener_sp(Listener::MakeListener("dummy"));163 ProcessSP process_sp = std::make_shared<DummyProcess>(target_sp, listener_sp);164 ASSERT_TRUE(process_sp);165 166 /*167 Should hit ShouldStop if state is eStateStopped168 */169 ProcessEventDataSP event_data_sp =170 std::make_shared<DummyProcessEventData>(process_sp, eStateStopped);171 EventSP event_sp = std::make_shared<Event>(0, event_data_sp);172 event_data_sp->SetUpdateStateOnRemoval(event_sp.get());173 event_data_sp->DoOnRemoval(event_sp.get());174 bool result = static_cast<DummyProcessEventData *>(event_data_sp.get())175 ->m_should_stop_hit_count == 1;176 ASSERT_TRUE(result);177 178 /*179 Should not hit ShouldStop if state is not eStateStopped180 */181 event_data_sp =182 std::make_shared<DummyProcessEventData>(process_sp, eStateStepping);183 event_sp = std::make_shared<Event>(0, event_data_sp);184 event_data_sp->SetUpdateStateOnRemoval(event_sp.get());185 event_data_sp->DoOnRemoval(event_sp.get());186 result = static_cast<DummyProcessEventData *>(event_data_sp.get())187 ->m_should_stop_hit_count == 0;188 ASSERT_TRUE(result);189}190#endif 191 192TEST_F(ProcessEventDataTest, ShouldStop) {193 ArchSpec arch("x86_64-apple-macosx-");194 195 Platform::SetHostPlatform(PlatformRemoteMacOSX::CreateInstance(true, &arch));196 197 DebuggerSP debugger_sp = Debugger::CreateInstance();198 ASSERT_TRUE(debugger_sp);199 200 TargetSP target_sp = CreateTarget(debugger_sp, arch);201 ASSERT_TRUE(target_sp);202 203 ListenerSP listener_sp(Listener::MakeListener("dummy"));204 ProcessSP process_sp = std::make_shared<DummyProcess>(target_sp, listener_sp);205 ASSERT_TRUE(process_sp);206 207 // wants to stop and has valid StopInfo208 ThreadSP thread_sp = CreateThread(process_sp, true, true);209 210 ProcessEventDataSP event_data_sp =211 std::make_shared<Process::ProcessEventData>(process_sp, eStateStopped);212 EventSP event_sp = std::make_shared<Event>(0, event_data_sp);213 /*214 Should stop if thread has valid StopInfo and not suspended215 */216 bool found_valid_stopinfo = false;217 bool should_stop =218 event_data_sp->ShouldStop(event_sp.get(), found_valid_stopinfo);219 ASSERT_TRUE(should_stop == true && found_valid_stopinfo == true);220 221 /*222 Should not stop if thread has valid StopInfo but was suspended223 */224 found_valid_stopinfo = false;225 thread_sp->SetResumeState(eStateSuspended);226 should_stop = event_data_sp->ShouldStop(event_sp.get(), found_valid_stopinfo);227 ASSERT_TRUE(should_stop == false && found_valid_stopinfo == false);228 229 /*230 Should not stop, thread-reason of stop does not want to stop in its231 callback and suspended thread who wants to (from previous stop)232 must be ignored.233 */234 event_data_sp =235 std::make_shared<Process::ProcessEventData>(process_sp, eStateStopped);236 event_sp = std::make_shared<Event>(0, event_data_sp);237 process_sp->GetThreadList().Clear();238 239 for (int i = 0; i < 6; i++) {240 if (i == 2) {241 // Does not want to stop but has valid StopInfo242 thread_sp = CreateThread(process_sp, false, true);243 } else if (i == 5) {244 // Wants to stop and has valid StopInfo245 thread_sp = CreateThread(process_sp, true, true);246 thread_sp->SetResumeState(eStateSuspended);247 } else {248 // Thread has no StopInfo i.e is not the reason of stop249 thread_sp = CreateThread(process_sp, false, false);250 }251 }252 ASSERT_TRUE(process_sp->GetThreadList().GetSize() == 6);253 254 found_valid_stopinfo = false;255 should_stop = event_data_sp->ShouldStop(event_sp.get(), found_valid_stopinfo);256 ASSERT_TRUE(should_stop == false && found_valid_stopinfo == true);257}258