blob: e2f18a9b40149a763b4088c05e0bdf503796b36a [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 Chen707b3c92010-10-11 22:25:46 +0000107# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
108# LLDB_COMMAND_TRACE and LLDB_NO_CLEANUP are set from '-t' and '-r dir' options.
109
110# By default, traceAlways is False.
Johnny Chen8d55a342010-08-31 17:42:54 +0000111if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
112 traceAlways = True
113else:
114 traceAlways = False
115
Johnny Chen707b3c92010-10-11 22:25:46 +0000116# By default, doCleanup is True.
117if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO":
118 doCleanup = False
119else:
120 doCleanup = True
121
Johnny Chen8d55a342010-08-31 17:42:54 +0000122
Johnny Chen00778092010-08-09 22:01:17 +0000123#
124# Some commonly used assert messages.
125#
126
Johnny Chenaa902922010-09-17 22:45:27 +0000127COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
128
Johnny Chen00778092010-08-09 22:01:17 +0000129CURRENT_EXECUTABLE_SET = "Current executable set successfully"
130
Johnny Chen7d1d7532010-09-02 21:23:12 +0000131PROCESS_IS_VALID = "Process is valid"
132
133PROCESS_KILLED = "Process is killed successfully"
134
Johnny Chen5ee88192010-08-27 23:47:36 +0000135RUN_SUCCEEDED = "Process is launched successfully"
Johnny Chen00778092010-08-09 22:01:17 +0000136
Johnny Chen17941842010-08-09 23:44:24 +0000137RUN_COMPLETED = "Process exited successfully"
Johnny Chen00778092010-08-09 22:01:17 +0000138
Johnny Chen67af43f2010-10-05 19:27:32 +0000139BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
140
Johnny Chen17941842010-08-09 23:44:24 +0000141BREAKPOINT_CREATED = "Breakpoint created successfully"
142
Johnny Chene76896c2010-08-17 21:33:31 +0000143BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
144
Johnny Chen17941842010-08-09 23:44:24 +0000145BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
Johnny Chen00778092010-08-09 22:01:17 +0000146
Johnny Chen703dbd02010-09-30 17:06:24 +0000147BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2"
148
Johnny Chenc70b02a2010-09-22 23:00:20 +0000149STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
150
Johnny Chen00778092010-08-09 22:01:17 +0000151STOPPED_DUE_TO_BREAKPOINT = "Process state is stopped due to breakpoint"
152
153STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
154
Johnny Chen3c884a02010-08-24 22:07:56 +0000155DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
156
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000157VALID_BREAKPOINT = "Got a valid breakpoint"
158
Johnny Chen5ee88192010-08-27 23:47:36 +0000159VALID_FILESPEC = "Got a valid filespec"
160
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000161VALID_PROCESS = "Got a valid process"
162
163VALID_TARGET = "Got a valid target"
164
Johnny Chen981463d2010-08-25 19:00:04 +0000165VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen00778092010-08-09 22:01:17 +0000166
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000167
Johnny Chen17941842010-08-09 23:44:24 +0000168#
169# And a generic "Command '%s' returns successfully" message generator.
170#
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000171def CMD_MSG(str, exe):
172 if exe:
173 return "Command '%s' returns successfully" % str
174 else:
175 return "'%s' compares successfully" % str
Johnny Chen17941842010-08-09 23:44:24 +0000176
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000177#
Johnny Chen27c41232010-08-26 21:49:29 +0000178# Returns an env variable array from the os.environ map object.
179#
180def EnvArray():
181 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
182
Johnny Chen8d55a342010-08-31 17:42:54 +0000183# From 2.7's subprocess.check_output() convenience function.
184def system(*popenargs, **kwargs):
185 r"""Run command with arguments and return its output as a byte string.
186
187 If the exit code was non-zero it raises a CalledProcessError. The
188 CalledProcessError object will have the return code in the returncode
189 attribute and output in the output attribute.
190
191 The arguments are the same as for the Popen constructor. Example:
192
193 >>> check_output(["ls", "-l", "/dev/null"])
194 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
195
196 The stdout argument is not allowed as it is used internally.
197 To capture standard error in the result, use stderr=STDOUT.
198
199 >>> check_output(["/bin/sh", "-c",
200 ... "ls -l non_existent_file ; exit 0"],
201 ... stderr=STDOUT)
202 'ls: non_existent_file: No such file or directory\n'
203 """
204 if 'stdout' in kwargs:
205 raise ValueError('stdout argument not allowed, it will be overridden.')
206 process = Popen(stdout=PIPE, *popenargs, **kwargs)
Johnny Chen1aad5c62010-09-14 22:01:40 +0000207 output, error = process.communicate()
Johnny Chen8d55a342010-08-31 17:42:54 +0000208 retcode = process.poll()
209
210 if traceAlways:
211 if isinstance(popenargs, types.StringTypes):
212 args = [popenargs]
213 else:
214 args = list(popenargs)
215 print >> sys.stderr
216 print >> sys.stderr, "os command:", args
Johnny Chene0490512010-09-14 22:39:02 +0000217 print >> sys.stderr, "stdout:", output
218 print >> sys.stderr, "stderr:", error
219 print >> sys.stderr, "retcode:", retcode
Johnny Chen1aad5c62010-09-14 22:01:40 +0000220 print >> sys.stderr
Johnny Chen8d55a342010-08-31 17:42:54 +0000221
222 if retcode:
223 cmd = kwargs.get("args")
224 if cmd is None:
225 cmd = popenargs[0]
Johnny Chen2fcc0e52010-09-16 18:26:06 +0000226 raise CalledProcessError(retcode, cmd)
Johnny Chen8d55a342010-08-31 17:42:54 +0000227 return output
228
Johnny Chen67af43f2010-10-05 19:27:32 +0000229def pointer_size():
230 """Return the pointer size of the host system."""
231 import ctypes
232 a_pointer = ctypes.c_void_p(0xffff)
233 return 8 * ctypes.sizeof(a_pointer)
234
Johnny Chen827edff2010-08-27 00:15:48 +0000235
Johnny Chen73258832010-08-05 23:42:46 +0000236class TestBase(unittest2.TestCase):
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000237 """This LLDB abstract base class is meant to be subclassed."""
238
Johnny Chenda884342010-10-01 22:59:49 +0000239 @classmethod
240 def skipLongRunningTest(cls):
241 """
242 By default, we skip long running test case.
243 This can be overridden by passing '-l' to the test driver (dotest.py).
244 """
245 if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]:
246 return False
247 else:
248 return True
249
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000250 # The concrete subclass should override this attribute.
Johnny Chenf02ec122010-07-03 20:41:42 +0000251 mydir = None
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000252
Johnny Chen6ca006c2010-08-16 21:28:10 +0000253 # State pertaining to the inferior process, if any.
Johnny Chen57b47382010-09-02 22:25:47 +0000254 # This reflects inferior process started through the command interface with
255 # either the lldb "run" or "process launch" command.
256 # See also self.runCmd().
Johnny Chen6ca006c2010-08-16 21:28:10 +0000257 runStarted = False
258
Johnny Chenf2b70232010-08-25 18:49:48 +0000259 # Maximum allowed attempts when launching the inferior process.
260 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
261 maxLaunchCount = 3;
262
263 # Time to wait before the next launching attempt in second(s).
264 # Can be overridden by the LLDB_TIME_WAIT environment variable.
265 timeWait = 1.0;
266
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000267 # Keep track of the old current working directory.
268 oldcwd = None
Johnny Chena2124952010-08-05 21:23:45 +0000269
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000270 @classmethod
271 def setUpClass(cls):
Johnny Chenda884342010-10-01 22:59:49 +0000272 """
273 Python unittest framework class setup fixture.
274 Do current directory manipulation.
275 """
276
Johnny Chenf02ec122010-07-03 20:41:42 +0000277 # Fail fast if 'mydir' attribute is not overridden.
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000278 if not cls.mydir or len(cls.mydir) == 0:
Johnny Chenf02ec122010-07-03 20:41:42 +0000279 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000280 # Save old working directory.
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000281 cls.oldcwd = os.getcwd()
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000282
283 # Change current working directory if ${LLDB_TEST} is defined.
284 # See also dotest.py which sets up ${LLDB_TEST}.
285 if ("LLDB_TEST" in os.environ):
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000286 if traceAlways:
Johnny Chen703dbd02010-09-30 17:06:24 +0000287 print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000288 os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
289
290 @classmethod
291 def tearDownClass(cls):
Johnny Chenda884342010-10-01 22:59:49 +0000292 """
293 Python unittest framework class teardown fixture.
294 Do class-wide cleanup.
295 """
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000296
Johnny Chen707b3c92010-10-11 22:25:46 +0000297 if doCleanup:
298 # First, let's do the platform-specific cleanup.
299 module = __import__(sys.platform)
300 if not module.cleanup():
301 raise Exception("Don't know how to do cleanup")
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000302
Johnny Chen707b3c92010-10-11 22:25:46 +0000303 # Subclass might have specific cleanup function defined.
304 if getattr(cls, "classCleanup", None):
305 if traceAlways:
306 print >> sys.stderr, "Call class-specific cleanup function for class:", cls
307 try:
308 cls.classCleanup()
309 except:
310 exc_type, exc_value, exc_tb = sys.exc_info()
311 traceback.print_exception(exc_type, exc_value, exc_tb)
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000312
313 # Restore old working directory.
314 if traceAlways:
Johnny Chen703dbd02010-09-30 17:06:24 +0000315 print >> sys.stderr, "Restore dir to:", cls.oldcwd
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000316 os.chdir(cls.oldcwd)
317
318 def setUp(self):
319 #import traceback
320 #traceback.print_stack()
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000321
Johnny Chen0ed37c92010-10-07 02:04:14 +0000322 if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and
323 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'):
324 time.sleep(0.5)
325
Johnny Chenf2b70232010-08-25 18:49:48 +0000326 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
327 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
328
329 if "LLDB_TIME_WAIT" in os.environ:
330 self.timeWait = float(os.environ["LLDB_TIME_WAIT"])
331
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000332 # Create the debugger instance if necessary.
333 try:
334 self.dbg = lldb.DBG
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000335 except AttributeError:
336 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf02ec122010-07-03 20:41:42 +0000337
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000338 if not self.dbg.IsValid():
339 raise Exception('Invalid debugger instance')
340
341 # We want our debugger to be synchronous.
342 self.dbg.SetAsync(False)
343
Johnny Chen7d1d7532010-09-02 21:23:12 +0000344 # There is no process associated with the debugger as yet.
Johnny Chen57b47382010-09-02 22:25:47 +0000345 # See also self.tearDown() where it checks whether self.process has a
346 # valid reference and calls self.process.Kill() to kill the process.
Johnny Chen7d1d7532010-09-02 21:23:12 +0000347 self.process = None
348
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000349 # Retrieve the associated command interpreter instance.
350 self.ci = self.dbg.GetCommandInterpreter()
351 if not self.ci:
352 raise Exception('Could not get the command interpreter')
353
354 # And the result object.
355 self.res = lldb.SBCommandReturnObject()
356
Johnny Chenc70b02a2010-09-22 23:00:20 +0000357 # These are for customized teardown cleanup.
358 self.dict = None
359 self.doTearDownCleanup = False
360
361 def setTearDownCleanup(self, dictionary=None):
362 self.dict = dictionary
363 self.doTearDownCleanup = True
364
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000365 def tearDown(self):
Johnny Chen7d1d7532010-09-02 21:23:12 +0000366 #import traceback
367 #traceback.print_stack()
368
369 # Terminate the current process being debugged, if any.
Johnny Chen6ca006c2010-08-16 21:28:10 +0000370 if self.runStarted:
Johnny Chen7d1d7532010-09-02 21:23:12 +0000371 self.runCmd("process kill", PROCESS_KILLED, check=False)
372 elif self.process and self.process.IsValid():
Johnny Chen0ed37c92010-10-07 02:04:14 +0000373 rc = self.invoke(self.process, "Kill")
Johnny Chen7d1d7532010-09-02 21:23:12 +0000374 self.assertTrue(rc.Success(), PROCESS_KILLED)
Johnny Chen0ed37c92010-10-07 02:04:14 +0000375 del self.process
Johnny Chen6ca006c2010-08-16 21:28:10 +0000376
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000377 del self.dbg
378
Johnny Chenc70b02a2010-09-22 23:00:20 +0000379 # Perform registered teardown cleanup.
Johnny Chen707b3c92010-10-11 22:25:46 +0000380 if doCleanup and self.doTearDownCleanup:
Johnny Chenc70b02a2010-09-22 23:00:20 +0000381 module = __import__(sys.platform)
382 if not module.cleanup(dictionary=self.dict):
383 raise Exception("Don't know how to do cleanup")
384
Johnny Chen63dfb272010-09-01 00:15:19 +0000385 def runCmd(self, cmd, msg=None, check=True, trace=False, setCookie=True):
Johnny Chen27f212d2010-08-19 23:26:59 +0000386 """
387 Ask the command interpreter to handle the command and then check its
388 return status.
389 """
390 # Fail fast if 'cmd' is not meaningful.
391 if not cmd or len(cmd) == 0:
392 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000393
Johnny Chen8d55a342010-08-31 17:42:54 +0000394 trace = (True if traceAlways else trace)
Johnny Chend0190a62010-08-23 17:10:44 +0000395
Johnny Chen63dfb272010-09-01 00:15:19 +0000396 running = (cmd.startswith("run") or cmd.startswith("process launch"))
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000397
Johnny Chen63dfb272010-09-01 00:15:19 +0000398 for i in range(self.maxLaunchCount if running else 1):
Johnny Chenf2b70232010-08-25 18:49:48 +0000399 self.ci.HandleCommand(cmd, self.res)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000400
Johnny Chenf2b70232010-08-25 18:49:48 +0000401 if trace:
402 print >> sys.stderr, "runCmd:", cmd
403 if self.res.Succeeded():
404 print >> sys.stderr, "output:", self.res.GetOutput()
405 else:
Johnny Chen65045f22010-10-08 17:21:27 +0000406 print >> sys.stderr, "runCmd failed!"
Johnny Chenf2b70232010-08-25 18:49:48 +0000407 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:
Johnny Chenb052f6c2010-09-23 23:35:28 +0000486 matched = output.find(str) != -1
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 Chen703dbd02010-09-30 17:06:24 +0000524 print >> sys.stderr, str(method) + ":", result
Johnny Chenf3c59232010-08-25 22:52:45 +0000525 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