blob: f950185d5adefd2efee5b9b5c2112972c4cfaa2c [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
135STOPPED_DUE_TO_BREAKPOINT = "Process state is stopped due to breakpoint"
136
137STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
138
Johnny Chen3c884a02010-08-24 22:07:56 +0000139DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
140
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000141VALID_BREAKPOINT = "Got a valid breakpoint"
142
Johnny Chen5ee88192010-08-27 23:47:36 +0000143VALID_FILESPEC = "Got a valid filespec"
144
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000145VALID_PROCESS = "Got a valid process"
146
147VALID_TARGET = "Got a valid target"
148
Johnny Chen981463d2010-08-25 19:00:04 +0000149VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen00778092010-08-09 22:01:17 +0000150
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000151
Johnny Chen17941842010-08-09 23:44:24 +0000152#
153# And a generic "Command '%s' returns successfully" message generator.
154#
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000155def CMD_MSG(str, exe):
156 if exe:
157 return "Command '%s' returns successfully" % str
158 else:
159 return "'%s' compares successfully" % str
Johnny Chen17941842010-08-09 23:44:24 +0000160
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000161#
Johnny Chen82d404c82010-08-27 18:08:58 +0000162# Returns the enum from the input string.
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000163#
Johnny Chen82d404c82010-08-27 18:08:58 +0000164def StopReasonEnum(string):
165 if string == "Invalid":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000166 return 0
Johnny Chen82d404c82010-08-27 18:08:58 +0000167 elif string == "None":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000168 return 1
Johnny Chen82d404c82010-08-27 18:08:58 +0000169 elif string == "Trace":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000170 return 2
Johnny Chen82d404c82010-08-27 18:08:58 +0000171 elif string == "Breakpoint":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000172 return 3
Johnny Chen82d404c82010-08-27 18:08:58 +0000173 elif string == "Watchpoint":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000174 return 4
Johnny Chen82d404c82010-08-27 18:08:58 +0000175 elif string == "Signal":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000176 return 5
Johnny Chen82d404c82010-08-27 18:08:58 +0000177 elif string == "Exception":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000178 return 6
Johnny Chen82d404c82010-08-27 18:08:58 +0000179 elif string == "PlanComplete":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000180 return 7
181 else:
182 raise Exception("Unknown stopReason string")
Johnny Chen17941842010-08-09 23:44:24 +0000183
Johnny Chen27c41232010-08-26 21:49:29 +0000184#
Johnny Chen82d404c82010-08-27 18:08:58 +0000185# Returns the stopReason string given an enum.
186#
187def StopReasonString(enum):
188 if enum == 0:
189 return "Invalid"
190 elif enum == 1:
191 return "None"
192 elif enum == 2:
193 return "Trace"
194 elif enum == 3:
195 return "Breakpoint"
196 elif enum == 4:
197 return "Watchpoint"
198 elif enum == 5:
199 return "Signal"
200 elif enum == 6:
201 return "Exception"
202 elif enum == 7:
203 return "PlanComplete"
204 else:
205 raise Exception("Unknown stopReason enum")
206
207#
Johnny Chen27c41232010-08-26 21:49:29 +0000208# Returns an env variable array from the os.environ map object.
209#
210def EnvArray():
211 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
212
Johnny Chen8d55a342010-08-31 17:42:54 +0000213# From 2.7's subprocess.check_output() convenience function.
214def system(*popenargs, **kwargs):
215 r"""Run command with arguments and return its output as a byte string.
216
217 If the exit code was non-zero it raises a CalledProcessError. The
218 CalledProcessError object will have the return code in the returncode
219 attribute and output in the output attribute.
220
221 The arguments are the same as for the Popen constructor. Example:
222
223 >>> check_output(["ls", "-l", "/dev/null"])
224 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
225
226 The stdout argument is not allowed as it is used internally.
227 To capture standard error in the result, use stderr=STDOUT.
228
229 >>> check_output(["/bin/sh", "-c",
230 ... "ls -l non_existent_file ; exit 0"],
231 ... stderr=STDOUT)
232 'ls: non_existent_file: No such file or directory\n'
233 """
234 if 'stdout' in kwargs:
235 raise ValueError('stdout argument not allowed, it will be overridden.')
236 process = Popen(stdout=PIPE, *popenargs, **kwargs)
Johnny Chen1aad5c62010-09-14 22:01:40 +0000237 output, error = process.communicate()
Johnny Chen8d55a342010-08-31 17:42:54 +0000238 retcode = process.poll()
239
240 if traceAlways:
241 if isinstance(popenargs, types.StringTypes):
242 args = [popenargs]
243 else:
244 args = list(popenargs)
245 print >> sys.stderr
246 print >> sys.stderr, "os command:", args
Johnny Chene0490512010-09-14 22:39:02 +0000247 print >> sys.stderr, "stdout:", output
248 print >> sys.stderr, "stderr:", error
249 print >> sys.stderr, "retcode:", retcode
Johnny Chen1aad5c62010-09-14 22:01:40 +0000250 print >> sys.stderr
Johnny Chen8d55a342010-08-31 17:42:54 +0000251
252 if retcode:
253 cmd = kwargs.get("args")
254 if cmd is None:
255 cmd = popenargs[0]
Johnny Chen2fcc0e52010-09-16 18:26:06 +0000256 raise CalledProcessError(retcode, cmd)
Johnny Chen8d55a342010-08-31 17:42:54 +0000257 return output
258
Johnny Chen827edff2010-08-27 00:15:48 +0000259
Johnny Chen73258832010-08-05 23:42:46 +0000260class TestBase(unittest2.TestCase):
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000261 """This LLDB abstract base class is meant to be subclassed."""
262
263 # The concrete subclass should override this attribute.
Johnny Chenf02ec122010-07-03 20:41:42 +0000264 mydir = None
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000265
Johnny Chen6ca006c2010-08-16 21:28:10 +0000266 # State pertaining to the inferior process, if any.
Johnny Chen57b47382010-09-02 22:25:47 +0000267 # This reflects inferior process started through the command interface with
268 # either the lldb "run" or "process launch" command.
269 # See also self.runCmd().
Johnny Chen6ca006c2010-08-16 21:28:10 +0000270 runStarted = False
271
Johnny Chenf2b70232010-08-25 18:49:48 +0000272 # Maximum allowed attempts when launching the inferior process.
273 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
274 maxLaunchCount = 3;
275
276 # Time to wait before the next launching attempt in second(s).
277 # Can be overridden by the LLDB_TIME_WAIT environment variable.
278 timeWait = 1.0;
279
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000280 # Keep track of the old current working directory.
281 oldcwd = None
Johnny Chena2124952010-08-05 21:23:45 +0000282
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000283 @classmethod
284 def setUpClass(cls):
Johnny Chenf02ec122010-07-03 20:41:42 +0000285 # Fail fast if 'mydir' attribute is not overridden.
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000286 if not cls.mydir or len(cls.mydir) == 0:
Johnny Chenf02ec122010-07-03 20:41:42 +0000287 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000288 # Save old working directory.
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000289 cls.oldcwd = os.getcwd()
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000290
291 # Change current working directory if ${LLDB_TEST} is defined.
292 # See also dotest.py which sets up ${LLDB_TEST}.
293 if ("LLDB_TEST" in os.environ):
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000294 if traceAlways:
295 print "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
296 os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
297
298 @classmethod
299 def tearDownClass(cls):
300 """Do class-wide cleanup."""
301
302 # First, let's do the platform-specific cleanup.
303 module = __import__(sys.platform)
304 if not module.cleanup():
305 raise Exception("Don't know how to do cleanup")
306
307 # Subclass might have specific cleanup function defined.
308 if getattr(cls, "classCleanup", None):
309 if traceAlways:
310 print "Call class-specific cleanup function for class:", cls
Johnny Chen90312a82010-09-21 22:34:45 +0000311 try:
312 cls.classCleanup()
313 except:
314 exc_type, exc_value, exc_tb = sys.exc_info()
315 traceback.print_exception(exc_type, exc_value, exc_tb)
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000316
317 # Restore old working directory.
318 if traceAlways:
319 print "Restore dir to:", cls.oldcwd
320 os.chdir(cls.oldcwd)
321
322 def setUp(self):
323 #import traceback
324 #traceback.print_stack()
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000325
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 Chenbf6ffa32010-07-03 03:41:59 +0000357 def tearDown(self):
Johnny Chen7d1d7532010-09-02 21:23:12 +0000358 #import traceback
359 #traceback.print_stack()
360
361 # Terminate the current process being debugged, if any.
Johnny Chen6ca006c2010-08-16 21:28:10 +0000362 if self.runStarted:
Johnny Chen7d1d7532010-09-02 21:23:12 +0000363 self.runCmd("process kill", PROCESS_KILLED, check=False)
364 elif self.process and self.process.IsValid():
365 rc = self.process.Kill()
366 self.assertTrue(rc.Success(), PROCESS_KILLED)
Johnny Chen6ca006c2010-08-16 21:28:10 +0000367
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000368 del self.dbg
369
Johnny Chen63dfb272010-09-01 00:15:19 +0000370 def runCmd(self, cmd, msg=None, check=True, trace=False, setCookie=True):
Johnny Chen27f212d2010-08-19 23:26:59 +0000371 """
372 Ask the command interpreter to handle the command and then check its
373 return status.
374 """
375 # Fail fast if 'cmd' is not meaningful.
376 if not cmd or len(cmd) == 0:
377 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000378
Johnny Chen8d55a342010-08-31 17:42:54 +0000379 trace = (True if traceAlways else trace)
Johnny Chend0190a62010-08-23 17:10:44 +0000380
Johnny Chen63dfb272010-09-01 00:15:19 +0000381 running = (cmd.startswith("run") or cmd.startswith("process launch"))
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000382
Johnny Chen63dfb272010-09-01 00:15:19 +0000383 for i in range(self.maxLaunchCount if running else 1):
Johnny Chenf2b70232010-08-25 18:49:48 +0000384 self.ci.HandleCommand(cmd, self.res)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000385
Johnny Chenf2b70232010-08-25 18:49:48 +0000386 if trace:
387 print >> sys.stderr, "runCmd:", cmd
388 if self.res.Succeeded():
389 print >> sys.stderr, "output:", self.res.GetOutput()
390 else:
391 print >> sys.stderr, self.res.GetError()
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000392
Johnny Chen725945d2010-09-03 22:35:47 +0000393 if running:
394 # For process launch, wait some time before possible next try.
395 time.sleep(self.timeWait)
396
Johnny Chenff3d01d2010-08-20 21:03:09 +0000397 if self.res.Succeeded():
Johnny Chenf2b70232010-08-25 18:49:48 +0000398 break
Johnny Chenf7f0cab2010-09-15 17:33:57 +0000399 elif running:
Johnny Chen9fa03212010-09-15 18:00:19 +0000400 print >> sys.stderr, "Command '" + cmd + "' failed!"
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000401
Johnny Chen7d1d7532010-09-02 21:23:12 +0000402 # Modify runStarted only if "run" or "process launch" was encountered.
403 if running:
404 self.runStarted = running and setCookie
Johnny Chen63dfb272010-09-01 00:15:19 +0000405
Johnny Chen27f212d2010-08-19 23:26:59 +0000406 if check:
407 self.assertTrue(self.res.Succeeded(),
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000408 msg if msg else CMD_MSG(cmd, True))
Johnny Chen27f212d2010-08-19 23:26:59 +0000409
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000410 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 +0000411 """
412 Similar to runCmd; with additional expect style output matching ability.
413
414 Ask the command interpreter to handle the command and then check its
415 return status. The 'msg' parameter specifies an informational assert
416 message. We expect the output from running the command to start with
Johnny Chenea88e942010-09-21 21:08:53 +0000417 'startstr', matches the substrings contained in 'substrs', and regexp
418 matches the patterns contained in 'patterns'.
Johnny Chenb3307862010-09-17 22:28:51 +0000419
420 If the keyword argument error is set to True, it signifies that the API
421 client is expecting the command to fail. In this case, the error stream
Johnny Chenaa902922010-09-17 22:45:27 +0000422 from running the command is retrieved and compared against the golden
Johnny Chenb3307862010-09-17 22:28:51 +0000423 input, instead.
Johnny Chenea88e942010-09-21 21:08:53 +0000424
425 If the keyword argument matching is set to False, it signifies that the API
426 client is expecting the output of the command not to match the golden
427 input.
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000428
429 Finally, the required argument 'str' represents the lldb command to be
430 sent to the command interpreter. In case the keyword argument 'exe' is
431 set to False, the 'str' is treated as a string to be matched/not-matched
432 against the golden input.
Johnny Chen27f212d2010-08-19 23:26:59 +0000433 """
Johnny Chen8d55a342010-08-31 17:42:54 +0000434 trace = (True if traceAlways else trace)
Johnny Chend0190a62010-08-23 17:10:44 +0000435
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000436 if exe:
437 # First run the command. If we are expecting error, set check=False.
438 self.runCmd(str, trace = (True if trace else False), check = not error)
Johnny Chen27f212d2010-08-19 23:26:59 +0000439
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000440 # Then compare the output against expected strings.
441 output = self.res.GetError() if error else self.res.GetOutput()
Johnny Chenb3307862010-09-17 22:28:51 +0000442
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000443 # If error is True, the API client expects the command to fail!
444 if error:
445 self.assertFalse(self.res.Succeeded(),
446 "Command '" + str + "' is expected to fail!")
447 else:
448 # No execution required, just compare str against the golden input.
449 output = str
450 if trace:
Johnny Chend64c3e72010-09-21 23:47:01 +0000451 print >> sys.stderr, "looking at:", output
Johnny Chenb3307862010-09-17 22:28:51 +0000452
Johnny Chenea88e942010-09-21 21:08:53 +0000453 # The heading says either "Expecting" or "Not expecting".
454 if trace:
455 heading = "Expecting" if matching else "Not expecting"
456
457 # Start from the startstr, if specified.
458 # If there's no startstr, set the initial state appropriately.
459 matched = output.startswith(startstr) if startstr else (True if matching else False)
Johnny Chenb145bba2010-08-20 18:25:15 +0000460
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000461 if startstr and trace:
Johnny Chenea88e942010-09-21 21:08:53 +0000462 print >> sys.stderr, "%s start string: %s" % (heading, startstr)
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000463 print >> sys.stderr, "Matched" if matched else "Not matched"
464 print >> sys.stderr
Johnny Chenb145bba2010-08-20 18:25:15 +0000465
Johnny Chenea88e942010-09-21 21:08:53 +0000466 # Look for sub strings, if specified.
467 keepgoing = matched if matching else not matched
468 if substrs and keepgoing:
Johnny Chen27f212d2010-08-19 23:26:59 +0000469 for str in substrs:
470 matched = output.find(str) > 0
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000471 if trace:
Johnny Chenea88e942010-09-21 21:08:53 +0000472 print >> sys.stderr, "%s sub string: %s" % (heading, str)
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000473 print >> sys.stderr, "Matched" if matched else "Not matched"
Johnny Chenea88e942010-09-21 21:08:53 +0000474 keepgoing = matched if matching else not matched
475 if not keepgoing:
Johnny Chen27f212d2010-08-19 23:26:59 +0000476 break
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000477 if trace:
478 print >> sys.stderr
Johnny Chen27f212d2010-08-19 23:26:59 +0000479
Johnny Chenea88e942010-09-21 21:08:53 +0000480 # Search for regular expression patterns, if specified.
481 keepgoing = matched if matching else not matched
482 if patterns and keepgoing:
483 for pattern in patterns:
484 # Match Objects always have a boolean value of True.
485 matched = bool(re.search(pattern, output))
486 if trace:
487 print >> sys.stderr, "%s pattern: %s" % (heading, pattern)
488 print >> sys.stderr, "Matched" if matched else "Not matched"
489 keepgoing = matched if matching else not matched
490 if not keepgoing:
491 break
492 if trace:
493 print >> sys.stderr
494
495 self.assertTrue(matched if matching else not matched,
Johnny Chen9c48b8d2010-09-21 23:33:30 +0000496 msg if msg else CMD_MSG(str, exe))
Johnny Chen27f212d2010-08-19 23:26:59 +0000497
Johnny Chenf3c59232010-08-25 22:52:45 +0000498 def invoke(self, obj, name, trace=False):
Johnny Chen61703c92010-08-25 22:56:10 +0000499 """Use reflection to call a method dynamically with no argument."""
Johnny Chen8d55a342010-08-31 17:42:54 +0000500 trace = (True if traceAlways else trace)
Johnny Chenf3c59232010-08-25 22:52:45 +0000501
502 method = getattr(obj, name)
503 import inspect
504 self.assertTrue(inspect.ismethod(method),
505 name + "is a method name of object: " + str(obj))
506 result = method()
Johnny Chen8d55a342010-08-31 17:42:54 +0000507 if trace:
Johnny Chenf3c59232010-08-25 22:52:45 +0000508 print str(method) + ":", result
509 return result
Johnny Chen827edff2010-08-27 00:15:48 +0000510
Johnny Chen13639082010-09-01 22:08:51 +0000511 def breakAfterLaunch(self, process, func, trace=False):
512 """
513 Perform some dancees after LaunchProcess() to break at func name.
514
515 Return True if we can successfully break at the func name in due time.
516 """
517 trace = (True if traceAlways else trace)
518
519 count = 0
520 while True:
521 # The stop reason of the thread should be breakpoint.
522 thread = process.GetThreadAtIndex(0)
523 SR = thread.GetStopReason()
524 if trace:
525 print >> sys.stderr, "StopReason =", StopReasonString(SR)
526
527 if SR == StopReasonEnum("Breakpoint"):
528 frame = thread.GetFrameAtIndex(0)
529 name = frame.GetFunction().GetName()
Johnny Chenea772bb2010-09-07 18:55:50 +0000530 if trace:
531 print >> sys.stderr, "function =", name
Johnny Chen13639082010-09-01 22:08:51 +0000532 if (name == func):
533 # We got what we want; now break out of the loop.
534 return True
535
536 # The inferior is in a transient state; continue the process.
537 time.sleep(1.0)
538 if trace:
539 print >> sys.stderr, "Continuing the process:", process
540 process.Continue()
541
542 count = count + 1
Johnny Chenae745562010-09-15 00:00:54 +0000543 if count == 15:
Johnny Chen13639082010-09-01 22:08:51 +0000544 if trace:
Johnny Chenae745562010-09-15 00:00:54 +0000545 print >> sys.stderr, "Reached 15 iterations, giving up..."
Johnny Chen13639082010-09-01 22:08:51 +0000546 # Enough iterations already, break out of the loop.
547 return False
548
549 # End of while loop.
550
551
Johnny Chen1394a4b2010-09-13 20:54:30 +0000552 def buildDefault(self, compiler=None):
Johnny Chen1b1b9ac2010-09-03 23:49:16 +0000553 """Platform specific way to build the default binaries."""
554 module = __import__(sys.platform)
Johnny Chen1394a4b2010-09-13 20:54:30 +0000555 if not module.buildDefault(compiler):
Johnny Chen1b1b9ac2010-09-03 23:49:16 +0000556 raise Exception("Don't know how to build default binary")
557
Johnny Chen1394a4b2010-09-13 20:54:30 +0000558 def buildDsym(self, compiler=None):
Johnny Chen2f1ad5e2010-08-30 22:26:48 +0000559 """Platform specific way to build binaries with dsym info."""
Johnny Chen8d55a342010-08-31 17:42:54 +0000560 module = __import__(sys.platform)
Johnny Chen1394a4b2010-09-13 20:54:30 +0000561 if not module.buildDsym(compiler):
Johnny Chen2f1ad5e2010-08-30 22:26:48 +0000562 raise Exception("Don't know how to build binary with dsym")
563
Johnny Chen1394a4b2010-09-13 20:54:30 +0000564 def buildDwarf(self, compiler=None):
Johnny Chen2f1ad5e2010-08-30 22:26:48 +0000565 """Platform specific way to build binaries with dwarf maps."""
Johnny Chen8d55a342010-08-31 17:42:54 +0000566 module = __import__(sys.platform)
Johnny Chen1394a4b2010-09-13 20:54:30 +0000567 if not module.buildDwarf(compiler):
Johnny Chen2f1ad5e2010-08-30 22:26:48 +0000568 raise Exception("Don't know how to build binary with dwarf")
569
Johnny Chen827edff2010-08-27 00:15:48 +0000570 def DebugSBValue(self, frame, val):
Johnny Chen8d55a342010-08-31 17:42:54 +0000571 """Debug print a SBValue object, if traceAlways is True."""
572 if not traceAlways:
Johnny Chen827edff2010-08-27 00:15:48 +0000573 return
574
575 err = sys.stderr
576 err.write(val.GetName() + ":\n")
577 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n')
578 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n')
579 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n')
580 err.write('\t' + "Value -> " + str(val.GetValue(frame)) + '\n')
581 err.write('\t' + "Summary -> " + str(val.GetSummary(frame)) + '\n')
582 err.write('\t' + "IsPtrType -> " + str(val.TypeIsPtrType()) + '\n')
583 err.write('\t' + "Location -> " + val.GetLocation(frame) + '\n')
584