blob: a4fd3bbfd033aee6739799329abb1adb78afd7fc [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
Johnny Chen4533dad2011-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 Chenbf6ffa32010-07-03 03:41:59 +000017$ echo $LLDB_TEST
18/Volumes/data/lldb/svn/trunk/test
19$ echo $PYTHONPATH
Johnny Chen8d55a342010-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 Chenbf6ffa32010-07-03 03:41:59 +000021$ 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
Johnny Chen57b47382010-09-02 22:25:47 +000028
29...
Johnny Chend0190a62010-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 Chen57b47382010-09-02 22:25:47 +000037...
Johnny Chend0190a62010-08-23 17:10:44 +000038
Johnny Chen57b47382010-09-02 22:25:47 +000039runCmd: frame variable strings
Johnny Chend0190a62010-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 Chen57b47382010-09-02 22:25:47 +000047runCmd: frame variable char_16
Johnny Chend0190a62010-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 Chen57b47382010-09-02 22:25:47 +000067runCmd: frame variable ushort_matrix
Johnny Chend0190a62010-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 Chen57b47382010-09-02 22:25:47 +000081runCmd: frame variable long_6
Johnny Chend0190a62010-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 Chenbf6ffa32010-07-03 03:41:59 +000096$
97"""
98
Johnny Chen90312a82010-09-21 22:34:45 +000099import os, sys, traceback
Johnny Chenea88e942010-09-21 21:08:53 +0000100import re
Johnny Chen8952a2d2010-08-30 21:35:00 +0000101from subprocess import *
Johnny Chen150c3cc2010-10-15 01:18:29 +0000102import StringIO
Johnny Chenf2b70232010-08-25 18:49:48 +0000103import time
Johnny Chena33a93c2010-08-30 23:08:52 +0000104import types
Johnny Chen73258832010-08-05 23:42:46 +0000105import unittest2
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000106import lldb
107
Johnny Chen707b3c92010-10-11 22:25:46 +0000108# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
Johnny Chend2047fa2011-01-19 18:18:47 +0000109# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options.
Johnny Chen707b3c92010-10-11 22:25:46 +0000110
111# By default, traceAlways is False.
Johnny Chen8d55a342010-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 Chen707b3c92010-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 Chen8d55a342010-08-31 17:42:54 +0000123
Johnny Chen00778092010-08-09 22:01:17 +0000124#
125# Some commonly used assert messages.
126#
127
Johnny Chenaa902922010-09-17 22:45:27 +0000128COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
129
Johnny Chen00778092010-08-09 22:01:17 +0000130CURRENT_EXECUTABLE_SET = "Current executable set successfully"
131
Johnny Chen7d1d7532010-09-02 21:23:12 +0000132PROCESS_IS_VALID = "Process is valid"
133
134PROCESS_KILLED = "Process is killed successfully"
135
Johnny Chend5f66fc2010-12-23 01:12:19 +0000136PROCESS_EXITED = "Process exited successfully"
137
138PROCESS_STOPPED = "Process status should be stopped"
139
Johnny Chen5ee88192010-08-27 23:47:36 +0000140RUN_SUCCEEDED = "Process is launched successfully"
Johnny Chen00778092010-08-09 22:01:17 +0000141
Johnny Chen17941842010-08-09 23:44:24 +0000142RUN_COMPLETED = "Process exited successfully"
Johnny Chen00778092010-08-09 22:01:17 +0000143
Johnny Chen67af43f2010-10-05 19:27:32 +0000144BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
145
Johnny Chen17941842010-08-09 23:44:24 +0000146BREAKPOINT_CREATED = "Breakpoint created successfully"
147
Johnny Chenf10af382010-12-04 00:07:24 +0000148BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
149
Johnny Chene76896c2010-08-17 21:33:31 +0000150BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
151
Johnny Chen17941842010-08-09 23:44:24 +0000152BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
Johnny Chen00778092010-08-09 22:01:17 +0000153
Johnny Chen703dbd02010-09-30 17:06:24 +0000154BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2"
155
Johnny Chen164f1e12010-10-15 18:07:09 +0000156BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3"
157
Johnny Chen89109ed12011-06-27 20:05:23 +0000158OBJECT_PRINTED_CORRECTLY = "Object printed correctly"
159
Johnny Chen5b3a3572010-12-09 18:22:12 +0000160SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
161
Johnny Chenc70b02a2010-09-22 23:00:20 +0000162STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
163
Johnny Chen1691a162011-04-15 16:44:48 +0000164STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
165
Johnny Chen5d6c4642010-11-10 23:46:38 +0000166STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
Johnny Chende0338b2010-11-10 20:20:06 +0000167
Johnny Chen5d6c4642010-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 Chen00778092010-08-09 22:01:17 +0000170
Johnny Chen2e431ce2010-10-20 18:38:48 +0000171STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
172
Johnny Chen0a3d1ca2010-12-13 21:49:58 +0000173STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
174
Johnny Chenc066ab42010-10-14 01:22:03 +0000175STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
176
Johnny Chen00778092010-08-09 22:01:17 +0000177STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
178
Johnny Chenf68cc122011-09-15 21:09:59 +0000179STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
180
Johnny Chen3c884a02010-08-24 22:07:56 +0000181DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
182
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000183VALID_BREAKPOINT = "Got a valid breakpoint"
184
Johnny Chen5bfb8ee2010-10-22 18:10:25 +0000185VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
186
Johnny Chen7209d84f2011-05-06 23:26:12 +0000187VALID_COMMAND_INTERPRETER = "Got a valid command interpreter"
188
Johnny Chen5ee88192010-08-27 23:47:36 +0000189VALID_FILESPEC = "Got a valid filespec"
190
Johnny Chen025d1b82010-12-08 01:25:21 +0000191VALID_MODULE = "Got a valid module"
192
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000193VALID_PROCESS = "Got a valid process"
194
Johnny Chen025d1b82010-12-08 01:25:21 +0000195VALID_SYMBOL = "Got a valid symbol"
196
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000197VALID_TARGET = "Got a valid target"
198
Johnny Chen15f247a2012-02-03 20:43:00 +0000199VALID_TYPE = "Got a valid type"
200
Johnny Chen5819ab42011-07-15 22:28:10 +0000201VALID_VARIABLE = "Got a valid variable"
202
Johnny Chen981463d2010-08-25 19:00:04 +0000203VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen00778092010-08-09 22:01:17 +0000204
Johnny Chenf68cc122011-09-15 21:09:59 +0000205WATCHPOINT_CREATED = "Watchpoint created successfully"
Johnny Chen5fca8ca2010-08-26 20:04:17 +0000206
Johnny Chenc0c67f22010-11-09 18:42:22 +0000207def CMD_MSG(str):
Johnny Chenaacf92e2011-05-31 22:16:51 +0000208 '''A generic "Command '%s' returns successfully" message generator.'''
Johnny Chenc0c67f22010-11-09 18:42:22 +0000209 return "Command '%s' returns successfully" % str
210
Johnny Chen3bc8ae42012-03-15 19:10:00 +0000211def COMPLETION_MSG(str_before, str_after):
Johnny Chen98aceb02012-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 Chenc0c67f22010-11-09 18:42:22 +0000215def EXP_MSG(str, exe):
Johnny Chenaacf92e2011-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 Chenc0c67f22010-11-09 18:42:22 +0000218 return "'%s' %s expected result" % (str, 'returns' if exe else 'matches')
Johnny Chen17941842010-08-09 23:44:24 +0000219
Johnny Chen3343f042010-10-19 19:11:38 +0000220def SETTING_MSG(setting):
Johnny Chenaacf92e2011-05-31 22:16:51 +0000221 '''A generic "Value of setting '%s' is correct" message generator.'''
Johnny Chen3343f042010-10-19 19:11:38 +0000222 return "Value of setting '%s' is correct" % setting
223
Johnny Chen27c41232010-08-26 21:49:29 +0000224def EnvArray():
Johnny Chenaacf92e2011-05-31 22:16:51 +0000225 """Returns an env variable array from the os.environ map object."""
Johnny Chen27c41232010-08-26 21:49:29 +0000226 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
227
Johnny Chen47ceb032010-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 Chencd9b7772010-10-12 00:09:25 +0000234 return i+1
Johnny Chen1691a162011-04-15 16:44:48 +0000235 raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename))
Johnny Chen47ceb032010-10-11 23:52:19 +0000236
Johnny Chen67af43f2010-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 Chen57816732012-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 Chen150c3cc2010-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 Chen690fcef2010-10-15 23:55:05 +0000267 """Create a StringIO instance; record the session obj and trace flag."""
Johnny Chen150c3cc2010-10-15 01:18:29 +0000268 StringIO.StringIO.__init__(self)
Johnny Chen0241f142011-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 Chenbfcf37f2011-08-16 17:06:45 +0000271 self.session = getattr(test, "session", None) if test else None
Johnny Chen150c3cc2010-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 Chen690fcef2010-10-15 23:55:05 +0000288 print >> sys.stderr, self.getvalue()
289 if self.session:
290 print >> self.session, self.getvalue()
Johnny Chen150c3cc2010-10-15 01:18:29 +0000291 self.close()
292
Johnny Chen690fcef2010-10-15 23:55:05 +0000293# From 2.7's subprocess.check_output() convenience function.
Johnny Chenac77f3b2011-03-23 20:28:59 +0000294# Return a tuple (stdoutdata, stderrdata).
Johnny Chen690fcef2010-10-15 23:55:05 +0000295def system(*popenargs, **kwargs):
Johnny Chen8eb14a92011-11-16 22:44:28 +0000296 r"""Run an os command with arguments and return its output as a byte string.
Johnny Chen690fcef2010-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 Chenac77f3b2011-03-23 20:28:59 +0000321 process = Popen(stdout=PIPE, stderr=PIPE, *popenargs, **kwargs)
Johnny Chen0bd8c312011-11-16 22:41:53 +0000322 pid = process.pid
Johnny Chen690fcef2010-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 Chen0bd8c312011-11-16 22:41:53 +0000333 print >> sbuf, "with pid:", pid
Johnny Chen690fcef2010-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 Chenac77f3b2011-03-23 20:28:59 +0000344 return (output, error)
Johnny Chen690fcef2010-10-15 23:55:05 +0000345
Johnny Chenab9c1dd2010-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 Collingbourne19f48d52011-06-20 19:06:20 +0000357def builder_module():
358 return __import__("builder_" + sys.platform)
359
Johnny Chena74bb0a2011-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 Chena74bb0a2011-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 Chenf1548d42012-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 Chen31963ce2011-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 Chenb5825b82011-08-19 01:17:09 +0000444 except Exception:
Johnny Chen31963ce2011-08-19 00:54:27 +0000445 if "clang" in compiler:
446 raise case._ExpectedFailure(sys.exc_info())
447 else:
Johnny Chenb5825b82011-08-19 01:17:09 +0000448 raise
Johnny Chen31963ce2011-08-19 00:54:27 +0000449
450 if "clang" in compiler:
451 raise case._UnexpectedSuccess
452 return wrapper
453
Johnny Chena33843f2011-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 Chena74bb0a2011-08-01 18:46:13 +0000475class Base(unittest2.TestCase):
Johnny Chen8334dad2010-10-22 23:15:46 +0000476 """
Johnny Chena74bb0a2011-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 Chen8334dad2010-10-22 23:15:46 +0000481 """
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000482 # The concrete subclass should override this attribute.
Johnny Chenf02ec122010-07-03 20:41:42 +0000483 mydir = None
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000484
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000485 # Keep track of the old current working directory.
486 oldcwd = None
Johnny Chena2124952010-08-05 21:23:45 +0000487
Johnny Chenfb4264c2011-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 Chen1a9f4dd2010-09-16 01:53:04 +0000492 @classmethod
493 def setUpClass(cls):
Johnny Chenda884342010-10-01 22:59:49 +0000494 """
495 Python unittest framework class setup fixture.
496 Do current directory manipulation.
497 """
498
Johnny Chenf02ec122010-07-03 20:41:42 +0000499 # Fail fast if 'mydir' attribute is not overridden.
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000500 if not cls.mydir or len(cls.mydir) == 0:
Johnny Chenf02ec122010-07-03 20:41:42 +0000501 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000502 # Save old working directory.
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000503 cls.oldcwd = os.getcwd()
Johnny Chenbf6ffa32010-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 Chen1a9f4dd2010-09-16 01:53:04 +0000508 if traceAlways:
Johnny Chen703dbd02010-09-30 17:06:24 +0000509 print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
Johnny Chen1a9f4dd2010-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 Chenda884342010-10-01 22:59:49 +0000514 """
515 Python unittest framework class teardown fixture.
516 Do class-wide cleanup.
517 """
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000518
Johnny Chen0fddfb22011-11-17 19:57:27 +0000519 if doCleanup and not lldb.skip_build_and_cleanup:
Johnny Chen707b3c92010-10-11 22:25:46 +0000520 # First, let's do the platform-specific cleanup.
Peter Collingbourne19f48d52011-06-20 19:06:20 +0000521 module = builder_module()
Johnny Chen707b3c92010-10-11 22:25:46 +0000522 if not module.cleanup():
523 raise Exception("Don't know how to do cleanup")
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000524
Johnny Chen707b3c92010-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 Chen1a9f4dd2010-09-16 01:53:04 +0000534
535 # Restore old working directory.
536 if traceAlways:
Johnny Chen703dbd02010-09-30 17:06:24 +0000537 print >> sys.stderr, "Restore dir to:", cls.oldcwd
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000538 os.chdir(cls.oldcwd)
539
Johnny Chena74bb0a2011-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 Chened492022011-06-21 00:53:00 +0000550
Johnny Chen1a9f4dd2010-09-16 01:53:04 +0000551 def setUp(self):
Johnny Chenfb4264c2011-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 Chen1a9f4dd2010-09-16 01:53:04 +0000556 #import traceback
557 #traceback.print_stack()
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000558
Johnny Chenaaa82ff2011-08-02 22:54:37 +0000559 if "LLDB_EXEC" in os.environ:
560 self.lldbExec = os.environ["LLDB_EXEC"]
Johnny Chend890bfc2011-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 Chenebe51722011-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 Chenaaa82ff2011-08-02 22:54:37 +0000573
Johnny Chen985e7402011-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 Chenf3e22ac2010-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 Chen4533dad2011-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 Chen5ccbccf2011-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 Chen4533dad2011-05-31 23:21:42 +0000605 except AttributeError:
606 pass
Johnny Chenf3e22ac2010-12-10 18:52:10 +0000607
Johnny Chen985e7402011-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 Chenfb4264c2011-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 Chenf79b0762011-08-16 00:48:58 +0000638 # And skipped tests.
639 self.__skipped__ = False
Johnny Chenfb4264c2011-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 Chen2a808582011-10-19 16:48:07 +0000648 def runHooks(self, child=None, child_prompt=None, use_cmd_api=False):
Johnny Chena737ba52011-10-19 01:06:21 +0000649 """Perform the run hooks to bring lldb debugger to the desired state.
650
Johnny Chen2a808582011-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 Chena737ba52011-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 Chen2a808582011-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 Chena737ba52011-10-19 01:06:21 +0000671
Johnny Chenfb4264c2011-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 Chen985e7402011-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 Chenac257132012-02-27 23:07:40 +0000743 # Give it one final blow to make sure the child is terminated.
744 self.child.close()
Johnny Chen985e7402011-08-01 21:13:26 +0000745
Johnny Chenfb4264c2011-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 Chen0fddfb22011-11-17 19:57:27 +0000756 self.cleanup(dictionary=self.dict)
Johnny Chenfb4264c2011-08-01 19:50:58 +0000757
758 # In rare cases where there are multiple teardown cleanups added.
759 if doCleanup and self.doTearDownCleanups:
Johnny Chenfb4264c2011-08-01 19:50:58 +0000760 if self.dicts:
761 for dict in reversed(self.dicts):
Johnny Chen0fddfb22011-11-17 19:57:27 +0000762 self.cleanup(dictionary=dict)
Johnny Chenfb4264c2011-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 Chenc5cc6252011-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 Chenfb4264c2011-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 Chenc5cc6252011-08-15 23:09:08 +0000843 elif self.__skipped__:
844 prefix = 'SkippedTest'
Johnny Chenfb4264c2011-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 Chenc5cc6252011-08-15 23:09:08 +0000851 if not self.__unexpected__ and not self.__skipped__:
Johnny Chenfb4264c2011-08-01 19:50:58 +0000852 for test, traceback in pairs:
853 if test is self:
854 print >> self.session, traceback
855
Johnny Chen8082a002011-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 Chen5daa6de2011-12-03 00:16:59 +0000862 # This records the compiler version used for the test.
863 system([self.getCompiler(), "-v"], sender=self)
864
Johnny Chenfb4264c2011-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)
Johnny Chen92f162a2012-04-19 19:39:11 +0000869 fname = os.path.join(dname, "%s-%s-%s-%s.log" % (prefix, self.getArchitecture(), self.getCompiler(), self.id()))
Johnny Chenfb4264c2011-08-01 19:50:58 +0000870 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 Chen8082a002011-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 Chenfb4264c2011-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 Chenb7bdd102011-08-24 19:48:51 +0000900 if arch:
901 option_str = "-A " + arch
Johnny Chenfb4264c2011-08-01 19:50:58 +0000902 else:
Johnny Chenb7bdd102011-08-24 19:48:51 +0000903 option_str = ""
904 if comp:
Johnny Chen531c0852012-03-16 20:44:00 +0000905 option_str += " -C " + comp
Johnny Chenb7bdd102011-08-24 19:48:51 +0000906 return option_str
Johnny Chenfb4264c2011-08-01 19:50:58 +0000907
908 # ==================================================
909 # Build methods supported through a plugin interface
910 # ==================================================
911
Johnny Chenfdc80a5c2012-02-01 01:49:50 +0000912 def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True):
Johnny Chenfb4264c2011-08-01 19:50:58 +0000913 """Platform specific way to build the default binaries."""
Johnny Chen0fddfb22011-11-17 19:57:27 +0000914 if lldb.skip_build_and_cleanup:
915 return
Johnny Chenfb4264c2011-08-01 19:50:58 +0000916 module = builder_module()
Johnny Chenfdc80a5c2012-02-01 01:49:50 +0000917 if not module.buildDefault(self, architecture, compiler, dictionary, clean):
Johnny Chenfb4264c2011-08-01 19:50:58 +0000918 raise Exception("Don't know how to build default binary")
919
Johnny Chenfdc80a5c2012-02-01 01:49:50 +0000920 def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True):
Johnny Chenfb4264c2011-08-01 19:50:58 +0000921 """Platform specific way to build binaries with dsym info."""
Johnny Chen0fddfb22011-11-17 19:57:27 +0000922 if lldb.skip_build_and_cleanup:
923 return
Johnny Chenfb4264c2011-08-01 19:50:58 +0000924 module = builder_module()
Johnny Chenfdc80a5c2012-02-01 01:49:50 +0000925 if not module.buildDsym(self, architecture, compiler, dictionary, clean):
Johnny Chenfb4264c2011-08-01 19:50:58 +0000926 raise Exception("Don't know how to build binary with dsym")
927
Johnny Chenfdc80a5c2012-02-01 01:49:50 +0000928 def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True):
Johnny Chenfb4264c2011-08-01 19:50:58 +0000929 """Platform specific way to build binaries with dwarf maps."""
Johnny Chen0fddfb22011-11-17 19:57:27 +0000930 if lldb.skip_build_and_cleanup:
931 return
Johnny Chenfb4264c2011-08-01 19:50:58 +0000932 module = builder_module()
Johnny Chenfdc80a5c2012-02-01 01:49:50 +0000933 if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
Johnny Chenfb4264c2011-08-01 19:50:58 +0000934 raise Exception("Don't know how to build binary with dwarf")
Johnny Chena74bb0a2011-08-01 18:46:13 +0000935
Johnny Chen9f4f5d92011-08-12 20:19:22 +0000936 def cleanup(self, dictionary=None):
937 """Platform specific way to do cleanup after build."""
Johnny Chen0fddfb22011-11-17 19:57:27 +0000938 if lldb.skip_build_and_cleanup:
939 return
Johnny Chen9f4f5d92011-08-12 20:19:22 +0000940 module = builder_module()
941 if not module.cleanup(self, dictionary):
Johnny Chen0fddfb22011-11-17 19:57:27 +0000942 raise Exception("Don't know how to do cleanup with dictionary: "+dictionary)
Johnny Chen9f4f5d92011-08-12 20:19:22 +0000943
Johnny Chena74bb0a2011-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 Chena74bb0a2011-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 Chened492022011-06-21 00:53:00 +00001032 # Insert some delay between successive test cases if specified.
1033 self.doDelay()
Johnny Chen0ed37c92010-10-07 02:04:14 +00001034
Johnny Chenf2b70232010-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 Chen430eb762010-10-19 16:00:42 +00001038 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
Johnny Chen4921b112010-11-29 20:20:34 +00001039 self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
Johnny Chenf2b70232010-08-25 18:49:48 +00001040
Johnny Chenbf6ffa32010-07-03 03:41:59 +00001041 # Create the debugger instance if necessary.
1042 try:
1043 self.dbg = lldb.DBG
Johnny Chenbf6ffa32010-07-03 03:41:59 +00001044 except AttributeError:
1045 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf02ec122010-07-03 20:41:42 +00001046
Johnny Chen3cd1e552011-05-25 19:06:18 +00001047 if not self.dbg:
Johnny Chenbf6ffa32010-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 Chen44d24972012-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 Chenbf6ffa32010-07-03 03:41:59 +00001065 def tearDown(self):
Johnny Chen7d1d7532010-09-02 21:23:12 +00001066 #import traceback
1067 #traceback.print_stack()
1068
Johnny Chenfb4264c2011-08-01 19:50:58 +00001069 Base.tearDown(self)
Johnny Chen707d8222010-10-19 23:40:13 +00001070
Johnny Chen3794ad92011-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 Chen6ca006c2010-08-16 21:28:10 +00001085
Johnny Chen44d24972012-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 Chenbf6ffa32010-07-03 03:41:59 +00001090 del self.dbg
Johnny Chen150c3cc2010-10-15 01:18:29 +00001091
Johnny Chen86268e42011-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 Chen5b67ca82011-06-15 21:38:39 +00001107 def runCmd(self, cmd, msg=None, check=True, trace=False):
Johnny Chen27f212d2010-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 Chen5bbb88f2010-08-20 17:57:32 +00001115
Johnny Chen8d55a342010-08-31 17:42:54 +00001116 trace = (True if traceAlways else trace)
Johnny Chend0190a62010-08-23 17:10:44 +00001117
Johnny Chen63dfb272010-09-01 00:15:19 +00001118 running = (cmd.startswith("run") or cmd.startswith("process launch"))
Johnny Chen5bbb88f2010-08-20 17:57:32 +00001119
Johnny Chen63dfb272010-09-01 00:15:19 +00001120 for i in range(self.maxLaunchCount if running else 1):
Johnny Chenf2b70232010-08-25 18:49:48 +00001121 self.ci.HandleCommand(cmd, self.res)
Johnny Chen5bbb88f2010-08-20 17:57:32 +00001122
Johnny Chen150c3cc2010-10-15 01:18:29 +00001123 with recording(self, trace) as sbuf:
1124 print >> sbuf, "runCmd:", cmd
Johnny Chenab254f52010-10-15 16:13:00 +00001125 if not check:
Johnny Chen27b107b2010-10-15 18:52:22 +00001126 print >> sbuf, "check of return status not required"
Johnny Chenf2b70232010-08-25 18:49:48 +00001127 if self.res.Succeeded():
Johnny Chen150c3cc2010-10-15 01:18:29 +00001128 print >> sbuf, "output:", self.res.GetOutput()
Johnny Chenf2b70232010-08-25 18:49:48 +00001129 else:
Johnny Chen150c3cc2010-10-15 01:18:29 +00001130 print >> sbuf, "runCmd failed!"
1131 print >> sbuf, self.res.GetError()
Johnny Chen5bbb88f2010-08-20 17:57:32 +00001132
Johnny Chenff3d01d2010-08-20 21:03:09 +00001133 if self.res.Succeeded():
Johnny Chenf2b70232010-08-25 18:49:48 +00001134 break
Johnny Chen150c3cc2010-10-15 01:18:29 +00001135 elif running:
Johnny Chencf7f74e2011-01-19 02:02:08 +00001136 # For process launch, wait some time before possible next try.
1137 time.sleep(self.timeWaitNextLaunch)
Johnny Chen150c3cc2010-10-15 01:18:29 +00001138 with recording(self, True) as sbuf:
1139 print >> sbuf, "Command '" + cmd + "' failed!"
Johnny Chen5bbb88f2010-08-20 17:57:32 +00001140
Johnny Chen27f212d2010-08-19 23:26:59 +00001141 if check:
1142 self.assertTrue(self.res.Succeeded(),
Johnny Chenc0c67f22010-11-09 18:42:22 +00001143 msg if msg else CMD_MSG(cmd))
Johnny Chen27f212d2010-08-19 23:26:59 +00001144
Johnny Chen86268e42011-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 Chen27f212d2010-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 Chenea88e942010-09-21 21:08:53 +00001152 'startstr', matches the substrings contained in 'substrs', and regexp
1153 matches the patterns contained in 'patterns'.
Johnny Chenb3307862010-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 Chenaa902922010-09-17 22:45:27 +00001157 from running the command is retrieved and compared against the golden
Johnny Chenb3307862010-09-17 22:28:51 +00001158 input, instead.
Johnny Chenea88e942010-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 Chen9c48b8d2010-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 Chen27f212d2010-08-19 23:26:59 +00001168 """
Johnny Chen8d55a342010-08-31 17:42:54 +00001169 trace = (True if traceAlways else trace)
Johnny Chend0190a62010-08-23 17:10:44 +00001170
Johnny Chen9c48b8d2010-09-21 23:33:30 +00001171 if exe:
1172 # First run the command. If we are expecting error, set check=False.
Johnny Chen62d4f862010-10-28 21:10:32 +00001173 # Pass the assert message along since it provides more semantic info.
Johnny Chenebfff952010-10-28 18:24:22 +00001174 self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error)
Johnny Chen27f212d2010-08-19 23:26:59 +00001175
Johnny Chen9c48b8d2010-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 Chenb3307862010-09-17 22:28:51 +00001178
Johnny Chen9c48b8d2010-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 Chen150c3cc2010-10-15 01:18:29 +00001186 with recording(self, trace) as sbuf:
1187 print >> sbuf, "looking at:", output
Johnny Chenb3307862010-09-17 22:28:51 +00001188
Johnny Chenea88e942010-09-21 21:08:53 +00001189 # The heading says either "Expecting" or "Not expecting".
Johnny Chen150c3cc2010-10-15 01:18:29 +00001190 heading = "Expecting" if matching else "Not expecting"
Johnny Chenea88e942010-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 Chenb145bba2010-08-20 18:25:15 +00001195
Johnny Chen150c3cc2010-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 Chenb145bba2010-08-20 18:25:15 +00001200
Johnny Chen86268e42011-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 Chenea88e942010-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 Chen27f212d2010-08-19 23:26:59 +00001212 for str in substrs:
Johnny Chenb052f6c2010-09-23 23:35:28 +00001213 matched = output.find(str) != -1
Johnny Chen150c3cc2010-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 Chenea88e942010-09-21 21:08:53 +00001217 keepgoing = matched if matching else not matched
1218 if not keepgoing:
Johnny Chen27f212d2010-08-19 23:26:59 +00001219 break
1220
Johnny Chenea88e942010-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 Chen150c3cc2010-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 Chenea88e942010-09-21 21:08:53 +00001230 keepgoing = matched if matching else not matched
1231 if not keepgoing:
1232 break
Johnny Chenea88e942010-09-21 21:08:53 +00001233
1234 self.assertTrue(matched if matching else not matched,
Johnny Chenc0c67f22010-11-09 18:42:22 +00001235 msg if msg else EXP_MSG(str, exe))
Johnny Chen27f212d2010-08-19 23:26:59 +00001236
Johnny Chenf3c59232010-08-25 22:52:45 +00001237 def invoke(self, obj, name, trace=False):
Johnny Chen61703c92010-08-25 22:56:10 +00001238 """Use reflection to call a method dynamically with no argument."""
Johnny Chen8d55a342010-08-31 17:42:54 +00001239 trace = (True if traceAlways else trace)
Johnny Chenf3c59232010-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 Chen150c3cc2010-10-15 01:18:29 +00001246 with recording(self, trace) as sbuf:
1247 print >> sbuf, str(method) + ":", result
Johnny Chenf3c59232010-08-25 22:52:45 +00001248 return result
Johnny Chen827edff2010-08-27 00:15:48 +00001249
Johnny Chenf359cf22011-05-27 23:36:52 +00001250 # =================================================
1251 # Misc. helper methods for debugging test execution
1252 # =================================================
1253
Johnny Chen56b92a72011-07-11 19:15:11 +00001254 def DebugSBValue(self, val):
Johnny Chen8d55a342010-08-31 17:42:54 +00001255 """Debug print a SBValue object, if traceAlways is True."""
Johnny Chende90f1d2011-04-27 17:43:07 +00001256 from lldbutil import value_type_to_str
Johnny Chen87bb5892010-11-03 21:37:58 +00001257
Johnny Chen8d55a342010-08-31 17:42:54 +00001258 if not traceAlways:
Johnny Chen827edff2010-08-27 00:15:48 +00001259 return
1260
1261 err = sys.stderr
1262 err.write(val.GetName() + ":\n")
Johnny Chen86268e42011-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 Chen827edff2010-08-27 00:15:48 +00001272
Johnny Chen36c5eb12011-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 Chenb877f1e2011-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