blob: 851b2de6794b872c2dacb9abd361df0ca28cae58 [file] [log] [blame]
Johnny Chena1affab2010-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 Chend0c24b22010-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 Chena1affab2010-07-03 03:41:59 +0000105$
106"""
107
108import os
Johnny Chen029acae2010-08-20 21:03:09 +0000109import sys
Johnny Chen65572482010-08-25 18:49:48 +0000110import time
Johnny Chen75e28f92010-08-05 23:42:46 +0000111import unittest2
Johnny Chena1affab2010-07-03 03:41:59 +0000112import lldb
113
Johnny Chen96f08d52010-08-09 22:01:17 +0000114#
115# Some commonly used assert messages.
116#
117
118CURRENT_EXECUTABLE_SET = "Current executable set successfully"
119
Johnny Chen029acae2010-08-20 21:03:09 +0000120RUN_STOPPED = "Process is launched and then stopped successfully"
Johnny Chen96f08d52010-08-09 22:01:17 +0000121
Johnny Chend85dae52010-08-09 23:44:24 +0000122RUN_COMPLETED = "Process exited successfully"
Johnny Chen96f08d52010-08-09 22:01:17 +0000123
Johnny Chend85dae52010-08-09 23:44:24 +0000124BREAKPOINT_CREATED = "Breakpoint created successfully"
125
Johnny Chen9b92c6e2010-08-17 21:33:31 +0000126BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
127
Johnny Chend85dae52010-08-09 23:44:24 +0000128BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
Johnny Chen96f08d52010-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 Chen4917e102010-08-24 22:07:56 +0000134DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
135
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000136VALID_BREAKPOINT = "Got a valid breakpoint"
137
138VALID_PROCESS = "Got a valid process"
139
140VALID_TARGET = "Got a valid target"
141
Johnny Chen22b95b22010-08-25 19:00:04 +0000142VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen96f08d52010-08-09 22:01:17 +0000143
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000144
Johnny Chend85dae52010-08-09 23:44:24 +0000145#
146# And a generic "Command '%s' returns successfully" message generator.
147#
148def CMD_MSG(command):
149 return "Command '%s' returns successfully" % (command)
150
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000151#
Johnny Chen6264bc62010-08-27 18:08:58 +0000152# Returns the enum from the input string.
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000153#
Johnny Chen6264bc62010-08-27 18:08:58 +0000154def StopReasonEnum(string):
155 if string == "Invalid":
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000156 return 0
Johnny Chen6264bc62010-08-27 18:08:58 +0000157 elif string == "None":
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000158 return 1
Johnny Chen6264bc62010-08-27 18:08:58 +0000159 elif string == "Trace":
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000160 return 2
Johnny Chen6264bc62010-08-27 18:08:58 +0000161 elif string == "Breakpoint":
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000162 return 3
Johnny Chen6264bc62010-08-27 18:08:58 +0000163 elif string == "Watchpoint":
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000164 return 4
Johnny Chen6264bc62010-08-27 18:08:58 +0000165 elif string == "Signal":
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000166 return 5
Johnny Chen6264bc62010-08-27 18:08:58 +0000167 elif string == "Exception":
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000168 return 6
Johnny Chen6264bc62010-08-27 18:08:58 +0000169 elif string == "PlanComplete":
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000170 return 7
171 else:
172 raise Exception("Unknown stopReason string")
Johnny Chend85dae52010-08-09 23:44:24 +0000173
Johnny Chenf4ce2882010-08-26 21:49:29 +0000174#
Johnny Chen6264bc62010-08-27 18:08:58 +0000175# Returns the stopReason string given an enum.
176#
177def StopReasonString(enum):
178 if enum == 0:
179 return "Invalid"
180 elif enum == 1:
181 return "None"
182 elif enum == 2:
183 return "Trace"
184 elif enum == 3:
185 return "Breakpoint"
186 elif enum == 4:
187 return "Watchpoint"
188 elif enum == 5:
189 return "Signal"
190 elif enum == 6:
191 return "Exception"
192 elif enum == 7:
193 return "PlanComplete"
194 else:
195 raise Exception("Unknown stopReason enum")
196
197#
Johnny Chenf4ce2882010-08-26 21:49:29 +0000198# Returns an env variable array from the os.environ map object.
199#
200def EnvArray():
201 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
202
Johnny Chen9c10c182010-08-27 00:15:48 +0000203
Johnny Chen75e28f92010-08-05 23:42:46 +0000204class TestBase(unittest2.TestCase):
Johnny Chena1affab2010-07-03 03:41:59 +0000205 """This LLDB abstract base class is meant to be subclassed."""
206
207 # The concrete subclass should override this attribute.
Johnny Chenf8c723b2010-07-03 20:41:42 +0000208 mydir = None
Johnny Chena1affab2010-07-03 03:41:59 +0000209
Johnny Chenffde4fc2010-08-16 21:28:10 +0000210 # State pertaining to the inferior process, if any.
211 runStarted = False
212
Johnny Chen65572482010-08-25 18:49:48 +0000213 # Maximum allowed attempts when launching the inferior process.
214 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
215 maxLaunchCount = 3;
216
217 # Time to wait before the next launching attempt in second(s).
218 # Can be overridden by the LLDB_TIME_WAIT environment variable.
219 timeWait = 1.0;
220
Johnny Chend0c24b22010-08-23 17:10:44 +0000221 # os.environ["LLDB_COMMAND_TRACE"], if set to "YES", will turn on this flag.
222 traceAlways = False;
223
Johnny Chena1affab2010-07-03 03:41:59 +0000224 def setUp(self):
Johnny Chen6ead27f2010-08-07 01:13:18 +0000225 #import traceback
Johnny Chen88f83042010-08-05 21:23:45 +0000226 #traceback.print_stack()
227
Johnny Chenf8c723b2010-07-03 20:41:42 +0000228 # Fail fast if 'mydir' attribute is not overridden.
229 if not self.mydir or len(self.mydir) == 0:
230 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chena1affab2010-07-03 03:41:59 +0000231 # Save old working directory.
232 self.oldcwd = os.getcwd()
233
234 # Change current working directory if ${LLDB_TEST} is defined.
235 # See also dotest.py which sets up ${LLDB_TEST}.
236 if ("LLDB_TEST" in os.environ):
237 os.chdir(os.path.join(os.environ["LLDB_TEST"], self.mydir));
238
Johnny Chen65572482010-08-25 18:49:48 +0000239 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
240 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
241
242 if "LLDB_TIME_WAIT" in os.environ:
243 self.timeWait = float(os.environ["LLDB_TIME_WAIT"])
244
Johnny Chend0c24b22010-08-23 17:10:44 +0000245 if ("LLDB_COMMAND_TRACE" in os.environ and
246 os.environ["LLDB_COMMAND_TRACE"] == "YES"):
247 self.traceAlways = True
248
Johnny Chena1affab2010-07-03 03:41:59 +0000249 # Create the debugger instance if necessary.
250 try:
251 self.dbg = lldb.DBG
Johnny Chena1affab2010-07-03 03:41:59 +0000252 except AttributeError:
253 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf8c723b2010-07-03 20:41:42 +0000254
Johnny Chena1affab2010-07-03 03:41:59 +0000255 if not self.dbg.IsValid():
256 raise Exception('Invalid debugger instance')
257
258 # We want our debugger to be synchronous.
259 self.dbg.SetAsync(False)
260
261 # Retrieve the associated command interpreter instance.
262 self.ci = self.dbg.GetCommandInterpreter()
263 if not self.ci:
264 raise Exception('Could not get the command interpreter')
265
266 # And the result object.
267 self.res = lldb.SBCommandReturnObject()
268
Johnny Chena1affab2010-07-03 03:41:59 +0000269 def tearDown(self):
Johnny Chenffde4fc2010-08-16 21:28:10 +0000270 # Finish the inferior process, if it was "run" previously.
271 if self.runStarted:
272 self.ci.HandleCommand("continue", self.res)
273
Johnny Chena1affab2010-07-03 03:41:59 +0000274 del self.dbg
275
276 # Restore old working directory.
277 os.chdir(self.oldcwd)
Johnny Chen8df95eb2010-08-19 23:26:59 +0000278
Johnny Chend0c24b22010-08-23 17:10:44 +0000279 def runCmd(self, cmd, msg=None, check=True, trace=False):
Johnny Chen8df95eb2010-08-19 23:26:59 +0000280 """
281 Ask the command interpreter to handle the command and then check its
282 return status.
283 """
284 # Fail fast if 'cmd' is not meaningful.
285 if not cmd or len(cmd) == 0:
286 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen4f995f02010-08-20 17:57:32 +0000287
Johnny Chend0c24b22010-08-23 17:10:44 +0000288 trace = (True if self.traceAlways else trace)
289
Johnny Chen65572482010-08-25 18:49:48 +0000290 self.runStarted = (cmd.startswith("run") or
291 cmd.startswith("process launch"))
Johnny Chen4f995f02010-08-20 17:57:32 +0000292
Johnny Chen65572482010-08-25 18:49:48 +0000293 for i in range(self.maxLaunchCount if self.runStarted else 1):
294 self.ci.HandleCommand(cmd, self.res)
Johnny Chen4f995f02010-08-20 17:57:32 +0000295
Johnny Chen65572482010-08-25 18:49:48 +0000296 if trace:
297 print >> sys.stderr, "runCmd:", cmd
298 if self.res.Succeeded():
299 print >> sys.stderr, "output:", self.res.GetOutput()
300 else:
301 print >> sys.stderr, self.res.GetError()
Johnny Chen4f995f02010-08-20 17:57:32 +0000302
Johnny Chen029acae2010-08-20 21:03:09 +0000303 if self.res.Succeeded():
Johnny Chen65572482010-08-25 18:49:48 +0000304 break
Johnny Chen029acae2010-08-20 21:03:09 +0000305 else:
Johnny Chen65572482010-08-25 18:49:48 +0000306 if self.runStarted:
307 # Process launch failed, wait some time before the next try.
308 time.sleep(self.timeWait)
Johnny Chen4f995f02010-08-20 17:57:32 +0000309
Johnny Chen8df95eb2010-08-19 23:26:59 +0000310 if check:
311 self.assertTrue(self.res.Succeeded(),
312 msg if msg else CMD_MSG(cmd))
313
Johnny Chend0c24b22010-08-23 17:10:44 +0000314 def expect(self, cmd, msg=None, startstr=None, substrs=None, trace=False):
Johnny Chen8df95eb2010-08-19 23:26:59 +0000315 """
316 Similar to runCmd; with additional expect style output matching ability.
317
318 Ask the command interpreter to handle the command and then check its
319 return status. The 'msg' parameter specifies an informational assert
320 message. We expect the output from running the command to start with
321 'startstr' and matches the substrings contained in 'substrs'.
322 """
Johnny Chene8b02f32010-08-20 19:17:39 +0000323
Johnny Chend0c24b22010-08-23 17:10:44 +0000324 trace = (True if self.traceAlways else trace)
325
Johnny Chene8b02f32010-08-20 19:17:39 +0000326 # First run the command.
Johnny Chend0c24b22010-08-23 17:10:44 +0000327 self.runCmd(cmd, trace = (True if trace else False))
Johnny Chen8df95eb2010-08-19 23:26:59 +0000328
Johnny Chene8b02f32010-08-20 19:17:39 +0000329 # Then compare the output against expected strings.
Johnny Chen8df95eb2010-08-19 23:26:59 +0000330 output = self.res.GetOutput()
331 matched = output.startswith(startstr) if startstr else True
Johnny Chenead35c82010-08-20 18:25:15 +0000332
Johnny Chen3f3fb132010-08-24 23:48:10 +0000333 if startstr and trace:
334 print >> sys.stderr, "Expecting start string:", startstr
335 print >> sys.stderr, "Matched" if matched else "Not matched"
336 print >> sys.stderr
Johnny Chenead35c82010-08-20 18:25:15 +0000337
Johnny Chen22b95b22010-08-25 19:00:04 +0000338 if substrs and matched:
Johnny Chen8df95eb2010-08-19 23:26:59 +0000339 for str in substrs:
340 matched = output.find(str) > 0
Johnny Chen3f3fb132010-08-24 23:48:10 +0000341 if trace:
342 print >> sys.stderr, "Expecting sub string:", str
343 print >> sys.stderr, "Matched" if matched else "Not matched"
Johnny Chen8df95eb2010-08-19 23:26:59 +0000344 if not matched:
345 break
Johnny Chen3f3fb132010-08-24 23:48:10 +0000346 if trace:
347 print >> sys.stderr
Johnny Chen8df95eb2010-08-19 23:26:59 +0000348
Johnny Chene8b02f32010-08-20 19:17:39 +0000349 self.assertTrue(matched, msg if msg else CMD_MSG(cmd))
Johnny Chen8df95eb2010-08-19 23:26:59 +0000350
Johnny Chena8b3cdd2010-08-25 22:52:45 +0000351 def invoke(self, obj, name, trace=False):
Johnny Chend8473bc2010-08-25 22:56:10 +0000352 """Use reflection to call a method dynamically with no argument."""
Johnny Chena8b3cdd2010-08-25 22:52:45 +0000353
354 trace = (True if self.traceAlways else trace)
355
356 method = getattr(obj, name)
357 import inspect
358 self.assertTrue(inspect.ismethod(method),
359 name + "is a method name of object: " + str(obj))
360 result = method()
361 if self.traceAlways:
362 print str(method) + ":", result
363 return result
Johnny Chen9c10c182010-08-27 00:15:48 +0000364
365 def DebugSBValue(self, frame, val):
366 """Debug print a SBValue object, if self.traceAlways is True."""
367 if not self.traceAlways:
368 return
369
370 err = sys.stderr
371 err.write(val.GetName() + ":\n")
372 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n')
373 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n')
374 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n')
375 err.write('\t' + "Value -> " + str(val.GetValue(frame)) + '\n')
376 err.write('\t' + "Summary -> " + str(val.GetSummary(frame)) + '\n')
377 err.write('\t' + "IsPtrType -> " + str(val.TypeIsPtrType()) + '\n')
378 err.write('\t' + "Location -> " + val.GetLocation(frame) + '\n')
379
380