blob: ea9e3228ba21195b309d1716b4fe01c6f101f30e [file] [log] [blame]
Johnny Chenbf6ffa32010-07-03 03:41:59 +00001"""
2LLDB module which provides the abstract base class of lldb test case.
3
4The concrete subclass can override lldbtest.TesBase in order to inherit the
5common behavior for unitest.TestCase.setUp/tearDown implemented in this file.
6
7The subclass should override the attribute mydir in order for the python runtime
8to locate the individual test cases when running as part of a large test suite
9or when running each test case as a separate python invocation.
10
11./dotest.py provides a test driver which sets up the environment to run the
12entire test suite. Users who want to run a test case on its own can specify the
13LLDB_TEST and PYTHONPATH environment variables, for example:
14
15$ export LLDB_TEST=$PWD
Johnny Chen8d55a342010-08-31 17:42:54 +000016$ export PYTHONPATH=/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:$LLDB_TEST:$LLDB_TEST/plugins
Johnny Chenbf6ffa32010-07-03 03:41:59 +000017$ echo $LLDB_TEST
18/Volumes/data/lldb/svn/trunk/test
19$ echo $PYTHONPATH
Johnny Chen8d55a342010-08-31 17:42:54 +000020/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:/Volumes/data/lldb/svn/trunk/test:/Volumes/data/lldb/svn/trunk/test/plugins
Johnny Chenbf6ffa32010-07-03 03:41:59 +000021$ python function_types/TestFunctionTypes.py
22.
23----------------------------------------------------------------------
24Ran 1 test in 0.363s
25
26OK
Johnny Chend0190a62010-08-23 17:10:44 +000027$ LLDB_COMMAND_TRACE=YES python array_types/TestArrayTypes.py
Johnny Chen57b47382010-09-02 22:25:47 +000028
29...
Johnny Chend0190a62010-08-23 17:10:44 +000030
31runCmd: breakpoint set -f main.c -l 42
32output: Breakpoint created: 1: file ='main.c', line = 42, locations = 1
33
34runCmd: run
35output: Launching '/Volumes/data/lldb/svn/trunk/test/array_types/a.out' (x86_64)
36
Johnny Chen57b47382010-09-02 22:25:47 +000037...
Johnny Chend0190a62010-08-23 17:10:44 +000038
Johnny Chen57b47382010-09-02 22:25:47 +000039runCmd: frame variable strings
Johnny Chend0190a62010-08-23 17:10:44 +000040output: (char *[4]) strings = {
41 (char *) strings[0] = 0x0000000100000f0c "Hello",
42 (char *) strings[1] = 0x0000000100000f12 "Hola",
43 (char *) strings[2] = 0x0000000100000f17 "Bonjour",
44 (char *) strings[3] = 0x0000000100000f1f "Guten Tag"
45}
46
Johnny Chen57b47382010-09-02 22:25:47 +000047runCmd: frame variable char_16
Johnny Chend0190a62010-08-23 17:10:44 +000048output: (char [16]) char_16 = {
49 (char) char_16[0] = 'H',
50 (char) char_16[1] = 'e',
51 (char) char_16[2] = 'l',
52 (char) char_16[3] = 'l',
53 (char) char_16[4] = 'o',
54 (char) char_16[5] = ' ',
55 (char) char_16[6] = 'W',
56 (char) char_16[7] = 'o',
57 (char) char_16[8] = 'r',
58 (char) char_16[9] = 'l',
59 (char) char_16[10] = 'd',
60 (char) char_16[11] = '\n',
61 (char) char_16[12] = '\0',
62 (char) char_16[13] = '\0',
63 (char) char_16[14] = '\0',
64 (char) char_16[15] = '\0'
65}
66
Johnny Chen57b47382010-09-02 22:25:47 +000067runCmd: frame variable ushort_matrix
Johnny Chend0190a62010-08-23 17:10:44 +000068output: (unsigned short [2][3]) ushort_matrix = {
69 (unsigned short [3]) ushort_matrix[0] = {
70 (unsigned short) ushort_matrix[0][0] = 0x0001,
71 (unsigned short) ushort_matrix[0][1] = 0x0002,
72 (unsigned short) ushort_matrix[0][2] = 0x0003
73 },
74 (unsigned short [3]) ushort_matrix[1] = {
75 (unsigned short) ushort_matrix[1][0] = 0x000b,
76 (unsigned short) ushort_matrix[1][1] = 0x0016,
77 (unsigned short) ushort_matrix[1][2] = 0x0021
78 }
79}
80
Johnny Chen57b47382010-09-02 22:25:47 +000081runCmd: frame variable long_6
Johnny Chend0190a62010-08-23 17:10:44 +000082output: (long [6]) long_6 = {
83 (long) long_6[0] = 1,
84 (long) long_6[1] = 2,
85 (long) long_6[2] = 3,
86 (long) long_6[3] = 4,
87 (long) long_6[4] = 5,
88 (long) long_6[5] = 6
89}
90
91.
92----------------------------------------------------------------------
93Ran 1 test in 0.349s
94
95OK
Johnny Chenbf6ffa32010-07-03 03:41:59 +000096$
97"""
98
Johnny Chen90312a82010-09-21 22:34:45 +000099import os, sys, traceback
Johnny Chenea88e942010-09-21 21:08:53 +0000100import re
Johnny Chen8952a2d2010-08-30 21:35:00 +0000101from subprocess import *
Johnny Chenf2b70232010-08-25 18:49:48 +0000102import time
Johnny Chena33a93c2010-08-30 23:08:52 +0000103import types
Johnny Chen73258832010-08-05 23:42:46 +0000104import unittest2
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000105import lldb
106
Johnny Chen8d55a342010-08-31 17:42:54 +0000107if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
108 traceAlways = True
109else:
110 traceAlways = False
111
112
Johnny Chen00778092010-08-09 22:01:17 +0000113#
114# Some commonly used assert messages.
115#
116
Johnny Chenaa902922010-09-17 22:45:27 +0000117COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
118
Johnny Chen00778092010-08-09 22:01:17 +0000119CURRENT_EXECUTABLE_SET = "Current executable set successfully"
120
Johnny Chen7d1d7532010-09-02 21:23:12 +0000121PROCESS_IS_VALID = "Process is valid"
122
123PROCESS_KILLED = "Process is killed successfully"
124
Johnny Chen5ee88192010-08-27 23:47:36 +0000125RUN_SUCCEEDED = "Process is launched successfully"
Johnny Chen00778092010-08-09 22:01:17 +0000126
Johnny Chen17941842010-08-09 23:44:24 +0000127RUN_COMPLETED = "Process exited successfully"
Johnny Chen00778092010-08-09 22:01:17 +0000128
Johnny Chen17941842010-08-09 23:44:24 +0000129BREAKPOINT_CREATED = "Breakpoint created successfully"
130
Johnny Chene76896c2010-08-17 21:33:31 +0000131BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
132
Johnny Chen17941842010-08-09 23:44:24 +0000133BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
Johnny Chen00778092010-08-09 22:01:17 +0000134
Johnny Chenc70b02a2010-09-22 23:00:20 +0000135STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
136
Johnny Chen00778092010-08-09 22:01:17 +0000137STOPPED_DUE_TO_BREAKPOINT = "Process state is stopped due to breakpoint"
138
139STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
140
Johnny Chen3c884a02010-08-24 22:07:56 +0000141DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
142
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000143VALID_BREAKPOINT = "Got a valid breakpoint"
144
Johnny Chen5ee88192010-08-27 23:47:36 +0000145VALID_FILESPEC = "Got a valid filespec"
146
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000147VALID_PROCESS = "Got a valid process"
148
149VALID_TARGET = "Got a valid target"
150
Johnny Chen981463d2010-08-25 19:00:04 +0000151VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen00778092010-08-09 22:01:17 +0000152
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000153
Johnny Chen17941842010-08-09 23:44:24 +0000154#
155# And a generic "Command '%s' returns successfully" message generator.
156#
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000157def CMD_MSG(str, exe):
158 if exe:
159 return "Command '%s' returns successfully" % str
160 else:
161 return "'%s' compares successfully" % str
Johnny Chen17941842010-08-09 23:44:24 +0000162
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000163#
Johnny Chen82d404c82010-08-27 18:08:58 +0000164# Returns the enum from the input string.
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000165#
Johnny Chen82d404c82010-08-27 18:08:58 +0000166def StopReasonEnum(string):
167 if string == "Invalid":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000168 return 0
Johnny Chen82d404c82010-08-27 18:08:58 +0000169 elif string == "None":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000170 return 1
Johnny Chen82d404c82010-08-27 18:08:58 +0000171 elif string == "Trace":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000172 return 2
Johnny Chen82d404c82010-08-27 18:08:58 +0000173 elif string == "Breakpoint":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000174 return 3
Johnny Chen82d404c82010-08-27 18:08:58 +0000175 elif string == "Watchpoint":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000176 return 4
Johnny Chen82d404c82010-08-27 18:08:58 +0000177 elif string == "Signal":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000178 return 5
Johnny Chen82d404c82010-08-27 18:08:58 +0000179 elif string == "Exception":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000180 return 6
Johnny Chen82d404c82010-08-27 18:08:58 +0000181 elif string == "PlanComplete":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000182 return 7
183 else:
184 raise Exception("Unknown stopReason string")
Johnny Chen17941842010-08-09 23:44:24 +0000185
Johnny Chen27c41232010-08-26 21:49:29 +0000186#
Johnny Chen82d404c82010-08-27 18:08:58 +0000187# Returns the stopReason string given an enum.
188#
189def StopReasonString(enum):
190 if enum == 0:
191 return "Invalid"
192 elif enum == 1:
193 return "None"
194 elif enum == 2:
195 return "Trace"
196 elif enum == 3:
197 return "Breakpoint"
198 elif enum == 4:
199 return "Watchpoint"
200 elif enum == 5:
201 return "Signal"
202 elif enum == 6:
203 return "Exception"
204 elif enum == 7:
205 return "PlanComplete"
206 else:
207 raise Exception("Unknown stopReason enum")
208
209#
Johnny Chen27c41232010-08-26 21:49:29 +0000210# Returns an env variable array from the os.environ map object.
211#
212def EnvArray():
213 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
214
Johnny Chen8d55a342010-08-31 17:42:54 +0000215# From 2.7's subprocess.check_output() convenience function.
216def system(*popenargs, **kwargs):
217 r"""Run command with arguments and return its output as a byte string.
218
219 If the exit code was non-zero it raises a CalledProcessError. The
220 CalledProcessError object will have the return code in the returncode
221 attribute and output in the output attribute.
222
223 The arguments are the same as for the Popen constructor. Example:
224
225 >>> check_output(["ls", "-l", "/dev/null"])
226 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
227
228 The stdout argument is not allowed as it is used internally.
229 To capture standard error in the result, use stderr=STDOUT.
230
231 >>> check_output(["/bin/sh", "-c",
232 ... "ls -l non_existent_file ; exit 0"],
233 ... stderr=STDOUT)
234 'ls: non_existent_file: No such file or directory\n'
235 """
236 if 'stdout' in kwargs:
237 raise ValueError('stdout argument not allowed, it will be overridden.')
238 process = Popen(stdout=PIPE, *popenargs, **kwargs)
Johnny Chen1aad5c62010-09-14 22:01:40 +0000239 output, error = process.communicate()
Johnny Chen8d55a342010-08-31 17:42:54 +0000240 retcode = process.poll()
241
242 if traceAlways:
243 if isinstance(popenargs, types.StringTypes):
244 args = [popenargs]
245 else:
246 args = list(popenargs)
247 print >> sys.stderr
248 print >> sys.stderr, "os command:", args
Johnny Chene0490512010-09-14 22:39:02 +0000249 print >> sys.stderr, "stdout:", output
250 print >> sys.stderr, "stderr:", error
251 print >> sys.stderr, "retcode:", retcode
Johnny Chen1aad5c62010-09-14 22:01:40 +0000252 print >> sys.stderr
Johnny Chen8d55a342010-08-31 17:42:54 +0000253
254 if retcode:
255 cmd = kwargs.get("args")
256 if cmd is None:
257 cmd = popenargs[0]
Johnny Chen2fcc0e52010-09-16 18:26:06 +0000258 raise CalledProcessError(retcode, cmd)
Johnny Chen8d55a342010-08-31 17:42:54 +0000259 return output
260
Johnny Chen827edff2010-08-27 00:15:48 +0000261
Johnny Chen73258832010-08-05 23:42:46 +0000262class TestBase(unittest2.TestCase):
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000263 """This LLDB abstract base class is meant to be subclassed."""
264
265 # The concrete subclass should override this attribute.
Johnny Chenf02ec122010-07-03 20:41:42 +0000266 mydir = None
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000267
Johnny Chen6ca006c2010-08-16 21:28:10 +0000268 # State pertaining to the inferior process, if any.
Johnny Chen57b47382010-09-02 22:25:47 +0000269 # This reflects inferior process started through the command interface with
270 # either the lldb "run" or "process launch" command.
271 # See also self.runCmd().
Johnny Chen6ca006c2010-08-16 21:28:10 +0000272 runStarted = False
273
Johnny Chenf2b70232010-08-25 18:49:48 +0000274 # Maximum allowed attempts when launching the inferior process.
275 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
276 maxLaunchCount = 3;
277
278 # Time to wait before the next launching attempt in second(s).
279 # Can be overridden by the LLDB_TIME_WAIT environment variable.
280 timeWait = 1.0;
281
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000282 # Keep track of the old current working directory.
283 oldcwd = None
Johnny Chena2124952010-08-05 21:23:45 +0000284
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000285 @classmethod
286 def setUpClass(cls):
Johnny Chenf02ec122010-07-03 20:41:42 +0000287 # Fail fast if 'mydir' attribute is not overridden.
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000288 if not cls.mydir or len(cls.mydir) == 0:
Johnny Chenf02ec122010-07-03 20:41:42 +0000289 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000290 # Save old working directory.
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000291 cls.oldcwd = os.getcwd()
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000292
293 # Change current working directory if ${LLDB_TEST} is defined.
294 # See also dotest.py which sets up ${LLDB_TEST}.
295 if ("LLDB_TEST" in os.environ):
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000296 if traceAlways:
297 print "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
298 os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
299
300 @classmethod
301 def tearDownClass(cls):
302 """Do class-wide cleanup."""
303
304 # First, let's do the platform-specific cleanup.
305 module = __import__(sys.platform)
306 if not module.cleanup():
307 raise Exception("Don't know how to do cleanup")
308
309 # Subclass might have specific cleanup function defined.
310 if getattr(cls, "classCleanup", None):
311 if traceAlways:
312 print "Call class-specific cleanup function for class:", cls
Johnny Chen90312a82010-09-21 22:34:45 +0000313 try:
314 cls.classCleanup()
315 except:
316 exc_type, exc_value, exc_tb = sys.exc_info()
317 traceback.print_exception(exc_type, exc_value, exc_tb)
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000318
319 # Restore old working directory.
320 if traceAlways:
321 print "Restore dir to:", cls.oldcwd
322 os.chdir(cls.oldcwd)
323
324 def setUp(self):
325 #import traceback
326 #traceback.print_stack()
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000327
Johnny Chenf2b70232010-08-25 18:49:48 +0000328 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
329 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
330
331 if "LLDB_TIME_WAIT" in os.environ:
332 self.timeWait = float(os.environ["LLDB_TIME_WAIT"])
333
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000334 # Create the debugger instance if necessary.
335 try:
336 self.dbg = lldb.DBG
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000337 except AttributeError:
338 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf02ec122010-07-03 20:41:42 +0000339
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000340 if not self.dbg.IsValid():
341 raise Exception('Invalid debugger instance')
342
343 # We want our debugger to be synchronous.
344 self.dbg.SetAsync(False)
345
Johnny Chen7d1d7532010-09-02 21:23:12 +0000346 # There is no process associated with the debugger as yet.
Johnny Chen57b47382010-09-02 22:25:47 +0000347 # See also self.tearDown() where it checks whether self.process has a
348 # valid reference and calls self.process.Kill() to kill the process.
Johnny Chen7d1d7532010-09-02 21:23:12 +0000349 self.process = None
350
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000351 # Retrieve the associated command interpreter instance.
352 self.ci = self.dbg.GetCommandInterpreter()
353 if not self.ci:
354 raise Exception('Could not get the command interpreter')
355
356 # And the result object.
357 self.res = lldb.SBCommandReturnObject()
358
Johnny Chenc70b02a2010-09-22 23:00:20 +0000359 # These are for customized teardown cleanup.
360 self.dict = None
361 self.doTearDownCleanup = False
362
363 def setTearDownCleanup(self, dictionary=None):
364 self.dict = dictionary
365 self.doTearDownCleanup = True
366
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000367 def tearDown(self):
Johnny Chen7d1d7532010-09-02 21:23:12 +0000368 #import traceback
369 #traceback.print_stack()
370
371 # Terminate the current process being debugged, if any.
Johnny Chen6ca006c2010-08-16 21:28:10 +0000372 if self.runStarted:
Johnny Chen7d1d7532010-09-02 21:23:12 +0000373 self.runCmd("process kill", PROCESS_KILLED, check=False)
374 elif self.process and self.process.IsValid():
375 rc = self.process.Kill()
376 self.assertTrue(rc.Success(), PROCESS_KILLED)
Johnny Chen6ca006c2010-08-16 21:28:10 +0000377
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000378 del self.dbg
379
Johnny Chenc70b02a2010-09-22 23:00:20 +0000380 # Perform registered teardown cleanup.
381 if self.doTearDownCleanup:
382 module = __import__(sys.platform)
383 if not module.cleanup(dictionary=self.dict):
384 raise Exception("Don't know how to do cleanup")
385
Johnny Chen63dfb272010-09-01 00:15:19 +0000386 def runCmd(self, cmd, msg=None, check=True, trace=False, setCookie=True):
Johnny Chen27f212d2010-08-19 23:26:59 +0000387 """
388 Ask the command interpreter to handle the command and then check its
389 return status.
390 """
391 # Fail fast if 'cmd' is not meaningful.
392 if not cmd or len(cmd) == 0:
393 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000394
Johnny Chen8d55a342010-08-31 17:42:54 +0000395 trace = (True if traceAlways else trace)
Johnny Chend0190a62010-08-23 17:10:44 +0000396
Johnny Chen63dfb272010-09-01 00:15:19 +0000397 running = (cmd.startswith("run") or cmd.startswith("process launch"))
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000398
Johnny Chen63dfb272010-09-01 00:15:19 +0000399 for i in range(self.maxLaunchCount if running else 1):
Johnny Chenf2b70232010-08-25 18:49:48 +0000400 self.ci.HandleCommand(cmd, self.res)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000401
Johnny Chenf2b70232010-08-25 18:49:48 +0000402 if trace:
403 print >> sys.stderr, "runCmd:", cmd
404 if self.res.Succeeded():
405 print >> sys.stderr, "output:", self.res.GetOutput()
406 else:
407 print >> sys.stderr, self.res.GetError()
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000408
Johnny Chen725945d2010-09-03 22:35:47 +0000409 if running:
410 # For process launch, wait some time before possible next try.
411 time.sleep(self.timeWait)
412
Johnny Chenff3d01d2010-08-20 21:03:09 +0000413 if self.res.Succeeded():
Johnny Chenf2b70232010-08-25 18:49:48 +0000414 break
Johnny Chenf7f0cab2010-09-15 17:33:57 +0000415 elif running:
Johnny Chen9fa03212010-09-15 18:00:19 +0000416 print >> sys.stderr, "Command '" + cmd + "' failed!"
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000417
Johnny Chen7d1d7532010-09-02 21:23:12 +0000418 # Modify runStarted only if "run" or "process launch" was encountered.
419 if running:
420 self.runStarted = running and setCookie
Johnny Chen63dfb272010-09-01 00:15:19 +0000421
Johnny Chen27f212d2010-08-19 23:26:59 +0000422 if check:
423 self.assertTrue(self.res.Succeeded(),
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000424 msg if msg else CMD_MSG(cmd, True))
Johnny Chen27f212d2010-08-19 23:26:59 +0000425
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000426 def expect(self, str, msg=None, patterns=None, startstr=None, substrs=None, trace=False, error=False, matching=True, exe=True):
Johnny Chen27f212d2010-08-19 23:26:59 +0000427 """
428 Similar to runCmd; with additional expect style output matching ability.
429
430 Ask the command interpreter to handle the command and then check its
431 return status. The 'msg' parameter specifies an informational assert
432 message. We expect the output from running the command to start with
Johnny Chenea88e942010-09-21 21:08:53 +0000433 'startstr', matches the substrings contained in 'substrs', and regexp
434 matches the patterns contained in 'patterns'.
Johnny Chenb3307862010-09-17 22:28:51 +0000435
436 If the keyword argument error is set to True, it signifies that the API
437 client is expecting the command to fail. In this case, the error stream
Johnny Chenaa902922010-09-17 22:45:27 +0000438 from running the command is retrieved and compared against the golden
Johnny Chenb3307862010-09-17 22:28:51 +0000439 input, instead.
Johnny Chenea88e942010-09-21 21:08:53 +0000440
441 If the keyword argument matching is set to False, it signifies that the API
442 client is expecting the output of the command not to match the golden
443 input.
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000444
445 Finally, the required argument 'str' represents the lldb command to be
446 sent to the command interpreter. In case the keyword argument 'exe' is
447 set to False, the 'str' is treated as a string to be matched/not-matched
448 against the golden input.
Johnny Chen27f212d2010-08-19 23:26:59 +0000449 """
Johnny Chen8d55a342010-08-31 17:42:54 +0000450 trace = (True if traceAlways else trace)
Johnny Chend0190a62010-08-23 17:10:44 +0000451
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000452 if exe:
453 # First run the command. If we are expecting error, set check=False.
454 self.runCmd(str, trace = (True if trace else False), check = not error)
Johnny Chen27f212d2010-08-19 23:26:59 +0000455
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000456 # Then compare the output against expected strings.
457 output = self.res.GetError() if error else self.res.GetOutput()
Johnny Chenb3307862010-09-17 22:28:51 +0000458
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000459 # If error is True, the API client expects the command to fail!
460 if error:
461 self.assertFalse(self.res.Succeeded(),
462 "Command '" + str + "' is expected to fail!")
463 else:
464 # No execution required, just compare str against the golden input.
465 output = str
466 if trace:
Johnny Chend64c3e72010-09-21 23:47:01 +0000467 print >> sys.stderr, "looking at:", output
Johnny Chenb3307862010-09-17 22:28:51 +0000468
Johnny Chenea88e942010-09-21 21:08:53 +0000469 # The heading says either "Expecting" or "Not expecting".
470 if trace:
471 heading = "Expecting" if matching else "Not expecting"
472
473 # Start from the startstr, if specified.
474 # If there's no startstr, set the initial state appropriately.
475 matched = output.startswith(startstr) if startstr else (True if matching else False)
Johnny Chenb145bba2010-08-20 18:25:15 +0000476
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000477 if startstr and trace:
Johnny Chenea88e942010-09-21 21:08:53 +0000478 print >> sys.stderr, "%s start string: %s" % (heading, startstr)
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000479 print >> sys.stderr, "Matched" if matched else "Not matched"
480 print >> sys.stderr
Johnny Chenb145bba2010-08-20 18:25:15 +0000481
Johnny Chenea88e942010-09-21 21:08:53 +0000482 # Look for sub strings, if specified.
483 keepgoing = matched if matching else not matched
484 if substrs and keepgoing:
Johnny Chen27f212d2010-08-19 23:26:59 +0000485 for str in substrs:
486 matched = output.find(str) > 0
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000487 if trace:
Johnny Chenea88e942010-09-21 21:08:53 +0000488 print >> sys.stderr, "%s sub string: %s" % (heading, str)
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000489 print >> sys.stderr, "Matched" if matched else "Not matched"
Johnny Chenea88e942010-09-21 21:08:53 +0000490 keepgoing = matched if matching else not matched
491 if not keepgoing:
Johnny Chen27f212d2010-08-19 23:26:59 +0000492 break
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000493 if trace:
494 print >> sys.stderr
Johnny Chen27f212d2010-08-19 23:26:59 +0000495
Johnny Chenea88e942010-09-21 21:08:53 +0000496 # Search for regular expression patterns, if specified.
497 keepgoing = matched if matching else not matched
498 if patterns and keepgoing:
499 for pattern in patterns:
500 # Match Objects always have a boolean value of True.
501 matched = bool(re.search(pattern, output))
502 if trace:
503 print >> sys.stderr, "%s pattern: %s" % (heading, pattern)
504 print >> sys.stderr, "Matched" if matched else "Not matched"
505 keepgoing = matched if matching else not matched
506 if not keepgoing:
507 break
508 if trace:
509 print >> sys.stderr
510
511 self.assertTrue(matched if matching else not matched,
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000512 msg if msg else CMD_MSG(str, exe))
Johnny Chen27f212d2010-08-19 23:26:59 +0000513
Johnny Chenf3c59232010-08-25 22:52:45 +0000514 def invoke(self, obj, name, trace=False):
Johnny Chen61703c92010-08-25 22:56:10 +0000515 """Use reflection to call a method dynamically with no argument."""
Johnny Chen8d55a342010-08-31 17:42:54 +0000516 trace = (True if traceAlways else trace)
Johnny Chenf3c59232010-08-25 22:52:45 +0000517
518 method = getattr(obj, name)
519 import inspect
520 self.assertTrue(inspect.ismethod(method),
521 name + "is a method name of object: " + str(obj))
522 result = method()
Johnny Chen8d55a342010-08-31 17:42:54 +0000523 if trace:
Johnny Chenf3c59232010-08-25 22:52:45 +0000524 print str(method) + ":", result
525 return result
Johnny Chen827edff2010-08-27 00:15:48 +0000526
Johnny Chen13639082010-09-01 22:08:51 +0000527 def breakAfterLaunch(self, process, func, trace=False):
528 """
529 Perform some dancees after LaunchProcess() to break at func name.
530
531 Return True if we can successfully break at the func name in due time.
532 """
533 trace = (True if traceAlways else trace)
534
535 count = 0
536 while True:
537 # The stop reason of the thread should be breakpoint.
538 thread = process.GetThreadAtIndex(0)
539 SR = thread.GetStopReason()
540 if trace:
541 print >> sys.stderr, "StopReason =", StopReasonString(SR)
542
543 if SR == StopReasonEnum("Breakpoint"):
544 frame = thread.GetFrameAtIndex(0)
545 name = frame.GetFunction().GetName()
Johnny Chenea772bb2010-09-07 18:55:50 +0000546 if trace:
547 print >> sys.stderr, "function =", name
Johnny Chen13639082010-09-01 22:08:51 +0000548 if (name == func):
549 # We got what we want; now break out of the loop.
550 return True
551
552 # The inferior is in a transient state; continue the process.
553 time.sleep(1.0)
554 if trace:
555 print >> sys.stderr, "Continuing the process:", process
556 process.Continue()
557
558 count = count + 1
Johnny Chenae745562010-09-15 00:00:54 +0000559 if count == 15:
Johnny Chen13639082010-09-01 22:08:51 +0000560 if trace:
Johnny Chenae745562010-09-15 00:00:54 +0000561 print >> sys.stderr, "Reached 15 iterations, giving up..."
Johnny Chen13639082010-09-01 22:08:51 +0000562 # Enough iterations already, break out of the loop.
563 return False
564
565 # End of while loop.
566
567
Johnny Chenc70b02a2010-09-22 23:00:20 +0000568 def buildDefault(self, architecture=None, compiler=None, dictionary=None):
Johnny Chen1b1b9ac2010-09-03 23:49:16 +0000569 """Platform specific way to build the default binaries."""
570 module = __import__(sys.platform)
Johnny Chenc70b02a2010-09-22 23:00:20 +0000571 if not module.buildDefault(architecture, compiler, dictionary):
Johnny Chen1b1b9ac2010-09-03 23:49:16 +0000572 raise Exception("Don't know how to build default binary")
573
Johnny Chenc70b02a2010-09-22 23:00:20 +0000574 def buildDsym(self, architecture=None, compiler=None, dictionary=None):
Johnny Chen2f1ad5e2010-08-30 22:26:48 +0000575 """Platform specific way to build binaries with dsym info."""
Johnny Chen8d55a342010-08-31 17:42:54 +0000576 module = __import__(sys.platform)
Johnny Chenc70b02a2010-09-22 23:00:20 +0000577 if not module.buildDsym(architecture, compiler, dictionary):
Johnny Chen2f1ad5e2010-08-30 22:26:48 +0000578 raise Exception("Don't know how to build binary with dsym")
579
Johnny Chenc70b02a2010-09-22 23:00:20 +0000580 def buildDwarf(self, architecture=None, compiler=None, dictionary=None):
Johnny Chen2f1ad5e2010-08-30 22:26:48 +0000581 """Platform specific way to build binaries with dwarf maps."""
Johnny Chen8d55a342010-08-31 17:42:54 +0000582 module = __import__(sys.platform)
Johnny Chenc70b02a2010-09-22 23:00:20 +0000583 if not module.buildDwarf(architecture, compiler, dictionary):
Johnny Chen2f1ad5e2010-08-30 22:26:48 +0000584 raise Exception("Don't know how to build binary with dwarf")
585
Johnny Chen827edff2010-08-27 00:15:48 +0000586 def DebugSBValue(self, frame, val):
Johnny Chen8d55a342010-08-31 17:42:54 +0000587 """Debug print a SBValue object, if traceAlways is True."""
588 if not traceAlways:
Johnny Chen827edff2010-08-27 00:15:48 +0000589 return
590
591 err = sys.stderr
592 err.write(val.GetName() + ":\n")
593 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n')
594 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n')
595 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n')
596 err.write('\t' + "Value -> " + str(val.GetValue(frame)) + '\n')
597 err.write('\t' + "Summary -> " + str(val.GetSummary(frame)) + '\n')
598 err.write('\t' + "IsPtrType -> " + str(val.TypeIsPtrType()) + '\n')
599 err.write('\t' + "Location -> " + val.GetLocation(frame) + '\n')
600