2013-03-09 04:29:13 +08:00
|
|
|
//
|
|
|
|
// 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"
|
|
|
|
|
2013-03-19 06:34:00 +08:00
|
|
|
using namespace lldb_perf;
|
2013-03-09 04:29:13 +08:00
|
|
|
|
|
|
|
TestCase::TestCase () :
|
|
|
|
m_debugger(),
|
|
|
|
m_target(),
|
|
|
|
m_process(),
|
|
|
|
m_thread(),
|
|
|
|
m_listener(),
|
|
|
|
m_verbose(false)
|
|
|
|
{
|
2013-03-15 03:00:42 +08:00
|
|
|
SBDebugger::Initialize();
|
2013-03-09 04:29:13 +08:00
|
|
|
SBHostOS::ThreadCreated ("<lldb-tester.app.main>");
|
|
|
|
m_debugger = SBDebugger::Create(false);
|
|
|
|
m_listener = m_debugger.GetListener();
|
|
|
|
}
|
|
|
|
|
2013-03-15 03:00:42 +08:00
|
|
|
void
|
|
|
|
TestCase::Setup (int argc, const char** argv)
|
|
|
|
{}
|
|
|
|
|
2013-03-09 04:29:13 +08:00
|
|
|
bool
|
|
|
|
TestCase::Launch (const char** args, const char* cwd)
|
|
|
|
{
|
|
|
|
m_process = m_target.LaunchSimple(args,NULL,cwd);
|
|
|
|
m_process.GetBroadcaster().AddListener(m_listener, SBProcess::eBroadcastBitStateChanged | SBProcess::eBroadcastBitInterrupt);
|
|
|
|
return m_process.IsValid ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TestCase::SetVerbose (bool b)
|
|
|
|
{
|
|
|
|
m_verbose = b;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
TestCase::GetVerbose ()
|
|
|
|
{
|
|
|
|
return m_verbose;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TestCase::Loop ()
|
|
|
|
{
|
|
|
|
int step = 0;
|
|
|
|
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;
|
|
|
|
for (auto thread_index = 0; thread_index < m_process.GetNumThreads(); thread_index++)
|
|
|
|
{
|
|
|
|
SBThread thread(m_process.GetThreadAtIndex(thread_index));
|
|
|
|
SBFrame frame(thread.GetFrameAtIndex(0));
|
|
|
|
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:
|
|
|
|
if (m_verbose) printf("trace\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eStopReasonPlanComplete:
|
|
|
|
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:
|
|
|
|
if (m_verbose) printf("exception\n");
|
|
|
|
fatal = true;
|
|
|
|
break;
|
|
|
|
case eStopReasonBreakpoint:
|
|
|
|
if (m_verbose) printf("breakpoint id = %lld.%lld\n",thread.GetStopReasonDataAtIndex(0),thread.GetStopReasonDataAtIndex(1));
|
|
|
|
break;
|
|
|
|
case eStopReasonWatchpoint:
|
|
|
|
if (m_verbose) printf("watchpoint id = %lld\n",thread.GetStopReasonDataAtIndex(0));
|
|
|
|
break;
|
|
|
|
case eStopReasonSignal:
|
|
|
|
if (m_verbose) printf("signal %d\n",(int)thread.GetStopReasonDataAtIndex(0));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fatal)
|
|
|
|
{
|
|
|
|
if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (m_verbose)
|
|
|
|
printf("RUNNING STEP %d\n",step);
|
2013-03-19 06:34:00 +08:00
|
|
|
ActionWanted action;
|
|
|
|
TestStep(step, action);
|
2013-03-09 04:29:13 +08:00
|
|
|
step++;
|
|
|
|
switch (action.type)
|
|
|
|
{
|
2013-03-19 06:34:00 +08:00
|
|
|
case ActionWanted::Type::eContinue:
|
2013-03-09 04:29:13 +08:00
|
|
|
m_debugger.HandleCommand("continue");
|
|
|
|
break;
|
2013-03-19 06:34:00 +08:00
|
|
|
case ActionWanted::Type::eFinish:
|
2013-03-09 04:29:13 +08:00
|
|
|
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",step);
|
|
|
|
exit(501);
|
|
|
|
}
|
|
|
|
m_process.SetSelectedThread(action.thread);
|
|
|
|
m_debugger.HandleCommand("finish");
|
|
|
|
break;
|
2013-03-19 06:34:00 +08:00
|
|
|
case ActionWanted::Type::eNext:
|
2013-03-09 04:29:13 +08:00
|
|
|
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",step);
|
|
|
|
exit(500);
|
|
|
|
}
|
|
|
|
m_process.SetSelectedThread(action.thread);
|
|
|
|
m_debugger.HandleCommand("next");
|
|
|
|
break;
|
2013-03-19 06:34:00 +08:00
|
|
|
case ActionWanted::Type::eKill:
|
2013-03-09 04:29:13 +08:00
|
|
|
if (m_verbose) printf("I want to die\n");
|
|
|
|
m_process.Kill();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (GetVerbose()) printf("I am gonna die at step %d\n",step);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TestCase::Run (TestCase& test, int argc, const char** argv)
|
|
|
|
{
|
|
|
|
test.Setup(argc, argv);
|
|
|
|
test.Loop();
|
|
|
|
test.Results();
|
|
|
|
}
|