blob: 9b5975ea9a62c9bb2b5ff718c15c9d5a13e71ad6 [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
16$ export PYTHONPATH=/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:$LLDB_TEST
17$ echo $LLDB_TEST
18/Volumes/data/lldb/svn/trunk/test
19$ echo $PYTHONPATH
20/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:/Volumes/data/lldb/svn/trunk/test
21$ 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
28LLDB_COMMAND_TRACE=YES python array_types/TestArrayTypes.py
29runCmd: file /Volumes/data/lldb/svn/trunk/test/array_types/a.out
30output: Current executable set to '/Volumes/data/lldb/svn/trunk/test/array_types/a.out' (x86_64).
31
32runCmd: breakpoint set -f main.c -l 42
33output: Breakpoint created: 1: file ='main.c', line = 42, locations = 1
34
35runCmd: run
36output: Launching '/Volumes/data/lldb/svn/trunk/test/array_types/a.out' (x86_64)
37
38runCmd: thread list
39output: Process 24987 state is Stopped
40 thread #1: tid = 0x2e03, pc = 0x0000000100000df4, where = a.out`main + 612 at /Volumes/data/lldb/svn/trunk/test/array_types/main.c:45, stop reason = breakpoint 1.1, queue = com.apple.main-thread
41
42runCmd: breakpoint list
43output: Current breakpoints:
441: file ='main.c', line = 42, locations = 1, resolved = 1
45 1.1: where = a.out`main + 612 at /Volumes/data/lldb/svn/trunk/test/array_types/main.c:45, address = 0x0000000100000df4, resolved, hit count = 1
46
47
48runCmd: variable list strings
49output: (char *[4]) strings = {
50 (char *) strings[0] = 0x0000000100000f0c "Hello",
51 (char *) strings[1] = 0x0000000100000f12 "Hola",
52 (char *) strings[2] = 0x0000000100000f17 "Bonjour",
53 (char *) strings[3] = 0x0000000100000f1f "Guten Tag"
54}
55
56runCmd: variable list char_16
57output: (char [16]) char_16 = {
58 (char) char_16[0] = 'H',
59 (char) char_16[1] = 'e',
60 (char) char_16[2] = 'l',
61 (char) char_16[3] = 'l',
62 (char) char_16[4] = 'o',
63 (char) char_16[5] = ' ',
64 (char) char_16[6] = 'W',
65 (char) char_16[7] = 'o',
66 (char) char_16[8] = 'r',
67 (char) char_16[9] = 'l',
68 (char) char_16[10] = 'd',
69 (char) char_16[11] = '\n',
70 (char) char_16[12] = '\0',
71 (char) char_16[13] = '\0',
72 (char) char_16[14] = '\0',
73 (char) char_16[15] = '\0'
74}
75
76runCmd: variable list ushort_matrix
77output: (unsigned short [2][3]) ushort_matrix = {
78 (unsigned short [3]) ushort_matrix[0] = {
79 (unsigned short) ushort_matrix[0][0] = 0x0001,
80 (unsigned short) ushort_matrix[0][1] = 0x0002,
81 (unsigned short) ushort_matrix[0][2] = 0x0003
82 },
83 (unsigned short [3]) ushort_matrix[1] = {
84 (unsigned short) ushort_matrix[1][0] = 0x000b,
85 (unsigned short) ushort_matrix[1][1] = 0x0016,
86 (unsigned short) ushort_matrix[1][2] = 0x0021
87 }
88}
89
90runCmd: variable list long_6
91output: (long [6]) long_6 = {
92 (long) long_6[0] = 1,
93 (long) long_6[1] = 2,
94 (long) long_6[2] = 3,
95 (long) long_6[3] = 4,
96 (long) long_6[4] = 5,
97 (long) long_6[5] = 6
98}
99
100.
101----------------------------------------------------------------------
102Ran 1 test in 0.349s
103
104OK
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000105$
106"""
107
108import os
Johnny Chenff3d01d2010-08-20 21:03:09 +0000109import sys
Johnny Chenf2b70232010-08-25 18:49:48 +0000110import time
Johnny Chen73258832010-08-05 23:42:46 +0000111import unittest2
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000112import lldb
113
Johnny Chen00778092010-08-09 22:01:17 +0000114#
115# Some commonly used assert messages.
116#
117
118CURRENT_EXECUTABLE_SET = "Current executable set successfully"
119
Johnny Chen5ee88192010-08-27 23:47:36 +0000120RUN_SUCCEEDED = "Process is launched successfully"
Johnny Chen00778092010-08-09 22:01:17 +0000121
Johnny Chen17941842010-08-09 23:44:24 +0000122RUN_COMPLETED = "Process exited successfully"
Johnny Chen00778092010-08-09 22:01:17 +0000123
Johnny Chen17941842010-08-09 23:44:24 +0000124BREAKPOINT_CREATED = "Breakpoint created successfully"
125
Johnny Chene76896c2010-08-17 21:33:31 +0000126BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
127
Johnny Chen17941842010-08-09 23:44:24 +0000128BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
Johnny Chen00778092010-08-09 22:01:17 +0000129
130STOPPED_DUE_TO_BREAKPOINT = "Process state is stopped due to breakpoint"
131
132STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
133
Johnny Chen3c884a02010-08-24 22:07:56 +0000134DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
135
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000136VALID_BREAKPOINT = "Got a valid breakpoint"
137
Johnny Chen5ee88192010-08-27 23:47:36 +0000138VALID_FILESPEC = "Got a valid filespec"
139
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000140VALID_PROCESS = "Got a valid process"
141
142VALID_TARGET = "Got a valid target"
143
Johnny Chen981463d2010-08-25 19:00:04 +0000144VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen00778092010-08-09 22:01:17 +0000145
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000146
Johnny Chen17941842010-08-09 23:44:24 +0000147#
148# And a generic "Command '%s' returns successfully" message generator.
149#
150def CMD_MSG(command):
151 return "Command '%s' returns successfully" % (command)
152
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000153#
Johnny Chen82d404c82010-08-27 18:08:58 +0000154# Returns the enum from the input string.
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000155#
Johnny Chen82d404c82010-08-27 18:08:58 +0000156def StopReasonEnum(string):
157 if string == "Invalid":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000158 return 0
Johnny Chen82d404c82010-08-27 18:08:58 +0000159 elif string == "None":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000160 return 1
Johnny Chen82d404c82010-08-27 18:08:58 +0000161 elif string == "Trace":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000162 return 2
Johnny Chen82d404c82010-08-27 18:08:58 +0000163 elif string == "Breakpoint":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000164 return 3
Johnny Chen82d404c82010-08-27 18:08:58 +0000165 elif string == "Watchpoint":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000166 return 4
Johnny Chen82d404c82010-08-27 18:08:58 +0000167 elif string == "Signal":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000168 return 5
Johnny Chen82d404c82010-08-27 18:08:58 +0000169 elif string == "Exception":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000170 return 6
Johnny Chen82d404c82010-08-27 18:08:58 +0000171 elif string == "PlanComplete":
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000172 return 7
173 else:
174 raise Exception("Unknown stopReason string")
Johnny Chen17941842010-08-09 23:44:24 +0000175
Johnny Chen27c41232010-08-26 21:49:29 +0000176#
Johnny Chen82d404c82010-08-27 18:08:58 +0000177# Returns the stopReason string given an enum.
178#
179def StopReasonString(enum):
180 if enum == 0:
181 return "Invalid"
182 elif enum == 1:
183 return "None"
184 elif enum == 2:
185 return "Trace"
186 elif enum == 3:
187 return "Breakpoint"
188 elif enum == 4:
189 return "Watchpoint"
190 elif enum == 5:
191 return "Signal"
192 elif enum == 6:
193 return "Exception"
194 elif enum == 7:
195 return "PlanComplete"
196 else:
197 raise Exception("Unknown stopReason enum")
198
199#
Johnny Chen27c41232010-08-26 21:49:29 +0000200# Returns an env variable array from the os.environ map object.
201#
202def EnvArray():
203 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
204
Johnny Chen827edff2010-08-27 00:15:48 +0000205
Johnny Chen73258832010-08-05 23:42:46 +0000206class TestBase(unittest2.TestCase):
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000207 """This LLDB abstract base class is meant to be subclassed."""
208
209 # The concrete subclass should override this attribute.
Johnny Chenf02ec122010-07-03 20:41:42 +0000210 mydir = None
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000211
Johnny Chen6ca006c2010-08-16 21:28:10 +0000212 # State pertaining to the inferior process, if any.
213 runStarted = False
214
Johnny Chenf2b70232010-08-25 18:49:48 +0000215 # Maximum allowed attempts when launching the inferior process.
216 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
217 maxLaunchCount = 3;
218
219 # Time to wait before the next launching attempt in second(s).
220 # Can be overridden by the LLDB_TIME_WAIT environment variable.
221 timeWait = 1.0;
222
Johnny Chend0190a62010-08-23 17:10:44 +0000223 # os.environ["LLDB_COMMAND_TRACE"], if set to "YES", will turn on this flag.
224 traceAlways = False;
225
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000226 def setUp(self):
Johnny Chen9289a652010-08-07 01:13:18 +0000227 #import traceback
Johnny Chena2124952010-08-05 21:23:45 +0000228 #traceback.print_stack()
229
Johnny Chenf02ec122010-07-03 20:41:42 +0000230 # Fail fast if 'mydir' attribute is not overridden.
231 if not self.mydir or len(self.mydir) == 0:
232 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000233 # Save old working directory.
234 self.oldcwd = os.getcwd()
235
236 # Change current working directory if ${LLDB_TEST} is defined.
237 # See also dotest.py which sets up ${LLDB_TEST}.
238 if ("LLDB_TEST" in os.environ):
239 os.chdir(os.path.join(os.environ["LLDB_TEST"], self.mydir));
240
Johnny Chenf2b70232010-08-25 18:49:48 +0000241 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
242 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
243
244 if "LLDB_TIME_WAIT" in os.environ:
245 self.timeWait = float(os.environ["LLDB_TIME_WAIT"])
246
Johnny Chend0190a62010-08-23 17:10:44 +0000247 if ("LLDB_COMMAND_TRACE" in os.environ and
248 os.environ["LLDB_COMMAND_TRACE"] == "YES"):
249 self.traceAlways = True
250
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000251 # Create the debugger instance if necessary.
252 try:
253 self.dbg = lldb.DBG
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000254 except AttributeError:
255 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf02ec122010-07-03 20:41:42 +0000256
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000257 if not self.dbg.IsValid():
258 raise Exception('Invalid debugger instance')
259
260 # We want our debugger to be synchronous.
261 self.dbg.SetAsync(False)
262
263 # Retrieve the associated command interpreter instance.
264 self.ci = self.dbg.GetCommandInterpreter()
265 if not self.ci:
266 raise Exception('Could not get the command interpreter')
267
268 # And the result object.
269 self.res = lldb.SBCommandReturnObject()
270
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000271 def tearDown(self):
Johnny Chen6ca006c2010-08-16 21:28:10 +0000272 # Finish the inferior process, if it was "run" previously.
273 if self.runStarted:
274 self.ci.HandleCommand("continue", self.res)
275
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000276 del self.dbg
277
278 # Restore old working directory.
279 os.chdir(self.oldcwd)
Johnny Chen27f212d2010-08-19 23:26:59 +0000280
Johnny Chend0190a62010-08-23 17:10:44 +0000281 def runCmd(self, cmd, msg=None, check=True, trace=False):
Johnny Chen27f212d2010-08-19 23:26:59 +0000282 """
283 Ask the command interpreter to handle the command and then check its
284 return status.
285 """
286 # Fail fast if 'cmd' is not meaningful.
287 if not cmd or len(cmd) == 0:
288 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000289
Johnny Chend0190a62010-08-23 17:10:44 +0000290 trace = (True if self.traceAlways else trace)
291
Johnny Chenf2b70232010-08-25 18:49:48 +0000292 self.runStarted = (cmd.startswith("run") or
293 cmd.startswith("process launch"))
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000294
Johnny Chenf2b70232010-08-25 18:49:48 +0000295 for i in range(self.maxLaunchCount if self.runStarted else 1):
296 self.ci.HandleCommand(cmd, self.res)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000297
Johnny Chenf2b70232010-08-25 18:49:48 +0000298 if trace:
299 print >> sys.stderr, "runCmd:", cmd
300 if self.res.Succeeded():
301 print >> sys.stderr, "output:", self.res.GetOutput()
302 else:
303 print >> sys.stderr, self.res.GetError()
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000304
Johnny Chenff3d01d2010-08-20 21:03:09 +0000305 if self.res.Succeeded():
Johnny Chenf2b70232010-08-25 18:49:48 +0000306 break
Johnny Chenff3d01d2010-08-20 21:03:09 +0000307 else:
Johnny Chenf2b70232010-08-25 18:49:48 +0000308 if self.runStarted:
309 # Process launch failed, wait some time before the next try.
310 time.sleep(self.timeWait)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000311
Johnny Chen27f212d2010-08-19 23:26:59 +0000312 if check:
313 self.assertTrue(self.res.Succeeded(),
314 msg if msg else CMD_MSG(cmd))
315
Johnny Chend0190a62010-08-23 17:10:44 +0000316 def expect(self, cmd, msg=None, startstr=None, substrs=None, trace=False):
Johnny Chen27f212d2010-08-19 23:26:59 +0000317 """
318 Similar to runCmd; with additional expect style output matching ability.
319
320 Ask the command interpreter to handle the command and then check its
321 return status. The 'msg' parameter specifies an informational assert
322 message. We expect the output from running the command to start with
323 'startstr' and matches the substrings contained in 'substrs'.
324 """
Johnny Chen74f26b82010-08-20 19:17:39 +0000325
Johnny Chend0190a62010-08-23 17:10:44 +0000326 trace = (True if self.traceAlways else trace)
327
Johnny Chen74f26b82010-08-20 19:17:39 +0000328 # First run the command.
Johnny Chend0190a62010-08-23 17:10:44 +0000329 self.runCmd(cmd, trace = (True if trace else False))
Johnny Chen27f212d2010-08-19 23:26:59 +0000330
Johnny Chen74f26b82010-08-20 19:17:39 +0000331 # Then compare the output against expected strings.
Johnny Chen27f212d2010-08-19 23:26:59 +0000332 output = self.res.GetOutput()
333 matched = output.startswith(startstr) if startstr else True
Johnny Chenb145bba2010-08-20 18:25:15 +0000334
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000335 if startstr and trace:
336 print >> sys.stderr, "Expecting start string:", startstr
337 print >> sys.stderr, "Matched" if matched else "Not matched"
338 print >> sys.stderr
Johnny Chenb145bba2010-08-20 18:25:15 +0000339
Johnny Chen981463d2010-08-25 19:00:04 +0000340 if substrs and matched:
Johnny Chen27f212d2010-08-19 23:26:59 +0000341 for str in substrs:
342 matched = output.find(str) > 0
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000343 if trace:
344 print >> sys.stderr, "Expecting sub string:", str
345 print >> sys.stderr, "Matched" if matched else "Not matched"
Johnny Chen27f212d2010-08-19 23:26:59 +0000346 if not matched:
347 break
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000348 if trace:
349 print >> sys.stderr
Johnny Chen27f212d2010-08-19 23:26:59 +0000350
Johnny Chen74f26b82010-08-20 19:17:39 +0000351 self.assertTrue(matched, msg if msg else CMD_MSG(cmd))
Johnny Chen27f212d2010-08-19 23:26:59 +0000352
Johnny Chenf3c59232010-08-25 22:52:45 +0000353 def invoke(self, obj, name, trace=False):
Johnny Chen61703c92010-08-25 22:56:10 +0000354 """Use reflection to call a method dynamically with no argument."""
Johnny Chenf3c59232010-08-25 22:52:45 +0000355
356 trace = (True if self.traceAlways else trace)
357
358 method = getattr(obj, name)
359 import inspect
360 self.assertTrue(inspect.ismethod(method),
361 name + "is a method name of object: " + str(obj))
362 result = method()
363 if self.traceAlways:
364 print str(method) + ":", result
365 return result
Johnny Chen827edff2010-08-27 00:15:48 +0000366
367 def DebugSBValue(self, frame, val):
368 """Debug print a SBValue object, if self.traceAlways is True."""
369 if not self.traceAlways:
370 return
371
372 err = sys.stderr
373 err.write(val.GetName() + ":\n")
374 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n')
375 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n')
376 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n')
377 err.write('\t' + "Value -> " + str(val.GetValue(frame)) + '\n')
378 err.write('\t' + "Summary -> " + str(val.GetSummary(frame)) + '\n')
379 err.write('\t' + "IsPtrType -> " + str(val.TypeIsPtrType()) + '\n')
380 err.write('\t' + "Location -> " + val.GetLocation(frame) + '\n')
381
382