brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · 88ea394 Raw
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