blob: 5da2343d03e63b2f03588437ec0bd992d5dc850f [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 Chenff3d01d2010-08-20 21:03:09 +0000120RUN_STOPPED = "Process is launched and then stopped 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
138VALID_PROCESS = "Got a valid process"
139
140VALID_TARGET = "Got a valid target"
141
Johnny Chen981463d2010-08-25 19:00:04 +0000142VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen00778092010-08-09 22:01:17 +0000143
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000144
Johnny Chen17941842010-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 Chen5fca8ca2010-08-26 20:04:17 +0000151#
152# Returns the enum from the input string stopReason.
153#
154def Enum(stopReason):
155 if stopReason == "Invalid":
156 return 0
157 elif stopReason == "None":
158 return 1
159 elif stopReason == "Trace":
160 return 2
161 elif stopReason == "Breakpoint":
162 return 3
163 elif stopReason == "Watchpoint":
164 return 4
165 elif stopReason == "Signal":
166 return 5
167 elif stopReason == "Exception":
168 return 6
169 elif stopReason == "PlanComplete":
170 return 7
171 else:
172 raise Exception("Unknown stopReason string")
Johnny Chen17941842010-08-09 23:44:24 +0000173
Johnny Chen73258832010-08-05 23:42:46 +0000174class TestBase(unittest2.TestCase):
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000175 """This LLDB abstract base class is meant to be subclassed."""
176
177 # The concrete subclass should override this attribute.
Johnny Chenf02ec122010-07-03 20:41:42 +0000178 mydir = None
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000179
Johnny Chen6ca006c2010-08-16 21:28:10 +0000180 # State pertaining to the inferior process, if any.
181 runStarted = False
182
Johnny Chenf2b70232010-08-25 18:49:48 +0000183 # Maximum allowed attempts when launching the inferior process.
184 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
185 maxLaunchCount = 3;
186
187 # Time to wait before the next launching attempt in second(s).
188 # Can be overridden by the LLDB_TIME_WAIT environment variable.
189 timeWait = 1.0;
190
Johnny Chend0190a62010-08-23 17:10:44 +0000191 # os.environ["LLDB_COMMAND_TRACE"], if set to "YES", will turn on this flag.
192 traceAlways = False;
193
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000194 def setUp(self):
Johnny Chen9289a652010-08-07 01:13:18 +0000195 #import traceback
Johnny Chena2124952010-08-05 21:23:45 +0000196 #traceback.print_stack()
197
Johnny Chenf02ec122010-07-03 20:41:42 +0000198 # Fail fast if 'mydir' attribute is not overridden.
199 if not self.mydir or len(self.mydir) == 0:
200 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000201 # Save old working directory.
202 self.oldcwd = os.getcwd()
203
204 # Change current working directory if ${LLDB_TEST} is defined.
205 # See also dotest.py which sets up ${LLDB_TEST}.
206 if ("LLDB_TEST" in os.environ):
207 os.chdir(os.path.join(os.environ["LLDB_TEST"], self.mydir));
208
Johnny Chenf2b70232010-08-25 18:49:48 +0000209 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
210 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
211
212 if "LLDB_TIME_WAIT" in os.environ:
213 self.timeWait = float(os.environ["LLDB_TIME_WAIT"])
214
Johnny Chend0190a62010-08-23 17:10:44 +0000215 if ("LLDB_COMMAND_TRACE" in os.environ and
216 os.environ["LLDB_COMMAND_TRACE"] == "YES"):
217 self.traceAlways = True
218
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000219 # Create the debugger instance if necessary.
220 try:
221 self.dbg = lldb.DBG
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000222 except AttributeError:
223 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf02ec122010-07-03 20:41:42 +0000224
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000225 if not self.dbg.IsValid():
226 raise Exception('Invalid debugger instance')
227
228 # We want our debugger to be synchronous.
229 self.dbg.SetAsync(False)
230
231 # Retrieve the associated command interpreter instance.
232 self.ci = self.dbg.GetCommandInterpreter()
233 if not self.ci:
234 raise Exception('Could not get the command interpreter')
235
236 # And the result object.
237 self.res = lldb.SBCommandReturnObject()
238
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000239 def tearDown(self):
Johnny Chen6ca006c2010-08-16 21:28:10 +0000240 # Finish the inferior process, if it was "run" previously.
241 if self.runStarted:
242 self.ci.HandleCommand("continue", self.res)
243
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000244 del self.dbg
245
246 # Restore old working directory.
247 os.chdir(self.oldcwd)
Johnny Chen27f212d2010-08-19 23:26:59 +0000248
Johnny Chend0190a62010-08-23 17:10:44 +0000249 def runCmd(self, cmd, msg=None, check=True, trace=False):
Johnny Chen27f212d2010-08-19 23:26:59 +0000250 """
251 Ask the command interpreter to handle the command and then check its
252 return status.
253 """
254 # Fail fast if 'cmd' is not meaningful.
255 if not cmd or len(cmd) == 0:
256 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000257
Johnny Chend0190a62010-08-23 17:10:44 +0000258 trace = (True if self.traceAlways else trace)
259
Johnny Chenf2b70232010-08-25 18:49:48 +0000260 self.runStarted = (cmd.startswith("run") or
261 cmd.startswith("process launch"))
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000262
Johnny Chenf2b70232010-08-25 18:49:48 +0000263 for i in range(self.maxLaunchCount if self.runStarted else 1):
264 self.ci.HandleCommand(cmd, self.res)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000265
Johnny Chenf2b70232010-08-25 18:49:48 +0000266 if trace:
267 print >> sys.stderr, "runCmd:", cmd
268 if self.res.Succeeded():
269 print >> sys.stderr, "output:", self.res.GetOutput()
270 else:
271 print >> sys.stderr, self.res.GetError()
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000272
Johnny Chenff3d01d2010-08-20 21:03:09 +0000273 if self.res.Succeeded():
Johnny Chenf2b70232010-08-25 18:49:48 +0000274 break
Johnny Chenff3d01d2010-08-20 21:03:09 +0000275 else:
Johnny Chenf2b70232010-08-25 18:49:48 +0000276 if self.runStarted:
277 # Process launch failed, wait some time before the next try.
278 time.sleep(self.timeWait)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000279
Johnny Chen27f212d2010-08-19 23:26:59 +0000280 if check:
281 self.assertTrue(self.res.Succeeded(),
282 msg if msg else CMD_MSG(cmd))
283
Johnny Chend0190a62010-08-23 17:10:44 +0000284 def expect(self, cmd, msg=None, startstr=None, substrs=None, trace=False):
Johnny Chen27f212d2010-08-19 23:26:59 +0000285 """
286 Similar to runCmd; with additional expect style output matching ability.
287
288 Ask the command interpreter to handle the command and then check its
289 return status. The 'msg' parameter specifies an informational assert
290 message. We expect the output from running the command to start with
291 'startstr' and matches the substrings contained in 'substrs'.
292 """
Johnny Chen74f26b82010-08-20 19:17:39 +0000293
Johnny Chend0190a62010-08-23 17:10:44 +0000294 trace = (True if self.traceAlways else trace)
295
Johnny Chen74f26b82010-08-20 19:17:39 +0000296 # First run the command.
Johnny Chend0190a62010-08-23 17:10:44 +0000297 self.runCmd(cmd, trace = (True if trace else False))
Johnny Chen27f212d2010-08-19 23:26:59 +0000298
Johnny Chen74f26b82010-08-20 19:17:39 +0000299 # Then compare the output against expected strings.
Johnny Chen27f212d2010-08-19 23:26:59 +0000300 output = self.res.GetOutput()
301 matched = output.startswith(startstr) if startstr else True
Johnny Chenb145bba2010-08-20 18:25:15 +0000302
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000303 if startstr and trace:
304 print >> sys.stderr, "Expecting start string:", startstr
305 print >> sys.stderr, "Matched" if matched else "Not matched"
306 print >> sys.stderr
Johnny Chenb145bba2010-08-20 18:25:15 +0000307
Johnny Chen981463d2010-08-25 19:00:04 +0000308 if substrs and matched:
Johnny Chen27f212d2010-08-19 23:26:59 +0000309 for str in substrs:
310 matched = output.find(str) > 0
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000311 if trace:
312 print >> sys.stderr, "Expecting sub string:", str
313 print >> sys.stderr, "Matched" if matched else "Not matched"
Johnny Chen27f212d2010-08-19 23:26:59 +0000314 if not matched:
315 break
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000316 if trace:
317 print >> sys.stderr
Johnny Chen27f212d2010-08-19 23:26:59 +0000318
Johnny Chen74f26b82010-08-20 19:17:39 +0000319 self.assertTrue(matched, msg if msg else CMD_MSG(cmd))
Johnny Chen27f212d2010-08-19 23:26:59 +0000320
Johnny Chenf3c59232010-08-25 22:52:45 +0000321 def invoke(self, obj, name, trace=False):
Johnny Chen61703c92010-08-25 22:56:10 +0000322 """Use reflection to call a method dynamically with no argument."""
Johnny Chenf3c59232010-08-25 22:52:45 +0000323
324 trace = (True if self.traceAlways else trace)
325
326 method = getattr(obj, name)
327 import inspect
328 self.assertTrue(inspect.ismethod(method),
329 name + "is a method name of object: " + str(obj))
330 result = method()
331 if self.traceAlways:
332 print str(method) + ":", result
333 return result