2010-07-03 11:41:59 +08:00
|
|
|
"""
|
|
|
|
LLDB module which provides the abstract base class of lldb test case.
|
|
|
|
|
|
|
|
The concrete subclass can override lldbtest.TesBase in order to inherit the
|
|
|
|
common behavior for unitest.TestCase.setUp/tearDown implemented in this file.
|
|
|
|
|
|
|
|
The subclass should override the attribute mydir in order for the python runtime
|
|
|
|
to locate the individual test cases when running as part of a large test suite
|
|
|
|
or when running each test case as a separate python invocation.
|
|
|
|
|
|
|
|
./dotest.py provides a test driver which sets up the environment to run the
|
|
|
|
entire test suite. Users who want to run a test case on its own can specify the
|
|
|
|
LLDB_TEST and PYTHONPATH environment variables, for example:
|
|
|
|
|
|
|
|
$ export LLDB_TEST=$PWD
|
|
|
|
$ export PYTHONPATH=/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:$LLDB_TEST
|
|
|
|
$ echo $LLDB_TEST
|
|
|
|
/Volumes/data/lldb/svn/trunk/test
|
|
|
|
$ echo $PYTHONPATH
|
|
|
|
/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:/Volumes/data/lldb/svn/trunk/test
|
|
|
|
$ python function_types/TestFunctionTypes.py
|
|
|
|
.
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
Ran 1 test in 0.363s
|
|
|
|
|
|
|
|
OK
|
|
|
|
$
|
|
|
|
"""
|
|
|
|
|
|
|
|
import os
|
2010-08-06 07:42:46 +08:00
|
|
|
import unittest2
|
2010-07-03 11:41:59 +08:00
|
|
|
import lldb
|
|
|
|
|
2010-08-10 06:01:17 +08:00
|
|
|
#
|
|
|
|
# Some commonly used assert messages.
|
|
|
|
#
|
|
|
|
|
|
|
|
CURRENT_EXECUTABLE_SET = "Current executable set successfully"
|
|
|
|
|
2010-08-10 07:44:24 +08:00
|
|
|
RUN_STOPPED = "Process is stopped successfully"
|
2010-08-10 06:01:17 +08:00
|
|
|
|
2010-08-10 07:44:24 +08:00
|
|
|
RUN_COMPLETED = "Process exited successfully"
|
2010-08-10 06:01:17 +08:00
|
|
|
|
2010-08-10 07:44:24 +08:00
|
|
|
BREAKPOINT_CREATED = "Breakpoint created successfully"
|
|
|
|
|
2010-08-18 05:33:31 +08:00
|
|
|
BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
|
|
|
|
|
2010-08-10 07:44:24 +08:00
|
|
|
BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
|
2010-08-10 06:01:17 +08:00
|
|
|
|
|
|
|
STOPPED_DUE_TO_BREAKPOINT = "Process state is stopped due to breakpoint"
|
|
|
|
|
|
|
|
STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
|
|
|
|
|
|
|
|
VARIABLES_DISPLAYED_CORRECTLY = "Show specified variable(s) correctly"
|
|
|
|
|
2010-08-10 07:44:24 +08:00
|
|
|
#
|
|
|
|
# And a generic "Command '%s' returns successfully" message generator.
|
|
|
|
#
|
|
|
|
def CMD_MSG(command):
|
|
|
|
return "Command '%s' returns successfully" % (command)
|
|
|
|
|
|
|
|
|
2010-08-06 07:42:46 +08:00
|
|
|
class TestBase(unittest2.TestCase):
|
2010-07-03 11:41:59 +08:00
|
|
|
"""This LLDB abstract base class is meant to be subclassed."""
|
|
|
|
|
|
|
|
# The concrete subclass should override this attribute.
|
2010-07-04 04:41:42 +08:00
|
|
|
mydir = None
|
2010-07-03 11:41:59 +08:00
|
|
|
|
2010-08-17 05:28:10 +08:00
|
|
|
# State pertaining to the inferior process, if any.
|
|
|
|
runStarted = False
|
|
|
|
|
2010-07-03 11:41:59 +08:00
|
|
|
def setUp(self):
|
2010-08-07 09:13:18 +08:00
|
|
|
#import traceback
|
2010-08-06 05:23:45 +08:00
|
|
|
#traceback.print_stack()
|
|
|
|
|
2010-07-04 04:41:42 +08:00
|
|
|
# Fail fast if 'mydir' attribute is not overridden.
|
|
|
|
if not self.mydir or len(self.mydir) == 0:
|
|
|
|
raise Exception("Subclasses must override the 'mydir' attribute.")
|
2010-07-03 11:41:59 +08:00
|
|
|
# Save old working directory.
|
|
|
|
self.oldcwd = os.getcwd()
|
|
|
|
|
|
|
|
# Change current working directory if ${LLDB_TEST} is defined.
|
|
|
|
# See also dotest.py which sets up ${LLDB_TEST}.
|
|
|
|
if ("LLDB_TEST" in os.environ):
|
|
|
|
os.chdir(os.path.join(os.environ["LLDB_TEST"], self.mydir));
|
|
|
|
|
|
|
|
# Create the debugger instance if necessary.
|
|
|
|
try:
|
|
|
|
self.dbg = lldb.DBG
|
|
|
|
except AttributeError:
|
|
|
|
self.dbg = lldb.SBDebugger.Create()
|
2010-07-04 04:41:42 +08:00
|
|
|
|
2010-07-03 11:41:59 +08:00
|
|
|
if not self.dbg.IsValid():
|
|
|
|
raise Exception('Invalid debugger instance')
|
|
|
|
|
|
|
|
# We want our debugger to be synchronous.
|
|
|
|
self.dbg.SetAsync(False)
|
|
|
|
|
|
|
|
# Retrieve the associated command interpreter instance.
|
|
|
|
self.ci = self.dbg.GetCommandInterpreter()
|
|
|
|
if not self.ci:
|
|
|
|
raise Exception('Could not get the command interpreter')
|
|
|
|
|
|
|
|
# And the result object.
|
|
|
|
self.res = lldb.SBCommandReturnObject()
|
|
|
|
|
|
|
|
def tearDown(self):
|
2010-08-17 05:28:10 +08:00
|
|
|
# Finish the inferior process, if it was "run" previously.
|
|
|
|
if self.runStarted:
|
|
|
|
self.ci.HandleCommand("continue", self.res)
|
|
|
|
|
2010-07-03 11:41:59 +08:00
|
|
|
del self.dbg
|
|
|
|
|
|
|
|
# Restore old working directory.
|
|
|
|
os.chdir(self.oldcwd)
|
2010-08-20 07:26:59 +08:00
|
|
|
|
2010-08-21 01:57:32 +08:00
|
|
|
def runCmd(self, cmd, msg=None, check=True, verbose=False):
|
2010-08-20 07:26:59 +08:00
|
|
|
"""
|
|
|
|
Ask the command interpreter to handle the command and then check its
|
|
|
|
return status.
|
|
|
|
"""
|
|
|
|
# Fail fast if 'cmd' is not meaningful.
|
|
|
|
if not cmd or len(cmd) == 0:
|
|
|
|
raise Exception("Bad 'cmd' parameter encountered")
|
2010-08-21 01:57:32 +08:00
|
|
|
|
|
|
|
if verbose:
|
|
|
|
print "runCmd:", cmd
|
|
|
|
|
2010-08-20 07:26:59 +08:00
|
|
|
self.ci.HandleCommand(cmd, self.res)
|
2010-08-21 01:57:32 +08:00
|
|
|
|
2010-08-20 07:53:55 +08:00
|
|
|
if cmd.startswith("run"):
|
2010-08-20 07:26:59 +08:00
|
|
|
self.runStarted = True
|
2010-08-21 01:57:32 +08:00
|
|
|
|
|
|
|
if not self.res.Succeeded():
|
|
|
|
print self.res.GetError()
|
|
|
|
|
|
|
|
if verbose:
|
|
|
|
print "output:", self.res.GetOutput()
|
|
|
|
|
2010-08-20 07:26:59 +08:00
|
|
|
if check:
|
|
|
|
self.assertTrue(self.res.Succeeded(),
|
|
|
|
msg if msg else CMD_MSG(cmd))
|
|
|
|
|
2010-08-21 01:57:32 +08:00
|
|
|
def expect(self, cmd, msg, startstr=None, substrs=None, verbose=False):
|
2010-08-20 07:26:59 +08:00
|
|
|
"""
|
|
|
|
Similar to runCmd; with additional expect style output matching ability.
|
|
|
|
|
|
|
|
Ask the command interpreter to handle the command and then check its
|
|
|
|
return status. The 'msg' parameter specifies an informational assert
|
|
|
|
message. We expect the output from running the command to start with
|
|
|
|
'startstr' and matches the substrings contained in 'substrs'.
|
|
|
|
"""
|
|
|
|
# Fail fast if 'msg' is not meaningful.
|
|
|
|
if not msg or len(msg) == 0:
|
|
|
|
raise Exception("Bad 'msg' parameter encountered")
|
2010-08-21 01:57:32 +08:00
|
|
|
self.runCmd(cmd, verbose = (True if verbose else False))
|
2010-08-20 07:26:59 +08:00
|
|
|
|
|
|
|
output = self.res.GetOutput()
|
|
|
|
matched = output.startswith(startstr) if startstr else True
|
|
|
|
if substrs:
|
|
|
|
for str in substrs:
|
|
|
|
matched = output.find(str) > 0
|
|
|
|
if not matched:
|
|
|
|
break
|
|
|
|
|
|
|
|
self.assertTrue(matched, msg)
|
|
|
|
|