lldbtest.py revision 058a24d100f6d1da87c06af25ef9102018859a30
1"""
2LLDB module which provides the abstract base class of lldb test case.
3
4The concrete subclass can override lldbtest.TesBase in order to inherit the
5common behavior for unitest.TestCase.setUp/tearDown implemented in this file.
6
7The subclass should override the attribute mydir in order for the python runtime
8to locate the individual test cases when running as part of a large test suite
9or when running each test case as a separate python invocation.
10
11./dotest.py provides a test driver which sets up the environment to run the
12entire test suite.  Users who want to run a test case on its own can specify the
13LLDB_TEST and PYTHONPATH environment variables, for example:
14
15$ export LLDB_TEST=$PWD
16$ export PYTHONPATH=/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:$LLDB_TEST:$LLDB_TEST/plugins
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----------------------------------------------------------------------
24Ran 1 test in 0.363s
25
26OK
27$ LLDB_COMMAND_TRACE=YES python array_types/TestArrayTypes.py
28
29...
30
31runCmd: breakpoint set -f main.c -l 42
32output: Breakpoint created: 1: file ='main.c', line = 42, locations = 1
33
34runCmd: run
35output: Launching '/Volumes/data/lldb/svn/trunk/test/array_types/a.out'  (x86_64)
36
37...
38
39runCmd: frame variable strings
40output: (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
47runCmd: frame variable char_16
48output: (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
67runCmd: frame variable ushort_matrix
68output: (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
81runCmd: frame variable long_6
82output: (long [6]) long_6 = {
83  (long) long_6[0] = 1,
84  (long) long_6[1] = 2,
85  (long) long_6[2] = 3,
86  (long) long_6[3] = 4,
87  (long) long_6[4] = 5,
88  (long) long_6[5] = 6
89}
90
91.
92----------------------------------------------------------------------
93Ran 1 test in 0.349s
94
95OK
96$
97"""
98
99import os, sys, traceback
100import re
101from subprocess import *
102import StringIO
103import time
104import types
105import unittest2
106import 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.
112if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
113    traceAlways = True
114else:
115    traceAlways = False
116
117# By default, doCleanup is True.
118if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO":
119    doCleanup = False
120else:
121    doCleanup = True
122
123
124#
125# Some commonly used assert messages.
126#
127
128COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
129
130CURRENT_EXECUTABLE_SET = "Current executable set successfully"
131
132PROCESS_IS_VALID = "Process is valid"
133
134PROCESS_KILLED = "Process is killed successfully"
135
136PROCESS_EXITED = "Process exited successfully"
137
138PROCESS_STOPPED = "Process status should be stopped"
139
140RUN_SUCCEEDED = "Process is launched successfully"
141
142RUN_COMPLETED = "Process exited successfully"
143
144BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
145
146BREAKPOINT_CREATED = "Breakpoint created successfully"
147
148BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
149
150BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
151
152BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
153
154BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2"
155
156BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3"
157
158SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
159
160STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
161
162STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
163
164STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
165
166STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
167    STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'")
168
169STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
170
171STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
172
173STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
174
175STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
176
177DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
178
179VALID_BREAKPOINT = "Got a valid breakpoint"
180
181VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
182
183VALID_FILESPEC = "Got a valid filespec"
184
185VALID_MODULE = "Got a valid module"
186
187VALID_PROCESS = "Got a valid process"
188
189VALID_SYMBOL = "Got a valid symbol"
190
191VALID_TARGET = "Got a valid target"
192
193VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
194
195
196#
197# And a generic "Command '%s' returns successfully" message generator.
198#
199def CMD_MSG(str):
200    return "Command '%s' returns successfully" % str
201
202#
203# And a generic "'%s' returns expected result" message generator if exe.
204# Otherwise, it's "'%s' matches expected result"
205#
206def EXP_MSG(str, exe):
207    return "'%s' %s expected result" % (str, 'returns' if exe else 'matches')
208
209#
210# And a generic "Value of setting '%s' is correct" message generator.
211#
212def SETTING_MSG(setting):
213    return "Value of setting '%s' is correct" % setting
214
215#
216# Returns an env variable array from the os.environ map object.
217#
218def EnvArray():
219    return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
220
221def line_number(filename, string_to_match):
222    """Helper function to return the line number of the first matched string."""
223    with open(filename, 'r') as f:
224        for i, line in enumerate(f):
225            if line.find(string_to_match) != -1:
226                # Found our match.
227                return i+1
228    raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename))
229
230def pointer_size():
231    """Return the pointer size of the host system."""
232    import ctypes
233    a_pointer = ctypes.c_void_p(0xffff)
234    return 8 * ctypes.sizeof(a_pointer)
235
236from functools import wraps
237def python_api_test(func):
238    """Decorate the item as a Python API only test."""
239    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
240        raise Exception("@python_api_test can only be used to decorate a test method")
241    @wraps(func)
242    def wrapper(self, *args, **kwargs):
243        if lldb.dont_do_python_api_test:
244            self.skipTest("Skip Python API tests")
245        return func(self, *args, **kwargs)
246
247    # Mark this function as such to separate them from lldb command line tests.
248    wrapper.__python_api_test__ = True
249    return wrapper
250
251class recording(StringIO.StringIO):
252    """
253    A nice little context manager for recording the debugger interactions into
254    our session object.  If trace flag is ON, it also emits the interactions
255    into the stderr.
256    """
257    def __init__(self, test, trace):
258        """Create a StringIO instance; record the session obj and trace flag."""
259        StringIO.StringIO.__init__(self)
260        self.session = test.session if test else None
261        self.trace = trace
262
263    def __enter__(self):
264        """
265        Context management protocol on entry to the body of the with statement.
266        Just return the StringIO object.
267        """
268        return self
269
270    def __exit__(self, type, value, tb):
271        """
272        Context management protocol on exit from the body of the with statement.
273        If trace is ON, it emits the recordings into stderr.  Always add the
274        recordings to our session object.  And close the StringIO object, too.
275        """
276        if self.trace:
277            print >> sys.stderr, self.getvalue()
278        if self.session:
279            print >> self.session, self.getvalue()
280        self.close()
281
282# From 2.7's subprocess.check_output() convenience function.
283# Return a tuple (stdoutdata, stderrdata).
284def system(*popenargs, **kwargs):
285    r"""Run command with arguments and return its output as a byte string.
286
287    If the exit code was non-zero it raises a CalledProcessError.  The
288    CalledProcessError object will have the return code in the returncode
289    attribute and output in the output attribute.
290
291    The arguments are the same as for the Popen constructor.  Example:
292
293    >>> check_output(["ls", "-l", "/dev/null"])
294    'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'
295
296    The stdout argument is not allowed as it is used internally.
297    To capture standard error in the result, use stderr=STDOUT.
298
299    >>> check_output(["/bin/sh", "-c",
300    ...               "ls -l non_existent_file ; exit 0"],
301    ...              stderr=STDOUT)
302    'ls: non_existent_file: No such file or directory\n'
303    """
304
305    # Assign the sender object to variable 'test' and remove it from kwargs.
306    test = kwargs.pop('sender', None)
307
308    if 'stdout' in kwargs:
309        raise ValueError('stdout argument not allowed, it will be overridden.')
310    process = Popen(stdout=PIPE, stderr=PIPE, *popenargs, **kwargs)
311    output, error = process.communicate()
312    retcode = process.poll()
313
314    with recording(test, traceAlways) as sbuf:
315        if isinstance(popenargs, types.StringTypes):
316            args = [popenargs]
317        else:
318            args = list(popenargs)
319        print >> sbuf
320        print >> sbuf, "os command:", args
321        print >> sbuf, "stdout:", output
322        print >> sbuf, "stderr:", error
323        print >> sbuf, "retcode:", retcode
324        print >> sbuf
325
326    if retcode:
327        cmd = kwargs.get("args")
328        if cmd is None:
329            cmd = popenargs[0]
330        raise CalledProcessError(retcode, cmd)
331    return (output, error)
332
333def getsource_if_available(obj):
334    """
335    Return the text of the source code for an object if available.  Otherwise,
336    a print representation is returned.
337    """
338    import inspect
339    try:
340        return inspect.getsource(obj)
341    except:
342        return repr(obj)
343
344class TestBase(unittest2.TestCase):
345    """
346    This abstract base class is meant to be subclassed.  It provides default
347    implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
348    among other things.
349
350    Important things for test class writers:
351
352        - Overwrite the mydir class attribute, otherwise your test class won't
353          run.  It specifies the relative directory to the top level 'test' so
354          the test harness can change to the correct working directory before
355          running your test.
356
357        - The setUp method sets up things to facilitate subsequent interactions
358          with the debugger as part of the test.  These include:
359              - create/get a debugger set with synchronous mode (self.dbg)
360              - get the command interpreter from with the debugger (self.ci)
361              - create a result object for use with the command interpreter
362                (self.result)
363              - plus other stuffs
364
365        - The tearDown method tries to perform some necessary cleanup on behalf
366          of the test to return the debugger to a good state for the next test.
367          These include:
368              - execute any tearDown hooks registered by the test method with
369                TestBase.addTearDownHook(); examples can be found in
370                settings/TestSettings.py
371              - kill the inferior process launched during the test method
372                    - if by 'run' or 'process launch' command, 'process kill'
373                      command is used
374                    - if the test method uses LLDB Python API to launch process,
375                      it should assign the process object to self.process; that
376                      way, tearDown will use self.process.Kill() on the object
377              - perform build cleanup before running the next test method in the
378                same test class; examples of registering for this service can be
379                found in types/TestIntegerTypes.py with the call:
380                    - self.setTearDownCleanup(dictionary=d)
381
382        - Similarly setUpClass and tearDownClass perform classwise setup and
383          teardown fixtures.  The tearDownClass method invokes a default build
384          cleanup for the entire test class;  also, subclasses can implement the
385          classmethod classCleanup(cls) to perform special class cleanup action.
386
387        - The instance methods runCmd and expect are used heavily by existing
388          test cases to send a command to the command interpreter and to perform
389          string/pattern matching on the output of such command execution.  The
390          expect method also provides a mode to peform string/pattern matching
391          without running a command.
392
393        - The build methods buildDefault, buildDsym, and buildDwarf are used to
394          build the binaries used during a particular test scenario.  A plugin
395          should be provided for the sys.platform running the test suite.  The
396          Mac OS X implementation is located in plugins/darwin.py.
397
398    """
399
400    @classmethod
401    def skipLongRunningTest(cls):
402        """
403        By default, we skip long running test case.
404        This can be overridden by passing '-l' to the test driver (dotest.py).
405        """
406        if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]:
407            return False
408        else:
409            return True
410
411    # The concrete subclass should override this attribute.
412    mydir = None
413
414    # State pertaining to the inferior process, if any.
415    # This reflects inferior process started through the command interface with
416    # either the lldb "run" or "process launch" command.
417    # See also self.runCmd().
418    runStarted = False
419
420    # Maximum allowed attempts when launching the inferior process.
421    # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
422    maxLaunchCount = 3;
423
424    # Time to wait before the next launching attempt in second(s).
425    # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
426    timeWaitNextLaunch = 1.0;
427
428    # Keep track of the old current working directory.
429    oldcwd = None
430
431    @classmethod
432    def setUpClass(cls):
433        """
434        Python unittest framework class setup fixture.
435        Do current directory manipulation.
436        """
437
438        # Fail fast if 'mydir' attribute is not overridden.
439        if not cls.mydir or len(cls.mydir) == 0:
440            raise Exception("Subclasses must override the 'mydir' attribute.")
441        # Save old working directory.
442        cls.oldcwd = os.getcwd()
443
444        # Change current working directory if ${LLDB_TEST} is defined.
445        # See also dotest.py which sets up ${LLDB_TEST}.
446        if ("LLDB_TEST" in os.environ):
447            if traceAlways:
448                print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
449            os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
450
451    @classmethod
452    def tearDownClass(cls):
453        """
454        Python unittest framework class teardown fixture.
455        Do class-wide cleanup.
456        """
457
458        if doCleanup:
459            # First, let's do the platform-specific cleanup.
460            module = __import__(sys.platform)
461            if not module.cleanup():
462                raise Exception("Don't know how to do cleanup")
463
464            # Subclass might have specific cleanup function defined.
465            if getattr(cls, "classCleanup", None):
466                if traceAlways:
467                    print >> sys.stderr, "Call class-specific cleanup function for class:", cls
468                try:
469                    cls.classCleanup()
470                except:
471                    exc_type, exc_value, exc_tb = sys.exc_info()
472                    traceback.print_exception(exc_type, exc_value, exc_tb)
473
474        # Restore old working directory.
475        if traceAlways:
476            print >> sys.stderr, "Restore dir to:", cls.oldcwd
477        os.chdir(cls.oldcwd)
478
479    def setUp(self):
480        #import traceback
481        #traceback.print_stack()
482
483        if "LLDB_EXEC" in os.environ:
484            self.lldbExec = os.environ["LLDB_EXEC"]
485
486        if lldb.blacklist:
487            className = self.__class__.__name__
488            classAndMethodName = "%s.%s" % (className, self._testMethodName)
489            if className in lldb.blacklist:
490                self.skipTest(lldb.blacklist.get(className))
491            elif classAndMethodName in lldb.blacklist:
492                self.skipTest(lldb.blacklist.get(classAndMethodName))
493
494        # Python API only test is decorated with @python_api_test,
495        # which also sets the "__python_api_test__" attribute of the
496        # function object to True.
497        if lldb.just_do_python_api_test:
498            testMethod = getattr(self, self._testMethodName)
499            if getattr(testMethod, "__python_api_test__", False):
500                pass
501            else:
502                self.skipTest("Skip lldb command line test")
503
504        if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and
505            os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'):
506            waitTime = 1.0
507            if "LLDB_TIME_WAIT_BETWEEN_TEST_CASES" in os.environ:
508                waitTime = float(os.environ["LLDB_TIME_WAIT_BETWEEN_TEST_CASES"])
509            time.sleep(waitTime)
510
511        if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
512            self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
513
514        if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
515            self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
516
517        # Create the debugger instance if necessary.
518        try:
519            self.dbg = lldb.DBG
520        except AttributeError:
521            self.dbg = lldb.SBDebugger.Create()
522
523        if not self.dbg.IsValid():
524            raise Exception('Invalid debugger instance')
525
526        # We want our debugger to be synchronous.
527        self.dbg.SetAsync(False)
528
529        # This is for the case of directly spawning 'lldb' and interacting with it
530        # using pexpect.
531        self.child = None
532        self.child_in_script_interpreter = False
533
534        # There is no process associated with the debugger as yet.
535        # See also self.tearDown() where it checks whether self.process has a
536        # valid reference and calls self.process.Kill() to kill the process.
537        self.process = None
538
539        # Retrieve the associated command interpreter instance.
540        self.ci = self.dbg.GetCommandInterpreter()
541        if not self.ci:
542            raise Exception('Could not get the command interpreter')
543
544        # And the result object.
545        self.res = lldb.SBCommandReturnObject()
546
547        # These are for customized teardown cleanup.
548        self.dict = None
549        self.doTearDownCleanup = False
550        # And in rare cases where there are multiple teardown cleanups.
551        self.dicts = []
552        self.doTearDownCleanups = False
553
554        # Create a string buffer to record the session info, to be dumped into a
555        # test case specific file if test failure is encountered.
556        self.session = StringIO.StringIO()
557
558        # Optimistically set __errored__, __failed__, __expected__ to False
559        # initially.  If the test errored/failed, the session info
560        # (self.session) is then dumped into a session specific file for
561        # diagnosis.
562        self.__errored__ = False
563        self.__failed__ = False
564        self.__expected__ = False
565
566        # See addTearDownHook(self, hook) which allows the client to add a hook
567        # function to be run during tearDown() time.
568        self.hooks = []
569
570        # See HideStdout(self).
571        self.sys_stdout_hidden = False
572
573    def markError(self):
574        """Callback invoked when an error (unexpected exception) errored."""
575        self.__errored__ = True
576        with recording(self, False) as sbuf:
577            # False because there's no need to write "ERROR" to the stderr twice.
578            # Once by the Python unittest framework, and a second time by us.
579            print >> sbuf, "ERROR"
580
581    def markFailure(self):
582        """Callback invoked when a failure (test assertion failure) occurred."""
583        self.__failed__ = True
584        with recording(self, False) as sbuf:
585            # False because there's no need to write "FAIL" to the stderr twice.
586            # Once by the Python unittest framework, and a second time by us.
587            print >> sbuf, "FAIL"
588
589    def markExpectedFailure(self):
590        """Callback invoked when an expected failure/error occurred."""
591        self.__expected__ = True
592        with recording(self, False) as sbuf:
593            # False because there's no need to write "expected failure" to the
594            # stderr twice.
595            # Once by the Python unittest framework, and a second time by us.
596            print >> sbuf, "expected failure"
597
598    def dumpSessionInfo(self):
599        """
600        Dump the debugger interactions leading to a test error/failure.  This
601        allows for more convenient postmortem analysis.
602
603        See also LLDBTestResult (dotest.py) which is a singlton class derived
604        from TextTestResult and overwrites addError, addFailure, and
605        addExpectedFailure methods to allow us to to mark the test instance as
606        such.
607        """
608
609        # We are here because self.tearDown() detected that this test instance
610        # either errored or failed.  The lldb.test_result singleton contains
611        # two lists (erros and failures) which get populated by the unittest
612        # framework.  Look over there for stack trace information.
613        #
614        # The lists contain 2-tuples of TestCase instances and strings holding
615        # formatted tracebacks.
616        #
617        # See http://docs.python.org/library/unittest.html#unittest.TestResult.
618        if self.__errored__:
619            pairs = lldb.test_result.errors
620            prefix = 'Error'
621        elif self.__failed__:
622            pairs = lldb.test_result.failures
623            prefix = 'Failure'
624        elif self.__expected__:
625            pairs = lldb.test_result.expectedFailures
626            prefix = 'ExpectedFailure'
627        else:
628            # Simply return, there's no session info to dump!
629            return
630
631        for test, traceback in pairs:
632            if test is self:
633                print >> self.session, traceback
634
635        dname = os.path.join(os.environ["LLDB_TEST"],
636                             os.environ["LLDB_SESSION_DIRNAME"])
637        if not os.path.isdir(dname):
638            os.mkdir(dname)
639        fname = os.path.join(dname, "%s-%s.log" % (prefix, self.id()))
640        with open(fname, "w") as f:
641            import datetime
642            print >> f, "Session info generated @", datetime.datetime.now().ctime()
643            print >> f, self.session.getvalue()
644            print >> f, "To rerun this test, issue the following command from the 'test' directory:\n"
645            print >> f, "./dotest.py %s -v -t -f %s.%s" % (self.getRunOptions(),
646                                                           self.__class__.__name__,
647                                                           self._testMethodName)
648
649    def setTearDownCleanup(self, dictionary=None):
650        """Register a cleanup action at tearDown() time with a dictinary"""
651        self.dict = dictionary
652        self.doTearDownCleanup = True
653
654    def addTearDownCleanup(self, dictionary):
655        """Add a cleanup action at tearDown() time with a dictinary"""
656        self.dicts.append(dictionary)
657        self.doTearDownCleanups = True
658
659    def addTearDownHook(self, hook):
660        """
661        Add a function to be run during tearDown() time.
662
663        Hooks are executed in a first come first serve manner.
664        """
665        if callable(hook):
666            with recording(self, traceAlways) as sbuf:
667                print >> sbuf, "Adding tearDown hook:", getsource_if_available(hook)
668            self.hooks.append(hook)
669
670    def tearDown(self):
671        #import traceback
672        #traceback.print_stack()
673
674        # Check and run any hook functions.
675        for hook in reversed(self.hooks):
676            with recording(self, traceAlways) as sbuf:
677                print >> sbuf, "Executing tearDown hook:", getsource_if_available(hook)
678            hook()
679
680        # This is for the case of directly spawning 'lldb' and interacting with it
681        # using pexpect.
682        import pexpect
683        if self.child and self.child.isalive():
684            with recording(self, traceAlways) as sbuf:
685                print >> sbuf, "tearing down the child process...."
686            if self.child_in_script_interpreter:
687                self.child.sendline('quit()')
688                self.child.expect_exact('(lldb) ')
689            self.child.sendline('quit')
690            try:
691                self.child.expect(pexpect.EOF)
692            except:
693                pass
694
695        # Terminate the current process being debugged, if any.
696        if self.runStarted:
697            self.runCmd("process kill", PROCESS_KILLED, check=False)
698        elif self.process and self.process.IsValid():
699            rc = self.invoke(self.process, "Kill")
700            self.assertTrue(rc.Success(), PROCESS_KILLED)
701            del self.process
702
703        del self.dbg
704        del self.hooks
705
706        # Perform registered teardown cleanup.
707        if doCleanup and self.doTearDownCleanup:
708            module = __import__(sys.platform)
709            if not module.cleanup(self, dictionary=self.dict):
710                raise Exception("Don't know how to do cleanup with dictionary: " + self.dict)
711
712        # In rare cases where there are multiple teardown cleanups added.
713        if doCleanup and self.doTearDownCleanups:
714            module = __import__(sys.platform)
715            if self.dicts:
716                for dict in reversed(self.dicts):
717                    if not module.cleanup(self, dictionary=dict):
718                        raise Exception("Don't know how to do cleanup with dictionary: " + dict)
719
720        # Decide whether to dump the session info.
721        self.dumpSessionInfo()
722
723    def runCmd(self, cmd, msg=None, check=True, trace=False, setCookie=True):
724        """
725        Ask the command interpreter to handle the command and then check its
726        return status.
727        """
728        # Fail fast if 'cmd' is not meaningful.
729        if not cmd or len(cmd) == 0:
730            raise Exception("Bad 'cmd' parameter encountered")
731
732        trace = (True if traceAlways else trace)
733
734        running = (cmd.startswith("run") or cmd.startswith("process launch"))
735
736        for i in range(self.maxLaunchCount if running else 1):
737            self.ci.HandleCommand(cmd, self.res)
738
739            with recording(self, trace) as sbuf:
740                print >> sbuf, "runCmd:", cmd
741                if not check:
742                    print >> sbuf, "check of return status not required"
743                if self.res.Succeeded():
744                    print >> sbuf, "output:", self.res.GetOutput()
745                else:
746                    print >> sbuf, "runCmd failed!"
747                    print >> sbuf, self.res.GetError()
748
749            if self.res.Succeeded():
750                break
751            elif running:
752                # For process launch, wait some time before possible next try.
753                time.sleep(self.timeWaitNextLaunch)
754                with recording(self, True) as sbuf:
755                    print >> sbuf, "Command '" + cmd + "' failed!"
756
757        # Modify runStarted only if "run" or "process launch" was encountered.
758        if running:
759            self.runStarted = running and setCookie
760
761        if check:
762            self.assertTrue(self.res.Succeeded(),
763                            msg if msg else CMD_MSG(cmd))
764
765    def expect(self, str, msg=None, patterns=None, startstr=None, substrs=None, trace=False, error=False, matching=True, exe=True):
766        """
767        Similar to runCmd; with additional expect style output matching ability.
768
769        Ask the command interpreter to handle the command and then check its
770        return status.  The 'msg' parameter specifies an informational assert
771        message.  We expect the output from running the command to start with
772        'startstr', matches the substrings contained in 'substrs', and regexp
773        matches the patterns contained in 'patterns'.
774
775        If the keyword argument error is set to True, it signifies that the API
776        client is expecting the command to fail.  In this case, the error stream
777        from running the command is retrieved and compared against the golden
778        input, instead.
779
780        If the keyword argument matching is set to False, it signifies that the API
781        client is expecting the output of the command not to match the golden
782        input.
783
784        Finally, the required argument 'str' represents the lldb command to be
785        sent to the command interpreter.  In case the keyword argument 'exe' is
786        set to False, the 'str' is treated as a string to be matched/not-matched
787        against the golden input.
788        """
789        trace = (True if traceAlways else trace)
790
791        if exe:
792            # First run the command.  If we are expecting error, set check=False.
793            # Pass the assert message along since it provides more semantic info.
794            self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error)
795
796            # Then compare the output against expected strings.
797            output = self.res.GetError() if error else self.res.GetOutput()
798
799            # If error is True, the API client expects the command to fail!
800            if error:
801                self.assertFalse(self.res.Succeeded(),
802                                 "Command '" + str + "' is expected to fail!")
803        else:
804            # No execution required, just compare str against the golden input.
805            output = str
806            with recording(self, trace) as sbuf:
807                print >> sbuf, "looking at:", output
808
809        # The heading says either "Expecting" or "Not expecting".
810        heading = "Expecting" if matching else "Not expecting"
811
812        # Start from the startstr, if specified.
813        # If there's no startstr, set the initial state appropriately.
814        matched = output.startswith(startstr) if startstr else (True if matching else False)
815
816        if startstr:
817            with recording(self, trace) as sbuf:
818                print >> sbuf, "%s start string: %s" % (heading, startstr)
819                print >> sbuf, "Matched" if matched else "Not matched"
820
821        # Look for sub strings, if specified.
822        keepgoing = matched if matching else not matched
823        if substrs and keepgoing:
824            for str in substrs:
825                matched = output.find(str) != -1
826                with recording(self, trace) as sbuf:
827                    print >> sbuf, "%s sub string: %s" % (heading, str)
828                    print >> sbuf, "Matched" if matched else "Not matched"
829                keepgoing = matched if matching else not matched
830                if not keepgoing:
831                    break
832
833        # Search for regular expression patterns, if specified.
834        keepgoing = matched if matching else not matched
835        if patterns and keepgoing:
836            for pattern in patterns:
837                # Match Objects always have a boolean value of True.
838                matched = bool(re.search(pattern, output))
839                with recording(self, trace) as sbuf:
840                    print >> sbuf, "%s pattern: %s" % (heading, pattern)
841                    print >> sbuf, "Matched" if matched else "Not matched"
842                keepgoing = matched if matching else not matched
843                if not keepgoing:
844                    break
845
846        self.assertTrue(matched if matching else not matched,
847                        msg if msg else EXP_MSG(str, exe))
848
849    def invoke(self, obj, name, trace=False):
850        """Use reflection to call a method dynamically with no argument."""
851        trace = (True if traceAlways else trace)
852
853        method = getattr(obj, name)
854        import inspect
855        self.assertTrue(inspect.ismethod(method),
856                        name + "is a method name of object: " + str(obj))
857        result = method()
858        with recording(self, trace) as sbuf:
859            print >> sbuf, str(method) + ":",  result
860        return result
861
862    def breakAfterLaunch(self, process, func, trace=False):
863        """
864        Perform some dances after Launch() to break at func name.
865
866        Return True if we can successfully break at the func name in due time.
867        """
868        trace = (True if traceAlways else trace)
869
870        count = 0
871        while True:
872            # The stop reason of the thread should be breakpoint.
873            thread = process.GetThreadAtIndex(0)
874            SR = thread.GetStopReason()
875            with recording(self, trace) as sbuf:
876                print >> sbuf, "StopReason =", stop_reason_to_str(SR)
877
878            if SR == lldb.eStopReasonBreakpoint:
879                frame = thread.GetFrameAtIndex(0)
880                name = frame.GetFunction().GetName()
881                with recording(self, trace) as sbuf:
882                    print >> sbuf, "function =", name
883                if (name == func):
884                    # We got what we want; now break out of the loop.
885                    return True
886
887            # The inferior is in a transient state; continue the process.
888            time.sleep(1.0)
889            with recording(self, trace) as sbuf:
890                print >> sbuf, "Continuing the process:", process
891            process.Continue()
892
893            count = count + 1
894            if count == 15:
895                with recording(self, trace) as sbuf:
896                    print >> sbuf, "Reached 15 iterations, giving up..."
897                # Enough iterations already, break out of the loop.
898                return False
899
900            # End of while loop.
901
902
903    def getArchitecture(self):
904        """Returns the architecture in effect the test suite is now running with."""
905        module = __import__(sys.platform)
906        return module.getArchitecture()
907
908    def getCompiler(self):
909        """Returns the compiler in effect the test suite is now running with."""
910        module = __import__(sys.platform)
911        return module.getCompiler()
912
913    def getRunOptions(self):
914        """Command line option for -A and -C to run this test again, called from
915        within dumpSessionInfo()."""
916        module = __import__(sys.platform)
917        arch = self.getArchitecture()
918        comp = self.getCompiler()
919        if not arch and not comp:
920            return ""
921        else:
922            return "%s %s" % ("-A "+arch if arch else "",
923                              "-C "+comp if comp else "")
924
925    def buildDefault(self, architecture=None, compiler=None, dictionary=None):
926        """Platform specific way to build the default binaries."""
927        module = __import__(sys.platform)
928        if not module.buildDefault(self, architecture, compiler, dictionary):
929            raise Exception("Don't know how to build default binary")
930
931    def buildDsym(self, architecture=None, compiler=None, dictionary=None):
932        """Platform specific way to build binaries with dsym info."""
933        module = __import__(sys.platform)
934        if not module.buildDsym(self, architecture, compiler, dictionary):
935            raise Exception("Don't know how to build binary with dsym")
936
937    def buildDwarf(self, architecture=None, compiler=None, dictionary=None):
938        """Platform specific way to build binaries with dwarf maps."""
939        module = __import__(sys.platform)
940        if not module.buildDwarf(self, architecture, compiler, dictionary):
941            raise Exception("Don't know how to build binary with dwarf")
942
943    def DebugSBValue(self, frame, val):
944        """Debug print a SBValue object, if traceAlways is True."""
945        from lldbutil import value_type_to_str
946
947        if not traceAlways:
948            return
949
950        err = sys.stderr
951        err.write(val.GetName() + ":\n")
952        err.write('\t' + "TypeName      -> " + val.GetTypeName()            + '\n')
953        err.write('\t' + "ByteSize      -> " + str(val.GetByteSize())       + '\n')
954        err.write('\t' + "NumChildren   -> " + str(val.GetNumChildren())    + '\n')
955        err.write('\t' + "Value         -> " + str(val.GetValue(frame))     + '\n')
956        err.write('\t' + "ValueType     -> " + value_type_to_str(val.GetValueType()) + '\n')
957        err.write('\t' + "Summary       -> " + str(val.GetSummary(frame))   + '\n')
958        err.write('\t' + "IsPointerType -> " + str(val.TypeIsPointerType()) + '\n')
959        err.write('\t' + "Location      -> " + val.GetLocation(frame)       + '\n')
960
961    def DebugPExpect(self, child):
962        """Debug the spwaned pexpect object."""
963        if not traceAlways:
964            return
965
966        print child
967
968    def TraceOn(self):
969        """Returns True if we are in trace mode (i.e., tracing lldb command execution)."""
970        return traceAlways
971
972    def HideStdout(self):
973        """Hide output to stdout from the user.
974
975        During test execution, there might be cases where we don't want to show the
976        standard output to the user.  For example,
977
978            self.runCmd(r'''sc print "\n\n\tHello!\n"''')
979
980        tests whether command abbreviation for 'script' works or not.  There is no
981        need to show the 'Hello' output to the user as long as the 'script' command
982        succeeds and we are not in TraceOn() mode (see the '-t' option).
983
984        In this case, the test method calls self.HideStdout(self) to redirect the
985        sys.stdout to a null device, and restores the sys.stdout upon teardown.
986
987        Note that you should only call this method at most once during a test case
988        execution.  Any subsequent call has no effect at all."""
989        if self.sys_stdout_hidden:
990            return
991
992        self.sys_stdout_hidden = True
993        old_stdout = sys.stdout
994        sys.stdout = open(os.devnull, 'w')
995        def restore_stdout():
996            sys.stdout = old_stdout
997        self.addTearDownHook(restore_stdout)
998