blob: 3bcdd5207e1caae04bfee0eb51cae9da72422046 [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
Johnny Chend8c1dd32011-05-31 23:21:42 +000016$ export PYTHONPATH=/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:$LLDB_TEST:$LLDB_TEST/plugins:$LLDB_TEST/pexpect-2.4
Johnny Chena1affab2010-07-03 03:41:59 +000017$ echo $LLDB_TEST
18/Volumes/data/lldb/svn/trunk/test
19$ echo $PYTHONPATH
Johnny Chen9de4ede2010-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 Chena1affab2010-07-03 03:41:59 +000021$ 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
Johnny Chen59ea45f2010-09-02 22:25:47 +000028
29...
Johnny Chend0c24b22010-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 Chen59ea45f2010-09-02 22:25:47 +000037...
Johnny Chend0c24b22010-08-23 17:10:44 +000038
Johnny Chen59ea45f2010-09-02 22:25:47 +000039runCmd: frame variable strings
Johnny Chend0c24b22010-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 Chen59ea45f2010-09-02 22:25:47 +000047runCmd: frame variable char_16
Johnny Chend0c24b22010-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 Chen59ea45f2010-09-02 22:25:47 +000067runCmd: frame variable ushort_matrix
Johnny Chend0c24b22010-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 Chen59ea45f2010-09-02 22:25:47 +000081runCmd: frame variable long_6
Johnny Chend0c24b22010-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 Chena1affab2010-07-03 03:41:59 +000096$
97"""
98
Johnny Chen93ae6042010-09-21 22:34:45 +000099import os, sys, traceback
Johnny Chen2d899752010-09-21 21:08:53 +0000100import re
Johnny Chena1cc8832010-08-30 21:35:00 +0000101from subprocess import *
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000102import StringIO
Johnny Chen65572482010-08-25 18:49:48 +0000103import time
Johnny Chen1acaf632010-08-30 23:08:52 +0000104import types
Johnny Chen75e28f92010-08-05 23:42:46 +0000105import unittest2
Johnny Chena1affab2010-07-03 03:41:59 +0000106import lldb
107
Johnny Chen548aefd2010-10-11 22:25:46 +0000108# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
Johnny Chen24af2962011-01-19 18:18:47 +0000109# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options.
Johnny Chen548aefd2010-10-11 22:25:46 +0000110
111# By default, traceAlways is False.
Johnny Chen9de4ede2010-08-31 17:42:54 +0000112if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
113 traceAlways = True
114else:
115 traceAlways = False
116
Johnny Chen548aefd2010-10-11 22:25:46 +0000117# By default, doCleanup is True.
118if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO":
119 doCleanup = False
120else:
121 doCleanup = True
122
Johnny Chen9de4ede2010-08-31 17:42:54 +0000123
Johnny Chen96f08d52010-08-09 22:01:17 +0000124#
125# Some commonly used assert messages.
126#
127
Johnny Chenee975b82010-09-17 22:45:27 +0000128COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
129
Johnny Chen96f08d52010-08-09 22:01:17 +0000130CURRENT_EXECUTABLE_SET = "Current executable set successfully"
131
Johnny Chen72a14342010-09-02 21:23:12 +0000132PROCESS_IS_VALID = "Process is valid"
133
134PROCESS_KILLED = "Process is killed successfully"
135
Johnny Chen0ace30f2010-12-23 01:12:19 +0000136PROCESS_EXITED = "Process exited successfully"
137
138PROCESS_STOPPED = "Process status should be stopped"
139
Johnny Chen1bb9f9a2010-08-27 23:47:36 +0000140RUN_SUCCEEDED = "Process is launched successfully"
Johnny Chen96f08d52010-08-09 22:01:17 +0000141
Johnny Chend85dae52010-08-09 23:44:24 +0000142RUN_COMPLETED = "Process exited successfully"
Johnny Chen96f08d52010-08-09 22:01:17 +0000143
Johnny Chen5349ee22010-10-05 19:27:32 +0000144BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
145
Johnny Chend85dae52010-08-09 23:44:24 +0000146BREAKPOINT_CREATED = "Breakpoint created successfully"
147
Johnny Chen1ad9e992010-12-04 00:07:24 +0000148BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
149
Johnny Chen9b92c6e2010-08-17 21:33:31 +0000150BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
151
Johnny Chend85dae52010-08-09 23:44:24 +0000152BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
Johnny Chen96f08d52010-08-09 22:01:17 +0000153
Johnny Chen72afa8d2010-09-30 17:06:24 +0000154BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2"
155
Johnny Chenc55dace2010-10-15 18:07:09 +0000156BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3"
157
Johnny Chenc0dbdc02011-06-27 20:05:23 +0000158OBJECT_PRINTED_CORRECTLY = "Object printed correctly"
159
Johnny Chen6f7abb02010-12-09 18:22:12 +0000160SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
161
Johnny Chen0b3ee552010-09-22 23:00:20 +0000162STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
163
Johnny Chen33cd0c32011-04-15 16:44:48 +0000164STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
165
Johnny Chene8587d02010-11-10 23:46:38 +0000166STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
Johnny Chenc82ac762010-11-10 20:20:06 +0000167
Johnny Chene8587d02010-11-10 23:46:38 +0000168STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
169 STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'")
Johnny Chen96f08d52010-08-09 22:01:17 +0000170
Johnny Chenf6bdb192010-10-20 18:38:48 +0000171STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
172
Johnny Chen7a4512b2010-12-13 21:49:58 +0000173STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
174
Johnny Chend7a4eb02010-10-14 01:22:03 +0000175STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
176
Johnny Chen96f08d52010-08-09 22:01:17 +0000177STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
178
Johnny Chen58c66e22011-09-15 21:09:59 +0000179STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
180
Johnny Chen4917e102010-08-24 22:07:56 +0000181DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
182
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000183VALID_BREAKPOINT = "Got a valid breakpoint"
184
Johnny Chen0601a292010-10-22 18:10:25 +0000185VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
186
Johnny Chenac910272011-05-06 23:26:12 +0000187VALID_COMMAND_INTERPRETER = "Got a valid command interpreter"
188
Johnny Chen1bb9f9a2010-08-27 23:47:36 +0000189VALID_FILESPEC = "Got a valid filespec"
190
Johnny Chen8fd886c2010-12-08 01:25:21 +0000191VALID_MODULE = "Got a valid module"
192
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000193VALID_PROCESS = "Got a valid process"
194
Johnny Chen8fd886c2010-12-08 01:25:21 +0000195VALID_SYMBOL = "Got a valid symbol"
196
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000197VALID_TARGET = "Got a valid target"
198
Johnny Chen2ef5eae2012-02-03 20:43:00 +0000199VALID_TYPE = "Got a valid type"
200
Johnny Chen5503d462011-07-15 22:28:10 +0000201VALID_VARIABLE = "Got a valid variable"
202
Johnny Chen22b95b22010-08-25 19:00:04 +0000203VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen96f08d52010-08-09 22:01:17 +0000204
Johnny Chen58c66e22011-09-15 21:09:59 +0000205WATCHPOINT_CREATED = "Watchpoint created successfully"
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000206
Johnny Chen05efcf782010-11-09 18:42:22 +0000207def CMD_MSG(str):
Johnny Chen006b5952011-05-31 22:16:51 +0000208 '''A generic "Command '%s' returns successfully" message generator.'''
Johnny Chen05efcf782010-11-09 18:42:22 +0000209 return "Command '%s' returns successfully" % str
210
Johnny Chendbe2c822012-03-15 19:10:00 +0000211def COMPLETION_MSG(str_before, str_after):
Johnny Chenfbcad682012-01-20 23:02:51 +0000212 '''A generic message generator for the completion mechanism.'''
213 return "'%s' successfully completes to '%s'" % (str_before, str_after)
214
Johnny Chen05efcf782010-11-09 18:42:22 +0000215def EXP_MSG(str, exe):
Johnny Chen006b5952011-05-31 22:16:51 +0000216 '''A generic "'%s' returns expected result" message generator if exe.
217 Otherwise, it generates "'%s' matches expected result" message.'''
Johnny Chen05efcf782010-11-09 18:42:22 +0000218 return "'%s' %s expected result" % (str, 'returns' if exe else 'matches')
Johnny Chend85dae52010-08-09 23:44:24 +0000219
Johnny Chendb9cbe92010-10-19 19:11:38 +0000220def SETTING_MSG(setting):
Johnny Chen006b5952011-05-31 22:16:51 +0000221 '''A generic "Value of setting '%s' is correct" message generator.'''
Johnny Chendb9cbe92010-10-19 19:11:38 +0000222 return "Value of setting '%s' is correct" % setting
223
Johnny Chenf4ce2882010-08-26 21:49:29 +0000224def EnvArray():
Johnny Chen006b5952011-05-31 22:16:51 +0000225 """Returns an env variable array from the os.environ map object."""
Johnny Chenf4ce2882010-08-26 21:49:29 +0000226 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
227
Johnny Chen14906002010-10-11 23:52:19 +0000228def line_number(filename, string_to_match):
229 """Helper function to return the line number of the first matched string."""
230 with open(filename, 'r') as f:
231 for i, line in enumerate(f):
232 if line.find(string_to_match) != -1:
233 # Found our match.
Johnny Chen0659e342010-10-12 00:09:25 +0000234 return i+1
Johnny Chen33cd0c32011-04-15 16:44:48 +0000235 raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename))
Johnny Chen14906002010-10-11 23:52:19 +0000236
Johnny Chen5349ee22010-10-05 19:27:32 +0000237def pointer_size():
238 """Return the pointer size of the host system."""
239 import ctypes
240 a_pointer = ctypes.c_void_p(0xffff)
241 return 8 * ctypes.sizeof(a_pointer)
242
Johnny Chen7be5d352012-02-09 02:01:59 +0000243def is_exe(fpath):
244 """Returns true if fpath is an executable."""
245 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
246
247def which(program):
248 """Returns the full path to a program; None otherwise."""
249 fpath, fname = os.path.split(program)
250 if fpath:
251 if is_exe(program):
252 return program
253 else:
254 for path in os.environ["PATH"].split(os.pathsep):
255 exe_file = os.path.join(path, program)
256 if is_exe(exe_file):
257 return exe_file
258 return None
259
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000260class recording(StringIO.StringIO):
261 """
262 A nice little context manager for recording the debugger interactions into
263 our session object. If trace flag is ON, it also emits the interactions
264 into the stderr.
265 """
266 def __init__(self, test, trace):
Johnny Chen1b7d6292010-10-15 23:55:05 +0000267 """Create a StringIO instance; record the session obj and trace flag."""
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000268 StringIO.StringIO.__init__(self)
Johnny Chen770683d2011-08-16 22:06:17 +0000269 # The test might not have undergone the 'setUp(self)' phase yet, so that
270 # the attribute 'session' might not even exist yet.
Johnny Chen8339f982011-08-16 17:06:45 +0000271 self.session = getattr(test, "session", None) if test else None
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000272 self.trace = trace
273
274 def __enter__(self):
275 """
276 Context management protocol on entry to the body of the with statement.
277 Just return the StringIO object.
278 """
279 return self
280
281 def __exit__(self, type, value, tb):
282 """
283 Context management protocol on exit from the body of the with statement.
284 If trace is ON, it emits the recordings into stderr. Always add the
285 recordings to our session object. And close the StringIO object, too.
286 """
287 if self.trace:
Johnny Chen1b7d6292010-10-15 23:55:05 +0000288 print >> sys.stderr, self.getvalue()
289 if self.session:
290 print >> self.session, self.getvalue()
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000291 self.close()
292
Johnny Chen1b7d6292010-10-15 23:55:05 +0000293# From 2.7's subprocess.check_output() convenience function.
Johnny Chen0bfa8592011-03-23 20:28:59 +0000294# Return a tuple (stdoutdata, stderrdata).
Johnny Chen1b7d6292010-10-15 23:55:05 +0000295def system(*popenargs, **kwargs):
Johnny Chen22ca65d2011-11-16 22:44:28 +0000296 r"""Run an os command with arguments and return its output as a byte string.
Johnny Chen1b7d6292010-10-15 23:55:05 +0000297
298 If the exit code was non-zero it raises a CalledProcessError. The
299 CalledProcessError object will have the return code in the returncode
300 attribute and output in the output attribute.
301
302 The arguments are the same as for the Popen constructor. Example:
303
304 >>> check_output(["ls", "-l", "/dev/null"])
305 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
306
307 The stdout argument is not allowed as it is used internally.
308 To capture standard error in the result, use stderr=STDOUT.
309
310 >>> check_output(["/bin/sh", "-c",
311 ... "ls -l non_existent_file ; exit 0"],
312 ... stderr=STDOUT)
313 'ls: non_existent_file: No such file or directory\n'
314 """
315
316 # Assign the sender object to variable 'test' and remove it from kwargs.
317 test = kwargs.pop('sender', None)
318
319 if 'stdout' in kwargs:
320 raise ValueError('stdout argument not allowed, it will be overridden.')
Johnny Chen0bfa8592011-03-23 20:28:59 +0000321 process = Popen(stdout=PIPE, stderr=PIPE, *popenargs, **kwargs)
Johnny Chen30b30cb2011-11-16 22:41:53 +0000322 pid = process.pid
Johnny Chen1b7d6292010-10-15 23:55:05 +0000323 output, error = process.communicate()
324 retcode = process.poll()
325
326 with recording(test, traceAlways) as sbuf:
327 if isinstance(popenargs, types.StringTypes):
328 args = [popenargs]
329 else:
330 args = list(popenargs)
331 print >> sbuf
332 print >> sbuf, "os command:", args
Johnny Chen30b30cb2011-11-16 22:41:53 +0000333 print >> sbuf, "with pid:", pid
Johnny Chen1b7d6292010-10-15 23:55:05 +0000334 print >> sbuf, "stdout:", output
335 print >> sbuf, "stderr:", error
336 print >> sbuf, "retcode:", retcode
337 print >> sbuf
338
339 if retcode:
340 cmd = kwargs.get("args")
341 if cmd is None:
342 cmd = popenargs[0]
343 raise CalledProcessError(retcode, cmd)
Johnny Chen0bfa8592011-03-23 20:28:59 +0000344 return (output, error)
Johnny Chen1b7d6292010-10-15 23:55:05 +0000345
Johnny Chen29867642010-11-01 20:35:01 +0000346def getsource_if_available(obj):
347 """
348 Return the text of the source code for an object if available. Otherwise,
349 a print representation is returned.
350 """
351 import inspect
352 try:
353 return inspect.getsource(obj)
354 except:
355 return repr(obj)
356
Peter Collingbourne39bd5362011-06-20 19:06:20 +0000357def builder_module():
358 return __import__("builder_" + sys.platform)
359
Johnny Chen366fb8c2011-08-01 18:46:13 +0000360#
361# Decorators for categorizing test cases.
362#
363
364from functools import wraps
365def python_api_test(func):
366 """Decorate the item as a Python API only test."""
367 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
368 raise Exception("@python_api_test can only be used to decorate a test method")
369 @wraps(func)
370 def wrapper(self, *args, **kwargs):
371 try:
372 if lldb.dont_do_python_api_test:
373 self.skipTest("python api tests")
374 except AttributeError:
375 pass
376 return func(self, *args, **kwargs)
377
378 # Mark this function as such to separate them from lldb command line tests.
379 wrapper.__python_api_test__ = True
380 return wrapper
381
Johnny Chen366fb8c2011-08-01 18:46:13 +0000382def benchmarks_test(func):
383 """Decorate the item as a benchmarks test."""
384 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
385 raise Exception("@benchmarks_test can only be used to decorate a test method")
386 @wraps(func)
387 def wrapper(self, *args, **kwargs):
388 try:
389 if not lldb.just_do_benchmarks_test:
390 self.skipTest("benchmarks tests")
391 except AttributeError:
392 pass
393 return func(self, *args, **kwargs)
394
395 # Mark this function as such to separate them from the regular tests.
396 wrapper.__benchmarks_test__ = True
397 return wrapper
398
Johnny Chena3ed7d82012-04-06 00:56:05 +0000399def dsym_test(func):
400 """Decorate the item as a dsym test."""
401 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
402 raise Exception("@dsym_test can only be used to decorate a test method")
403 @wraps(func)
404 def wrapper(self, *args, **kwargs):
405 try:
406 if lldb.dont_do_dsym_test:
407 self.skipTest("dsym tests")
408 except AttributeError:
409 pass
410 return func(self, *args, **kwargs)
411
412 # Mark this function as such to separate them from the regular tests.
413 wrapper.__dsym_test__ = True
414 return wrapper
415
416def dwarf_test(func):
417 """Decorate the item as a dwarf test."""
418 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
419 raise Exception("@dwarf_test can only be used to decorate a test method")
420 @wraps(func)
421 def wrapper(self, *args, **kwargs):
422 try:
423 if lldb.dont_do_dwarf_test:
424 self.skipTest("dwarf tests")
425 except AttributeError:
426 pass
427 return func(self, *args, **kwargs)
428
429 # Mark this function as such to separate them from the regular tests.
430 wrapper.__dwarf_test__ = True
431 return wrapper
432
Johnny Chen65040cb2011-08-19 00:54:27 +0000433def expectedFailureClang(func):
434 """Decorate the item as a Clang only expectedFailure."""
435 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
436 raise Exception("@expectedFailureClang can only be used to decorate a test method")
437 @wraps(func)
438 def wrapper(*args, **kwargs):
439 from unittest2 import case
440 self = args[0]
441 compiler = self.getCompiler()
442 try:
443 func(*args, **kwargs)
Johnny Chen7c9136b2011-08-19 01:17:09 +0000444 except Exception:
Johnny Chen65040cb2011-08-19 00:54:27 +0000445 if "clang" in compiler:
446 raise case._ExpectedFailure(sys.exc_info())
447 else:
Johnny Chen7c9136b2011-08-19 01:17:09 +0000448 raise
Johnny Chen65040cb2011-08-19 00:54:27 +0000449
450 if "clang" in compiler:
451 raise case._UnexpectedSuccess
452 return wrapper
453
Johnny Chen869e2962011-12-22 21:14:31 +0000454def expectedFailurei386(func):
455 """Decorate the item as an i386 only expectedFailure."""
456 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
457 raise Exception("@expectedFailurei386 can only be used to decorate a test method")
458 @wraps(func)
459 def wrapper(*args, **kwargs):
460 from unittest2 import case
461 self = args[0]
462 arch = self.getArchitecture()
463 try:
464 func(*args, **kwargs)
465 except Exception:
466 if "i386" in arch:
467 raise case._ExpectedFailure(sys.exc_info())
468 else:
469 raise
470
471 if "i386" in arch:
472 raise case._UnexpectedSuccess
473 return wrapper
474
Johnny Chen366fb8c2011-08-01 18:46:13 +0000475class Base(unittest2.TestCase):
Johnny Chen607b7a12010-10-22 23:15:46 +0000476 """
Johnny Chen366fb8c2011-08-01 18:46:13 +0000477 Abstract base for performing lldb (see TestBase) or other generic tests (see
478 BenchBase for one example). lldbtest.Base works with the test driver to
479 accomplish things.
480
Johnny Chen607b7a12010-10-22 23:15:46 +0000481 """
Johnny Chena1affab2010-07-03 03:41:59 +0000482 # The concrete subclass should override this attribute.
Johnny Chenf8c723b2010-07-03 20:41:42 +0000483 mydir = None
Johnny Chena1affab2010-07-03 03:41:59 +0000484
Johnny Chend3521cc2010-09-16 01:53:04 +0000485 # Keep track of the old current working directory.
486 oldcwd = None
Johnny Chen88f83042010-08-05 21:23:45 +0000487
Johnny Chencbe51262011-08-01 19:50:58 +0000488 def TraceOn(self):
489 """Returns True if we are in trace mode (tracing detailed test execution)."""
490 return traceAlways
491
Johnny Chend3521cc2010-09-16 01:53:04 +0000492 @classmethod
493 def setUpClass(cls):
Johnny Chen41998192010-10-01 22:59:49 +0000494 """
495 Python unittest framework class setup fixture.
496 Do current directory manipulation.
497 """
498
Johnny Chenf8c723b2010-07-03 20:41:42 +0000499 # Fail fast if 'mydir' attribute is not overridden.
Johnny Chend3521cc2010-09-16 01:53:04 +0000500 if not cls.mydir or len(cls.mydir) == 0:
Johnny Chenf8c723b2010-07-03 20:41:42 +0000501 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chena1affab2010-07-03 03:41:59 +0000502 # Save old working directory.
Johnny Chend3521cc2010-09-16 01:53:04 +0000503 cls.oldcwd = os.getcwd()
Johnny Chena1affab2010-07-03 03:41:59 +0000504
505 # Change current working directory if ${LLDB_TEST} is defined.
506 # See also dotest.py which sets up ${LLDB_TEST}.
507 if ("LLDB_TEST" in os.environ):
Johnny Chend3521cc2010-09-16 01:53:04 +0000508 if traceAlways:
Johnny Chen72afa8d2010-09-30 17:06:24 +0000509 print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
Johnny Chend3521cc2010-09-16 01:53:04 +0000510 os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
511
512 @classmethod
513 def tearDownClass(cls):
Johnny Chen41998192010-10-01 22:59:49 +0000514 """
515 Python unittest framework class teardown fixture.
516 Do class-wide cleanup.
517 """
Johnny Chend3521cc2010-09-16 01:53:04 +0000518
Johnny Chen028d8eb2011-11-17 19:57:27 +0000519 if doCleanup and not lldb.skip_build_and_cleanup:
Johnny Chen548aefd2010-10-11 22:25:46 +0000520 # First, let's do the platform-specific cleanup.
Peter Collingbourne39bd5362011-06-20 19:06:20 +0000521 module = builder_module()
Johnny Chen548aefd2010-10-11 22:25:46 +0000522 if not module.cleanup():
523 raise Exception("Don't know how to do cleanup")
Johnny Chend3521cc2010-09-16 01:53:04 +0000524
Johnny Chen548aefd2010-10-11 22:25:46 +0000525 # Subclass might have specific cleanup function defined.
526 if getattr(cls, "classCleanup", None):
527 if traceAlways:
528 print >> sys.stderr, "Call class-specific cleanup function for class:", cls
529 try:
530 cls.classCleanup()
531 except:
532 exc_type, exc_value, exc_tb = sys.exc_info()
533 traceback.print_exception(exc_type, exc_value, exc_tb)
Johnny Chend3521cc2010-09-16 01:53:04 +0000534
535 # Restore old working directory.
536 if traceAlways:
Johnny Chen72afa8d2010-09-30 17:06:24 +0000537 print >> sys.stderr, "Restore dir to:", cls.oldcwd
Johnny Chend3521cc2010-09-16 01:53:04 +0000538 os.chdir(cls.oldcwd)
539
Johnny Chen366fb8c2011-08-01 18:46:13 +0000540 @classmethod
541 def skipLongRunningTest(cls):
542 """
543 By default, we skip long running test case.
544 This can be overridden by passing '-l' to the test driver (dotest.py).
545 """
546 if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]:
547 return False
548 else:
549 return True
Johnny Chen9a9fcf62011-06-21 00:53:00 +0000550
Johnny Chend3521cc2010-09-16 01:53:04 +0000551 def setUp(self):
Johnny Chencbe51262011-08-01 19:50:58 +0000552 """Fixture for unittest test case setup.
553
554 It works with the test driver to conditionally skip tests and does other
555 initializations."""
Johnny Chend3521cc2010-09-16 01:53:04 +0000556 #import traceback
557 #traceback.print_stack()
Johnny Chena1affab2010-07-03 03:41:59 +0000558
Johnny Chen113388f2011-08-02 22:54:37 +0000559 if "LLDB_EXEC" in os.environ:
560 self.lldbExec = os.environ["LLDB_EXEC"]
Johnny Chen6033bed2011-08-26 00:00:01 +0000561 else:
562 self.lldbExec = None
563 if "LLDB_HERE" in os.environ:
564 self.lldbHere = os.environ["LLDB_HERE"]
565 else:
566 self.lldbHere = None
Johnny Chen7d7f4472011-10-07 19:21:09 +0000567 # If we spawn an lldb process for test (via pexpect), do not load the
568 # init file unless told otherwise.
569 if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]:
570 self.lldbOption = ""
571 else:
572 self.lldbOption = "--no-lldbinit"
Johnny Chen113388f2011-08-02 22:54:37 +0000573
Johnny Chen71cb7972011-08-01 21:13:26 +0000574 # Assign the test method name to self.testMethodName.
575 #
576 # For an example of the use of this attribute, look at test/types dir.
577 # There are a bunch of test cases under test/types and we don't want the
578 # module cacheing subsystem to be confused with executable name "a.out"
579 # used for all the test cases.
580 self.testMethodName = self._testMethodName
581
Johnny Chen3ebdacc2010-12-10 18:52:10 +0000582 # Python API only test is decorated with @python_api_test,
583 # which also sets the "__python_api_test__" attribute of the
584 # function object to True.
Johnny Chend8c1dd32011-05-31 23:21:42 +0000585 try:
586 if lldb.just_do_python_api_test:
587 testMethod = getattr(self, self._testMethodName)
588 if getattr(testMethod, "__python_api_test__", False):
589 pass
590 else:
Johnny Chen82ccf402011-07-30 01:39:58 +0000591 self.skipTest("non python api test")
592 except AttributeError:
593 pass
594
595 # Benchmarks test is decorated with @benchmarks_test,
596 # which also sets the "__benchmarks_test__" attribute of the
597 # function object to True.
598 try:
599 if lldb.just_do_benchmarks_test:
600 testMethod = getattr(self, self._testMethodName)
601 if getattr(testMethod, "__benchmarks_test__", False):
602 pass
603 else:
604 self.skipTest("non benchmarks test")
Johnny Chend8c1dd32011-05-31 23:21:42 +0000605 except AttributeError:
606 pass
Johnny Chen3ebdacc2010-12-10 18:52:10 +0000607
Johnny Chen71cb7972011-08-01 21:13:26 +0000608 # This is for the case of directly spawning 'lldb'/'gdb' and interacting
609 # with it using pexpect.
610 self.child = None
611 self.child_prompt = "(lldb) "
612 # If the child is interacting with the embedded script interpreter,
613 # there are two exits required during tear down, first to quit the
614 # embedded script interpreter and second to quit the lldb command
615 # interpreter.
616 self.child_in_script_interpreter = False
617
Johnny Chencbe51262011-08-01 19:50:58 +0000618 # These are for customized teardown cleanup.
619 self.dict = None
620 self.doTearDownCleanup = False
621 # And in rare cases where there are multiple teardown cleanups.
622 self.dicts = []
623 self.doTearDownCleanups = False
624
625 # Create a string buffer to record the session info, to be dumped into a
626 # test case specific file if test failure is encountered.
627 self.session = StringIO.StringIO()
628
629 # Optimistically set __errored__, __failed__, __expected__ to False
630 # initially. If the test errored/failed, the session info
631 # (self.session) is then dumped into a session specific file for
632 # diagnosis.
633 self.__errored__ = False
634 self.__failed__ = False
635 self.__expected__ = False
636 # We are also interested in unexpected success.
637 self.__unexpected__ = False
Johnny Chencd1df5a2011-08-16 00:48:58 +0000638 # And skipped tests.
639 self.__skipped__ = False
Johnny Chencbe51262011-08-01 19:50:58 +0000640
641 # See addTearDownHook(self, hook) which allows the client to add a hook
642 # function to be run during tearDown() time.
643 self.hooks = []
644
645 # See HideStdout(self).
646 self.sys_stdout_hidden = False
647
Johnny Chen644ad082011-10-19 16:48:07 +0000648 def runHooks(self, child=None, child_prompt=None, use_cmd_api=False):
Johnny Chen5f3c5672011-10-19 01:06:21 +0000649 """Perform the run hooks to bring lldb debugger to the desired state.
650
Johnny Chen644ad082011-10-19 16:48:07 +0000651 By default, expect a pexpect spawned child and child prompt to be
652 supplied (use_cmd_api=False). If use_cmd_api is true, ignore the child
653 and child prompt and use self.runCmd() to run the hooks one by one.
654
Johnny Chen5f3c5672011-10-19 01:06:21 +0000655 Note that child is a process spawned by pexpect.spawn(). If not, your
656 test case is mostly likely going to fail.
657
658 See also dotest.py where lldb.runHooks are processed/populated.
659 """
660 if not lldb.runHooks:
661 self.skipTest("No runhooks specified for lldb, skip the test")
Johnny Chen644ad082011-10-19 16:48:07 +0000662 if use_cmd_api:
663 for hook in lldb.runhooks:
664 self.runCmd(hook)
665 else:
666 if not child or not child_prompt:
667 self.fail("Both child and child_prompt need to be defined.")
668 for hook in lldb.runHooks:
669 child.sendline(hook)
670 child.expect_exact(child_prompt)
Johnny Chen5f3c5672011-10-19 01:06:21 +0000671
Johnny Chencbe51262011-08-01 19:50:58 +0000672 def HideStdout(self):
673 """Hide output to stdout from the user.
674
675 During test execution, there might be cases where we don't want to show the
676 standard output to the user. For example,
677
678 self.runCmd(r'''sc print "\n\n\tHello!\n"''')
679
680 tests whether command abbreviation for 'script' works or not. There is no
681 need to show the 'Hello' output to the user as long as the 'script' command
682 succeeds and we are not in TraceOn() mode (see the '-t' option).
683
684 In this case, the test method calls self.HideStdout(self) to redirect the
685 sys.stdout to a null device, and restores the sys.stdout upon teardown.
686
687 Note that you should only call this method at most once during a test case
688 execution. Any subsequent call has no effect at all."""
689 if self.sys_stdout_hidden:
690 return
691
692 self.sys_stdout_hidden = True
693 old_stdout = sys.stdout
694 sys.stdout = open(os.devnull, 'w')
695 def restore_stdout():
696 sys.stdout = old_stdout
697 self.addTearDownHook(restore_stdout)
698
699 # =======================================================================
700 # Methods for customized teardown cleanups as well as execution of hooks.
701 # =======================================================================
702
703 def setTearDownCleanup(self, dictionary=None):
704 """Register a cleanup action at tearDown() time with a dictinary"""
705 self.dict = dictionary
706 self.doTearDownCleanup = True
707
708 def addTearDownCleanup(self, dictionary):
709 """Add a cleanup action at tearDown() time with a dictinary"""
710 self.dicts.append(dictionary)
711 self.doTearDownCleanups = True
712
713 def addTearDownHook(self, hook):
714 """
715 Add a function to be run during tearDown() time.
716
717 Hooks are executed in a first come first serve manner.
718 """
719 if callable(hook):
720 with recording(self, traceAlways) as sbuf:
721 print >> sbuf, "Adding tearDown hook:", getsource_if_available(hook)
722 self.hooks.append(hook)
723
724 def tearDown(self):
725 """Fixture for unittest test case teardown."""
726 #import traceback
727 #traceback.print_stack()
728
Johnny Chen71cb7972011-08-01 21:13:26 +0000729 # This is for the case of directly spawning 'lldb' and interacting with it
730 # using pexpect.
731 import pexpect
732 if self.child and self.child.isalive():
733 with recording(self, traceAlways) as sbuf:
734 print >> sbuf, "tearing down the child process...."
735 if self.child_in_script_interpreter:
736 self.child.sendline('quit()')
737 self.child.expect_exact(self.child_prompt)
738 self.child.sendline('quit')
739 try:
740 self.child.expect(pexpect.EOF)
741 except:
742 pass
Johnny Chenf0ff42a2012-02-27 23:07:40 +0000743 # Give it one final blow to make sure the child is terminated.
744 self.child.close()
Johnny Chen71cb7972011-08-01 21:13:26 +0000745
Johnny Chencbe51262011-08-01 19:50:58 +0000746 # Check and run any hook functions.
747 for hook in reversed(self.hooks):
748 with recording(self, traceAlways) as sbuf:
749 print >> sbuf, "Executing tearDown hook:", getsource_if_available(hook)
750 hook()
751
752 del self.hooks
753
754 # Perform registered teardown cleanup.
755 if doCleanup and self.doTearDownCleanup:
Johnny Chen028d8eb2011-11-17 19:57:27 +0000756 self.cleanup(dictionary=self.dict)
Johnny Chencbe51262011-08-01 19:50:58 +0000757
758 # In rare cases where there are multiple teardown cleanups added.
759 if doCleanup and self.doTearDownCleanups:
Johnny Chencbe51262011-08-01 19:50:58 +0000760 if self.dicts:
761 for dict in reversed(self.dicts):
Johnny Chen028d8eb2011-11-17 19:57:27 +0000762 self.cleanup(dictionary=dict)
Johnny Chencbe51262011-08-01 19:50:58 +0000763
764 # Decide whether to dump the session info.
765 self.dumpSessionInfo()
766
767 # =========================================================
768 # Various callbacks to allow introspection of test progress
769 # =========================================================
770
771 def markError(self):
772 """Callback invoked when an error (unexpected exception) errored."""
773 self.__errored__ = True
774 with recording(self, False) as sbuf:
775 # False because there's no need to write "ERROR" to the stderr twice.
776 # Once by the Python unittest framework, and a second time by us.
777 print >> sbuf, "ERROR"
778
779 def markFailure(self):
780 """Callback invoked when a failure (test assertion failure) occurred."""
781 self.__failed__ = True
782 with recording(self, False) as sbuf:
783 # False because there's no need to write "FAIL" to the stderr twice.
784 # Once by the Python unittest framework, and a second time by us.
785 print >> sbuf, "FAIL"
786
787 def markExpectedFailure(self):
788 """Callback invoked when an expected failure/error occurred."""
789 self.__expected__ = True
790 with recording(self, False) as sbuf:
791 # False because there's no need to write "expected failure" to the
792 # stderr twice.
793 # Once by the Python unittest framework, and a second time by us.
794 print >> sbuf, "expected failure"
795
Johnny Chenf5b89092011-08-15 23:09:08 +0000796 def markSkippedTest(self):
797 """Callback invoked when a test is skipped."""
798 self.__skipped__ = True
799 with recording(self, False) as sbuf:
800 # False because there's no need to write "skipped test" to the
801 # stderr twice.
802 # Once by the Python unittest framework, and a second time by us.
803 print >> sbuf, "skipped test"
804
Johnny Chencbe51262011-08-01 19:50:58 +0000805 def markUnexpectedSuccess(self):
806 """Callback invoked when an unexpected success occurred."""
807 self.__unexpected__ = True
808 with recording(self, False) as sbuf:
809 # False because there's no need to write "unexpected success" to the
810 # stderr twice.
811 # Once by the Python unittest framework, and a second time by us.
812 print >> sbuf, "unexpected success"
813
814 def dumpSessionInfo(self):
815 """
816 Dump the debugger interactions leading to a test error/failure. This
817 allows for more convenient postmortem analysis.
818
819 See also LLDBTestResult (dotest.py) which is a singlton class derived
820 from TextTestResult and overwrites addError, addFailure, and
821 addExpectedFailure methods to allow us to to mark the test instance as
822 such.
823 """
824
825 # We are here because self.tearDown() detected that this test instance
826 # either errored or failed. The lldb.test_result singleton contains
827 # two lists (erros and failures) which get populated by the unittest
828 # framework. Look over there for stack trace information.
829 #
830 # The lists contain 2-tuples of TestCase instances and strings holding
831 # formatted tracebacks.
832 #
833 # See http://docs.python.org/library/unittest.html#unittest.TestResult.
834 if self.__errored__:
835 pairs = lldb.test_result.errors
836 prefix = 'Error'
837 elif self.__failed__:
838 pairs = lldb.test_result.failures
839 prefix = 'Failure'
840 elif self.__expected__:
841 pairs = lldb.test_result.expectedFailures
842 prefix = 'ExpectedFailure'
Johnny Chenf5b89092011-08-15 23:09:08 +0000843 elif self.__skipped__:
844 prefix = 'SkippedTest'
Johnny Chencbe51262011-08-01 19:50:58 +0000845 elif self.__unexpected__:
846 prefix = "UnexpectedSuccess"
847 else:
848 # Simply return, there's no session info to dump!
849 return
850
Johnny Chenf5b89092011-08-15 23:09:08 +0000851 if not self.__unexpected__ and not self.__skipped__:
Johnny Chencbe51262011-08-01 19:50:58 +0000852 for test, traceback in pairs:
853 if test is self:
854 print >> self.session, traceback
855
Johnny Chen6fd55f12011-08-11 00:16:28 +0000856 testMethod = getattr(self, self._testMethodName)
857 if getattr(testMethod, "__benchmarks_test__", False):
858 benchmarks = True
859 else:
860 benchmarks = False
861
Johnny Chendfa0cdb2011-12-03 00:16:59 +0000862 # This records the compiler version used for the test.
863 system([self.getCompiler(), "-v"], sender=self)
864
Johnny Chencbe51262011-08-01 19:50:58 +0000865 dname = os.path.join(os.environ["LLDB_TEST"],
866 os.environ["LLDB_SESSION_DIRNAME"])
867 if not os.path.isdir(dname):
868 os.mkdir(dname)
869 fname = os.path.join(dname, "%s-%s.log" % (prefix, self.id()))
870 with open(fname, "w") as f:
871 import datetime
872 print >> f, "Session info generated @", datetime.datetime.now().ctime()
873 print >> f, self.session.getvalue()
874 print >> f, "To rerun this test, issue the following command from the 'test' directory:\n"
Johnny Chen6fd55f12011-08-11 00:16:28 +0000875 print >> f, "./dotest.py %s -v %s -f %s.%s" % (self.getRunOptions(),
876 ('+b' if benchmarks else '-t'),
Johnny Chencbe51262011-08-01 19:50:58 +0000877 self.__class__.__name__,
878 self._testMethodName)
879
880 # ====================================================
881 # Config. methods supported through a plugin interface
882 # (enables reading of the current test configuration)
883 # ====================================================
884
885 def getArchitecture(self):
886 """Returns the architecture in effect the test suite is running with."""
887 module = builder_module()
888 return module.getArchitecture()
889
890 def getCompiler(self):
891 """Returns the compiler in effect the test suite is running with."""
892 module = builder_module()
893 return module.getCompiler()
894
895 def getRunOptions(self):
896 """Command line option for -A and -C to run this test again, called from
897 self.dumpSessionInfo()."""
898 arch = self.getArchitecture()
899 comp = self.getCompiler()
Johnny Chenb7058c52011-08-24 19:48:51 +0000900 if arch:
901 option_str = "-A " + arch
Johnny Chencbe51262011-08-01 19:50:58 +0000902 else:
Johnny Chenb7058c52011-08-24 19:48:51 +0000903 option_str = ""
904 if comp:
Johnny Chene1219bf2012-03-16 20:44:00 +0000905 option_str += " -C " + comp
Johnny Chenb7058c52011-08-24 19:48:51 +0000906 return option_str
Johnny Chencbe51262011-08-01 19:50:58 +0000907
908 # ==================================================
909 # Build methods supported through a plugin interface
910 # ==================================================
911
Johnny Chencbf15912012-02-01 01:49:50 +0000912 def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True):
Johnny Chencbe51262011-08-01 19:50:58 +0000913 """Platform specific way to build the default binaries."""
Johnny Chen028d8eb2011-11-17 19:57:27 +0000914 if lldb.skip_build_and_cleanup:
915 return
Johnny Chencbe51262011-08-01 19:50:58 +0000916 module = builder_module()
Johnny Chencbf15912012-02-01 01:49:50 +0000917 if not module.buildDefault(self, architecture, compiler, dictionary, clean):
Johnny Chencbe51262011-08-01 19:50:58 +0000918 raise Exception("Don't know how to build default binary")
919
Johnny Chencbf15912012-02-01 01:49:50 +0000920 def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True):
Johnny Chencbe51262011-08-01 19:50:58 +0000921 """Platform specific way to build binaries with dsym info."""
Johnny Chen028d8eb2011-11-17 19:57:27 +0000922 if lldb.skip_build_and_cleanup:
923 return
Johnny Chencbe51262011-08-01 19:50:58 +0000924 module = builder_module()
Johnny Chencbf15912012-02-01 01:49:50 +0000925 if not module.buildDsym(self, architecture, compiler, dictionary, clean):
Johnny Chencbe51262011-08-01 19:50:58 +0000926 raise Exception("Don't know how to build binary with dsym")
927
Johnny Chencbf15912012-02-01 01:49:50 +0000928 def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True):
Johnny Chencbe51262011-08-01 19:50:58 +0000929 """Platform specific way to build binaries with dwarf maps."""
Johnny Chen028d8eb2011-11-17 19:57:27 +0000930 if lldb.skip_build_and_cleanup:
931 return
Johnny Chencbe51262011-08-01 19:50:58 +0000932 module = builder_module()
Johnny Chencbf15912012-02-01 01:49:50 +0000933 if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
Johnny Chencbe51262011-08-01 19:50:58 +0000934 raise Exception("Don't know how to build binary with dwarf")
Johnny Chen366fb8c2011-08-01 18:46:13 +0000935
Johnny Chen7f9985a2011-08-12 20:19:22 +0000936 def cleanup(self, dictionary=None):
937 """Platform specific way to do cleanup after build."""
Johnny Chen028d8eb2011-11-17 19:57:27 +0000938 if lldb.skip_build_and_cleanup:
939 return
Johnny Chen7f9985a2011-08-12 20:19:22 +0000940 module = builder_module()
941 if not module.cleanup(self, dictionary):
Johnny Chen028d8eb2011-11-17 19:57:27 +0000942 raise Exception("Don't know how to do cleanup with dictionary: "+dictionary)
Johnny Chen7f9985a2011-08-12 20:19:22 +0000943
Johnny Chen366fb8c2011-08-01 18:46:13 +0000944
945class TestBase(Base):
946 """
947 This abstract base class is meant to be subclassed. It provides default
948 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
949 among other things.
950
951 Important things for test class writers:
952
953 - Overwrite the mydir class attribute, otherwise your test class won't
954 run. It specifies the relative directory to the top level 'test' so
955 the test harness can change to the correct working directory before
956 running your test.
957
958 - The setUp method sets up things to facilitate subsequent interactions
959 with the debugger as part of the test. These include:
960 - populate the test method name
961 - create/get a debugger set with synchronous mode (self.dbg)
962 - get the command interpreter from with the debugger (self.ci)
963 - create a result object for use with the command interpreter
964 (self.res)
965 - plus other stuffs
966
967 - The tearDown method tries to perform some necessary cleanup on behalf
968 of the test to return the debugger to a good state for the next test.
969 These include:
970 - execute any tearDown hooks registered by the test method with
971 TestBase.addTearDownHook(); examples can be found in
972 settings/TestSettings.py
973 - kill the inferior process associated with each target, if any,
974 and, then delete the target from the debugger's target list
975 - perform build cleanup before running the next test method in the
976 same test class; examples of registering for this service can be
977 found in types/TestIntegerTypes.py with the call:
978 - self.setTearDownCleanup(dictionary=d)
979
980 - Similarly setUpClass and tearDownClass perform classwise setup and
981 teardown fixtures. The tearDownClass method invokes a default build
982 cleanup for the entire test class; also, subclasses can implement the
983 classmethod classCleanup(cls) to perform special class cleanup action.
984
985 - The instance methods runCmd and expect are used heavily by existing
986 test cases to send a command to the command interpreter and to perform
987 string/pattern matching on the output of such command execution. The
988 expect method also provides a mode to peform string/pattern matching
989 without running a command.
990
991 - The build methods buildDefault, buildDsym, and buildDwarf are used to
992 build the binaries used during a particular test scenario. A plugin
993 should be provided for the sys.platform running the test suite. The
994 Mac OS X implementation is located in plugins/darwin.py.
995 """
996
997 # Maximum allowed attempts when launching the inferior process.
998 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
999 maxLaunchCount = 3;
1000
1001 # Time to wait before the next launching attempt in second(s).
1002 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
1003 timeWaitNextLaunch = 1.0;
1004
1005 def doDelay(self):
1006 """See option -w of dotest.py."""
1007 if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and
1008 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'):
1009 waitTime = 1.0
1010 if "LLDB_TIME_WAIT_BETWEEN_TEST_CASES" in os.environ:
1011 waitTime = float(os.environ["LLDB_TIME_WAIT_BETWEEN_TEST_CASES"])
1012 time.sleep(waitTime)
1013
1014 def setUp(self):
1015 #import traceback
1016 #traceback.print_stack()
1017
1018 # Works with the test driver to conditionally skip tests via decorators.
1019 Base.setUp(self)
1020
Johnny Chen366fb8c2011-08-01 18:46:13 +00001021 try:
1022 if lldb.blacklist:
1023 className = self.__class__.__name__
1024 classAndMethodName = "%s.%s" % (className, self._testMethodName)
1025 if className in lldb.blacklist:
1026 self.skipTest(lldb.blacklist.get(className))
1027 elif classAndMethodName in lldb.blacklist:
1028 self.skipTest(lldb.blacklist.get(classAndMethodName))
1029 except AttributeError:
1030 pass
1031
Johnny Chen9a9fcf62011-06-21 00:53:00 +00001032 # Insert some delay between successive test cases if specified.
1033 self.doDelay()
Johnny Chene47649c2010-10-07 02:04:14 +00001034
Johnny Chen65572482010-08-25 18:49:48 +00001035 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
1036 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
1037
Johnny Chend2965212010-10-19 16:00:42 +00001038 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
Johnny Chen458a67e2010-11-29 20:20:34 +00001039 self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
Johnny Chen65572482010-08-25 18:49:48 +00001040
Johnny Chena1affab2010-07-03 03:41:59 +00001041 # Create the debugger instance if necessary.
1042 try:
1043 self.dbg = lldb.DBG
Johnny Chena1affab2010-07-03 03:41:59 +00001044 except AttributeError:
1045 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf8c723b2010-07-03 20:41:42 +00001046
Johnny Chen960ce122011-05-25 19:06:18 +00001047 if not self.dbg:
Johnny Chena1affab2010-07-03 03:41:59 +00001048 raise Exception('Invalid debugger instance')
1049
1050 # We want our debugger to be synchronous.
1051 self.dbg.SetAsync(False)
1052
1053 # Retrieve the associated command interpreter instance.
1054 self.ci = self.dbg.GetCommandInterpreter()
1055 if not self.ci:
1056 raise Exception('Could not get the command interpreter')
1057
1058 # And the result object.
1059 self.res = lldb.SBCommandReturnObject()
1060
Johnny Chenac97a6b2012-04-16 18:55:15 +00001061 # Run global pre-flight code, if defined via the config file.
1062 if lldb.pre_flight:
1063 lldb.pre_flight(self)
1064
Johnny Chena1affab2010-07-03 03:41:59 +00001065 def tearDown(self):
Johnny Chen72a14342010-09-02 21:23:12 +00001066 #import traceback
1067 #traceback.print_stack()
1068
Johnny Chencbe51262011-08-01 19:50:58 +00001069 Base.tearDown(self)
Johnny Chen705737b2010-10-19 23:40:13 +00001070
Johnny Chen409646d2011-06-15 21:24:24 +00001071 # Delete the target(s) from the debugger as a general cleanup step.
1072 # This includes terminating the process for each target, if any.
1073 # We'd like to reuse the debugger for our next test without incurring
1074 # the initialization overhead.
1075 targets = []
1076 for target in self.dbg:
1077 if target:
1078 targets.append(target)
1079 process = target.GetProcess()
1080 if process:
1081 rc = self.invoke(process, "Kill")
1082 self.assertTrue(rc.Success(), PROCESS_KILLED)
1083 for target in targets:
1084 self.dbg.DeleteTarget(target)
Johnny Chenffde4fc2010-08-16 21:28:10 +00001085
Johnny Chenac97a6b2012-04-16 18:55:15 +00001086 # Run global post-flight code, if defined via the config file.
1087 if lldb.post_flight:
1088 lldb.post_flight(self)
1089
Johnny Chena1affab2010-07-03 03:41:59 +00001090 del self.dbg
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001091
Johnny Chen90c56e62011-09-30 21:48:35 +00001092 def switch_to_thread_with_stop_reason(self, stop_reason):
1093 """
1094 Run the 'thread list' command, and select the thread with stop reason as
1095 'stop_reason'. If no such thread exists, no select action is done.
1096 """
1097 from lldbutil import stop_reason_to_str
1098 self.runCmd('thread list')
1099 output = self.res.GetOutput()
1100 thread_line_pattern = re.compile("^[ *] thread #([0-9]+):.*stop reason = %s" %
1101 stop_reason_to_str(stop_reason))
1102 for line in output.splitlines():
1103 matched = thread_line_pattern.match(line)
1104 if matched:
1105 self.runCmd('thread select %s' % matched.group(1))
1106
Johnny Chenef6f4762011-06-15 21:38:39 +00001107 def runCmd(self, cmd, msg=None, check=True, trace=False):
Johnny Chen8df95eb2010-08-19 23:26:59 +00001108 """
1109 Ask the command interpreter to handle the command and then check its
1110 return status.
1111 """
1112 # Fail fast if 'cmd' is not meaningful.
1113 if not cmd or len(cmd) == 0:
1114 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen4f995f02010-08-20 17:57:32 +00001115
Johnny Chen9de4ede2010-08-31 17:42:54 +00001116 trace = (True if traceAlways else trace)
Johnny Chend0c24b22010-08-23 17:10:44 +00001117
Johnny Chen21f33412010-09-01 00:15:19 +00001118 running = (cmd.startswith("run") or cmd.startswith("process launch"))
Johnny Chen4f995f02010-08-20 17:57:32 +00001119
Johnny Chen21f33412010-09-01 00:15:19 +00001120 for i in range(self.maxLaunchCount if running else 1):
Johnny Chen65572482010-08-25 18:49:48 +00001121 self.ci.HandleCommand(cmd, self.res)
Johnny Chen4f995f02010-08-20 17:57:32 +00001122
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001123 with recording(self, trace) as sbuf:
1124 print >> sbuf, "runCmd:", cmd
Johnny Chen7c565c82010-10-15 16:13:00 +00001125 if not check:
Johnny Chen31cf8e22010-10-15 18:52:22 +00001126 print >> sbuf, "check of return status not required"
Johnny Chen65572482010-08-25 18:49:48 +00001127 if self.res.Succeeded():
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001128 print >> sbuf, "output:", self.res.GetOutput()
Johnny Chen65572482010-08-25 18:49:48 +00001129 else:
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001130 print >> sbuf, "runCmd failed!"
1131 print >> sbuf, self.res.GetError()
Johnny Chen4f995f02010-08-20 17:57:32 +00001132
Johnny Chen029acae2010-08-20 21:03:09 +00001133 if self.res.Succeeded():
Johnny Chen65572482010-08-25 18:49:48 +00001134 break
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001135 elif running:
Johnny Chendcb37222011-01-19 02:02:08 +00001136 # For process launch, wait some time before possible next try.
1137 time.sleep(self.timeWaitNextLaunch)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001138 with recording(self, True) as sbuf:
1139 print >> sbuf, "Command '" + cmd + "' failed!"
Johnny Chen4f995f02010-08-20 17:57:32 +00001140
Johnny Chen8df95eb2010-08-19 23:26:59 +00001141 if check:
1142 self.assertTrue(self.res.Succeeded(),
Johnny Chen05efcf782010-11-09 18:42:22 +00001143 msg if msg else CMD_MSG(cmd))
Johnny Chen8df95eb2010-08-19 23:26:59 +00001144
Johnny Chen90c56e62011-09-30 21:48:35 +00001145 def expect(self, str, msg=None, patterns=None, startstr=None, endstr=None, substrs=None, trace=False, error=False, matching=True, exe=True):
Johnny Chen8df95eb2010-08-19 23:26:59 +00001146 """
1147 Similar to runCmd; with additional expect style output matching ability.
1148
1149 Ask the command interpreter to handle the command and then check its
1150 return status. The 'msg' parameter specifies an informational assert
1151 message. We expect the output from running the command to start with
Johnny Chen2d899752010-09-21 21:08:53 +00001152 'startstr', matches the substrings contained in 'substrs', and regexp
1153 matches the patterns contained in 'patterns'.
Johnny Chen9792f8e2010-09-17 22:28:51 +00001154
1155 If the keyword argument error is set to True, it signifies that the API
1156 client is expecting the command to fail. In this case, the error stream
Johnny Chenee975b82010-09-17 22:45:27 +00001157 from running the command is retrieved and compared against the golden
Johnny Chen9792f8e2010-09-17 22:28:51 +00001158 input, instead.
Johnny Chen2d899752010-09-21 21:08:53 +00001159
1160 If the keyword argument matching is set to False, it signifies that the API
1161 client is expecting the output of the command not to match the golden
1162 input.
Johnny Chen8e06de92010-09-21 23:33:30 +00001163
1164 Finally, the required argument 'str' represents the lldb command to be
1165 sent to the command interpreter. In case the keyword argument 'exe' is
1166 set to False, the 'str' is treated as a string to be matched/not-matched
1167 against the golden input.
Johnny Chen8df95eb2010-08-19 23:26:59 +00001168 """
Johnny Chen9de4ede2010-08-31 17:42:54 +00001169 trace = (True if traceAlways else trace)
Johnny Chend0c24b22010-08-23 17:10:44 +00001170
Johnny Chen8e06de92010-09-21 23:33:30 +00001171 if exe:
1172 # First run the command. If we are expecting error, set check=False.
Johnny Chen60881f62010-10-28 21:10:32 +00001173 # Pass the assert message along since it provides more semantic info.
Johnny Chen05dd8932010-10-28 18:24:22 +00001174 self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error)
Johnny Chen8df95eb2010-08-19 23:26:59 +00001175
Johnny Chen8e06de92010-09-21 23:33:30 +00001176 # Then compare the output against expected strings.
1177 output = self.res.GetError() if error else self.res.GetOutput()
Johnny Chen9792f8e2010-09-17 22:28:51 +00001178
Johnny Chen8e06de92010-09-21 23:33:30 +00001179 # If error is True, the API client expects the command to fail!
1180 if error:
1181 self.assertFalse(self.res.Succeeded(),
1182 "Command '" + str + "' is expected to fail!")
1183 else:
1184 # No execution required, just compare str against the golden input.
1185 output = str
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001186 with recording(self, trace) as sbuf:
1187 print >> sbuf, "looking at:", output
Johnny Chen9792f8e2010-09-17 22:28:51 +00001188
Johnny Chen2d899752010-09-21 21:08:53 +00001189 # The heading says either "Expecting" or "Not expecting".
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001190 heading = "Expecting" if matching else "Not expecting"
Johnny Chen2d899752010-09-21 21:08:53 +00001191
1192 # Start from the startstr, if specified.
1193 # If there's no startstr, set the initial state appropriately.
1194 matched = output.startswith(startstr) if startstr else (True if matching else False)
Johnny Chenead35c82010-08-20 18:25:15 +00001195
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001196 if startstr:
1197 with recording(self, trace) as sbuf:
1198 print >> sbuf, "%s start string: %s" % (heading, startstr)
1199 print >> sbuf, "Matched" if matched else "Not matched"
Johnny Chenead35c82010-08-20 18:25:15 +00001200
Johnny Chen90c56e62011-09-30 21:48:35 +00001201 # Look for endstr, if specified.
1202 keepgoing = matched if matching else not matched
1203 if endstr:
1204 matched = output.endswith(endstr)
1205 with recording(self, trace) as sbuf:
1206 print >> sbuf, "%s end string: %s" % (heading, endstr)
1207 print >> sbuf, "Matched" if matched else "Not matched"
1208
Johnny Chen2d899752010-09-21 21:08:53 +00001209 # Look for sub strings, if specified.
1210 keepgoing = matched if matching else not matched
1211 if substrs and keepgoing:
Johnny Chen8df95eb2010-08-19 23:26:59 +00001212 for str in substrs:
Johnny Chen091bb1d2010-09-23 23:35:28 +00001213 matched = output.find(str) != -1
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001214 with recording(self, trace) as sbuf:
1215 print >> sbuf, "%s sub string: %s" % (heading, str)
1216 print >> sbuf, "Matched" if matched else "Not matched"
Johnny Chen2d899752010-09-21 21:08:53 +00001217 keepgoing = matched if matching else not matched
1218 if not keepgoing:
Johnny Chen8df95eb2010-08-19 23:26:59 +00001219 break
1220
Johnny Chen2d899752010-09-21 21:08:53 +00001221 # Search for regular expression patterns, if specified.
1222 keepgoing = matched if matching else not matched
1223 if patterns and keepgoing:
1224 for pattern in patterns:
1225 # Match Objects always have a boolean value of True.
1226 matched = bool(re.search(pattern, output))
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001227 with recording(self, trace) as sbuf:
1228 print >> sbuf, "%s pattern: %s" % (heading, pattern)
1229 print >> sbuf, "Matched" if matched else "Not matched"
Johnny Chen2d899752010-09-21 21:08:53 +00001230 keepgoing = matched if matching else not matched
1231 if not keepgoing:
1232 break
Johnny Chen2d899752010-09-21 21:08:53 +00001233
1234 self.assertTrue(matched if matching else not matched,
Johnny Chen05efcf782010-11-09 18:42:22 +00001235 msg if msg else EXP_MSG(str, exe))
Johnny Chen8df95eb2010-08-19 23:26:59 +00001236
Johnny Chena8b3cdd2010-08-25 22:52:45 +00001237 def invoke(self, obj, name, trace=False):
Johnny Chend8473bc2010-08-25 22:56:10 +00001238 """Use reflection to call a method dynamically with no argument."""
Johnny Chen9de4ede2010-08-31 17:42:54 +00001239 trace = (True if traceAlways else trace)
Johnny Chena8b3cdd2010-08-25 22:52:45 +00001240
1241 method = getattr(obj, name)
1242 import inspect
1243 self.assertTrue(inspect.ismethod(method),
1244 name + "is a method name of object: " + str(obj))
1245 result = method()
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001246 with recording(self, trace) as sbuf:
1247 print >> sbuf, str(method) + ":", result
Johnny Chena8b3cdd2010-08-25 22:52:45 +00001248 return result
Johnny Chen9c10c182010-08-27 00:15:48 +00001249
Johnny Chenb8770312011-05-27 23:36:52 +00001250 # =================================================
1251 # Misc. helper methods for debugging test execution
1252 # =================================================
1253
Johnny Chen57cd6dd2011-07-11 19:15:11 +00001254 def DebugSBValue(self, val):
Johnny Chen9de4ede2010-08-31 17:42:54 +00001255 """Debug print a SBValue object, if traceAlways is True."""
Johnny Chen47342d52011-04-27 17:43:07 +00001256 from lldbutil import value_type_to_str
Johnny Chen2c8d1592010-11-03 21:37:58 +00001257
Johnny Chen9de4ede2010-08-31 17:42:54 +00001258 if not traceAlways:
Johnny Chen9c10c182010-08-27 00:15:48 +00001259 return
1260
1261 err = sys.stderr
1262 err.write(val.GetName() + ":\n")
Johnny Chen90c56e62011-09-30 21:48:35 +00001263 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n')
1264 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n')
1265 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n')
1266 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n')
1267 err.write('\t' + "ValueAsUnsigned -> " + str(val.GetValueAsUnsigned())+ '\n')
1268 err.write('\t' + "ValueType -> " + value_type_to_str(val.GetValueType()) + '\n')
1269 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n')
1270 err.write('\t' + "IsPointerType -> " + str(val.TypeIsPointerType()) + '\n')
1271 err.write('\t' + "Location -> " + val.GetLocation() + '\n')
Johnny Chen9c10c182010-08-27 00:15:48 +00001272
Johnny Chend7e04d92011-08-05 20:17:27 +00001273 def DebugSBType(self, type):
1274 """Debug print a SBType object, if traceAlways is True."""
1275 if not traceAlways:
1276 return
1277
1278 err = sys.stderr
1279 err.write(type.GetName() + ":\n")
1280 err.write('\t' + "ByteSize -> " + str(type.GetByteSize()) + '\n')
1281 err.write('\t' + "IsPointerType -> " + str(type.IsPointerType()) + '\n')
1282 err.write('\t' + "IsReferenceType -> " + str(type.IsReferenceType()) + '\n')
1283
Johnny Chen73041472011-03-12 01:18:19 +00001284 def DebugPExpect(self, child):
1285 """Debug the spwaned pexpect object."""
1286 if not traceAlways:
1287 return
1288
1289 print child