hanchenye-llvm-project/lldb/tools/lldb-perf/lib/TestCase.cpp

205 lines
6.2 KiB
C++

//
// TestCase.cpp
// PerfTestDriver
//
// Created by Enrico Granata on 3/7/13.
// Copyright (c) 2013 Apple Inc. All rights reserved.
//
#include "TestCase.h"
#include "Xcode.h"
using namespace lldb_perf;
TestCase::TestCase () :
m_debugger(),
m_target(),
m_process(),
m_thread(),
m_listener(),
m_verbose(false),
m_step(0)
{
SBDebugger::Initialize();
SBHostOS::ThreadCreated ("<lldb-tester.app.main>");
m_debugger = SBDebugger::Create(false);
m_listener = m_debugger.GetListener();
}
bool
TestCase::Setup (int argc, const char** argv)
{
return false;
}
bool
TestCase::Launch (lldb::SBLaunchInfo &launch_info)
{
lldb::SBError error;
m_process = m_target.Launch (launch_info, error);
if (!error.Success())
fprintf (stderr, "error: %s\n", error.GetCString());
if (m_process.IsValid())
{
m_process.GetBroadcaster().AddListener(m_listener, SBProcess::eBroadcastBitStateChanged | SBProcess::eBroadcastBitInterrupt);
return true;
}
return false;
}
void
TestCase::SetVerbose (bool b)
{
m_verbose = b;
}
bool
TestCase::GetVerbose ()
{
return m_verbose;
}
void
TestCase::Loop ()
{
SBEvent evt;
while (true)
{
m_listener.WaitForEvent (UINT32_MAX,evt);
StateType state = SBProcess::GetStateFromEvent (evt);
if (m_verbose)
printf("event = %s\n",SBDebugger::StateAsCString(state));
if (SBProcess::GetRestartedFromEvent(evt))
continue;
switch (state)
{
case eStateInvalid:
case eStateDetached:
case eStateCrashed:
case eStateUnloaded:
break;
case eStateExited:
return;
case eStateConnected:
case eStateAttaching:
case eStateLaunching:
case eStateRunning:
case eStateStepping:
continue;
case eStateStopped:
case eStateSuspended:
{
bool fatal = false;
bool selected_thread = false;
for (auto thread_index = 0; thread_index < m_process.GetNumThreads(); thread_index++)
{
SBThread thread(m_process.GetThreadAtIndex(thread_index));
SBFrame frame(thread.GetFrameAtIndex(0));
bool select_thread = false;
StopReason stop_reason = thread.GetStopReason();
if (m_verbose) printf("tid = 0x%llx pc = 0x%llx ",thread.GetThreadID(),frame.GetPC());
switch (stop_reason)
{
case eStopReasonNone:
if (m_verbose) printf("none\n");
break;
case eStopReasonTrace:
select_thread = true;
if (m_verbose) printf("trace\n");
break;
case eStopReasonPlanComplete:
select_thread = true;
if (m_verbose) printf("plan complete\n");
break;
case eStopReasonThreadExiting:
if (m_verbose) printf("thread exiting\n");
break;
case eStopReasonExec:
if (m_verbose) printf("exec\n");
break;
case eStopReasonInvalid:
if (m_verbose) printf("invalid\n");
break;
case eStopReasonException:
select_thread = true;
if (m_verbose) printf("exception\n");
fatal = true;
break;
case eStopReasonBreakpoint:
select_thread = true;
if (m_verbose) printf("breakpoint id = %lld.%lld\n",thread.GetStopReasonDataAtIndex(0),thread.GetStopReasonDataAtIndex(1));
break;
case eStopReasonWatchpoint:
select_thread = true;
if (m_verbose) printf("watchpoint id = %lld\n",thread.GetStopReasonDataAtIndex(0));
break;
case eStopReasonSignal:
select_thread = true;
if (m_verbose) printf("signal %d\n",(int)thread.GetStopReasonDataAtIndex(0));
break;
}
if (select_thread && !selected_thread)
{
m_thread = thread;
selected_thread = m_process.SetSelectedThread(thread);
}
}
if (fatal)
{
if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
exit(1);
}
if (m_verbose)
printf("RUNNING STEP %d\n",m_step);
ActionWanted action;
TestStep(m_step, action);
m_step++;
SBError err;
switch (action.type)
{
case ActionWanted::Type::eContinue:
err = m_process.Continue();
break;
case ActionWanted::Type::eStepOut:
if (action.thread.IsValid() == false)
{
if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
if (m_verbose) printf("[finish invalid] I am gonna die at step %d\n",m_step);
exit(501);
}
m_process.SetSelectedThread(action.thread);
action.thread.StepOut();
break;
case ActionWanted::Type::eNext:
if (action.thread.IsValid() == false)
{
if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
if (m_verbose) printf("[next invalid] I am gonna die at step %d\n",m_step);
exit(500);
}
m_process.SetSelectedThread(action.thread);
action.thread.StepOver();
break;
case ActionWanted::Type::eKill:
if (m_verbose) printf("I want to die\n");
m_process.Kill();
return;
}
}
}
}
if (GetVerbose()) printf("I am gonna die at step %d\n",m_step);
}
void
TestCase::Run (TestCase& test, int argc, const char** argv)
{
if (test.Setup(argc, argv))
{
test.Loop();
test.Results();
}
}