2010-07-03 03:41:59 +00: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
|
2010-08-31 17:42:54 +00:00
|
|
|
$ export PYTHONPATH=/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:$LLDB_TEST:$LLDB_TEST/plugins
|
2010-07-03 03:41:59 +00:00
|
|
|
$ echo $LLDB_TEST
|
|
|
|
/Volumes/data/lldb/svn/trunk/test
|
|
|
|
$ echo $PYTHONPATH
|
2010-08-31 17:42:54 +00:00
|
|
|
/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:/Volumes/data/lldb/svn/trunk/test:/Volumes/data/lldb/svn/trunk/test/plugins
|
2010-07-03 03:41:59 +00:00
|
|
|
$ python function_types/TestFunctionTypes.py
|
|
|
|
.
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
Ran 1 test in 0.363s
|
|
|
|
|
2010-08-23 17:10:44 +00:00
|
|
|
OK
|
|
|
|
$ LLDB_COMMAND_TRACE=YES python array_types/TestArrayTypes.py
|
2010-09-02 22:25:47 +00:00
|
|
|
|
|
|
|
...
|
2010-08-23 17:10:44 +00:00
|
|
|
|
|
|
|
runCmd: breakpoint set -f main.c -l 42
|
|
|
|
output: Breakpoint created: 1: file ='main.c', line = 42, locations = 1
|
|
|
|
|
|
|
|
runCmd: run
|
|
|
|
output: Launching '/Volumes/data/lldb/svn/trunk/test/array_types/a.out' (x86_64)
|
|
|
|
|
2010-09-02 22:25:47 +00:00
|
|
|
...
|
2010-08-23 17:10:44 +00:00
|
|
|
|
2010-09-02 22:25:47 +00:00
|
|
|
runCmd: frame variable strings
|
2010-08-23 17:10:44 +00:00
|
|
|
output: (char *[4]) strings = {
|
|
|
|
(char *) strings[0] = 0x0000000100000f0c "Hello",
|
|
|
|
(char *) strings[1] = 0x0000000100000f12 "Hola",
|
|
|
|
(char *) strings[2] = 0x0000000100000f17 "Bonjour",
|
|
|
|
(char *) strings[3] = 0x0000000100000f1f "Guten Tag"
|
|
|
|
}
|
|
|
|
|
2010-09-02 22:25:47 +00:00
|
|
|
runCmd: frame variable char_16
|
2010-08-23 17:10:44 +00:00
|
|
|
output: (char [16]) char_16 = {
|
|
|
|
(char) char_16[0] = 'H',
|
|
|
|
(char) char_16[1] = 'e',
|
|
|
|
(char) char_16[2] = 'l',
|
|
|
|
(char) char_16[3] = 'l',
|
|
|
|
(char) char_16[4] = 'o',
|
|
|
|
(char) char_16[5] = ' ',
|
|
|
|
(char) char_16[6] = 'W',
|
|
|
|
(char) char_16[7] = 'o',
|
|
|
|
(char) char_16[8] = 'r',
|
|
|
|
(char) char_16[9] = 'l',
|
|
|
|
(char) char_16[10] = 'd',
|
|
|
|
(char) char_16[11] = '\n',
|
|
|
|
(char) char_16[12] = '\0',
|
|
|
|
(char) char_16[13] = '\0',
|
|
|
|
(char) char_16[14] = '\0',
|
|
|
|
(char) char_16[15] = '\0'
|
|
|
|
}
|
|
|
|
|
2010-09-02 22:25:47 +00:00
|
|
|
runCmd: frame variable ushort_matrix
|
2010-08-23 17:10:44 +00:00
|
|
|
output: (unsigned short [2][3]) ushort_matrix = {
|
|
|
|
(unsigned short [3]) ushort_matrix[0] = {
|
|
|
|
(unsigned short) ushort_matrix[0][0] = 0x0001,
|
|
|
|
(unsigned short) ushort_matrix[0][1] = 0x0002,
|
|
|
|
(unsigned short) ushort_matrix[0][2] = 0x0003
|
|
|
|
},
|
|
|
|
(unsigned short [3]) ushort_matrix[1] = {
|
|
|
|
(unsigned short) ushort_matrix[1][0] = 0x000b,
|
|
|
|
(unsigned short) ushort_matrix[1][1] = 0x0016,
|
|
|
|
(unsigned short) ushort_matrix[1][2] = 0x0021
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-02 22:25:47 +00:00
|
|
|
runCmd: frame variable long_6
|
2010-08-23 17:10:44 +00:00
|
|
|
output: (long [6]) long_6 = {
|
|
|
|
(long) long_6[0] = 1,
|
|
|
|
(long) long_6[1] = 2,
|
|
|
|
(long) long_6[2] = 3,
|
|
|
|
(long) long_6[3] = 4,
|
|
|
|
(long) long_6[4] = 5,
|
|
|
|
(long) long_6[5] = 6
|
|
|
|
}
|
|
|
|
|
|
|
|
.
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
Ran 1 test in 0.349s
|
|
|
|
|
2010-07-03 03:41:59 +00:00
|
|
|
OK
|
|
|
|
$
|
|
|
|
"""
|
|
|
|
|
2010-09-21 22:34:45 +00:00
|
|
|
import os, sys, traceback
|
2010-09-21 21:08:53 +00:00
|
|
|
import re
|
2010-08-30 21:35:00 +00:00
|
|
|
from subprocess import *
|
2010-08-25 18:49:48 +00:00
|
|
|
import time
|
2010-08-30 23:08:52 +00:00
|
|
|
import types
|
2010-08-05 23:42:46 +00:00
|
|
|
import unittest2
|
2010-07-03 03:41:59 +00:00
|
|
|
import lldb
|
|
|
|
|
2010-08-31 17:42:54 +00:00
|
|
|
if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
|
|
|
|
traceAlways = True
|
|
|
|
else:
|
|
|
|
traceAlways = False
|
|
|
|
|
|
|
|
|
2010-08-09 22:01:17 +00:00
|
|
|
#
|
|
|
|
# Some commonly used assert messages.
|
|
|
|
#
|
|
|
|
|
2010-09-17 22:45:27 +00:00
|
|
|
COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
|
|
|
|
|
2010-08-09 22:01:17 +00:00
|
|
|
CURRENT_EXECUTABLE_SET = "Current executable set successfully"
|
|
|
|
|
2010-09-02 21:23:12 +00:00
|
|
|
PROCESS_IS_VALID = "Process is valid"
|
|
|
|
|
|
|
|
PROCESS_KILLED = "Process is killed successfully"
|
|
|
|
|
2010-08-27 23:47:36 +00:00
|
|
|
RUN_SUCCEEDED = "Process is launched successfully"
|
2010-08-09 22:01:17 +00:00
|
|
|
|
2010-08-09 23:44:24 +00:00
|
|
|
RUN_COMPLETED = "Process exited successfully"
|
2010-08-09 22:01:17 +00:00
|
|
|
|
2010-08-09 23:44:24 +00:00
|
|
|
BREAKPOINT_CREATED = "Breakpoint created successfully"
|
|
|
|
|
2010-08-17 21:33:31 +00:00
|
|
|
BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
|
|
|
|
|
2010-08-09 23:44:24 +00:00
|
|
|
BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
|
2010-08-09 22:01:17 +00: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"
|
|
|
|
|
2010-08-24 22:07:56 +00:00
|
|
|
DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
|
|
|
|
|
2010-08-26 20:04:17 +00:00
|
|
|
VALID_BREAKPOINT = "Got a valid breakpoint"
|
|
|
|
|
2010-08-27 23:47:36 +00:00
|
|
|
VALID_FILESPEC = "Got a valid filespec"
|
|
|
|
|
2010-08-26 20:04:17 +00:00
|
|
|
VALID_PROCESS = "Got a valid process"
|
|
|
|
|
|
|
|
VALID_TARGET = "Got a valid target"
|
|
|
|
|
2010-08-25 19:00:04 +00:00
|
|
|
VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
|
2010-08-09 22:01:17 +00:00
|
|
|
|
2010-08-26 20:04:17 +00:00
|
|
|
|
2010-08-09 23:44:24 +00:00
|
|
|
#
|
|
|
|
# And a generic "Command '%s' returns successfully" message generator.
|
|
|
|
#
|
2010-09-21 23:33:30 +00:00
|
|
|
def CMD_MSG(str, exe):
|
|
|
|
if exe:
|
|
|
|
return "Command '%s' returns successfully" % str
|
|
|
|
else:
|
|
|
|
return "'%s' compares successfully" % str
|
2010-08-09 23:44:24 +00:00
|
|
|
|
2010-08-26 20:04:17 +00:00
|
|
|
#
|
2010-08-27 18:08:58 +00:00
|
|
|
# Returns the enum from the input string.
|
2010-08-26 20:04:17 +00:00
|
|
|
#
|
2010-08-27 18:08:58 +00:00
|
|
|
def StopReasonEnum(string):
|
|
|
|
if string == "Invalid":
|
2010-08-26 20:04:17 +00:00
|
|
|
return 0
|
2010-08-27 18:08:58 +00:00
|
|
|
elif string == "None":
|
2010-08-26 20:04:17 +00:00
|
|
|
return 1
|
2010-08-27 18:08:58 +00:00
|
|
|
elif string == "Trace":
|
2010-08-26 20:04:17 +00:00
|
|
|
return 2
|
2010-08-27 18:08:58 +00:00
|
|
|
elif string == "Breakpoint":
|
2010-08-26 20:04:17 +00:00
|
|
|
return 3
|
2010-08-27 18:08:58 +00:00
|
|
|
elif string == "Watchpoint":
|
2010-08-26 20:04:17 +00:00
|
|
|
return 4
|
2010-08-27 18:08:58 +00:00
|
|
|
elif string == "Signal":
|
2010-08-26 20:04:17 +00:00
|
|
|
return 5
|
2010-08-27 18:08:58 +00:00
|
|
|
elif string == "Exception":
|
2010-08-26 20:04:17 +00:00
|
|
|
return 6
|
2010-08-27 18:08:58 +00:00
|
|
|
elif string == "PlanComplete":
|
2010-08-26 20:04:17 +00:00
|
|
|
return 7
|
|
|
|
else:
|
|
|
|
raise Exception("Unknown stopReason string")
|
2010-08-09 23:44:24 +00:00
|
|
|
|
2010-08-27 18:08:58 +00:00
|
|
|
#
|
|
|
|
# Returns the stopReason string given an enum.
|
|
|
|
#
|
|
|
|
def StopReasonString(enum):
|
|
|
|
if enum == 0:
|
|
|
|
return "Invalid"
|
|
|
|
elif enum == 1:
|
|
|
|
return "None"
|
|
|
|
elif enum == 2:
|
|
|
|
return "Trace"
|
|
|
|
elif enum == 3:
|
|
|
|
return "Breakpoint"
|
|
|
|
elif enum == 4:
|
|
|
|
return "Watchpoint"
|
|
|
|
elif enum == 5:
|
|
|
|
return "Signal"
|
|
|
|
elif enum == 6:
|
|
|
|
return "Exception"
|
|
|
|
elif enum == 7:
|
|
|
|
return "PlanComplete"
|
|
|
|
else:
|
|
|
|
raise Exception("Unknown stopReason enum")
|
|
|
|
|
2010-08-26 21:49:29 +00:00
|
|
|
#
|
|
|
|
# Returns an env variable array from the os.environ map object.
|
|
|
|
#
|
|
|
|
def EnvArray():
|
|
|
|
return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
|
|
|
|
|
2010-08-31 17:42:54 +00:00
|
|
|
# From 2.7's subprocess.check_output() convenience function.
|
|
|
|
def system(*popenargs, **kwargs):
|
|
|
|
r"""Run command with arguments and return its output as a byte string.
|
|
|
|
|
|
|
|
If the exit code was non-zero it raises a CalledProcessError. The
|
|
|
|
CalledProcessError object will have the return code in the returncode
|
|
|
|
attribute and output in the output attribute.
|
|
|
|
|
|
|
|
The arguments are the same as for the Popen constructor. Example:
|
|
|
|
|
|
|
|
>>> check_output(["ls", "-l", "/dev/null"])
|
|
|
|
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
|
|
|
|
|
|
|
|
The stdout argument is not allowed as it is used internally.
|
|
|
|
To capture standard error in the result, use stderr=STDOUT.
|
|
|
|
|
|
|
|
>>> check_output(["/bin/sh", "-c",
|
|
|
|
... "ls -l non_existent_file ; exit 0"],
|
|
|
|
... stderr=STDOUT)
|
|
|
|
'ls: non_existent_file: No such file or directory\n'
|
|
|
|
"""
|
|
|
|
if 'stdout' in kwargs:
|
|
|
|
raise ValueError('stdout argument not allowed, it will be overridden.')
|
|
|
|
process = Popen(stdout=PIPE, *popenargs, **kwargs)
|
2010-09-14 22:01:40 +00:00
|
|
|
output, error = process.communicate()
|
2010-08-31 17:42:54 +00:00
|
|
|
retcode = process.poll()
|
|
|
|
|
|
|
|
if traceAlways:
|
|
|
|
if isinstance(popenargs, types.StringTypes):
|
|
|
|
args = [popenargs]
|
|
|
|
else:
|
|
|
|
args = list(popenargs)
|
|
|
|
print >> sys.stderr
|
|
|
|
print >> sys.stderr, "os command:", args
|
2010-09-14 22:39:02 +00:00
|
|
|
print >> sys.stderr, "stdout:", output
|
|
|
|
print >> sys.stderr, "stderr:", error
|
|
|
|
print >> sys.stderr, "retcode:", retcode
|
2010-09-14 22:01:40 +00:00
|
|
|
print >> sys.stderr
|
2010-08-31 17:42:54 +00:00
|
|
|
|
|
|
|
if retcode:
|
|
|
|
cmd = kwargs.get("args")
|
|
|
|
if cmd is None:
|
|
|
|
cmd = popenargs[0]
|
2010-09-16 18:26:06 +00:00
|
|
|
raise CalledProcessError(retcode, cmd)
|
2010-08-31 17:42:54 +00:00
|
|
|
return output
|
|
|
|
|
2010-08-27 00:15:48 +00:00
|
|
|
|
2010-08-05 23:42:46 +00:00
|
|
|
class TestBase(unittest2.TestCase):
|
2010-07-03 03:41:59 +00:00
|
|
|
"""This LLDB abstract base class is meant to be subclassed."""
|
|
|
|
|
|
|
|
# The concrete subclass should override this attribute.
|
2010-07-03 20:41:42 +00:00
|
|
|
mydir = None
|
2010-07-03 03:41:59 +00:00
|
|
|
|
2010-08-16 21:28:10 +00:00
|
|
|
# State pertaining to the inferior process, if any.
|
2010-09-02 22:25:47 +00:00
|
|
|
# This reflects inferior process started through the command interface with
|
|
|
|
# either the lldb "run" or "process launch" command.
|
|
|
|
# See also self.runCmd().
|
2010-08-16 21:28:10 +00:00
|
|
|
runStarted = False
|
|
|
|
|
2010-08-25 18:49:48 +00:00
|
|
|
# Maximum allowed attempts when launching the inferior process.
|
|
|
|
# Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
|
|
|
|
maxLaunchCount = 3;
|
|
|
|
|
|
|
|
# Time to wait before the next launching attempt in second(s).
|
|
|
|
# Can be overridden by the LLDB_TIME_WAIT environment variable.
|
|
|
|
timeWait = 1.0;
|
|
|
|
|
2010-09-16 01:53:04 +00:00
|
|
|
# Keep track of the old current working directory.
|
|
|
|
oldcwd = None
|
2010-08-05 21:23:45 +00:00
|
|
|
|
2010-09-16 01:53:04 +00:00
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
2010-07-03 20:41:42 +00:00
|
|
|
# Fail fast if 'mydir' attribute is not overridden.
|
2010-09-16 01:53:04 +00:00
|
|
|
if not cls.mydir or len(cls.mydir) == 0:
|
2010-07-03 20:41:42 +00:00
|
|
|
raise Exception("Subclasses must override the 'mydir' attribute.")
|
2010-07-03 03:41:59 +00:00
|
|
|
# Save old working directory.
|
2010-09-16 01:53:04 +00:00
|
|
|
cls.oldcwd = os.getcwd()
|
2010-07-03 03:41:59 +00:00
|
|
|
|
|
|
|
# Change current working directory if ${LLDB_TEST} is defined.
|
|
|
|
# See also dotest.py which sets up ${LLDB_TEST}.
|
|
|
|
if ("LLDB_TEST" in os.environ):
|
2010-09-16 01:53:04 +00:00
|
|
|
if traceAlways:
|
|
|
|
print "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
|
|
|
|
os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def tearDownClass(cls):
|
|
|
|
"""Do class-wide cleanup."""
|
|
|
|
|
|
|
|
# First, let's do the platform-specific cleanup.
|
|
|
|
module = __import__(sys.platform)
|
|
|
|
if not module.cleanup():
|
|
|
|
raise Exception("Don't know how to do cleanup")
|
|
|
|
|
|
|
|
# Subclass might have specific cleanup function defined.
|
|
|
|
if getattr(cls, "classCleanup", None):
|
|
|
|
if traceAlways:
|
|
|
|
print "Call class-specific cleanup function for class:", cls
|
2010-09-21 22:34:45 +00:00
|
|
|
try:
|
|
|
|
cls.classCleanup()
|
|
|
|
except:
|
|
|
|
exc_type, exc_value, exc_tb = sys.exc_info()
|
|
|
|
traceback.print_exception(exc_type, exc_value, exc_tb)
|
2010-09-16 01:53:04 +00:00
|
|
|
|
|
|
|
# Restore old working directory.
|
|
|
|
if traceAlways:
|
|
|
|
print "Restore dir to:", cls.oldcwd
|
|
|
|
os.chdir(cls.oldcwd)
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
#import traceback
|
|
|
|
#traceback.print_stack()
|
2010-07-03 03:41:59 +00:00
|
|
|
|
2010-08-25 18:49:48 +00:00
|
|
|
if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
|
|
|
|
self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
|
|
|
|
|
|
|
|
if "LLDB_TIME_WAIT" in os.environ:
|
|
|
|
self.timeWait = float(os.environ["LLDB_TIME_WAIT"])
|
|
|
|
|
2010-07-03 03:41:59 +00:00
|
|
|
# Create the debugger instance if necessary.
|
|
|
|
try:
|
|
|
|
self.dbg = lldb.DBG
|
|
|
|
except AttributeError:
|
|
|
|
self.dbg = lldb.SBDebugger.Create()
|
2010-07-03 20:41:42 +00:00
|
|
|
|
2010-07-03 03:41:59 +00:00
|
|
|
if not self.dbg.IsValid():
|
|
|
|
raise Exception('Invalid debugger instance')
|
|
|
|
|
|
|
|
# We want our debugger to be synchronous.
|
|
|
|
self.dbg.SetAsync(False)
|
|
|
|
|
2010-09-02 21:23:12 +00:00
|
|
|
# There is no process associated with the debugger as yet.
|
2010-09-02 22:25:47 +00:00
|
|
|
# See also self.tearDown() where it checks whether self.process has a
|
|
|
|
# valid reference and calls self.process.Kill() to kill the process.
|
2010-09-02 21:23:12 +00:00
|
|
|
self.process = None
|
|
|
|
|
2010-07-03 03:41:59 +00:00
|
|
|
# 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-09-02 21:23:12 +00:00
|
|
|
#import traceback
|
|
|
|
#traceback.print_stack()
|
|
|
|
|
|
|
|
# Terminate the current process being debugged, if any.
|
2010-08-16 21:28:10 +00:00
|
|
|
if self.runStarted:
|
2010-09-02 21:23:12 +00:00
|
|
|
self.runCmd("process kill", PROCESS_KILLED, check=False)
|
|
|
|
elif self.process and self.process.IsValid():
|
|
|
|
rc = self.process.Kill()
|
|
|
|
self.assertTrue(rc.Success(), PROCESS_KILLED)
|
2010-08-16 21:28:10 +00:00
|
|
|
|
2010-07-03 03:41:59 +00:00
|
|
|
del self.dbg
|
|
|
|
|
2010-09-01 00:15:19 +00:00
|
|
|
def runCmd(self, cmd, msg=None, check=True, trace=False, setCookie=True):
|
2010-08-19 23:26:59 +00: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-20 17:57:32 +00:00
|
|
|
|
2010-08-31 17:42:54 +00:00
|
|
|
trace = (True if traceAlways else trace)
|
2010-08-23 17:10:44 +00:00
|
|
|
|
2010-09-01 00:15:19 +00:00
|
|
|
running = (cmd.startswith("run") or cmd.startswith("process launch"))
|
2010-08-20 17:57:32 +00:00
|
|
|
|
2010-09-01 00:15:19 +00:00
|
|
|
for i in range(self.maxLaunchCount if running else 1):
|
2010-08-25 18:49:48 +00:00
|
|
|
self.ci.HandleCommand(cmd, self.res)
|
2010-08-20 17:57:32 +00:00
|
|
|
|
2010-08-25 18:49:48 +00:00
|
|
|
if trace:
|
|
|
|
print >> sys.stderr, "runCmd:", cmd
|
|
|
|
if self.res.Succeeded():
|
|
|
|
print >> sys.stderr, "output:", self.res.GetOutput()
|
|
|
|
else:
|
|
|
|
print >> sys.stderr, self.res.GetError()
|
2010-08-20 17:57:32 +00:00
|
|
|
|
2010-09-03 22:35:47 +00:00
|
|
|
if running:
|
|
|
|
# For process launch, wait some time before possible next try.
|
|
|
|
time.sleep(self.timeWait)
|
|
|
|
|
2010-08-20 21:03:09 +00:00
|
|
|
if self.res.Succeeded():
|
2010-08-25 18:49:48 +00:00
|
|
|
break
|
2010-09-15 17:33:57 +00:00
|
|
|
elif running:
|
2010-09-15 18:00:19 +00:00
|
|
|
print >> sys.stderr, "Command '" + cmd + "' failed!"
|
2010-08-20 17:57:32 +00:00
|
|
|
|
2010-09-02 21:23:12 +00:00
|
|
|
# Modify runStarted only if "run" or "process launch" was encountered.
|
|
|
|
if running:
|
|
|
|
self.runStarted = running and setCookie
|
2010-09-01 00:15:19 +00:00
|
|
|
|
2010-08-19 23:26:59 +00:00
|
|
|
if check:
|
|
|
|
self.assertTrue(self.res.Succeeded(),
|
2010-09-21 23:33:30 +00:00
|
|
|
msg if msg else CMD_MSG(cmd, True))
|
2010-08-19 23:26:59 +00:00
|
|
|
|
2010-09-21 23:33:30 +00:00
|
|
|
def expect(self, str, msg=None, patterns=None, startstr=None, substrs=None, trace=False, error=False, matching=True, exe=True):
|
2010-08-19 23:26:59 +00: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
|
2010-09-21 21:08:53 +00:00
|
|
|
'startstr', matches the substrings contained in 'substrs', and regexp
|
|
|
|
matches the patterns contained in 'patterns'.
|
2010-09-17 22:28:51 +00:00
|
|
|
|
|
|
|
If the keyword argument error is set to True, it signifies that the API
|
|
|
|
client is expecting the command to fail. In this case, the error stream
|
2010-09-17 22:45:27 +00:00
|
|
|
from running the command is retrieved and compared against the golden
|
2010-09-17 22:28:51 +00:00
|
|
|
input, instead.
|
2010-09-21 21:08:53 +00:00
|
|
|
|
|
|
|
If the keyword argument matching is set to False, it signifies that the API
|
|
|
|
client is expecting the output of the command not to match the golden
|
|
|
|
input.
|
2010-09-21 23:33:30 +00:00
|
|
|
|
|
|
|
Finally, the required argument 'str' represents the lldb command to be
|
|
|
|
sent to the command interpreter. In case the keyword argument 'exe' is
|
|
|
|
set to False, the 'str' is treated as a string to be matched/not-matched
|
|
|
|
against the golden input.
|
2010-08-19 23:26:59 +00:00
|
|
|
"""
|
2010-08-31 17:42:54 +00:00
|
|
|
trace = (True if traceAlways else trace)
|
2010-08-23 17:10:44 +00:00
|
|
|
|
2010-09-21 23:33:30 +00:00
|
|
|
if exe:
|
|
|
|
# First run the command. If we are expecting error, set check=False.
|
|
|
|
self.runCmd(str, trace = (True if trace else False), check = not error)
|
2010-08-19 23:26:59 +00:00
|
|
|
|
2010-09-21 23:33:30 +00:00
|
|
|
# Then compare the output against expected strings.
|
|
|
|
output = self.res.GetError() if error else self.res.GetOutput()
|
2010-09-17 22:28:51 +00:00
|
|
|
|
2010-09-21 23:33:30 +00:00
|
|
|
# If error is True, the API client expects the command to fail!
|
|
|
|
if error:
|
|
|
|
self.assertFalse(self.res.Succeeded(),
|
|
|
|
"Command '" + str + "' is expected to fail!")
|
|
|
|
else:
|
|
|
|
# No execution required, just compare str against the golden input.
|
|
|
|
output = str
|
|
|
|
if trace:
|
|
|
|
print >> sys.stderr, "look at:", output
|
2010-09-17 22:28:51 +00:00
|
|
|
|
2010-09-21 21:08:53 +00:00
|
|
|
# The heading says either "Expecting" or "Not expecting".
|
|
|
|
if trace:
|
|
|
|
heading = "Expecting" if matching else "Not expecting"
|
|
|
|
|
|
|
|
# Start from the startstr, if specified.
|
|
|
|
# If there's no startstr, set the initial state appropriately.
|
|
|
|
matched = output.startswith(startstr) if startstr else (True if matching else False)
|
2010-08-20 18:25:15 +00:00
|
|
|
|
2010-08-24 23:48:10 +00:00
|
|
|
if startstr and trace:
|
2010-09-21 21:08:53 +00:00
|
|
|
print >> sys.stderr, "%s start string: %s" % (heading, startstr)
|
2010-08-24 23:48:10 +00:00
|
|
|
print >> sys.stderr, "Matched" if matched else "Not matched"
|
|
|
|
print >> sys.stderr
|
2010-08-20 18:25:15 +00:00
|
|
|
|
2010-09-21 21:08:53 +00:00
|
|
|
# Look for sub strings, if specified.
|
|
|
|
keepgoing = matched if matching else not matched
|
|
|
|
if substrs and keepgoing:
|
2010-08-19 23:26:59 +00:00
|
|
|
for str in substrs:
|
|
|
|
matched = output.find(str) > 0
|
2010-08-24 23:48:10 +00:00
|
|
|
if trace:
|
2010-09-21 21:08:53 +00:00
|
|
|
print >> sys.stderr, "%s sub string: %s" % (heading, str)
|
|
|
|
print >> sys.stderr, "Matched" if matched else "Not matched"
|
|
|
|
keepgoing = matched if matching else not matched
|
|
|
|
if not keepgoing:
|
|
|
|
break
|
|
|
|
if trace:
|
|
|
|
print >> sys.stderr
|
|
|
|
|
|
|
|
# Search for regular expression patterns, if specified.
|
|
|
|
keepgoing = matched if matching else not matched
|
|
|
|
if patterns and keepgoing:
|
|
|
|
for pattern in patterns:
|
|
|
|
# Match Objects always have a boolean value of True.
|
|
|
|
matched = bool(re.search(pattern, output))
|
|
|
|
if trace:
|
|
|
|
print >> sys.stderr, "%s pattern: %s" % (heading, pattern)
|
2010-08-24 23:48:10 +00:00
|
|
|
print >> sys.stderr, "Matched" if matched else "Not matched"
|
2010-09-21 21:08:53 +00:00
|
|
|
keepgoing = matched if matching else not matched
|
|
|
|
if not keepgoing:
|
2010-08-19 23:26:59 +00:00
|
|
|
break
|
2010-08-24 23:48:10 +00:00
|
|
|
if trace:
|
|
|
|
print >> sys.stderr
|
2010-08-19 23:26:59 +00:00
|
|
|
|
2010-09-21 21:08:53 +00:00
|
|
|
self.assertTrue(matched if matching else not matched,
|
2010-09-21 23:33:30 +00:00
|
|
|
msg if msg else CMD_MSG(str, exe))
|
2010-08-19 23:26:59 +00:00
|
|
|
|
2010-08-25 22:52:45 +00:00
|
|
|
def invoke(self, obj, name, trace=False):
|
2010-08-25 22:56:10 +00:00
|
|
|
"""Use reflection to call a method dynamically with no argument."""
|
2010-08-31 17:42:54 +00:00
|
|
|
trace = (True if traceAlways else trace)
|
2010-08-25 22:52:45 +00:00
|
|
|
|
|
|
|
method = getattr(obj, name)
|
|
|
|
import inspect
|
|
|
|
self.assertTrue(inspect.ismethod(method),
|
|
|
|
name + "is a method name of object: " + str(obj))
|
|
|
|
result = method()
|
2010-08-31 17:42:54 +00:00
|
|
|
if trace:
|
2010-08-25 22:52:45 +00:00
|
|
|
print str(method) + ":", result
|
|
|
|
return result
|
2010-08-27 00:15:48 +00:00
|
|
|
|
2010-09-01 22:08:51 +00:00
|
|
|
def breakAfterLaunch(self, process, func, trace=False):
|
|
|
|
"""
|
|
|
|
Perform some dancees after LaunchProcess() to break at func name.
|
|
|
|
|
|
|
|
Return True if we can successfully break at the func name in due time.
|
|
|
|
"""
|
|
|
|
trace = (True if traceAlways else trace)
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
while True:
|
|
|
|
# The stop reason of the thread should be breakpoint.
|
|
|
|
thread = process.GetThreadAtIndex(0)
|
|
|
|
SR = thread.GetStopReason()
|
|
|
|
if trace:
|
|
|
|
print >> sys.stderr, "StopReason =", StopReasonString(SR)
|
|
|
|
|
|
|
|
if SR == StopReasonEnum("Breakpoint"):
|
|
|
|
frame = thread.GetFrameAtIndex(0)
|
|
|
|
name = frame.GetFunction().GetName()
|
2010-09-07 18:55:50 +00:00
|
|
|
if trace:
|
|
|
|
print >> sys.stderr, "function =", name
|
2010-09-01 22:08:51 +00:00
|
|
|
if (name == func):
|
|
|
|
# We got what we want; now break out of the loop.
|
|
|
|
return True
|
|
|
|
|
|
|
|
# The inferior is in a transient state; continue the process.
|
|
|
|
time.sleep(1.0)
|
|
|
|
if trace:
|
|
|
|
print >> sys.stderr, "Continuing the process:", process
|
|
|
|
process.Continue()
|
|
|
|
|
|
|
|
count = count + 1
|
2010-09-15 00:00:54 +00:00
|
|
|
if count == 15:
|
2010-09-01 22:08:51 +00:00
|
|
|
if trace:
|
2010-09-15 00:00:54 +00:00
|
|
|
print >> sys.stderr, "Reached 15 iterations, giving up..."
|
2010-09-01 22:08:51 +00:00
|
|
|
# Enough iterations already, break out of the loop.
|
|
|
|
return False
|
|
|
|
|
|
|
|
# End of while loop.
|
|
|
|
|
|
|
|
|
2010-09-13 20:54:30 +00:00
|
|
|
def buildDefault(self, compiler=None):
|
2010-09-03 23:49:16 +00:00
|
|
|
"""Platform specific way to build the default binaries."""
|
|
|
|
module = __import__(sys.platform)
|
2010-09-13 20:54:30 +00:00
|
|
|
if not module.buildDefault(compiler):
|
2010-09-03 23:49:16 +00:00
|
|
|
raise Exception("Don't know how to build default binary")
|
|
|
|
|
2010-09-13 20:54:30 +00:00
|
|
|
def buildDsym(self, compiler=None):
|
2010-08-30 22:26:48 +00:00
|
|
|
"""Platform specific way to build binaries with dsym info."""
|
2010-08-31 17:42:54 +00:00
|
|
|
module = __import__(sys.platform)
|
2010-09-13 20:54:30 +00:00
|
|
|
if not module.buildDsym(compiler):
|
2010-08-30 22:26:48 +00:00
|
|
|
raise Exception("Don't know how to build binary with dsym")
|
|
|
|
|
2010-09-13 20:54:30 +00:00
|
|
|
def buildDwarf(self, compiler=None):
|
2010-08-30 22:26:48 +00:00
|
|
|
"""Platform specific way to build binaries with dwarf maps."""
|
2010-08-31 17:42:54 +00:00
|
|
|
module = __import__(sys.platform)
|
2010-09-13 20:54:30 +00:00
|
|
|
if not module.buildDwarf(compiler):
|
2010-08-30 22:26:48 +00:00
|
|
|
raise Exception("Don't know how to build binary with dwarf")
|
|
|
|
|
2010-08-27 00:15:48 +00:00
|
|
|
def DebugSBValue(self, frame, val):
|
2010-08-31 17:42:54 +00:00
|
|
|
"""Debug print a SBValue object, if traceAlways is True."""
|
|
|
|
if not traceAlways:
|
2010-08-27 00:15:48 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
err = sys.stderr
|
|
|
|
err.write(val.GetName() + ":\n")
|
|
|
|
err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n')
|
|
|
|
err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n')
|
|
|
|
err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n')
|
|
|
|
err.write('\t' + "Value -> " + str(val.GetValue(frame)) + '\n')
|
|
|
|
err.write('\t' + "Summary -> " + str(val.GetSummary(frame)) + '\n')
|
|
|
|
err.write('\t' + "IsPtrType -> " + str(val.TypeIsPtrType()) + '\n')
|
|
|
|
err.write('\t' + "Location -> " + val.GetLocation(frame) + '\n')
|
|
|
|
|