blob: 0207e6d0cef10d69d2f2a19d5b81e1aacebe478e [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
Johnny Chene39170b2012-05-16 20:41:28 +000012entire of part of the test suite . Example:
Johnny Chena1affab2010-07-03 03:41:59 +000013
Johnny Chene39170b2012-05-16 20:41:28 +000014# Exercises the test suite in the types directory....
15/Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types
Johnny Chen59ea45f2010-09-02 22:25:47 +000016...
Johnny Chend0c24b22010-08-23 17:10:44 +000017
Johnny Chene39170b2012-05-16 20:41:28 +000018Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42'
19Command invoked: python ./dotest.py -A x86_64 types
20compilers=['clang']
Johnny Chend0c24b22010-08-23 17:10:44 +000021
Johnny Chene39170b2012-05-16 20:41:28 +000022Configuration: arch=x86_64 compiler=clang
Johnny Chend0c24b22010-08-23 17:10:44 +000023----------------------------------------------------------------------
Johnny Chene39170b2012-05-16 20:41:28 +000024Collected 72 tests
25
26........................................................................
27----------------------------------------------------------------------
28Ran 72 tests in 135.468s
Johnny Chend0c24b22010-08-23 17:10:44 +000029
30OK
Johnny Chena1affab2010-07-03 03:41:59 +000031$
32"""
33
Johnny Chen93ae6042010-09-21 22:34:45 +000034import os, sys, traceback
Johnny Chen2d899752010-09-21 21:08:53 +000035import re
Johnny Chena1cc8832010-08-30 21:35:00 +000036from subprocess import *
Johnny Chen84a6d6f2010-10-15 01:18:29 +000037import StringIO
Johnny Chen65572482010-08-25 18:49:48 +000038import time
Johnny Chen1acaf632010-08-30 23:08:52 +000039import types
Johnny Chen75e28f92010-08-05 23:42:46 +000040import unittest2
Johnny Chena1affab2010-07-03 03:41:59 +000041import lldb
42
Johnny Chen548aefd2010-10-11 22:25:46 +000043# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
Johnny Chen24af2962011-01-19 18:18:47 +000044# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options.
Johnny Chen548aefd2010-10-11 22:25:46 +000045
46# By default, traceAlways is False.
Johnny Chen9de4ede2010-08-31 17:42:54 +000047if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
48 traceAlways = True
49else:
50 traceAlways = False
51
Johnny Chen548aefd2010-10-11 22:25:46 +000052# By default, doCleanup is True.
53if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO":
54 doCleanup = False
55else:
56 doCleanup = True
57
Johnny Chen9de4ede2010-08-31 17:42:54 +000058
Johnny Chen96f08d52010-08-09 22:01:17 +000059#
60# Some commonly used assert messages.
61#
62
Johnny Chenee975b82010-09-17 22:45:27 +000063COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
64
Johnny Chen96f08d52010-08-09 22:01:17 +000065CURRENT_EXECUTABLE_SET = "Current executable set successfully"
66
Johnny Chen72a14342010-09-02 21:23:12 +000067PROCESS_IS_VALID = "Process is valid"
68
69PROCESS_KILLED = "Process is killed successfully"
70
Johnny Chen0ace30f2010-12-23 01:12:19 +000071PROCESS_EXITED = "Process exited successfully"
72
73PROCESS_STOPPED = "Process status should be stopped"
74
Johnny Chen1bb9f9a2010-08-27 23:47:36 +000075RUN_SUCCEEDED = "Process is launched successfully"
Johnny Chen96f08d52010-08-09 22:01:17 +000076
Johnny Chend85dae52010-08-09 23:44:24 +000077RUN_COMPLETED = "Process exited successfully"
Johnny Chen96f08d52010-08-09 22:01:17 +000078
Johnny Chen5349ee22010-10-05 19:27:32 +000079BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
80
Johnny Chend85dae52010-08-09 23:44:24 +000081BREAKPOINT_CREATED = "Breakpoint created successfully"
82
Johnny Chen1ad9e992010-12-04 00:07:24 +000083BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
84
Johnny Chen9b92c6e2010-08-17 21:33:31 +000085BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
86
Johnny Chend85dae52010-08-09 23:44:24 +000087BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
Johnny Chen96f08d52010-08-09 22:01:17 +000088
Johnny Chen72afa8d2010-09-30 17:06:24 +000089BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2"
90
Johnny Chenc55dace2010-10-15 18:07:09 +000091BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3"
92
Johnny Chenc0dbdc02011-06-27 20:05:23 +000093OBJECT_PRINTED_CORRECTLY = "Object printed correctly"
94
Johnny Chen6f7abb02010-12-09 18:22:12 +000095SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
96
Johnny Chen0b3ee552010-09-22 23:00:20 +000097STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
98
Johnny Chen33cd0c32011-04-15 16:44:48 +000099STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
100
Johnny Chene8587d02010-11-10 23:46:38 +0000101STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
Johnny Chenc82ac762010-11-10 20:20:06 +0000102
Johnny Chene8587d02010-11-10 23:46:38 +0000103STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
104 STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'")
Johnny Chen96f08d52010-08-09 22:01:17 +0000105
Johnny Chenf6bdb192010-10-20 18:38:48 +0000106STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
107
Johnny Chen7a4512b2010-12-13 21:49:58 +0000108STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
109
Johnny Chend7a4eb02010-10-14 01:22:03 +0000110STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
111
Johnny Chen96f08d52010-08-09 22:01:17 +0000112STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
113
Johnny Chen58c66e22011-09-15 21:09:59 +0000114STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
115
Johnny Chen4917e102010-08-24 22:07:56 +0000116DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
117
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000118VALID_BREAKPOINT = "Got a valid breakpoint"
119
Johnny Chen0601a292010-10-22 18:10:25 +0000120VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
121
Johnny Chenac910272011-05-06 23:26:12 +0000122VALID_COMMAND_INTERPRETER = "Got a valid command interpreter"
123
Johnny Chen1bb9f9a2010-08-27 23:47:36 +0000124VALID_FILESPEC = "Got a valid filespec"
125
Johnny Chen8fd886c2010-12-08 01:25:21 +0000126VALID_MODULE = "Got a valid module"
127
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000128VALID_PROCESS = "Got a valid process"
129
Johnny Chen8fd886c2010-12-08 01:25:21 +0000130VALID_SYMBOL = "Got a valid symbol"
131
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000132VALID_TARGET = "Got a valid target"
133
Johnny Chen2ef5eae2012-02-03 20:43:00 +0000134VALID_TYPE = "Got a valid type"
135
Johnny Chen5503d462011-07-15 22:28:10 +0000136VALID_VARIABLE = "Got a valid variable"
137
Johnny Chen22b95b22010-08-25 19:00:04 +0000138VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
Johnny Chen96f08d52010-08-09 22:01:17 +0000139
Johnny Chen58c66e22011-09-15 21:09:59 +0000140WATCHPOINT_CREATED = "Watchpoint created successfully"
Johnny Chenb4d1fff2010-08-26 20:04:17 +0000141
Johnny Chen05efcf782010-11-09 18:42:22 +0000142def CMD_MSG(str):
Johnny Chen006b5952011-05-31 22:16:51 +0000143 '''A generic "Command '%s' returns successfully" message generator.'''
Johnny Chen05efcf782010-11-09 18:42:22 +0000144 return "Command '%s' returns successfully" % str
145
Johnny Chendbe2c822012-03-15 19:10:00 +0000146def COMPLETION_MSG(str_before, str_after):
Johnny Chenfbcad682012-01-20 23:02:51 +0000147 '''A generic message generator for the completion mechanism.'''
148 return "'%s' successfully completes to '%s'" % (str_before, str_after)
149
Johnny Chen05efcf782010-11-09 18:42:22 +0000150def EXP_MSG(str, exe):
Johnny Chen006b5952011-05-31 22:16:51 +0000151 '''A generic "'%s' returns expected result" message generator if exe.
152 Otherwise, it generates "'%s' matches expected result" message.'''
Johnny Chen05efcf782010-11-09 18:42:22 +0000153 return "'%s' %s expected result" % (str, 'returns' if exe else 'matches')
Johnny Chend85dae52010-08-09 23:44:24 +0000154
Johnny Chendb9cbe92010-10-19 19:11:38 +0000155def SETTING_MSG(setting):
Johnny Chen006b5952011-05-31 22:16:51 +0000156 '''A generic "Value of setting '%s' is correct" message generator.'''
Johnny Chendb9cbe92010-10-19 19:11:38 +0000157 return "Value of setting '%s' is correct" % setting
158
Johnny Chenf4ce2882010-08-26 21:49:29 +0000159def EnvArray():
Johnny Chen006b5952011-05-31 22:16:51 +0000160 """Returns an env variable array from the os.environ map object."""
Johnny Chenf4ce2882010-08-26 21:49:29 +0000161 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
162
Johnny Chen14906002010-10-11 23:52:19 +0000163def line_number(filename, string_to_match):
164 """Helper function to return the line number of the first matched string."""
165 with open(filename, 'r') as f:
166 for i, line in enumerate(f):
167 if line.find(string_to_match) != -1:
168 # Found our match.
Johnny Chen0659e342010-10-12 00:09:25 +0000169 return i+1
Johnny Chen33cd0c32011-04-15 16:44:48 +0000170 raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename))
Johnny Chen14906002010-10-11 23:52:19 +0000171
Johnny Chen5349ee22010-10-05 19:27:32 +0000172def pointer_size():
173 """Return the pointer size of the host system."""
174 import ctypes
175 a_pointer = ctypes.c_void_p(0xffff)
176 return 8 * ctypes.sizeof(a_pointer)
177
Johnny Chen7be5d352012-02-09 02:01:59 +0000178def is_exe(fpath):
179 """Returns true if fpath is an executable."""
180 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
181
182def which(program):
183 """Returns the full path to a program; None otherwise."""
184 fpath, fname = os.path.split(program)
185 if fpath:
186 if is_exe(program):
187 return program
188 else:
189 for path in os.environ["PATH"].split(os.pathsep):
190 exe_file = os.path.join(path, program)
191 if is_exe(exe_file):
192 return exe_file
193 return None
194
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000195class recording(StringIO.StringIO):
196 """
197 A nice little context manager for recording the debugger interactions into
198 our session object. If trace flag is ON, it also emits the interactions
199 into the stderr.
200 """
201 def __init__(self, test, trace):
Johnny Chen1b7d6292010-10-15 23:55:05 +0000202 """Create a StringIO instance; record the session obj and trace flag."""
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000203 StringIO.StringIO.__init__(self)
Johnny Chen770683d2011-08-16 22:06:17 +0000204 # The test might not have undergone the 'setUp(self)' phase yet, so that
205 # the attribute 'session' might not even exist yet.
Johnny Chen8339f982011-08-16 17:06:45 +0000206 self.session = getattr(test, "session", None) if test else None
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000207 self.trace = trace
208
209 def __enter__(self):
210 """
211 Context management protocol on entry to the body of the with statement.
212 Just return the StringIO object.
213 """
214 return self
215
216 def __exit__(self, type, value, tb):
217 """
218 Context management protocol on exit from the body of the with statement.
219 If trace is ON, it emits the recordings into stderr. Always add the
220 recordings to our session object. And close the StringIO object, too.
221 """
222 if self.trace:
Johnny Chen1b7d6292010-10-15 23:55:05 +0000223 print >> sys.stderr, self.getvalue()
224 if self.session:
225 print >> self.session, self.getvalue()
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000226 self.close()
227
Johnny Chen1b7d6292010-10-15 23:55:05 +0000228# From 2.7's subprocess.check_output() convenience function.
Johnny Chen0bfa8592011-03-23 20:28:59 +0000229# Return a tuple (stdoutdata, stderrdata).
Johnny Chen1b7d6292010-10-15 23:55:05 +0000230def system(*popenargs, **kwargs):
Johnny Chen22ca65d2011-11-16 22:44:28 +0000231 r"""Run an os command with arguments and return its output as a byte string.
Johnny Chen1b7d6292010-10-15 23:55:05 +0000232
233 If the exit code was non-zero it raises a CalledProcessError. The
234 CalledProcessError object will have the return code in the returncode
235 attribute and output in the output attribute.
236
237 The arguments are the same as for the Popen constructor. Example:
238
239 >>> check_output(["ls", "-l", "/dev/null"])
240 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
241
242 The stdout argument is not allowed as it is used internally.
243 To capture standard error in the result, use stderr=STDOUT.
244
245 >>> check_output(["/bin/sh", "-c",
246 ... "ls -l non_existent_file ; exit 0"],
247 ... stderr=STDOUT)
248 'ls: non_existent_file: No such file or directory\n'
249 """
250
251 # Assign the sender object to variable 'test' and remove it from kwargs.
252 test = kwargs.pop('sender', None)
253
254 if 'stdout' in kwargs:
255 raise ValueError('stdout argument not allowed, it will be overridden.')
Johnny Chen0bfa8592011-03-23 20:28:59 +0000256 process = Popen(stdout=PIPE, stderr=PIPE, *popenargs, **kwargs)
Johnny Chen30b30cb2011-11-16 22:41:53 +0000257 pid = process.pid
Johnny Chen1b7d6292010-10-15 23:55:05 +0000258 output, error = process.communicate()
259 retcode = process.poll()
260
261 with recording(test, traceAlways) as sbuf:
262 if isinstance(popenargs, types.StringTypes):
263 args = [popenargs]
264 else:
265 args = list(popenargs)
266 print >> sbuf
267 print >> sbuf, "os command:", args
Johnny Chen30b30cb2011-11-16 22:41:53 +0000268 print >> sbuf, "with pid:", pid
Johnny Chen1b7d6292010-10-15 23:55:05 +0000269 print >> sbuf, "stdout:", output
270 print >> sbuf, "stderr:", error
271 print >> sbuf, "retcode:", retcode
272 print >> sbuf
273
274 if retcode:
275 cmd = kwargs.get("args")
276 if cmd is None:
277 cmd = popenargs[0]
278 raise CalledProcessError(retcode, cmd)
Johnny Chen0bfa8592011-03-23 20:28:59 +0000279 return (output, error)
Johnny Chen1b7d6292010-10-15 23:55:05 +0000280
Johnny Chen29867642010-11-01 20:35:01 +0000281def getsource_if_available(obj):
282 """
283 Return the text of the source code for an object if available. Otherwise,
284 a print representation is returned.
285 """
286 import inspect
287 try:
288 return inspect.getsource(obj)
289 except:
290 return repr(obj)
291
Peter Collingbourne39bd5362011-06-20 19:06:20 +0000292def builder_module():
293 return __import__("builder_" + sys.platform)
294
Johnny Chen366fb8c2011-08-01 18:46:13 +0000295#
296# Decorators for categorizing test cases.
297#
298
299from functools import wraps
300def python_api_test(func):
301 """Decorate the item as a Python API only test."""
302 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
303 raise Exception("@python_api_test can only be used to decorate a test method")
304 @wraps(func)
305 def wrapper(self, *args, **kwargs):
306 try:
307 if lldb.dont_do_python_api_test:
308 self.skipTest("python api tests")
309 except AttributeError:
310 pass
311 return func(self, *args, **kwargs)
312
313 # Mark this function as such to separate them from lldb command line tests.
314 wrapper.__python_api_test__ = True
315 return wrapper
316
Johnny Chen366fb8c2011-08-01 18:46:13 +0000317def benchmarks_test(func):
318 """Decorate the item as a benchmarks test."""
319 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
320 raise Exception("@benchmarks_test can only be used to decorate a test method")
321 @wraps(func)
322 def wrapper(self, *args, **kwargs):
323 try:
324 if not lldb.just_do_benchmarks_test:
325 self.skipTest("benchmarks tests")
326 except AttributeError:
327 pass
328 return func(self, *args, **kwargs)
329
330 # Mark this function as such to separate them from the regular tests.
331 wrapper.__benchmarks_test__ = True
332 return wrapper
333
Johnny Chena3ed7d82012-04-06 00:56:05 +0000334def dsym_test(func):
335 """Decorate the item as a dsym test."""
336 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
337 raise Exception("@dsym_test can only be used to decorate a test method")
338 @wraps(func)
339 def wrapper(self, *args, **kwargs):
340 try:
341 if lldb.dont_do_dsym_test:
342 self.skipTest("dsym tests")
343 except AttributeError:
344 pass
345 return func(self, *args, **kwargs)
346
347 # Mark this function as such to separate them from the regular tests.
348 wrapper.__dsym_test__ = True
349 return wrapper
350
351def dwarf_test(func):
352 """Decorate the item as a dwarf test."""
353 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
354 raise Exception("@dwarf_test can only be used to decorate a test method")
355 @wraps(func)
356 def wrapper(self, *args, **kwargs):
357 try:
358 if lldb.dont_do_dwarf_test:
359 self.skipTest("dwarf tests")
360 except AttributeError:
361 pass
362 return func(self, *args, **kwargs)
363
364 # Mark this function as such to separate them from the regular tests.
365 wrapper.__dwarf_test__ = True
366 return wrapper
367
Johnny Chen65040cb2011-08-19 00:54:27 +0000368def expectedFailureClang(func):
369 """Decorate the item as a Clang only expectedFailure."""
370 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
371 raise Exception("@expectedFailureClang can only be used to decorate a test method")
372 @wraps(func)
373 def wrapper(*args, **kwargs):
374 from unittest2 import case
375 self = args[0]
376 compiler = self.getCompiler()
377 try:
378 func(*args, **kwargs)
Johnny Chen7c9136b2011-08-19 01:17:09 +0000379 except Exception:
Johnny Chen65040cb2011-08-19 00:54:27 +0000380 if "clang" in compiler:
381 raise case._ExpectedFailure(sys.exc_info())
382 else:
Johnny Chen7c9136b2011-08-19 01:17:09 +0000383 raise
Johnny Chen65040cb2011-08-19 00:54:27 +0000384
385 if "clang" in compiler:
386 raise case._UnexpectedSuccess
387 return wrapper
388
Johnny Chen869e2962011-12-22 21:14:31 +0000389def expectedFailurei386(func):
390 """Decorate the item as an i386 only expectedFailure."""
391 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
392 raise Exception("@expectedFailurei386 can only be used to decorate a test method")
393 @wraps(func)
394 def wrapper(*args, **kwargs):
395 from unittest2 import case
396 self = args[0]
397 arch = self.getArchitecture()
398 try:
399 func(*args, **kwargs)
400 except Exception:
401 if "i386" in arch:
402 raise case._ExpectedFailure(sys.exc_info())
403 else:
404 raise
405
406 if "i386" in arch:
407 raise case._UnexpectedSuccess
408 return wrapper
409
Johnny Chen366fb8c2011-08-01 18:46:13 +0000410class Base(unittest2.TestCase):
Johnny Chen607b7a12010-10-22 23:15:46 +0000411 """
Johnny Chen366fb8c2011-08-01 18:46:13 +0000412 Abstract base for performing lldb (see TestBase) or other generic tests (see
413 BenchBase for one example). lldbtest.Base works with the test driver to
414 accomplish things.
415
Johnny Chen607b7a12010-10-22 23:15:46 +0000416 """
Johnny Chena1affab2010-07-03 03:41:59 +0000417 # The concrete subclass should override this attribute.
Johnny Chenf8c723b2010-07-03 20:41:42 +0000418 mydir = None
Johnny Chena1affab2010-07-03 03:41:59 +0000419
Johnny Chend3521cc2010-09-16 01:53:04 +0000420 # Keep track of the old current working directory.
421 oldcwd = None
Johnny Chen88f83042010-08-05 21:23:45 +0000422
Johnny Chencbe51262011-08-01 19:50:58 +0000423 def TraceOn(self):
424 """Returns True if we are in trace mode (tracing detailed test execution)."""
425 return traceAlways
426
Johnny Chend3521cc2010-09-16 01:53:04 +0000427 @classmethod
428 def setUpClass(cls):
Johnny Chen41998192010-10-01 22:59:49 +0000429 """
430 Python unittest framework class setup fixture.
431 Do current directory manipulation.
432 """
433
Johnny Chenf8c723b2010-07-03 20:41:42 +0000434 # Fail fast if 'mydir' attribute is not overridden.
Johnny Chend3521cc2010-09-16 01:53:04 +0000435 if not cls.mydir or len(cls.mydir) == 0:
Johnny Chenf8c723b2010-07-03 20:41:42 +0000436 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chena1affab2010-07-03 03:41:59 +0000437 # Save old working directory.
Johnny Chend3521cc2010-09-16 01:53:04 +0000438 cls.oldcwd = os.getcwd()
Johnny Chena1affab2010-07-03 03:41:59 +0000439
440 # Change current working directory if ${LLDB_TEST} is defined.
441 # See also dotest.py which sets up ${LLDB_TEST}.
442 if ("LLDB_TEST" in os.environ):
Johnny Chend3521cc2010-09-16 01:53:04 +0000443 if traceAlways:
Johnny Chen72afa8d2010-09-30 17:06:24 +0000444 print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
Johnny Chend3521cc2010-09-16 01:53:04 +0000445 os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
446
447 @classmethod
448 def tearDownClass(cls):
Johnny Chen41998192010-10-01 22:59:49 +0000449 """
450 Python unittest framework class teardown fixture.
451 Do class-wide cleanup.
452 """
Johnny Chend3521cc2010-09-16 01:53:04 +0000453
Johnny Chen028d8eb2011-11-17 19:57:27 +0000454 if doCleanup and not lldb.skip_build_and_cleanup:
Johnny Chen548aefd2010-10-11 22:25:46 +0000455 # First, let's do the platform-specific cleanup.
Peter Collingbourne39bd5362011-06-20 19:06:20 +0000456 module = builder_module()
Johnny Chen548aefd2010-10-11 22:25:46 +0000457 if not module.cleanup():
458 raise Exception("Don't know how to do cleanup")
Johnny Chend3521cc2010-09-16 01:53:04 +0000459
Johnny Chen548aefd2010-10-11 22:25:46 +0000460 # Subclass might have specific cleanup function defined.
461 if getattr(cls, "classCleanup", None):
462 if traceAlways:
463 print >> sys.stderr, "Call class-specific cleanup function for class:", cls
464 try:
465 cls.classCleanup()
466 except:
467 exc_type, exc_value, exc_tb = sys.exc_info()
468 traceback.print_exception(exc_type, exc_value, exc_tb)
Johnny Chend3521cc2010-09-16 01:53:04 +0000469
470 # Restore old working directory.
471 if traceAlways:
Johnny Chen72afa8d2010-09-30 17:06:24 +0000472 print >> sys.stderr, "Restore dir to:", cls.oldcwd
Johnny Chend3521cc2010-09-16 01:53:04 +0000473 os.chdir(cls.oldcwd)
474
Johnny Chen366fb8c2011-08-01 18:46:13 +0000475 @classmethod
476 def skipLongRunningTest(cls):
477 """
478 By default, we skip long running test case.
479 This can be overridden by passing '-l' to the test driver (dotest.py).
480 """
481 if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]:
482 return False
483 else:
484 return True
Johnny Chen9a9fcf62011-06-21 00:53:00 +0000485
Johnny Chend3521cc2010-09-16 01:53:04 +0000486 def setUp(self):
Johnny Chencbe51262011-08-01 19:50:58 +0000487 """Fixture for unittest test case setup.
488
489 It works with the test driver to conditionally skip tests and does other
490 initializations."""
Johnny Chend3521cc2010-09-16 01:53:04 +0000491 #import traceback
492 #traceback.print_stack()
Johnny Chena1affab2010-07-03 03:41:59 +0000493
Johnny Chen113388f2011-08-02 22:54:37 +0000494 if "LLDB_EXEC" in os.environ:
495 self.lldbExec = os.environ["LLDB_EXEC"]
Johnny Chen6033bed2011-08-26 00:00:01 +0000496 else:
497 self.lldbExec = None
498 if "LLDB_HERE" in os.environ:
499 self.lldbHere = os.environ["LLDB_HERE"]
500 else:
501 self.lldbHere = None
Johnny Chen7d7f4472011-10-07 19:21:09 +0000502 # If we spawn an lldb process for test (via pexpect), do not load the
503 # init file unless told otherwise.
504 if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]:
505 self.lldbOption = ""
506 else:
507 self.lldbOption = "--no-lldbinit"
Johnny Chen113388f2011-08-02 22:54:37 +0000508
Johnny Chen71cb7972011-08-01 21:13:26 +0000509 # Assign the test method name to self.testMethodName.
510 #
511 # For an example of the use of this attribute, look at test/types dir.
512 # There are a bunch of test cases under test/types and we don't want the
513 # module cacheing subsystem to be confused with executable name "a.out"
514 # used for all the test cases.
515 self.testMethodName = self._testMethodName
516
Johnny Chen3ebdacc2010-12-10 18:52:10 +0000517 # Python API only test is decorated with @python_api_test,
518 # which also sets the "__python_api_test__" attribute of the
519 # function object to True.
Johnny Chend8c1dd32011-05-31 23:21:42 +0000520 try:
521 if lldb.just_do_python_api_test:
522 testMethod = getattr(self, self._testMethodName)
523 if getattr(testMethod, "__python_api_test__", False):
524 pass
525 else:
Johnny Chen82ccf402011-07-30 01:39:58 +0000526 self.skipTest("non python api test")
527 except AttributeError:
528 pass
529
530 # Benchmarks test is decorated with @benchmarks_test,
531 # which also sets the "__benchmarks_test__" attribute of the
532 # function object to True.
533 try:
534 if lldb.just_do_benchmarks_test:
535 testMethod = getattr(self, self._testMethodName)
536 if getattr(testMethod, "__benchmarks_test__", False):
537 pass
538 else:
539 self.skipTest("non benchmarks test")
Johnny Chend8c1dd32011-05-31 23:21:42 +0000540 except AttributeError:
541 pass
Johnny Chen3ebdacc2010-12-10 18:52:10 +0000542
Johnny Chen71cb7972011-08-01 21:13:26 +0000543 # This is for the case of directly spawning 'lldb'/'gdb' and interacting
544 # with it using pexpect.
545 self.child = None
546 self.child_prompt = "(lldb) "
547 # If the child is interacting with the embedded script interpreter,
548 # there are two exits required during tear down, first to quit the
549 # embedded script interpreter and second to quit the lldb command
550 # interpreter.
551 self.child_in_script_interpreter = False
552
Johnny Chencbe51262011-08-01 19:50:58 +0000553 # These are for customized teardown cleanup.
554 self.dict = None
555 self.doTearDownCleanup = False
556 # And in rare cases where there are multiple teardown cleanups.
557 self.dicts = []
558 self.doTearDownCleanups = False
559
560 # Create a string buffer to record the session info, to be dumped into a
561 # test case specific file if test failure is encountered.
562 self.session = StringIO.StringIO()
563
564 # Optimistically set __errored__, __failed__, __expected__ to False
565 # initially. If the test errored/failed, the session info
566 # (self.session) is then dumped into a session specific file for
567 # diagnosis.
568 self.__errored__ = False
569 self.__failed__ = False
570 self.__expected__ = False
571 # We are also interested in unexpected success.
572 self.__unexpected__ = False
Johnny Chencd1df5a2011-08-16 00:48:58 +0000573 # And skipped tests.
574 self.__skipped__ = False
Johnny Chencbe51262011-08-01 19:50:58 +0000575
576 # See addTearDownHook(self, hook) which allows the client to add a hook
577 # function to be run during tearDown() time.
578 self.hooks = []
579
580 # See HideStdout(self).
581 self.sys_stdout_hidden = False
582
Johnny Chen644ad082011-10-19 16:48:07 +0000583 def runHooks(self, child=None, child_prompt=None, use_cmd_api=False):
Johnny Chen5f3c5672011-10-19 01:06:21 +0000584 """Perform the run hooks to bring lldb debugger to the desired state.
585
Johnny Chen644ad082011-10-19 16:48:07 +0000586 By default, expect a pexpect spawned child and child prompt to be
587 supplied (use_cmd_api=False). If use_cmd_api is true, ignore the child
588 and child prompt and use self.runCmd() to run the hooks one by one.
589
Johnny Chen5f3c5672011-10-19 01:06:21 +0000590 Note that child is a process spawned by pexpect.spawn(). If not, your
591 test case is mostly likely going to fail.
592
593 See also dotest.py where lldb.runHooks are processed/populated.
594 """
595 if not lldb.runHooks:
596 self.skipTest("No runhooks specified for lldb, skip the test")
Johnny Chen644ad082011-10-19 16:48:07 +0000597 if use_cmd_api:
598 for hook in lldb.runhooks:
599 self.runCmd(hook)
600 else:
601 if not child or not child_prompt:
602 self.fail("Both child and child_prompt need to be defined.")
603 for hook in lldb.runHooks:
604 child.sendline(hook)
605 child.expect_exact(child_prompt)
Johnny Chen5f3c5672011-10-19 01:06:21 +0000606
Johnny Chencbe51262011-08-01 19:50:58 +0000607 def HideStdout(self):
608 """Hide output to stdout from the user.
609
610 During test execution, there might be cases where we don't want to show the
611 standard output to the user. For example,
612
613 self.runCmd(r'''sc print "\n\n\tHello!\n"''')
614
615 tests whether command abbreviation for 'script' works or not. There is no
616 need to show the 'Hello' output to the user as long as the 'script' command
617 succeeds and we are not in TraceOn() mode (see the '-t' option).
618
619 In this case, the test method calls self.HideStdout(self) to redirect the
620 sys.stdout to a null device, and restores the sys.stdout upon teardown.
621
622 Note that you should only call this method at most once during a test case
623 execution. Any subsequent call has no effect at all."""
624 if self.sys_stdout_hidden:
625 return
626
627 self.sys_stdout_hidden = True
628 old_stdout = sys.stdout
629 sys.stdout = open(os.devnull, 'w')
630 def restore_stdout():
631 sys.stdout = old_stdout
632 self.addTearDownHook(restore_stdout)
633
634 # =======================================================================
635 # Methods for customized teardown cleanups as well as execution of hooks.
636 # =======================================================================
637
638 def setTearDownCleanup(self, dictionary=None):
639 """Register a cleanup action at tearDown() time with a dictinary"""
640 self.dict = dictionary
641 self.doTearDownCleanup = True
642
643 def addTearDownCleanup(self, dictionary):
644 """Add a cleanup action at tearDown() time with a dictinary"""
645 self.dicts.append(dictionary)
646 self.doTearDownCleanups = True
647
648 def addTearDownHook(self, hook):
649 """
650 Add a function to be run during tearDown() time.
651
652 Hooks are executed in a first come first serve manner.
653 """
654 if callable(hook):
655 with recording(self, traceAlways) as sbuf:
656 print >> sbuf, "Adding tearDown hook:", getsource_if_available(hook)
657 self.hooks.append(hook)
658
659 def tearDown(self):
660 """Fixture for unittest test case teardown."""
661 #import traceback
662 #traceback.print_stack()
663
Johnny Chen71cb7972011-08-01 21:13:26 +0000664 # This is for the case of directly spawning 'lldb' and interacting with it
665 # using pexpect.
666 import pexpect
667 if self.child and self.child.isalive():
668 with recording(self, traceAlways) as sbuf:
669 print >> sbuf, "tearing down the child process...."
670 if self.child_in_script_interpreter:
671 self.child.sendline('quit()')
672 self.child.expect_exact(self.child_prompt)
673 self.child.sendline('quit')
674 try:
675 self.child.expect(pexpect.EOF)
676 except:
677 pass
Johnny Chenf0ff42a2012-02-27 23:07:40 +0000678 # Give it one final blow to make sure the child is terminated.
679 self.child.close()
Johnny Chen71cb7972011-08-01 21:13:26 +0000680
Johnny Chencbe51262011-08-01 19:50:58 +0000681 # Check and run any hook functions.
682 for hook in reversed(self.hooks):
683 with recording(self, traceAlways) as sbuf:
684 print >> sbuf, "Executing tearDown hook:", getsource_if_available(hook)
685 hook()
686
687 del self.hooks
688
689 # Perform registered teardown cleanup.
690 if doCleanup and self.doTearDownCleanup:
Johnny Chen028d8eb2011-11-17 19:57:27 +0000691 self.cleanup(dictionary=self.dict)
Johnny Chencbe51262011-08-01 19:50:58 +0000692
693 # In rare cases where there are multiple teardown cleanups added.
694 if doCleanup and self.doTearDownCleanups:
Johnny Chencbe51262011-08-01 19:50:58 +0000695 if self.dicts:
696 for dict in reversed(self.dicts):
Johnny Chen028d8eb2011-11-17 19:57:27 +0000697 self.cleanup(dictionary=dict)
Johnny Chencbe51262011-08-01 19:50:58 +0000698
699 # Decide whether to dump the session info.
700 self.dumpSessionInfo()
701
702 # =========================================================
703 # Various callbacks to allow introspection of test progress
704 # =========================================================
705
706 def markError(self):
707 """Callback invoked when an error (unexpected exception) errored."""
708 self.__errored__ = True
709 with recording(self, False) as sbuf:
710 # False because there's no need to write "ERROR" to the stderr twice.
711 # Once by the Python unittest framework, and a second time by us.
712 print >> sbuf, "ERROR"
713
714 def markFailure(self):
715 """Callback invoked when a failure (test assertion failure) occurred."""
716 self.__failed__ = True
717 with recording(self, False) as sbuf:
718 # False because there's no need to write "FAIL" to the stderr twice.
719 # Once by the Python unittest framework, and a second time by us.
720 print >> sbuf, "FAIL"
721
722 def markExpectedFailure(self):
723 """Callback invoked when an expected failure/error occurred."""
724 self.__expected__ = True
725 with recording(self, False) as sbuf:
726 # False because there's no need to write "expected failure" to the
727 # stderr twice.
728 # Once by the Python unittest framework, and a second time by us.
729 print >> sbuf, "expected failure"
730
Johnny Chenf5b89092011-08-15 23:09:08 +0000731 def markSkippedTest(self):
732 """Callback invoked when a test is skipped."""
733 self.__skipped__ = True
734 with recording(self, False) as sbuf:
735 # False because there's no need to write "skipped test" to the
736 # stderr twice.
737 # Once by the Python unittest framework, and a second time by us.
738 print >> sbuf, "skipped test"
739
Johnny Chencbe51262011-08-01 19:50:58 +0000740 def markUnexpectedSuccess(self):
741 """Callback invoked when an unexpected success occurred."""
742 self.__unexpected__ = True
743 with recording(self, False) as sbuf:
744 # False because there's no need to write "unexpected success" to the
745 # stderr twice.
746 # Once by the Python unittest framework, and a second time by us.
747 print >> sbuf, "unexpected success"
748
749 def dumpSessionInfo(self):
750 """
751 Dump the debugger interactions leading to a test error/failure. This
752 allows for more convenient postmortem analysis.
753
754 See also LLDBTestResult (dotest.py) which is a singlton class derived
755 from TextTestResult and overwrites addError, addFailure, and
756 addExpectedFailure methods to allow us to to mark the test instance as
757 such.
758 """
759
760 # We are here because self.tearDown() detected that this test instance
761 # either errored or failed. The lldb.test_result singleton contains
762 # two lists (erros and failures) which get populated by the unittest
763 # framework. Look over there for stack trace information.
764 #
765 # The lists contain 2-tuples of TestCase instances and strings holding
766 # formatted tracebacks.
767 #
768 # See http://docs.python.org/library/unittest.html#unittest.TestResult.
769 if self.__errored__:
770 pairs = lldb.test_result.errors
771 prefix = 'Error'
772 elif self.__failed__:
773 pairs = lldb.test_result.failures
774 prefix = 'Failure'
775 elif self.__expected__:
776 pairs = lldb.test_result.expectedFailures
777 prefix = 'ExpectedFailure'
Johnny Chenf5b89092011-08-15 23:09:08 +0000778 elif self.__skipped__:
779 prefix = 'SkippedTest'
Johnny Chencbe51262011-08-01 19:50:58 +0000780 elif self.__unexpected__:
781 prefix = "UnexpectedSuccess"
782 else:
783 # Simply return, there's no session info to dump!
784 return
785
Johnny Chenf5b89092011-08-15 23:09:08 +0000786 if not self.__unexpected__ and not self.__skipped__:
Johnny Chencbe51262011-08-01 19:50:58 +0000787 for test, traceback in pairs:
788 if test is self:
789 print >> self.session, traceback
790
Johnny Chen6fd55f12011-08-11 00:16:28 +0000791 testMethod = getattr(self, self._testMethodName)
792 if getattr(testMethod, "__benchmarks_test__", False):
793 benchmarks = True
794 else:
795 benchmarks = False
796
Johnny Chendfa0cdb2011-12-03 00:16:59 +0000797 # This records the compiler version used for the test.
798 system([self.getCompiler(), "-v"], sender=self)
799
Johnny Chencbe51262011-08-01 19:50:58 +0000800 dname = os.path.join(os.environ["LLDB_TEST"],
801 os.environ["LLDB_SESSION_DIRNAME"])
802 if not os.path.isdir(dname):
803 os.mkdir(dname)
Johnny Chenfb3c7752012-04-19 19:39:11 +0000804 fname = os.path.join(dname, "%s-%s-%s-%s.log" % (prefix, self.getArchitecture(), self.getCompiler(), self.id()))
Johnny Chencbe51262011-08-01 19:50:58 +0000805 with open(fname, "w") as f:
806 import datetime
807 print >> f, "Session info generated @", datetime.datetime.now().ctime()
808 print >> f, self.session.getvalue()
809 print >> f, "To rerun this test, issue the following command from the 'test' directory:\n"
Johnny Chen6fd55f12011-08-11 00:16:28 +0000810 print >> f, "./dotest.py %s -v %s -f %s.%s" % (self.getRunOptions(),
811 ('+b' if benchmarks else '-t'),
Johnny Chencbe51262011-08-01 19:50:58 +0000812 self.__class__.__name__,
813 self._testMethodName)
814
815 # ====================================================
816 # Config. methods supported through a plugin interface
817 # (enables reading of the current test configuration)
818 # ====================================================
819
820 def getArchitecture(self):
821 """Returns the architecture in effect the test suite is running with."""
822 module = builder_module()
823 return module.getArchitecture()
824
825 def getCompiler(self):
826 """Returns the compiler in effect the test suite is running with."""
827 module = builder_module()
828 return module.getCompiler()
829
830 def getRunOptions(self):
831 """Command line option for -A and -C to run this test again, called from
832 self.dumpSessionInfo()."""
833 arch = self.getArchitecture()
834 comp = self.getCompiler()
Johnny Chenb7058c52011-08-24 19:48:51 +0000835 if arch:
836 option_str = "-A " + arch
Johnny Chencbe51262011-08-01 19:50:58 +0000837 else:
Johnny Chenb7058c52011-08-24 19:48:51 +0000838 option_str = ""
839 if comp:
Johnny Chene1219bf2012-03-16 20:44:00 +0000840 option_str += " -C " + comp
Johnny Chenb7058c52011-08-24 19:48:51 +0000841 return option_str
Johnny Chencbe51262011-08-01 19:50:58 +0000842
843 # ==================================================
844 # Build methods supported through a plugin interface
845 # ==================================================
846
Johnny Chencbf15912012-02-01 01:49:50 +0000847 def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True):
Johnny Chencbe51262011-08-01 19:50:58 +0000848 """Platform specific way to build the default binaries."""
Johnny Chen028d8eb2011-11-17 19:57:27 +0000849 if lldb.skip_build_and_cleanup:
850 return
Johnny Chencbe51262011-08-01 19:50:58 +0000851 module = builder_module()
Johnny Chencbf15912012-02-01 01:49:50 +0000852 if not module.buildDefault(self, architecture, compiler, dictionary, clean):
Johnny Chencbe51262011-08-01 19:50:58 +0000853 raise Exception("Don't know how to build default binary")
854
Johnny Chencbf15912012-02-01 01:49:50 +0000855 def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True):
Johnny Chencbe51262011-08-01 19:50:58 +0000856 """Platform specific way to build binaries with dsym info."""
Johnny Chen028d8eb2011-11-17 19:57:27 +0000857 if lldb.skip_build_and_cleanup:
858 return
Johnny Chencbe51262011-08-01 19:50:58 +0000859 module = builder_module()
Johnny Chencbf15912012-02-01 01:49:50 +0000860 if not module.buildDsym(self, architecture, compiler, dictionary, clean):
Johnny Chencbe51262011-08-01 19:50:58 +0000861 raise Exception("Don't know how to build binary with dsym")
862
Johnny Chencbf15912012-02-01 01:49:50 +0000863 def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True):
Johnny Chencbe51262011-08-01 19:50:58 +0000864 """Platform specific way to build binaries with dwarf maps."""
Johnny Chen028d8eb2011-11-17 19:57:27 +0000865 if lldb.skip_build_and_cleanup:
866 return
Johnny Chencbe51262011-08-01 19:50:58 +0000867 module = builder_module()
Johnny Chencbf15912012-02-01 01:49:50 +0000868 if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
Johnny Chencbe51262011-08-01 19:50:58 +0000869 raise Exception("Don't know how to build binary with dwarf")
Johnny Chen366fb8c2011-08-01 18:46:13 +0000870
Johnny Chen7f9985a2011-08-12 20:19:22 +0000871 def cleanup(self, dictionary=None):
872 """Platform specific way to do cleanup after build."""
Johnny Chen028d8eb2011-11-17 19:57:27 +0000873 if lldb.skip_build_and_cleanup:
874 return
Johnny Chen7f9985a2011-08-12 20:19:22 +0000875 module = builder_module()
876 if not module.cleanup(self, dictionary):
Johnny Chen028d8eb2011-11-17 19:57:27 +0000877 raise Exception("Don't know how to do cleanup with dictionary: "+dictionary)
Johnny Chen7f9985a2011-08-12 20:19:22 +0000878
Johnny Chen366fb8c2011-08-01 18:46:13 +0000879
880class TestBase(Base):
881 """
882 This abstract base class is meant to be subclassed. It provides default
883 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
884 among other things.
885
886 Important things for test class writers:
887
888 - Overwrite the mydir class attribute, otherwise your test class won't
889 run. It specifies the relative directory to the top level 'test' so
890 the test harness can change to the correct working directory before
891 running your test.
892
893 - The setUp method sets up things to facilitate subsequent interactions
894 with the debugger as part of the test. These include:
895 - populate the test method name
896 - create/get a debugger set with synchronous mode (self.dbg)
897 - get the command interpreter from with the debugger (self.ci)
898 - create a result object for use with the command interpreter
899 (self.res)
900 - plus other stuffs
901
902 - The tearDown method tries to perform some necessary cleanup on behalf
903 of the test to return the debugger to a good state for the next test.
904 These include:
905 - execute any tearDown hooks registered by the test method with
906 TestBase.addTearDownHook(); examples can be found in
907 settings/TestSettings.py
908 - kill the inferior process associated with each target, if any,
909 and, then delete the target from the debugger's target list
910 - perform build cleanup before running the next test method in the
911 same test class; examples of registering for this service can be
912 found in types/TestIntegerTypes.py with the call:
913 - self.setTearDownCleanup(dictionary=d)
914
915 - Similarly setUpClass and tearDownClass perform classwise setup and
916 teardown fixtures. The tearDownClass method invokes a default build
917 cleanup for the entire test class; also, subclasses can implement the
918 classmethod classCleanup(cls) to perform special class cleanup action.
919
920 - The instance methods runCmd and expect are used heavily by existing
921 test cases to send a command to the command interpreter and to perform
922 string/pattern matching on the output of such command execution. The
923 expect method also provides a mode to peform string/pattern matching
924 without running a command.
925
926 - The build methods buildDefault, buildDsym, and buildDwarf are used to
927 build the binaries used during a particular test scenario. A plugin
928 should be provided for the sys.platform running the test suite. The
929 Mac OS X implementation is located in plugins/darwin.py.
930 """
931
932 # Maximum allowed attempts when launching the inferior process.
933 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
934 maxLaunchCount = 3;
935
936 # Time to wait before the next launching attempt in second(s).
937 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
938 timeWaitNextLaunch = 1.0;
939
940 def doDelay(self):
941 """See option -w of dotest.py."""
942 if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and
943 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'):
944 waitTime = 1.0
945 if "LLDB_TIME_WAIT_BETWEEN_TEST_CASES" in os.environ:
946 waitTime = float(os.environ["LLDB_TIME_WAIT_BETWEEN_TEST_CASES"])
947 time.sleep(waitTime)
948
949 def setUp(self):
950 #import traceback
951 #traceback.print_stack()
952
953 # Works with the test driver to conditionally skip tests via decorators.
954 Base.setUp(self)
955
Johnny Chen366fb8c2011-08-01 18:46:13 +0000956 try:
957 if lldb.blacklist:
958 className = self.__class__.__name__
959 classAndMethodName = "%s.%s" % (className, self._testMethodName)
960 if className in lldb.blacklist:
961 self.skipTest(lldb.blacklist.get(className))
962 elif classAndMethodName in lldb.blacklist:
963 self.skipTest(lldb.blacklist.get(classAndMethodName))
964 except AttributeError:
965 pass
966
Johnny Chen9a9fcf62011-06-21 00:53:00 +0000967 # Insert some delay between successive test cases if specified.
968 self.doDelay()
Johnny Chene47649c2010-10-07 02:04:14 +0000969
Johnny Chen65572482010-08-25 18:49:48 +0000970 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
971 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
972
Johnny Chend2965212010-10-19 16:00:42 +0000973 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
Johnny Chen458a67e2010-11-29 20:20:34 +0000974 self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
Johnny Chen65572482010-08-25 18:49:48 +0000975
Johnny Chena1affab2010-07-03 03:41:59 +0000976 # Create the debugger instance if necessary.
977 try:
978 self.dbg = lldb.DBG
Johnny Chena1affab2010-07-03 03:41:59 +0000979 except AttributeError:
980 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf8c723b2010-07-03 20:41:42 +0000981
Johnny Chen960ce122011-05-25 19:06:18 +0000982 if not self.dbg:
Johnny Chena1affab2010-07-03 03:41:59 +0000983 raise Exception('Invalid debugger instance')
984
985 # We want our debugger to be synchronous.
986 self.dbg.SetAsync(False)
987
988 # Retrieve the associated command interpreter instance.
989 self.ci = self.dbg.GetCommandInterpreter()
990 if not self.ci:
991 raise Exception('Could not get the command interpreter')
992
993 # And the result object.
994 self.res = lldb.SBCommandReturnObject()
995
Johnny Chenac97a6b2012-04-16 18:55:15 +0000996 # Run global pre-flight code, if defined via the config file.
997 if lldb.pre_flight:
998 lldb.pre_flight(self)
999
Johnny Chena1affab2010-07-03 03:41:59 +00001000 def tearDown(self):
Johnny Chen72a14342010-09-02 21:23:12 +00001001 #import traceback
1002 #traceback.print_stack()
1003
Johnny Chencbe51262011-08-01 19:50:58 +00001004 Base.tearDown(self)
Johnny Chen705737b2010-10-19 23:40:13 +00001005
Johnny Chen409646d2011-06-15 21:24:24 +00001006 # Delete the target(s) from the debugger as a general cleanup step.
1007 # This includes terminating the process for each target, if any.
1008 # We'd like to reuse the debugger for our next test without incurring
1009 # the initialization overhead.
1010 targets = []
1011 for target in self.dbg:
1012 if target:
1013 targets.append(target)
1014 process = target.GetProcess()
1015 if process:
1016 rc = self.invoke(process, "Kill")
1017 self.assertTrue(rc.Success(), PROCESS_KILLED)
1018 for target in targets:
1019 self.dbg.DeleteTarget(target)
Johnny Chenffde4fc2010-08-16 21:28:10 +00001020
Johnny Chenac97a6b2012-04-16 18:55:15 +00001021 # Run global post-flight code, if defined via the config file.
1022 if lldb.post_flight:
1023 lldb.post_flight(self)
1024
Johnny Chena1affab2010-07-03 03:41:59 +00001025 del self.dbg
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001026
Johnny Chen90c56e62011-09-30 21:48:35 +00001027 def switch_to_thread_with_stop_reason(self, stop_reason):
1028 """
1029 Run the 'thread list' command, and select the thread with stop reason as
1030 'stop_reason'. If no such thread exists, no select action is done.
1031 """
1032 from lldbutil import stop_reason_to_str
1033 self.runCmd('thread list')
1034 output = self.res.GetOutput()
1035 thread_line_pattern = re.compile("^[ *] thread #([0-9]+):.*stop reason = %s" %
1036 stop_reason_to_str(stop_reason))
1037 for line in output.splitlines():
1038 matched = thread_line_pattern.match(line)
1039 if matched:
1040 self.runCmd('thread select %s' % matched.group(1))
1041
Johnny Chenef6f4762011-06-15 21:38:39 +00001042 def runCmd(self, cmd, msg=None, check=True, trace=False):
Johnny Chen8df95eb2010-08-19 23:26:59 +00001043 """
1044 Ask the command interpreter to handle the command and then check its
1045 return status.
1046 """
1047 # Fail fast if 'cmd' is not meaningful.
1048 if not cmd or len(cmd) == 0:
1049 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen4f995f02010-08-20 17:57:32 +00001050
Johnny Chen9de4ede2010-08-31 17:42:54 +00001051 trace = (True if traceAlways else trace)
Johnny Chend0c24b22010-08-23 17:10:44 +00001052
Johnny Chen21f33412010-09-01 00:15:19 +00001053 running = (cmd.startswith("run") or cmd.startswith("process launch"))
Johnny Chen4f995f02010-08-20 17:57:32 +00001054
Johnny Chen21f33412010-09-01 00:15:19 +00001055 for i in range(self.maxLaunchCount if running else 1):
Johnny Chen65572482010-08-25 18:49:48 +00001056 self.ci.HandleCommand(cmd, self.res)
Johnny Chen4f995f02010-08-20 17:57:32 +00001057
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001058 with recording(self, trace) as sbuf:
1059 print >> sbuf, "runCmd:", cmd
Johnny Chen7c565c82010-10-15 16:13:00 +00001060 if not check:
Johnny Chen31cf8e22010-10-15 18:52:22 +00001061 print >> sbuf, "check of return status not required"
Johnny Chen65572482010-08-25 18:49:48 +00001062 if self.res.Succeeded():
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001063 print >> sbuf, "output:", self.res.GetOutput()
Johnny Chen65572482010-08-25 18:49:48 +00001064 else:
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001065 print >> sbuf, "runCmd failed!"
1066 print >> sbuf, self.res.GetError()
Johnny Chen4f995f02010-08-20 17:57:32 +00001067
Johnny Chen029acae2010-08-20 21:03:09 +00001068 if self.res.Succeeded():
Johnny Chen65572482010-08-25 18:49:48 +00001069 break
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001070 elif running:
Johnny Chendcb37222011-01-19 02:02:08 +00001071 # For process launch, wait some time before possible next try.
1072 time.sleep(self.timeWaitNextLaunch)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001073 with recording(self, True) as sbuf:
1074 print >> sbuf, "Command '" + cmd + "' failed!"
Johnny Chen4f995f02010-08-20 17:57:32 +00001075
Johnny Chen8df95eb2010-08-19 23:26:59 +00001076 if check:
1077 self.assertTrue(self.res.Succeeded(),
Johnny Chen05efcf782010-11-09 18:42:22 +00001078 msg if msg else CMD_MSG(cmd))
Johnny Chen8df95eb2010-08-19 23:26:59 +00001079
Johnny Chen90c56e62011-09-30 21:48:35 +00001080 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 +00001081 """
1082 Similar to runCmd; with additional expect style output matching ability.
1083
1084 Ask the command interpreter to handle the command and then check its
1085 return status. The 'msg' parameter specifies an informational assert
1086 message. We expect the output from running the command to start with
Johnny Chen2d899752010-09-21 21:08:53 +00001087 'startstr', matches the substrings contained in 'substrs', and regexp
1088 matches the patterns contained in 'patterns'.
Johnny Chen9792f8e2010-09-17 22:28:51 +00001089
1090 If the keyword argument error is set to True, it signifies that the API
1091 client is expecting the command to fail. In this case, the error stream
Johnny Chenee975b82010-09-17 22:45:27 +00001092 from running the command is retrieved and compared against the golden
Johnny Chen9792f8e2010-09-17 22:28:51 +00001093 input, instead.
Johnny Chen2d899752010-09-21 21:08:53 +00001094
1095 If the keyword argument matching is set to False, it signifies that the API
1096 client is expecting the output of the command not to match the golden
1097 input.
Johnny Chen8e06de92010-09-21 23:33:30 +00001098
1099 Finally, the required argument 'str' represents the lldb command to be
1100 sent to the command interpreter. In case the keyword argument 'exe' is
1101 set to False, the 'str' is treated as a string to be matched/not-matched
1102 against the golden input.
Johnny Chen8df95eb2010-08-19 23:26:59 +00001103 """
Johnny Chen9de4ede2010-08-31 17:42:54 +00001104 trace = (True if traceAlways else trace)
Johnny Chend0c24b22010-08-23 17:10:44 +00001105
Johnny Chen8e06de92010-09-21 23:33:30 +00001106 if exe:
1107 # First run the command. If we are expecting error, set check=False.
Johnny Chen60881f62010-10-28 21:10:32 +00001108 # Pass the assert message along since it provides more semantic info.
Johnny Chen05dd8932010-10-28 18:24:22 +00001109 self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error)
Johnny Chen8df95eb2010-08-19 23:26:59 +00001110
Johnny Chen8e06de92010-09-21 23:33:30 +00001111 # Then compare the output against expected strings.
1112 output = self.res.GetError() if error else self.res.GetOutput()
Johnny Chen9792f8e2010-09-17 22:28:51 +00001113
Johnny Chen8e06de92010-09-21 23:33:30 +00001114 # If error is True, the API client expects the command to fail!
1115 if error:
1116 self.assertFalse(self.res.Succeeded(),
1117 "Command '" + str + "' is expected to fail!")
1118 else:
1119 # No execution required, just compare str against the golden input.
1120 output = str
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001121 with recording(self, trace) as sbuf:
1122 print >> sbuf, "looking at:", output
Johnny Chen9792f8e2010-09-17 22:28:51 +00001123
Johnny Chen2d899752010-09-21 21:08:53 +00001124 # The heading says either "Expecting" or "Not expecting".
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001125 heading = "Expecting" if matching else "Not expecting"
Johnny Chen2d899752010-09-21 21:08:53 +00001126
1127 # Start from the startstr, if specified.
1128 # If there's no startstr, set the initial state appropriately.
1129 matched = output.startswith(startstr) if startstr else (True if matching else False)
Johnny Chenead35c82010-08-20 18:25:15 +00001130
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001131 if startstr:
1132 with recording(self, trace) as sbuf:
1133 print >> sbuf, "%s start string: %s" % (heading, startstr)
1134 print >> sbuf, "Matched" if matched else "Not matched"
Johnny Chenead35c82010-08-20 18:25:15 +00001135
Johnny Chen90c56e62011-09-30 21:48:35 +00001136 # Look for endstr, if specified.
1137 keepgoing = matched if matching else not matched
1138 if endstr:
1139 matched = output.endswith(endstr)
1140 with recording(self, trace) as sbuf:
1141 print >> sbuf, "%s end string: %s" % (heading, endstr)
1142 print >> sbuf, "Matched" if matched else "Not matched"
1143
Johnny Chen2d899752010-09-21 21:08:53 +00001144 # Look for sub strings, if specified.
1145 keepgoing = matched if matching else not matched
1146 if substrs and keepgoing:
Johnny Chen8df95eb2010-08-19 23:26:59 +00001147 for str in substrs:
Johnny Chen091bb1d2010-09-23 23:35:28 +00001148 matched = output.find(str) != -1
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001149 with recording(self, trace) as sbuf:
1150 print >> sbuf, "%s sub string: %s" % (heading, str)
1151 print >> sbuf, "Matched" if matched else "Not matched"
Johnny Chen2d899752010-09-21 21:08:53 +00001152 keepgoing = matched if matching else not matched
1153 if not keepgoing:
Johnny Chen8df95eb2010-08-19 23:26:59 +00001154 break
1155
Johnny Chen2d899752010-09-21 21:08:53 +00001156 # Search for regular expression patterns, if specified.
1157 keepgoing = matched if matching else not matched
1158 if patterns and keepgoing:
1159 for pattern in patterns:
1160 # Match Objects always have a boolean value of True.
1161 matched = bool(re.search(pattern, output))
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001162 with recording(self, trace) as sbuf:
1163 print >> sbuf, "%s pattern: %s" % (heading, pattern)
1164 print >> sbuf, "Matched" if matched else "Not matched"
Johnny Chen2d899752010-09-21 21:08:53 +00001165 keepgoing = matched if matching else not matched
1166 if not keepgoing:
1167 break
Johnny Chen2d899752010-09-21 21:08:53 +00001168
1169 self.assertTrue(matched if matching else not matched,
Johnny Chen05efcf782010-11-09 18:42:22 +00001170 msg if msg else EXP_MSG(str, exe))
Johnny Chen8df95eb2010-08-19 23:26:59 +00001171
Johnny Chena8b3cdd2010-08-25 22:52:45 +00001172 def invoke(self, obj, name, trace=False):
Johnny Chend8473bc2010-08-25 22:56:10 +00001173 """Use reflection to call a method dynamically with no argument."""
Johnny Chen9de4ede2010-08-31 17:42:54 +00001174 trace = (True if traceAlways else trace)
Johnny Chena8b3cdd2010-08-25 22:52:45 +00001175
1176 method = getattr(obj, name)
1177 import inspect
1178 self.assertTrue(inspect.ismethod(method),
1179 name + "is a method name of object: " + str(obj))
1180 result = method()
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001181 with recording(self, trace) as sbuf:
1182 print >> sbuf, str(method) + ":", result
Johnny Chena8b3cdd2010-08-25 22:52:45 +00001183 return result
Johnny Chen9c10c182010-08-27 00:15:48 +00001184
Johnny Chenb8770312011-05-27 23:36:52 +00001185 # =================================================
1186 # Misc. helper methods for debugging test execution
1187 # =================================================
1188
Johnny Chen57cd6dd2011-07-11 19:15:11 +00001189 def DebugSBValue(self, val):
Johnny Chen9de4ede2010-08-31 17:42:54 +00001190 """Debug print a SBValue object, if traceAlways is True."""
Johnny Chen47342d52011-04-27 17:43:07 +00001191 from lldbutil import value_type_to_str
Johnny Chen2c8d1592010-11-03 21:37:58 +00001192
Johnny Chen9de4ede2010-08-31 17:42:54 +00001193 if not traceAlways:
Johnny Chen9c10c182010-08-27 00:15:48 +00001194 return
1195
1196 err = sys.stderr
1197 err.write(val.GetName() + ":\n")
Johnny Chen90c56e62011-09-30 21:48:35 +00001198 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n')
1199 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n')
1200 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n')
1201 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n')
1202 err.write('\t' + "ValueAsUnsigned -> " + str(val.GetValueAsUnsigned())+ '\n')
1203 err.write('\t' + "ValueType -> " + value_type_to_str(val.GetValueType()) + '\n')
1204 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n')
1205 err.write('\t' + "IsPointerType -> " + str(val.TypeIsPointerType()) + '\n')
1206 err.write('\t' + "Location -> " + val.GetLocation() + '\n')
Johnny Chen9c10c182010-08-27 00:15:48 +00001207
Johnny Chend7e04d92011-08-05 20:17:27 +00001208 def DebugSBType(self, type):
1209 """Debug print a SBType object, if traceAlways is True."""
1210 if not traceAlways:
1211 return
1212
1213 err = sys.stderr
1214 err.write(type.GetName() + ":\n")
1215 err.write('\t' + "ByteSize -> " + str(type.GetByteSize()) + '\n')
1216 err.write('\t' + "IsPointerType -> " + str(type.IsPointerType()) + '\n')
1217 err.write('\t' + "IsReferenceType -> " + str(type.IsReferenceType()) + '\n')
1218
Johnny Chen73041472011-03-12 01:18:19 +00001219 def DebugPExpect(self, child):
1220 """Debug the spwaned pexpect object."""
1221 if not traceAlways:
1222 return
1223
1224 print child