Add the capability of supplying the pre/post-flight functions to the test suite such...
[lldb.git] / lldb / test / lldbtest.py
1 """
2 LLDB module which provides the abstract base class of lldb test case.
3
4 The concrete subclass can override lldbtest.TesBase in order to inherit the
5 common behavior for unitest.TestCase.setUp/tearDown implemented in this file.
6
7 The subclass should override the attribute mydir in order for the python runtime
8 to locate the individual test cases when running as part of a large test suite
9 or 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
12 entire test suite.  Users who want to run a test case on its own can specify the
13 LLDB_TEST and PYTHONPATH environment variables, for example:
14
15 $ export LLDB_TEST=$PWD
16 $ export PYTHONPATH=/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:$LLDB_TEST:$LLDB_TEST/plugins:$LLDB_TEST/pexpect-2.4
17 $ echo $LLDB_TEST
18 /Volumes/data/lldb/svn/trunk/test
19 $ echo $PYTHONPATH
20 /Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:/Volumes/data/lldb/svn/trunk/test:/Volumes/data/lldb/svn/trunk/test/plugins
21 $ python function_types/TestFunctionTypes.py
22 .
23 ----------------------------------------------------------------------
24 Ran 1 test in 0.363s
25
26 OK
27 $ LLDB_COMMAND_TRACE=YES python array_types/TestArrayTypes.py
28
29 ...
30
31 runCmd: breakpoint set -f main.c -l 42
32 output: Breakpoint created: 1: file ='main.c', line = 42, locations = 1
33
34 runCmd: run
35 output: Launching '/Volumes/data/lldb/svn/trunk/test/array_types/a.out'  (x86_64)
36
37 ...
38
39 runCmd: frame variable strings
40 output: (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
47 runCmd: frame variable char_16
48 output: (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
67 runCmd: frame variable ushort_matrix
68 output: (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
81 runCmd: frame variable long_6
82 output: (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 ----------------------------------------------------------------------
93 Ran 1 test in 0.349s
94
95 OK
96
97 """
98
99 import os, sys, traceback
100 import re
101 from subprocess import *
102 import StringIO
103 import time
104 import types
105 import unittest2
106 import lldb
107
108 # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
109 # LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options.
110
111 # By default, traceAlways is False.
112 if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
113     traceAlways = True
114 else:
115     traceAlways = False
116
117 # By default, doCleanup is True.
118 if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO":
119     doCleanup = False
120 else:
121     doCleanup = True
122
123
124 #
125 # Some commonly used assert messages.
126 #
127
128 COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
129
130 CURRENT_EXECUTABLE_SET = "Current executable set successfully"
131
132 PROCESS_IS_VALID = "Process is valid"
133
134 PROCESS_KILLED = "Process is killed successfully"
135
136 PROCESS_EXITED = "Process exited successfully"
137
138 PROCESS_STOPPED = "Process status should be stopped"
139
140 RUN_SUCCEEDED = "Process is launched successfully"
141
142 RUN_COMPLETED = "Process exited successfully"
143
144 BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
145
146 BREAKPOINT_CREATED = "Breakpoint created successfully"
147
148 BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
149
150 BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
151
152 BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
153
154 BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2"
155
156 BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3"
157
158 OBJECT_PRINTED_CORRECTLY = "Object printed correctly"
159
160 SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
161
162 STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
163
164 STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
165
166 STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
167
168 STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
169     STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'")
170
171 STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
172
173 STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
174
175 STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
176
177 STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
178
179 STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
180
181 DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
182
183 VALID_BREAKPOINT = "Got a valid breakpoint"
184
185 VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
186
187 VALID_COMMAND_INTERPRETER = "Got a valid command interpreter"
188
189 VALID_FILESPEC = "Got a valid filespec"
190
191 VALID_MODULE = "Got a valid module"
192
193 VALID_PROCESS = "Got a valid process"
194
195 VALID_SYMBOL = "Got a valid symbol"
196
197 VALID_TARGET = "Got a valid target"
198
199 VALID_TYPE = "Got a valid type"
200
201 VALID_VARIABLE = "Got a valid variable"
202
203 VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
204
205 WATCHPOINT_CREATED = "Watchpoint created successfully"
206
207 def CMD_MSG(str):
208     '''A generic "Command '%s' returns successfully" message generator.'''
209     return "Command '%s' returns successfully" % str
210
211 def COMPLETION_MSG(str_before, str_after):
212     '''A generic message generator for the completion mechanism.'''
213     return "'%s' successfully completes to '%s'" % (str_before, str_after)
214
215 def EXP_MSG(str, exe):
216     '''A generic "'%s' returns expected result" message generator if exe.
217     Otherwise, it generates "'%s' matches expected result" message.'''
218     return "'%s' %s expected result" % (str, 'returns' if exe else 'matches')
219
220 def SETTING_MSG(setting):
221     '''A generic "Value of setting '%s' is correct" message generator.'''
222     return "Value of setting '%s' is correct" % setting
223
224 def EnvArray():
225     """Returns an env variable array from the os.environ map object."""
226     return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
227
228 def 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.
234                 return i+1
235     raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename))
236
237 def 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
243 def 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
247 def 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
260 class 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):
267         """Create a StringIO instance; record the session obj and trace flag."""
268         StringIO.StringIO.__init__(self)
269         # The test might not have undergone the 'setUp(self)' phase yet, so that
270         # the attribute 'session' might not even exist yet.
271         self.session = getattr(test, "session", None) if test else None
272         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:
288             print >> sys.stderr, self.getvalue()
289         if self.session:
290             print >> self.session, self.getvalue()
291         self.close()
292
293 # From 2.7's subprocess.check_output() convenience function.
294 # Return a tuple (stdoutdata, stderrdata).
295 def system(*popenargs, **kwargs):
296     r"""Run an os command with arguments and return its output as a byte string.
297
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.')
321     process = Popen(stdout=PIPE, stderr=PIPE, *popenargs, **kwargs)
322     pid = process.pid
323     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
333         print >> sbuf, "with pid:", pid
334         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)
344     return (output, error)
345
346 def 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
357 def builder_module():
358     return __import__("builder_" + sys.platform)
359
360 #
361 # Decorators for categorizing test cases.
362 #
363
364 from functools import wraps
365 def 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
382 def 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
399 def 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
416 def 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
433 def 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)
444         except Exception:
445             if "clang" in compiler:
446                 raise case._ExpectedFailure(sys.exc_info())
447             else:
448                 raise
449
450         if "clang" in compiler:
451             raise case._UnexpectedSuccess
452     return wrapper
453
454 def 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
475 class Base(unittest2.TestCase):
476     """
477     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     
481     """
482     # The concrete subclass should override this attribute.
483     mydir = None
484
485     # Keep track of the old current working directory.
486     oldcwd = None
487
488     def TraceOn(self):
489         """Returns True if we are in trace mode (tracing detailed test execution)."""
490         return traceAlways
491
492     @classmethod
493     def setUpClass(cls):
494         """
495         Python unittest framework class setup fixture.
496         Do current directory manipulation.
497         """
498
499         # Fail fast if 'mydir' attribute is not overridden.
500         if not cls.mydir or len(cls.mydir) == 0:
501             raise Exception("Subclasses must override the 'mydir' attribute.")
502         # Save old working directory.
503         cls.oldcwd = os.getcwd()
504
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):
508             if traceAlways:
509                 print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
510             os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
511
512     @classmethod
513     def tearDownClass(cls):
514         """
515         Python unittest framework class teardown fixture.
516         Do class-wide cleanup.
517         """
518
519         if doCleanup and not lldb.skip_build_and_cleanup:
520             # First, let's do the platform-specific cleanup.
521             module = builder_module()
522             if not module.cleanup():
523                 raise Exception("Don't know how to do cleanup")
524
525             # 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)
534
535         # Restore old working directory.
536         if traceAlways:
537             print >> sys.stderr, "Restore dir to:", cls.oldcwd
538         os.chdir(cls.oldcwd)
539
540     @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
550
551     def setUp(self):
552         """Fixture for unittest test case setup.
553
554         It works with the test driver to conditionally skip tests and does other
555         initializations."""
556         #import traceback
557         #traceback.print_stack()
558
559         if "LLDB_EXEC" in os.environ:
560             self.lldbExec = os.environ["LLDB_EXEC"]
561         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
567         # 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"
573
574         # 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
582         # 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.
585         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:
591                     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")
605         except AttributeError:
606             pass
607
608         # 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
618         # 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
638         # And skipped tests.
639         self.__skipped__ = False
640
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
648     def runHooks(self, child=None, child_prompt=None, use_cmd_api=False):
649         """Perform the run hooks to bring lldb debugger to the desired state.
650
651         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
655         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")
662         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)
671
672     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
729         # 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
743             # Give it one final blow to make sure the child is terminated.
744             self.child.close()
745
746         # 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:
756             self.cleanup(dictionary=self.dict)
757
758         # In rare cases where there are multiple teardown cleanups added.
759         if doCleanup and self.doTearDownCleanups:
760             if self.dicts:
761                 for dict in reversed(self.dicts):
762                     self.cleanup(dictionary=dict)
763
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
796     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
805     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'
843         elif self.__skipped__:
844             prefix = 'SkippedTest'
845         elif self.__unexpected__:
846             prefix = "UnexpectedSuccess"
847         else:
848             # Simply return, there's no session info to dump!
849             return
850
851         if not self.__unexpected__ and not self.__skipped__:
852             for test, traceback in pairs:
853                 if test is self:
854                     print >> self.session, traceback
855
856         testMethod = getattr(self, self._testMethodName)
857         if getattr(testMethod, "__benchmarks_test__", False):
858             benchmarks = True
859         else:
860             benchmarks = False
861
862         # This records the compiler version used for the test.
863         system([self.getCompiler(), "-v"], sender=self)
864
865         dname = os.path.join(os.environ["LLDB_TEST"],
866                              os.environ["LLDB_SESSION_DIRNAME"])
867         if not os.path.isdir(dname):
868             os.mkdir(dname)
869         fname = os.path.join(dname, "%s-%s.log" % (prefix, self.id()))
870         with open(fname, "w") as f:
871             import datetime
872             print >> f, "Session info generated @", datetime.datetime.now().ctime()
873             print >> f, self.session.getvalue()
874             print >> f, "To rerun this test, issue the following command from the 'test' directory:\n"
875             print >> f, "./dotest.py %s -v %s -f %s.%s" % (self.getRunOptions(),
876                                                            ('+b' if benchmarks else '-t'),
877                                                            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()
900         if arch:
901             option_str = "-A " + arch
902         else:
903             option_str = ""
904         if comp:
905             option_str += " -C " + comp
906         return option_str
907
908     # ==================================================
909     # Build methods supported through a plugin interface
910     # ==================================================
911
912     def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True):
913         """Platform specific way to build the default binaries."""
914         if lldb.skip_build_and_cleanup:
915             return
916         module = builder_module()
917         if not module.buildDefault(self, architecture, compiler, dictionary, clean):
918             raise Exception("Don't know how to build default binary")
919
920     def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True):
921         """Platform specific way to build binaries with dsym info."""
922         if lldb.skip_build_and_cleanup:
923             return
924         module = builder_module()
925         if not module.buildDsym(self, architecture, compiler, dictionary, clean):
926             raise Exception("Don't know how to build binary with dsym")
927
928     def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True):
929         """Platform specific way to build binaries with dwarf maps."""
930         if lldb.skip_build_and_cleanup:
931             return
932         module = builder_module()
933         if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
934             raise Exception("Don't know how to build binary with dwarf")
935
936     def cleanup(self, dictionary=None):
937         """Platform specific way to do cleanup after build."""
938         if lldb.skip_build_and_cleanup:
939             return
940         module = builder_module()
941         if not module.cleanup(self, dictionary):
942             raise Exception("Don't know how to do cleanup with dictionary: "+dictionary)
943
944
945 class 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
1021         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
1032         # Insert some delay between successive test cases if specified.
1033         self.doDelay()
1034
1035         if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
1036             self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
1037
1038         if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
1039             self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
1040
1041         # Create the debugger instance if necessary.
1042         try:
1043             self.dbg = lldb.DBG
1044         except AttributeError:
1045             self.dbg = lldb.SBDebugger.Create()
1046
1047         if not self.dbg:
1048             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
1061         # Run global pre-flight code, if defined via the config file.
1062         if lldb.pre_flight:
1063             lldb.pre_flight(self)
1064
1065     def tearDown(self):
1066         #import traceback
1067         #traceback.print_stack()
1068
1069         Base.tearDown(self)
1070
1071         # 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)
1085
1086         # Run global post-flight code, if defined via the config file.
1087         if lldb.post_flight:
1088             lldb.post_flight(self)
1089
1090         del self.dbg
1091
1092     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
1107     def runCmd(self, cmd, msg=None, check=True, trace=False):
1108         """
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")
1115
1116         trace = (True if traceAlways else trace)
1117
1118         running = (cmd.startswith("run") or cmd.startswith("process launch"))
1119
1120         for i in range(self.maxLaunchCount if running else 1):
1121             self.ci.HandleCommand(cmd, self.res)
1122
1123             with recording(self, trace) as sbuf:
1124                 print >> sbuf, "runCmd:", cmd
1125                 if not check:
1126                     print >> sbuf, "check of return status not required"
1127                 if self.res.Succeeded():
1128                     print >> sbuf, "output:", self.res.GetOutput()
1129                 else:
1130                     print >> sbuf, "runCmd failed!"
1131                     print >> sbuf, self.res.GetError()
1132
1133             if self.res.Succeeded():
1134                 break
1135             elif running:
1136                 # For process launch, wait some time before possible next try.
1137                 time.sleep(self.timeWaitNextLaunch)
1138                 with recording(self, True) as sbuf:
1139                     print >> sbuf, "Command '" + cmd + "' failed!"
1140
1141         if check:
1142             self.assertTrue(self.res.Succeeded(),
1143                             msg if msg else CMD_MSG(cmd))
1144
1145     def expect(self, str, msg=None, patterns=None, startstr=None, endstr=None, substrs=None, trace=False, error=False, matching=True, exe=True):
1146         """
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
1152         'startstr', matches the substrings contained in 'substrs', and regexp
1153         matches the patterns contained in 'patterns'.
1154
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
1157         from running the command is retrieved and compared against the golden
1158         input, instead.
1159
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.
1163
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.
1168         """
1169         trace = (True if traceAlways else trace)
1170
1171         if exe:
1172             # First run the command.  If we are expecting error, set check=False.
1173             # Pass the assert message along since it provides more semantic info.
1174             self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error)
1175
1176             # Then compare the output against expected strings.
1177             output = self.res.GetError() if error else self.res.GetOutput()
1178
1179             # 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
1186             with recording(self, trace) as sbuf:
1187                 print >> sbuf, "looking at:", output
1188
1189         # The heading says either "Expecting" or "Not expecting".
1190         heading = "Expecting" if matching else "Not expecting"
1191
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)
1195
1196         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"
1200
1201         # 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
1209         # Look for sub strings, if specified.
1210         keepgoing = matched if matching else not matched
1211         if substrs and keepgoing:
1212             for str in substrs:
1213                 matched = output.find(str) != -1
1214                 with recording(self, trace) as sbuf:
1215                     print >> sbuf, "%s sub string: %s" % (heading, str)
1216                     print >> sbuf, "Matched" if matched else "Not matched"
1217                 keepgoing = matched if matching else not matched
1218                 if not keepgoing:
1219                     break
1220
1221         # 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))
1227                 with recording(self, trace) as sbuf:
1228                     print >> sbuf, "%s pattern: %s" % (heading, pattern)
1229                     print >> sbuf, "Matched" if matched else "Not matched"
1230                 keepgoing = matched if matching else not matched
1231                 if not keepgoing:
1232                     break
1233
1234         self.assertTrue(matched if matching else not matched,
1235                         msg if msg else EXP_MSG(str, exe))
1236
1237     def invoke(self, obj, name, trace=False):
1238         """Use reflection to call a method dynamically with no argument."""
1239         trace = (True if traceAlways else trace)
1240         
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()
1246         with recording(self, trace) as sbuf:
1247             print >> sbuf, str(method) + ":",  result
1248         return result
1249
1250     # =================================================
1251     # Misc. helper methods for debugging test execution
1252     # =================================================
1253
1254     def DebugSBValue(self, val):
1255         """Debug print a SBValue object, if traceAlways is True."""
1256         from lldbutil import value_type_to_str
1257
1258         if not traceAlways:
1259             return
1260
1261         err = sys.stderr
1262         err.write(val.GetName() + ":\n")
1263         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')
1272
1273     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
1284     def DebugPExpect(self, child):
1285         """Debug the spwaned pexpect object."""
1286         if not traceAlways:
1287             return
1288
1289         print child