blob: 26c8bd8335aff3260b9fddde44325996562abf5a [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 Chen981463d2010-08-25 19:00:04 +0000136VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen00778092010-08-09 22:01:17 +0000137
Johnny Chen17941842010-08-09 23:44:24 +0000138#
139# And a generic "Command '%s' returns successfully" message generator.
140#
141def CMD_MSG(command):
142 return "Command '%s' returns successfully" % (command)
143
144
Johnny Chen73258832010-08-05 23:42:46 +0000145class TestBase(unittest2.TestCase):
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000146 """This LLDB abstract base class is meant to be subclassed."""
147
148 # The concrete subclass should override this attribute.
Johnny Chenf02ec122010-07-03 20:41:42 +0000149 mydir = None
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000150
Johnny Chen6ca006c2010-08-16 21:28:10 +0000151 # State pertaining to the inferior process, if any.
152 runStarted = False
153
Johnny Chenf2b70232010-08-25 18:49:48 +0000154 # Maximum allowed attempts when launching the inferior process.
155 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
156 maxLaunchCount = 3;
157
158 # Time to wait before the next launching attempt in second(s).
159 # Can be overridden by the LLDB_TIME_WAIT environment variable.
160 timeWait = 1.0;
161
Johnny Chend0190a62010-08-23 17:10:44 +0000162 # os.environ["LLDB_COMMAND_TRACE"], if set to "YES", will turn on this flag.
163 traceAlways = False;
164
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000165 def setUp(self):
Johnny Chen9289a652010-08-07 01:13:18 +0000166 #import traceback
Johnny Chena2124952010-08-05 21:23:45 +0000167 #traceback.print_stack()
168
Johnny Chenf02ec122010-07-03 20:41:42 +0000169 # Fail fast if 'mydir' attribute is not overridden.
170 if not self.mydir or len(self.mydir) == 0:
171 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000172 # Save old working directory.
173 self.oldcwd = os.getcwd()
174
175 # Change current working directory if ${LLDB_TEST} is defined.
176 # See also dotest.py which sets up ${LLDB_TEST}.
177 if ("LLDB_TEST" in os.environ):
178 os.chdir(os.path.join(os.environ["LLDB_TEST"], self.mydir));
179
Johnny Chenf2b70232010-08-25 18:49:48 +0000180 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
181 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
182
183 if "LLDB_TIME_WAIT" in os.environ:
184 self.timeWait = float(os.environ["LLDB_TIME_WAIT"])
185
Johnny Chend0190a62010-08-23 17:10:44 +0000186 if ("LLDB_COMMAND_TRACE" in os.environ and
187 os.environ["LLDB_COMMAND_TRACE"] == "YES"):
188 self.traceAlways = True
189
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000190 # Create the debugger instance if necessary.
191 try:
192 self.dbg = lldb.DBG
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000193 except AttributeError:
194 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf02ec122010-07-03 20:41:42 +0000195
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000196 if not self.dbg.IsValid():
197 raise Exception('Invalid debugger instance')
198
199 # We want our debugger to be synchronous.
200 self.dbg.SetAsync(False)
201
202 # Retrieve the associated command interpreter instance.
203 self.ci = self.dbg.GetCommandInterpreter()
204 if not self.ci:
205 raise Exception('Could not get the command interpreter')
206
207 # And the result object.
208 self.res = lldb.SBCommandReturnObject()
209
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000210 def tearDown(self):
Johnny Chen6ca006c2010-08-16 21:28:10 +0000211 # Finish the inferior process, if it was "run" previously.
212 if self.runStarted:
213 self.ci.HandleCommand("continue", self.res)
214
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000215 del self.dbg
216
217 # Restore old working directory.
218 os.chdir(self.oldcwd)
Johnny Chen27f212d2010-08-19 23:26:59 +0000219
Johnny Chend0190a62010-08-23 17:10:44 +0000220 def runCmd(self, cmd, msg=None, check=True, trace=False):
Johnny Chen27f212d2010-08-19 23:26:59 +0000221 """
222 Ask the command interpreter to handle the command and then check its
223 return status.
224 """
225 # Fail fast if 'cmd' is not meaningful.
226 if not cmd or len(cmd) == 0:
227 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000228
Johnny Chend0190a62010-08-23 17:10:44 +0000229 trace = (True if self.traceAlways else trace)
230
Johnny Chenf2b70232010-08-25 18:49:48 +0000231 self.runStarted = (cmd.startswith("run") or
232 cmd.startswith("process launch"))
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000233
Johnny Chenf2b70232010-08-25 18:49:48 +0000234 for i in range(self.maxLaunchCount if self.runStarted else 1):
235 self.ci.HandleCommand(cmd, self.res)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000236
Johnny Chenf2b70232010-08-25 18:49:48 +0000237 if trace:
238 print >> sys.stderr, "runCmd:", cmd
239 if self.res.Succeeded():
240 print >> sys.stderr, "output:", self.res.GetOutput()
241 else:
242 print >> sys.stderr, self.res.GetError()
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000243
Johnny Chenff3d01d2010-08-20 21:03:09 +0000244 if self.res.Succeeded():
Johnny Chenf2b70232010-08-25 18:49:48 +0000245 break
Johnny Chenff3d01d2010-08-20 21:03:09 +0000246 else:
Johnny Chenf2b70232010-08-25 18:49:48 +0000247 if self.runStarted:
248 # Process launch failed, wait some time before the next try.
249 time.sleep(self.timeWait)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000250
Johnny Chen27f212d2010-08-19 23:26:59 +0000251 if check:
252 self.assertTrue(self.res.Succeeded(),
253 msg if msg else CMD_MSG(cmd))
254
Johnny Chend0190a62010-08-23 17:10:44 +0000255 def expect(self, cmd, msg=None, startstr=None, substrs=None, trace=False):
Johnny Chen27f212d2010-08-19 23:26:59 +0000256 """
257 Similar to runCmd; with additional expect style output matching ability.
258
259 Ask the command interpreter to handle the command and then check its
260 return status. The 'msg' parameter specifies an informational assert
261 message. We expect the output from running the command to start with
262 'startstr' and matches the substrings contained in 'substrs'.
263 """
Johnny Chen74f26b82010-08-20 19:17:39 +0000264
Johnny Chend0190a62010-08-23 17:10:44 +0000265 trace = (True if self.traceAlways else trace)
266
Johnny Chen74f26b82010-08-20 19:17:39 +0000267 # First run the command.
Johnny Chend0190a62010-08-23 17:10:44 +0000268 self.runCmd(cmd, trace = (True if trace else False))
Johnny Chen27f212d2010-08-19 23:26:59 +0000269
Johnny Chen74f26b82010-08-20 19:17:39 +0000270 # Then compare the output against expected strings.
Johnny Chen27f212d2010-08-19 23:26:59 +0000271 output = self.res.GetOutput()
272 matched = output.startswith(startstr) if startstr else True
Johnny Chenb145bba2010-08-20 18:25:15 +0000273
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000274 if startstr and trace:
275 print >> sys.stderr, "Expecting start string:", startstr
276 print >> sys.stderr, "Matched" if matched else "Not matched"
277 print >> sys.stderr
Johnny Chenb145bba2010-08-20 18:25:15 +0000278
Johnny Chen981463d2010-08-25 19:00:04 +0000279 if substrs and matched:
Johnny Chen27f212d2010-08-19 23:26:59 +0000280 for str in substrs:
281 matched = output.find(str) > 0
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000282 if trace:
283 print >> sys.stderr, "Expecting sub string:", str
284 print >> sys.stderr, "Matched" if matched else "Not matched"
Johnny Chen27f212d2010-08-19 23:26:59 +0000285 if not matched:
286 break
Johnny Chenc7c9fcf2010-08-24 23:48:10 +0000287 if trace:
288 print >> sys.stderr
Johnny Chen27f212d2010-08-19 23:26:59 +0000289
Johnny Chen74f26b82010-08-20 19:17:39 +0000290 self.assertTrue(matched, msg if msg else CMD_MSG(cmd))
Johnny Chen27f212d2010-08-19 23:26:59 +0000291
Johnny Chenf3c59232010-08-25 22:52:45 +0000292 def invoke(self, obj, name, trace=False):
293 """Use reflection to call a method dynamically without any argument."""
294
295 trace = (True if self.traceAlways else trace)
296
297 method = getattr(obj, name)
298 import inspect
299 self.assertTrue(inspect.ismethod(method),
300 name + "is a method name of object: " + str(obj))
301 result = method()
302 if self.traceAlways:
303 print str(method) + ":", result
304 return result