lldbtest.py revision 4d82e973c42d78ac83bcd819329ca017f6dcabb5
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 of part of the test suite .  Example:
13
14# Exercises the test suite in the types directory....
15/Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types
16...
17
18Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42'
19Command invoked: python ./dotest.py -A x86_64 types
20compilers=['clang']
21
22Configuration: arch=x86_64 compiler=clang
23----------------------------------------------------------------------
24Collected 72 tests
25
26........................................................................
27----------------------------------------------------------------------
28Ran 72 tests in 135.468s
29
30OK
31$
32"""
33
34import os, sys, traceback
35import os.path
36import re
37from subprocess import *
38import StringIO
39import time
40import types
41import unittest2
42import lldb
43
44# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
45# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options.
46
47# By default, traceAlways is False.
48if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
49    traceAlways = True
50else:
51    traceAlways = False
52
53# By default, doCleanup is True.
54if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO":
55    doCleanup = False
56else:
57    doCleanup = True
58
59
60#
61# Some commonly used assert messages.
62#
63
64COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
65
66CURRENT_EXECUTABLE_SET = "Current executable set successfully"
67
68PROCESS_IS_VALID = "Process is valid"
69
70PROCESS_KILLED = "Process is killed successfully"
71
72PROCESS_EXITED = "Process exited successfully"
73
74PROCESS_STOPPED = "Process status should be stopped"
75
76RUN_SUCCEEDED = "Process is launched successfully"
77
78RUN_COMPLETED = "Process exited successfully"
79
80BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
81
82BREAKPOINT_CREATED = "Breakpoint created successfully"
83
84BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
85
86BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
87
88BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
89
90BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2"
91
92BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3"
93
94MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable."
95
96OBJECT_PRINTED_CORRECTLY = "Object printed correctly"
97
98SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
99
100STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
101
102STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
103
104STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
105
106STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
107    STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'")
108
109STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
110
111STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
112
113STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
114
115STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
116
117STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
118
119DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
120
121VALID_BREAKPOINT = "Got a valid breakpoint"
122
123VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
124
125VALID_COMMAND_INTERPRETER = "Got a valid command interpreter"
126
127VALID_FILESPEC = "Got a valid filespec"
128
129VALID_MODULE = "Got a valid module"
130
131VALID_PROCESS = "Got a valid process"
132
133VALID_SYMBOL = "Got a valid symbol"
134
135VALID_TARGET = "Got a valid target"
136
137VALID_TYPE = "Got a valid type"
138
139VALID_VARIABLE = "Got a valid variable"
140
141VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
142
143WATCHPOINT_CREATED = "Watchpoint created successfully"
144
145def CMD_MSG(str):
146    '''A generic "Command '%s' returns successfully" message generator.'''
147    return "Command '%s' returns successfully" % str
148
149def COMPLETION_MSG(str_before, str_after):
150    '''A generic message generator for the completion mechanism.'''
151    return "'%s' successfully completes to '%s'" % (str_before, str_after)
152
153def EXP_MSG(str, exe):
154    '''A generic "'%s' returns expected result" message generator if exe.
155    Otherwise, it generates "'%s' matches expected result" message.'''
156    return "'%s' %s expected result" % (str, 'returns' if exe else 'matches')
157
158def SETTING_MSG(setting):
159    '''A generic "Value of setting '%s' is correct" message generator.'''
160    return "Value of setting '%s' is correct" % setting
161
162def EnvArray():
163    """Returns an env variable array from the os.environ map object."""
164    return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
165
166def line_number(filename, string_to_match):
167    """Helper function to return the line number of the first matched string."""
168    with open(filename, 'r') as f:
169        for i, line in enumerate(f):
170            if line.find(string_to_match) != -1:
171                # Found our match.
172                return i+1
173    raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename))
174
175def pointer_size():
176    """Return the pointer size of the host system."""
177    import ctypes
178    a_pointer = ctypes.c_void_p(0xffff)
179    return 8 * ctypes.sizeof(a_pointer)
180
181def is_exe(fpath):
182    """Returns true if fpath is an executable."""
183    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
184
185def which(program):
186    """Returns the full path to a program; None otherwise."""
187    fpath, fname = os.path.split(program)
188    if fpath:
189        if is_exe(program):
190            return program
191    else:
192        for path in os.environ["PATH"].split(os.pathsep):
193            exe_file = os.path.join(path, program)
194            if is_exe(exe_file):
195                return exe_file
196    return None
197
198class recording(StringIO.StringIO):
199    """
200    A nice little context manager for recording the debugger interactions into
201    our session object.  If trace flag is ON, it also emits the interactions
202    into the stderr.
203    """
204    def __init__(self, test, trace):
205        """Create a StringIO instance; record the session obj and trace flag."""
206        StringIO.StringIO.__init__(self)
207        # The test might not have undergone the 'setUp(self)' phase yet, so that
208        # the attribute 'session' might not even exist yet.
209        self.session = getattr(test, "session", None) if test else None
210        self.trace = trace
211
212    def __enter__(self):
213        """
214        Context management protocol on entry to the body of the with statement.
215        Just return the StringIO object.
216        """
217        return self
218
219    def __exit__(self, type, value, tb):
220        """
221        Context management protocol on exit from the body of the with statement.
222        If trace is ON, it emits the recordings into stderr.  Always add the
223        recordings to our session object.  And close the StringIO object, too.
224        """
225        if self.trace:
226            print >> sys.stderr, self.getvalue()
227        if self.session:
228            print >> self.session, self.getvalue()
229        self.close()
230
231# From 2.7's subprocess.check_output() convenience function.
232# Return a tuple (stdoutdata, stderrdata).
233def system(*popenargs, **kwargs):
234    r"""Run an os command with arguments and return its output as a byte string.
235
236    If the exit code was non-zero it raises a CalledProcessError.  The
237    CalledProcessError object will have the return code in the returncode
238    attribute and output in the output attribute.
239
240    The arguments are the same as for the Popen constructor.  Example:
241
242    >>> check_output(["ls", "-l", "/dev/null"])
243    'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'
244
245    The stdout argument is not allowed as it is used internally.
246    To capture standard error in the result, use stderr=STDOUT.
247
248    >>> check_output(["/bin/sh", "-c",
249    ...               "ls -l non_existent_file ; exit 0"],
250    ...              stderr=STDOUT)
251    'ls: non_existent_file: No such file or directory\n'
252    """
253
254    # Assign the sender object to variable 'test' and remove it from kwargs.
255    test = kwargs.pop('sender', None)
256
257    if 'stdout' in kwargs:
258        raise ValueError('stdout argument not allowed, it will be overridden.')
259    process = Popen(stdout=PIPE, stderr=PIPE, *popenargs, **kwargs)
260    pid = process.pid
261    output, error = process.communicate()
262    retcode = process.poll()
263
264    with recording(test, traceAlways) as sbuf:
265        if isinstance(popenargs, types.StringTypes):
266            args = [popenargs]
267        else:
268            args = list(popenargs)
269        print >> sbuf
270        print >> sbuf, "os command:", args
271        print >> sbuf, "with pid:", pid
272        print >> sbuf, "stdout:", output
273        print >> sbuf, "stderr:", error
274        print >> sbuf, "retcode:", retcode
275        print >> sbuf
276
277    if retcode:
278        cmd = kwargs.get("args")
279        if cmd is None:
280            cmd = popenargs[0]
281        raise CalledProcessError(retcode, cmd)
282    return (output, error)
283
284def getsource_if_available(obj):
285    """
286    Return the text of the source code for an object if available.  Otherwise,
287    a print representation is returned.
288    """
289    import inspect
290    try:
291        return inspect.getsource(obj)
292    except:
293        return repr(obj)
294
295def builder_module():
296    return __import__("builder_" + sys.platform)
297
298#
299# Decorators for categorizing test cases.
300#
301
302from functools import wraps
303def python_api_test(func):
304    """Decorate the item as a Python API only test."""
305    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
306        raise Exception("@python_api_test can only be used to decorate a test method")
307    @wraps(func)
308    def wrapper(self, *args, **kwargs):
309        try:
310            if lldb.dont_do_python_api_test:
311                self.skipTest("python api tests")
312        except AttributeError:
313            pass
314        return func(self, *args, **kwargs)
315
316    # Mark this function as such to separate them from lldb command line tests.
317    wrapper.__python_api_test__ = True
318    return wrapper
319
320def benchmarks_test(func):
321    """Decorate the item as a benchmarks test."""
322    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
323        raise Exception("@benchmarks_test can only be used to decorate a test method")
324    @wraps(func)
325    def wrapper(self, *args, **kwargs):
326        try:
327            if not lldb.just_do_benchmarks_test:
328                self.skipTest("benchmarks tests")
329        except AttributeError:
330            pass
331        return func(self, *args, **kwargs)
332
333    # Mark this function as such to separate them from the regular tests.
334    wrapper.__benchmarks_test__ = True
335    return wrapper
336
337def dsym_test(func):
338    """Decorate the item as a dsym test."""
339    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
340        raise Exception("@dsym_test can only be used to decorate a test method")
341    @wraps(func)
342    def wrapper(self, *args, **kwargs):
343        try:
344            if lldb.dont_do_dsym_test:
345                self.skipTest("dsym tests")
346        except AttributeError:
347            pass
348        return func(self, *args, **kwargs)
349
350    # Mark this function as such to separate them from the regular tests.
351    wrapper.__dsym_test__ = True
352    return wrapper
353
354def dwarf_test(func):
355    """Decorate the item as a dwarf test."""
356    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
357        raise Exception("@dwarf_test can only be used to decorate a test method")
358    @wraps(func)
359    def wrapper(self, *args, **kwargs):
360        try:
361            if lldb.dont_do_dwarf_test:
362                self.skipTest("dwarf tests")
363        except AttributeError:
364            pass
365        return func(self, *args, **kwargs)
366
367    # Mark this function as such to separate them from the regular tests.
368    wrapper.__dwarf_test__ = True
369    return wrapper
370
371def expectedFailureCompiler(func,compiler,bugnumber=None):
372     if callable(bugnumber):
373        @wraps(bugnumber)
374        def expectedFailureCompiler_easy_wrapper(*args, **kwargs):
375            from unittest2 import case
376            self = args[0]
377            test_compiler = self.getCompiler()
378            try:
379                bugnumber(*args, **kwargs)
380            except Exception:
381                if compiler in test_compiler:
382                    raise case._ExpectedFailure(sys.exc_info(),None)
383                else:
384                    raise
385            if compiler in test_compiler:
386                raise case._UnexpectedSuccess(sys.exc_info(),None)
387        return expectedFailureCompiler_easy_wrapper
388     else:
389        def expectedFailureCompiler_impl(func):
390              @wraps(func)
391              def wrapper(*args, **kwargs):
392                from unittest2 import case
393                self = args[0]
394                test_compiler = self.getCompiler()
395                try:
396                    func(*args, **kwargs)
397                except Exception:
398                    if compiler in test_compiler:
399                        raise case._ExpectedFailure(sys.exc_info(),bugnumber)
400                    else:
401                        raise
402                if compiler in test_compiler:
403                    raise case._UnexpectedSuccess(sys.exc_info(),bugnumber)
404              return wrapper
405        return expectedFailureCompiler_impl
406
407def expectedFailureGcc(func):
408    """Decorate the item as a GCC only expectedFailure."""
409    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
410        raise Exception("@expectedFailureClang can only be used to decorate a test method")
411    return expectedFailureCompiler(func, "gcc")
412
413def expectedFailureClang(func):
414    """Decorate the item as a Clang only expectedFailure."""
415    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
416        raise Exception("@expectedFailureClang can only be used to decorate a test method")
417    return expectedFailureCompiler(func, "clang")
418
419def expectedFailurei386(bugnumber=None):
420     if callable(bugnumber):
421        @wraps(bugnumber)
422        def expectedFailurei386_easy_wrapper(*args, **kwargs):
423            from unittest2 import case
424            self = args[0]
425            arch = self.getArchitecture()
426            try:
427                bugnumber(*args, **kwargs)
428            except Exception:
429                if "i386" in arch:
430                    raise case._ExpectedFailure(sys.exc_info(),None)
431                else:
432                    raise
433            if "i386" in arch:
434                raise case._UnexpectedSuccess(sys.exc_info(),None)
435        return expectedFailurei386_easy_wrapper
436     else:
437        def expectedFailurei386_impl(func):
438              @wraps(func)
439              def wrapper(*args, **kwargs):
440                from unittest2 import case
441                self = args[0]
442                arch = self.getArchitecture()
443                try:
444                    func(*args, **kwargs)
445                except Exception:
446                    if "i386" in arch:
447                        raise case._ExpectedFailure(sys.exc_info(),bugnumber)
448                    else:
449                        raise
450                if "i386" in arch:
451                    raise case._UnexpectedSuccess(sys.exc_info(),bugnumber)
452              return wrapper
453        return expectedFailurei386_impl
454
455def expectedFailureLinux(bugnumber=None):
456     if callable(bugnumber):
457        @wraps(bugnumber)
458        def expectedFailureLinux_easy_wrapper(*args, **kwargs):
459            from unittest2 import case
460            self = args[0]
461            platform = sys.platform
462            try:
463                bugnumber(*args, **kwargs)
464            except Exception:
465                if "linux" in platform:
466                    raise case._ExpectedFailure(sys.exc_info(),None)
467                else:
468                    raise
469            if "linux" in platform:
470                raise case._UnexpectedSuccess(sys.exc_info(),None)
471        return expectedFailureLinux_easy_wrapper
472     else:
473        def expectedFailureLinux_impl(func):
474              @wraps(func)
475              def wrapper(*args, **kwargs):
476                from unittest2 import case
477                self = args[0]
478                platform = sys.platform
479                try:
480                    func(*args, **kwargs)
481                except Exception:
482                    if "linux" in platform:
483                        raise case._ExpectedFailure(sys.exc_info(),bugnumber)
484                    else:
485                        raise
486                if "linux" in platform:
487                    raise case._UnexpectedSuccess(sys.exc_info(),bugnumber)
488              return wrapper
489        return expectedFailureLinux_impl
490
491def skipOnLinux(func):
492    """Decorate the item to skip tests that should be skipped on Linux."""
493    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
494        raise Exception("@skipOnLinux can only be used to decorate a test method")
495    @wraps(func)
496    def wrapper(*args, **kwargs):
497        from unittest2 import case
498        self = args[0]
499        platform = sys.platform
500        if "linux" in platform:
501            self.skipTest("skip on linux")
502        else:
503            func(*args, **kwargs)
504    return wrapper
505
506def skipIfGcc(func):
507    """Decorate the item to skip tests that should be skipped if building with gcc ."""
508    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
509        raise Exception("@skipOnLinux can only be used to decorate a test method")
510    @wraps(func)
511    def wrapper(*args, **kwargs):
512        from unittest2 import case
513        self = args[0]
514        compiler = self.getCompiler()
515        if "gcc" in compiler:
516            self.skipTest("skipping because gcc is the test compiler")
517        else:
518            func(*args, **kwargs)
519    return wrapper
520
521
522class Base(unittest2.TestCase):
523    """
524    Abstract base for performing lldb (see TestBase) or other generic tests (see
525    BenchBase for one example).  lldbtest.Base works with the test driver to
526    accomplish things.
527
528    """
529
530    # The concrete subclass should override this attribute.
531    mydir = None
532
533    # Keep track of the old current working directory.
534    oldcwd = None
535
536    def TraceOn(self):
537        """Returns True if we are in trace mode (tracing detailed test execution)."""
538        return traceAlways
539
540    @classmethod
541    def setUpClass(cls):
542        """
543        Python unittest framework class setup fixture.
544        Do current directory manipulation.
545        """
546
547        # Fail fast if 'mydir' attribute is not overridden.
548        if not cls.mydir or len(cls.mydir) == 0:
549            raise Exception("Subclasses must override the 'mydir' attribute.")
550
551        # Save old working directory.
552        cls.oldcwd = os.getcwd()
553
554        # Change current working directory if ${LLDB_TEST} is defined.
555        # See also dotest.py which sets up ${LLDB_TEST}.
556        if ("LLDB_TEST" in os.environ):
557            if traceAlways:
558                print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
559            os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
560
561    @classmethod
562    def tearDownClass(cls):
563        """
564        Python unittest framework class teardown fixture.
565        Do class-wide cleanup.
566        """
567
568        if doCleanup and not lldb.skip_build_and_cleanup:
569            # First, let's do the platform-specific cleanup.
570            module = builder_module()
571            if not module.cleanup():
572                raise Exception("Don't know how to do cleanup")
573
574            # Subclass might have specific cleanup function defined.
575            if getattr(cls, "classCleanup", None):
576                if traceAlways:
577                    print >> sys.stderr, "Call class-specific cleanup function for class:", cls
578                try:
579                    cls.classCleanup()
580                except:
581                    exc_type, exc_value, exc_tb = sys.exc_info()
582                    traceback.print_exception(exc_type, exc_value, exc_tb)
583
584        # Restore old working directory.
585        if traceAlways:
586            print >> sys.stderr, "Restore dir to:", cls.oldcwd
587        os.chdir(cls.oldcwd)
588
589    @classmethod
590    def skipLongRunningTest(cls):
591        """
592        By default, we skip long running test case.
593        This can be overridden by passing '-l' to the test driver (dotest.py).
594        """
595        if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]:
596            return False
597        else:
598            return True
599
600    def setUp(self):
601        """Fixture for unittest test case setup.
602
603        It works with the test driver to conditionally skip tests and does other
604        initializations."""
605        #import traceback
606        #traceback.print_stack()
607
608        if "LLDB_EXEC" in os.environ:
609            self.lldbExec = os.environ["LLDB_EXEC"]
610        else:
611            self.lldbExec = None
612        if "LLDB_HERE" in os.environ:
613            self.lldbHere = os.environ["LLDB_HERE"]
614        else:
615            self.lldbHere = None
616        # If we spawn an lldb process for test (via pexpect), do not load the
617        # init file unless told otherwise.
618        if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]:
619            self.lldbOption = ""
620        else:
621            self.lldbOption = "--no-lldbinit"
622
623        # Assign the test method name to self.testMethodName.
624        #
625        # For an example of the use of this attribute, look at test/types dir.
626        # There are a bunch of test cases under test/types and we don't want the
627        # module cacheing subsystem to be confused with executable name "a.out"
628        # used for all the test cases.
629        self.testMethodName = self._testMethodName
630
631        # Python API only test is decorated with @python_api_test,
632        # which also sets the "__python_api_test__" attribute of the
633        # function object to True.
634        try:
635            if lldb.just_do_python_api_test:
636                testMethod = getattr(self, self._testMethodName)
637                if getattr(testMethod, "__python_api_test__", False):
638                    pass
639                else:
640                    self.skipTest("non python api test")
641        except AttributeError:
642            pass
643
644        # Benchmarks test is decorated with @benchmarks_test,
645        # which also sets the "__benchmarks_test__" attribute of the
646        # function object to True.
647        try:
648            if lldb.just_do_benchmarks_test:
649                testMethod = getattr(self, self._testMethodName)
650                if getattr(testMethod, "__benchmarks_test__", False):
651                    pass
652                else:
653                    self.skipTest("non benchmarks test")
654        except AttributeError:
655            pass
656
657        # This is for the case of directly spawning 'lldb'/'gdb' and interacting
658        # with it using pexpect.
659        self.child = None
660        self.child_prompt = "(lldb) "
661        # If the child is interacting with the embedded script interpreter,
662        # there are two exits required during tear down, first to quit the
663        # embedded script interpreter and second to quit the lldb command
664        # interpreter.
665        self.child_in_script_interpreter = False
666
667        # These are for customized teardown cleanup.
668        self.dict = None
669        self.doTearDownCleanup = False
670        # And in rare cases where there are multiple teardown cleanups.
671        self.dicts = []
672        self.doTearDownCleanups = False
673
674        # List of spawned subproces.Popen objects
675        self.subprocesses = []
676
677        # Create a string buffer to record the session info, to be dumped into a
678        # test case specific file if test failure is encountered.
679        self.session = StringIO.StringIO()
680
681        # Optimistically set __errored__, __failed__, __expected__ to False
682        # initially.  If the test errored/failed, the session info
683        # (self.session) is then dumped into a session specific file for
684        # diagnosis.
685        self.__errored__    = False
686        self.__failed__     = False
687        self.__expected__   = False
688        # We are also interested in unexpected success.
689        self.__unexpected__ = False
690        # And skipped tests.
691        self.__skipped__ = False
692
693        # See addTearDownHook(self, hook) which allows the client to add a hook
694        # function to be run during tearDown() time.
695        self.hooks = []
696
697        # See HideStdout(self).
698        self.sys_stdout_hidden = False
699
700        # set environment variable names for finding shared libraries
701        if sys.platform.startswith("darwin"):
702            self.dylibPath = 'DYLD_LIBRARY_PATH'
703        elif sys.platform.startswith("linux") or sys.platform.startswith("freebsd"):
704            self.dylibPath = 'LD_LIBRARY_PATH'
705
706    def runHooks(self, child=None, child_prompt=None, use_cmd_api=False):
707        """Perform the run hooks to bring lldb debugger to the desired state.
708
709        By default, expect a pexpect spawned child and child prompt to be
710        supplied (use_cmd_api=False).  If use_cmd_api is true, ignore the child
711        and child prompt and use self.runCmd() to run the hooks one by one.
712
713        Note that child is a process spawned by pexpect.spawn().  If not, your
714        test case is mostly likely going to fail.
715
716        See also dotest.py where lldb.runHooks are processed/populated.
717        """
718        if not lldb.runHooks:
719            self.skipTest("No runhooks specified for lldb, skip the test")
720        if use_cmd_api:
721            for hook in lldb.runhooks:
722                self.runCmd(hook)
723        else:
724            if not child or not child_prompt:
725                self.fail("Both child and child_prompt need to be defined.")
726            for hook in lldb.runHooks:
727                child.sendline(hook)
728                child.expect_exact(child_prompt)
729
730    def setAsync(self, value):
731        """ Sets async mode to True/False and ensures it is reset after the testcase completes."""
732        old_async = self.dbg.GetAsync()
733        self.dbg.SetAsync(value)
734        self.addTearDownHook(lambda: self.dbg.SetAsync(old_async))
735
736    def cleanupSubprocesses(self):
737        # Ensure any subprocesses are cleaned up
738        for p in self.subprocesses:
739            if p.poll() == None:
740                p.terminate()
741            del p
742        del self.subprocesses[:]
743
744    def spawnSubprocess(self, executable, args=[]):
745        """ Creates a subprocess.Popen object with the specified executable and arguments,
746            saves it in self.subprocesses, and returns the object.
747            NOTE: if using this function, ensure you also call:
748
749              self.addTearDownHook(self.cleanupSubprocesses)
750
751            otherwise the test suite will leak processes.
752        """
753
754        # Don't display the stdout if not in TraceOn() mode.
755        proc = Popen([executable] + args,
756                     stdout = open(os.devnull) if not self.TraceOn() else None,
757                     stdin = PIPE)
758        self.subprocesses.append(proc)
759        return proc
760
761    def HideStdout(self):
762        """Hide output to stdout from the user.
763
764        During test execution, there might be cases where we don't want to show the
765        standard output to the user.  For example,
766
767            self.runCmd(r'''sc print "\n\n\tHello!\n"''')
768
769        tests whether command abbreviation for 'script' works or not.  There is no
770        need to show the 'Hello' output to the user as long as the 'script' command
771        succeeds and we are not in TraceOn() mode (see the '-t' option).
772
773        In this case, the test method calls self.HideStdout(self) to redirect the
774        sys.stdout to a null device, and restores the sys.stdout upon teardown.
775
776        Note that you should only call this method at most once during a test case
777        execution.  Any subsequent call has no effect at all."""
778        if self.sys_stdout_hidden:
779            return
780
781        self.sys_stdout_hidden = True
782        old_stdout = sys.stdout
783        sys.stdout = open(os.devnull, 'w')
784        def restore_stdout():
785            sys.stdout = old_stdout
786        self.addTearDownHook(restore_stdout)
787
788    # =======================================================================
789    # Methods for customized teardown cleanups as well as execution of hooks.
790    # =======================================================================
791
792    def setTearDownCleanup(self, dictionary=None):
793        """Register a cleanup action at tearDown() time with a dictinary"""
794        self.dict = dictionary
795        self.doTearDownCleanup = True
796
797    def addTearDownCleanup(self, dictionary):
798        """Add a cleanup action at tearDown() time with a dictinary"""
799        self.dicts.append(dictionary)
800        self.doTearDownCleanups = True
801
802    def addTearDownHook(self, hook):
803        """
804        Add a function to be run during tearDown() time.
805
806        Hooks are executed in a first come first serve manner.
807        """
808        if callable(hook):
809            with recording(self, traceAlways) as sbuf:
810                print >> sbuf, "Adding tearDown hook:", getsource_if_available(hook)
811            self.hooks.append(hook)
812
813    def tearDown(self):
814        """Fixture for unittest test case teardown."""
815        #import traceback
816        #traceback.print_stack()
817
818        # This is for the case of directly spawning 'lldb' and interacting with it
819        # using pexpect.
820        import pexpect
821        if self.child and self.child.isalive():
822            with recording(self, traceAlways) as sbuf:
823                print >> sbuf, "tearing down the child process...."
824            try:
825                if self.child_in_script_interpreter:
826                    self.child.sendline('quit()')
827                    self.child.expect_exact(self.child_prompt)
828                self.child.sendline('settings set interpreter.prompt-on-quit false')
829                self.child.sendline('quit')
830                self.child.expect(pexpect.EOF)
831            except ValueError, ExceptionPexpect:
832                # child is already terminated
833                pass
834
835            # Give it one final blow to make sure the child is terminated.
836            self.child.close()
837
838        # Check and run any hook functions.
839        for hook in reversed(self.hooks):
840            with recording(self, traceAlways) as sbuf:
841                print >> sbuf, "Executing tearDown hook:", getsource_if_available(hook)
842            hook()
843
844        del self.hooks
845
846        # Perform registered teardown cleanup.
847        if doCleanup and self.doTearDownCleanup:
848            self.cleanup(dictionary=self.dict)
849
850        # In rare cases where there are multiple teardown cleanups added.
851        if doCleanup and self.doTearDownCleanups:
852            if self.dicts:
853                for dict in reversed(self.dicts):
854                    self.cleanup(dictionary=dict)
855
856        # Decide whether to dump the session info.
857        self.dumpSessionInfo()
858
859    # =========================================================
860    # Various callbacks to allow introspection of test progress
861    # =========================================================
862
863    def markError(self):
864        """Callback invoked when an error (unexpected exception) errored."""
865        self.__errored__ = True
866        with recording(self, False) as sbuf:
867            # False because there's no need to write "ERROR" to the stderr twice.
868            # Once by the Python unittest framework, and a second time by us.
869            print >> sbuf, "ERROR"
870
871    def markFailure(self):
872        """Callback invoked when a failure (test assertion failure) occurred."""
873        self.__failed__ = True
874        with recording(self, False) as sbuf:
875            # False because there's no need to write "FAIL" to the stderr twice.
876            # Once by the Python unittest framework, and a second time by us.
877            print >> sbuf, "FAIL"
878
879    def markExpectedFailure(self,err,bugnumber):
880        """Callback invoked when an expected failure/error occurred."""
881        self.__expected__ = True
882        with recording(self, False) as sbuf:
883            # False because there's no need to write "expected failure" to the
884            # stderr twice.
885            # Once by the Python unittest framework, and a second time by us.
886            if bugnumber == None:
887                print >> sbuf, "expected failure"
888            else:
889                print >> sbuf, "expected failure (problem id:" + str(bugnumber) + ")"
890
891    def markSkippedTest(self):
892        """Callback invoked when a test is skipped."""
893        self.__skipped__ = True
894        with recording(self, False) as sbuf:
895            # False because there's no need to write "skipped test" to the
896            # stderr twice.
897            # Once by the Python unittest framework, and a second time by us.
898            print >> sbuf, "skipped test"
899
900    def markUnexpectedSuccess(self, bugnumber):
901        """Callback invoked when an unexpected success occurred."""
902        self.__unexpected__ = True
903        with recording(self, False) as sbuf:
904            # False because there's no need to write "unexpected success" to the
905            # stderr twice.
906            # Once by the Python unittest framework, and a second time by us.
907            if bugnumber == None:
908                print >> sbuf, "unexpected success"
909            else:
910                print >> sbuf, "unexpected success (problem id:" + str(bugnumber) + ")"
911
912    def dumpSessionInfo(self):
913        """
914        Dump the debugger interactions leading to a test error/failure.  This
915        allows for more convenient postmortem analysis.
916
917        See also LLDBTestResult (dotest.py) which is a singlton class derived
918        from TextTestResult and overwrites addError, addFailure, and
919        addExpectedFailure methods to allow us to to mark the test instance as
920        such.
921        """
922
923        # We are here because self.tearDown() detected that this test instance
924        # either errored or failed.  The lldb.test_result singleton contains
925        # two lists (erros and failures) which get populated by the unittest
926        # framework.  Look over there for stack trace information.
927        #
928        # The lists contain 2-tuples of TestCase instances and strings holding
929        # formatted tracebacks.
930        #
931        # See http://docs.python.org/library/unittest.html#unittest.TestResult.
932        if self.__errored__:
933            pairs = lldb.test_result.errors
934            prefix = 'Error'
935        elif self.__failed__:
936            pairs = lldb.test_result.failures
937            prefix = 'Failure'
938        elif self.__expected__:
939            pairs = lldb.test_result.expectedFailures
940            prefix = 'ExpectedFailure'
941        elif self.__skipped__:
942            prefix = 'SkippedTest'
943        elif self.__unexpected__:
944            prefix = "UnexpectedSuccess"
945        else:
946            # Simply return, there's no session info to dump!
947            return
948
949        if not self.__unexpected__ and not self.__skipped__:
950            for test, traceback in pairs:
951                if test is self:
952                    print >> self.session, traceback
953
954        testMethod = getattr(self, self._testMethodName)
955        if getattr(testMethod, "__benchmarks_test__", False):
956            benchmarks = True
957        else:
958            benchmarks = False
959
960        # This records the compiler version used for the test.
961        system([self.getCompiler(), "-v"], sender=self)
962
963        dname = os.path.join(os.environ["LLDB_TEST"],
964                             os.environ["LLDB_SESSION_DIRNAME"])
965        if not os.path.isdir(dname):
966            os.mkdir(dname)
967        fname = os.path.join(dname, "%s-%s-%s-%s.log" % (prefix, self.getArchitecture(), "_".join(self.getCompiler().split('/')), self.id()))
968        with open(fname, "w") as f:
969            import datetime
970            print >> f, "Session info generated @", datetime.datetime.now().ctime()
971            print >> f, self.session.getvalue()
972            print >> f, "To rerun this test, issue the following command from the 'test' directory:\n"
973            print >> f, "./dotest.py %s -v %s -f %s.%s" % (self.getRunOptions(),
974                                                           ('+b' if benchmarks else '-t'),
975                                                           self.__class__.__name__,
976                                                           self._testMethodName)
977
978    # ====================================================
979    # Config. methods supported through a plugin interface
980    # (enables reading of the current test configuration)
981    # ====================================================
982
983    def getArchitecture(self):
984        """Returns the architecture in effect the test suite is running with."""
985        module = builder_module()
986        return module.getArchitecture()
987
988    def getCompiler(self):
989        """Returns the compiler in effect the test suite is running with."""
990        module = builder_module()
991        return module.getCompiler()
992
993    def getRunOptions(self):
994        """Command line option for -A and -C to run this test again, called from
995        self.dumpSessionInfo()."""
996        arch = self.getArchitecture()
997        comp = self.getCompiler()
998        if arch:
999            option_str = "-A " + arch
1000        else:
1001            option_str = ""
1002        if comp:
1003            option_str += " -C " + comp
1004        return option_str
1005
1006    # ==================================================
1007    # Build methods supported through a plugin interface
1008    # ==================================================
1009
1010    def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True):
1011        """Platform specific way to build the default binaries."""
1012        if lldb.skip_build_and_cleanup:
1013            return
1014        module = builder_module()
1015        if not module.buildDefault(self, architecture, compiler, dictionary, clean):
1016            raise Exception("Don't know how to build default binary")
1017
1018    def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True):
1019        """Platform specific way to build binaries with dsym info."""
1020        if lldb.skip_build_and_cleanup:
1021            return
1022        module = builder_module()
1023        if not module.buildDsym(self, architecture, compiler, dictionary, clean):
1024            raise Exception("Don't know how to build binary with dsym")
1025
1026    def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True):
1027        """Platform specific way to build binaries with dwarf maps."""
1028        if lldb.skip_build_and_cleanup:
1029            return
1030        module = builder_module()
1031        if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
1032            raise Exception("Don't know how to build binary with dwarf")
1033
1034    def cleanup(self, dictionary=None):
1035        """Platform specific way to do cleanup after build."""
1036        if lldb.skip_build_and_cleanup:
1037            return
1038        module = builder_module()
1039        if not module.cleanup(self, dictionary):
1040            raise Exception("Don't know how to do cleanup with dictionary: "+dictionary)
1041
1042
1043class TestBase(Base):
1044    """
1045    This abstract base class is meant to be subclassed.  It provides default
1046    implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
1047    among other things.
1048
1049    Important things for test class writers:
1050
1051        - Overwrite the mydir class attribute, otherwise your test class won't
1052          run.  It specifies the relative directory to the top level 'test' so
1053          the test harness can change to the correct working directory before
1054          running your test.
1055
1056        - The setUp method sets up things to facilitate subsequent interactions
1057          with the debugger as part of the test.  These include:
1058              - populate the test method name
1059              - create/get a debugger set with synchronous mode (self.dbg)
1060              - get the command interpreter from with the debugger (self.ci)
1061              - create a result object for use with the command interpreter
1062                (self.res)
1063              - plus other stuffs
1064
1065        - The tearDown method tries to perform some necessary cleanup on behalf
1066          of the test to return the debugger to a good state for the next test.
1067          These include:
1068              - execute any tearDown hooks registered by the test method with
1069                TestBase.addTearDownHook(); examples can be found in
1070                settings/TestSettings.py
1071              - kill the inferior process associated with each target, if any,
1072                and, then delete the target from the debugger's target list
1073              - perform build cleanup before running the next test method in the
1074                same test class; examples of registering for this service can be
1075                found in types/TestIntegerTypes.py with the call:
1076                    - self.setTearDownCleanup(dictionary=d)
1077
1078        - Similarly setUpClass and tearDownClass perform classwise setup and
1079          teardown fixtures.  The tearDownClass method invokes a default build
1080          cleanup for the entire test class;  also, subclasses can implement the
1081          classmethod classCleanup(cls) to perform special class cleanup action.
1082
1083        - The instance methods runCmd and expect are used heavily by existing
1084          test cases to send a command to the command interpreter and to perform
1085          string/pattern matching on the output of such command execution.  The
1086          expect method also provides a mode to peform string/pattern matching
1087          without running a command.
1088
1089        - The build methods buildDefault, buildDsym, and buildDwarf are used to
1090          build the binaries used during a particular test scenario.  A plugin
1091          should be provided for the sys.platform running the test suite.  The
1092          Mac OS X implementation is located in plugins/darwin.py.
1093    """
1094
1095    # Maximum allowed attempts when launching the inferior process.
1096    # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
1097    maxLaunchCount = 3;
1098
1099    # Time to wait before the next launching attempt in second(s).
1100    # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
1101    timeWaitNextLaunch = 1.0;
1102
1103    def doDelay(self):
1104        """See option -w of dotest.py."""
1105        if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and
1106            os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'):
1107            waitTime = 1.0
1108            if "LLDB_TIME_WAIT_BETWEEN_TEST_CASES" in os.environ:
1109                waitTime = float(os.environ["LLDB_TIME_WAIT_BETWEEN_TEST_CASES"])
1110            time.sleep(waitTime)
1111
1112    # Returns the list of categories to which this test case belongs
1113    # by default, look for a ".categories" file, and read its contents
1114    # if no such file exists, traverse the hierarchy - we guarantee
1115    # a .categories to exist at the top level directory so we do not end up
1116    # looping endlessly - subclasses are free to define their own categories
1117    # in whatever way makes sense to them
1118    def getCategories(self):
1119        import inspect
1120        import os.path
1121        folder = inspect.getfile(self.__class__)
1122        folder = os.path.dirname(folder)
1123        while folder != '/':
1124                categories_file_name = os.path.join(folder,".categories")
1125                if os.path.exists(categories_file_name):
1126                        categories_file = open(categories_file_name,'r')
1127                        categories = categories_file.readline()
1128                        categories_file.close()
1129                        categories = str.replace(categories,'\n','')
1130                        categories = str.replace(categories,'\r','')
1131                        return categories.split(',')
1132                else:
1133                        folder = os.path.dirname(folder)
1134                        continue
1135
1136    def setUp(self):
1137        #import traceback
1138        #traceback.print_stack()
1139
1140        # Works with the test driver to conditionally skip tests via decorators.
1141        Base.setUp(self)
1142
1143        try:
1144            if lldb.blacklist:
1145                className = self.__class__.__name__
1146                classAndMethodName = "%s.%s" % (className, self._testMethodName)
1147                if className in lldb.blacklist:
1148                    self.skipTest(lldb.blacklist.get(className))
1149                elif classAndMethodName in lldb.blacklist:
1150                    self.skipTest(lldb.blacklist.get(classAndMethodName))
1151        except AttributeError:
1152            pass
1153
1154        # Insert some delay between successive test cases if specified.
1155        self.doDelay()
1156
1157        if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
1158            self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
1159
1160        if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
1161            self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
1162
1163        # Create the debugger instance if necessary.
1164        try:
1165            self.dbg = lldb.DBG
1166        except AttributeError:
1167            self.dbg = lldb.SBDebugger.Create()
1168
1169        if not self.dbg:
1170            raise Exception('Invalid debugger instance')
1171
1172        # We want our debugger to be synchronous.
1173        self.dbg.SetAsync(False)
1174
1175        # Retrieve the associated command interpreter instance.
1176        self.ci = self.dbg.GetCommandInterpreter()
1177        if not self.ci:
1178            raise Exception('Could not get the command interpreter')
1179
1180        # And the result object.
1181        self.res = lldb.SBCommandReturnObject()
1182
1183        # Run global pre-flight code, if defined via the config file.
1184        if lldb.pre_flight:
1185            lldb.pre_flight(self)
1186
1187    # utility methods that tests can use to access the current objects
1188    def target(self):
1189        if not self.dbg:
1190            raise Exception('Invalid debugger instance')
1191        return self.dbg.GetSelectedTarget()
1192
1193    def process(self):
1194        if not self.dbg:
1195            raise Exception('Invalid debugger instance')
1196        return self.dbg.GetSelectedTarget().GetProcess()
1197
1198    def thread(self):
1199        if not self.dbg:
1200            raise Exception('Invalid debugger instance')
1201        return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread()
1202
1203    def frame(self):
1204        if not self.dbg:
1205            raise Exception('Invalid debugger instance')
1206        return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
1207
1208    def tearDown(self):
1209        #import traceback
1210        #traceback.print_stack()
1211
1212        Base.tearDown(self)
1213
1214        # Delete the target(s) from the debugger as a general cleanup step.
1215        # This includes terminating the process for each target, if any.
1216        # We'd like to reuse the debugger for our next test without incurring
1217        # the initialization overhead.
1218        targets = []
1219        for target in self.dbg:
1220            if target:
1221                targets.append(target)
1222                process = target.GetProcess()
1223                if process:
1224                    rc = self.invoke(process, "Kill")
1225                    self.assertTrue(rc.Success(), PROCESS_KILLED)
1226        for target in targets:
1227            self.dbg.DeleteTarget(target)
1228
1229        # Run global post-flight code, if defined via the config file.
1230        if lldb.post_flight:
1231            lldb.post_flight(self)
1232
1233        del self.dbg
1234
1235    def switch_to_thread_with_stop_reason(self, stop_reason):
1236        """
1237        Run the 'thread list' command, and select the thread with stop reason as
1238        'stop_reason'.  If no such thread exists, no select action is done.
1239        """
1240        from lldbutil import stop_reason_to_str
1241        self.runCmd('thread list')
1242        output = self.res.GetOutput()
1243        thread_line_pattern = re.compile("^[ *] thread #([0-9]+):.*stop reason = %s" %
1244                                         stop_reason_to_str(stop_reason))
1245        for line in output.splitlines():
1246            matched = thread_line_pattern.match(line)
1247            if matched:
1248                self.runCmd('thread select %s' % matched.group(1))
1249
1250    def runCmd(self, cmd, msg=None, check=True, trace=False):
1251        """
1252        Ask the command interpreter to handle the command and then check its
1253        return status.
1254        """
1255        # Fail fast if 'cmd' is not meaningful.
1256        if not cmd or len(cmd) == 0:
1257            raise Exception("Bad 'cmd' parameter encountered")
1258
1259        trace = (True if traceAlways else trace)
1260
1261        running = (cmd.startswith("run") or cmd.startswith("process launch"))
1262
1263        for i in range(self.maxLaunchCount if running else 1):
1264            self.ci.HandleCommand(cmd, self.res)
1265
1266            with recording(self, trace) as sbuf:
1267                print >> sbuf, "runCmd:", cmd
1268                if not check:
1269                    print >> sbuf, "check of return status not required"
1270                if self.res.Succeeded():
1271                    print >> sbuf, "output:", self.res.GetOutput()
1272                else:
1273                    print >> sbuf, "runCmd failed!"
1274                    print >> sbuf, self.res.GetError()
1275
1276            if self.res.Succeeded():
1277                break
1278            elif running:
1279                # For process launch, wait some time before possible next try.
1280                time.sleep(self.timeWaitNextLaunch)
1281                with recording(self, trace) as sbuf:
1282                    print >> sbuf, "Command '" + cmd + "' failed!"
1283
1284        if check:
1285            self.assertTrue(self.res.Succeeded(),
1286                            msg if msg else CMD_MSG(cmd))
1287
1288    def match (self, str, patterns, msg=None, trace=False, error=False, matching=True, exe=True):
1289        """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern
1290
1291        Otherwise, all the arguments have the same meanings as for the expect function"""
1292
1293        trace = (True if traceAlways else trace)
1294
1295        if exe:
1296            # First run the command.  If we are expecting error, set check=False.
1297            # Pass the assert message along since it provides more semantic info.
1298            self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error)
1299
1300            # Then compare the output against expected strings.
1301            output = self.res.GetError() if error else self.res.GetOutput()
1302
1303            # If error is True, the API client expects the command to fail!
1304            if error:
1305                self.assertFalse(self.res.Succeeded(),
1306                                 "Command '" + str + "' is expected to fail!")
1307        else:
1308            # No execution required, just compare str against the golden input.
1309            output = str
1310            with recording(self, trace) as sbuf:
1311                print >> sbuf, "looking at:", output
1312
1313        # The heading says either "Expecting" or "Not expecting".
1314        heading = "Expecting" if matching else "Not expecting"
1315
1316        for pattern in patterns:
1317            # Match Objects always have a boolean value of True.
1318            match_object = re.search(pattern, output)
1319            matched = bool(match_object)
1320            with recording(self, trace) as sbuf:
1321                print >> sbuf, "%s pattern: %s" % (heading, pattern)
1322                print >> sbuf, "Matched" if matched else "Not matched"
1323            if matched:
1324                break
1325
1326        self.assertTrue(matched if matching else not matched,
1327                        msg if msg else EXP_MSG(str, exe))
1328
1329        return match_object
1330
1331    def expect(self, str, msg=None, patterns=None, startstr=None, endstr=None, substrs=None, trace=False, error=False, matching=True, exe=True):
1332        """
1333        Similar to runCmd; with additional expect style output matching ability.
1334
1335        Ask the command interpreter to handle the command and then check its
1336        return status.  The 'msg' parameter specifies an informational assert
1337        message.  We expect the output from running the command to start with
1338        'startstr', matches the substrings contained in 'substrs', and regexp
1339        matches the patterns contained in 'patterns'.
1340
1341        If the keyword argument error is set to True, it signifies that the API
1342        client is expecting the command to fail.  In this case, the error stream
1343        from running the command is retrieved and compared against the golden
1344        input, instead.
1345
1346        If the keyword argument matching is set to False, it signifies that the API
1347        client is expecting the output of the command not to match the golden
1348        input.
1349
1350        Finally, the required argument 'str' represents the lldb command to be
1351        sent to the command interpreter.  In case the keyword argument 'exe' is
1352        set to False, the 'str' is treated as a string to be matched/not-matched
1353        against the golden input.
1354        """
1355        trace = (True if traceAlways else trace)
1356
1357        if exe:
1358            # First run the command.  If we are expecting error, set check=False.
1359            # Pass the assert message along since it provides more semantic info.
1360            self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error)
1361
1362            # Then compare the output against expected strings.
1363            output = self.res.GetError() if error else self.res.GetOutput()
1364
1365            # If error is True, the API client expects the command to fail!
1366            if error:
1367                self.assertFalse(self.res.Succeeded(),
1368                                 "Command '" + str + "' is expected to fail!")
1369        else:
1370            # No execution required, just compare str against the golden input.
1371            if isinstance(str,lldb.SBCommandReturnObject):
1372                output = str.GetOutput()
1373            else:
1374                output = str
1375            with recording(self, trace) as sbuf:
1376                print >> sbuf, "looking at:", output
1377
1378        # The heading says either "Expecting" or "Not expecting".
1379        heading = "Expecting" if matching else "Not expecting"
1380
1381        # Start from the startstr, if specified.
1382        # If there's no startstr, set the initial state appropriately.
1383        matched = output.startswith(startstr) if startstr else (True if matching else False)
1384
1385        if startstr:
1386            with recording(self, trace) as sbuf:
1387                print >> sbuf, "%s start string: %s" % (heading, startstr)
1388                print >> sbuf, "Matched" if matched else "Not matched"
1389
1390        # Look for endstr, if specified.
1391        keepgoing = matched if matching else not matched
1392        if endstr:
1393            matched = output.endswith(endstr)
1394            with recording(self, trace) as sbuf:
1395                print >> sbuf, "%s end string: %s" % (heading, endstr)
1396                print >> sbuf, "Matched" if matched else "Not matched"
1397
1398        # Look for sub strings, if specified.
1399        keepgoing = matched if matching else not matched
1400        if substrs and keepgoing:
1401            for str in substrs:
1402                matched = output.find(str) != -1
1403                with recording(self, trace) as sbuf:
1404                    print >> sbuf, "%s sub string: %s" % (heading, str)
1405                    print >> sbuf, "Matched" if matched else "Not matched"
1406                keepgoing = matched if matching else not matched
1407                if not keepgoing:
1408                    break
1409
1410        # Search for regular expression patterns, if specified.
1411        keepgoing = matched if matching else not matched
1412        if patterns and keepgoing:
1413            for pattern in patterns:
1414                # Match Objects always have a boolean value of True.
1415                matched = bool(re.search(pattern, output))
1416                with recording(self, trace) as sbuf:
1417                    print >> sbuf, "%s pattern: %s" % (heading, pattern)
1418                    print >> sbuf, "Matched" if matched else "Not matched"
1419                keepgoing = matched if matching else not matched
1420                if not keepgoing:
1421                    break
1422
1423        self.assertTrue(matched if matching else not matched,
1424                        msg if msg else EXP_MSG(str, exe))
1425
1426    def invoke(self, obj, name, trace=False):
1427        """Use reflection to call a method dynamically with no argument."""
1428        trace = (True if traceAlways else trace)
1429
1430        method = getattr(obj, name)
1431        import inspect
1432        self.assertTrue(inspect.ismethod(method),
1433                        name + "is a method name of object: " + str(obj))
1434        result = method()
1435        with recording(self, trace) as sbuf:
1436            print >> sbuf, str(method) + ":",  result
1437        return result
1438
1439    # =================================================
1440    # Misc. helper methods for debugging test execution
1441    # =================================================
1442
1443    def DebugSBValue(self, val):
1444        """Debug print a SBValue object, if traceAlways is True."""
1445        from lldbutil import value_type_to_str
1446
1447        if not traceAlways:
1448            return
1449
1450        err = sys.stderr
1451        err.write(val.GetName() + ":\n")
1452        err.write('\t' + "TypeName         -> " + val.GetTypeName()            + '\n')
1453        err.write('\t' + "ByteSize         -> " + str(val.GetByteSize())       + '\n')
1454        err.write('\t' + "NumChildren      -> " + str(val.GetNumChildren())    + '\n')
1455        err.write('\t' + "Value            -> " + str(val.GetValue())          + '\n')
1456        err.write('\t' + "ValueAsUnsigned  -> " + str(val.GetValueAsUnsigned())+ '\n')
1457        err.write('\t' + "ValueType        -> " + value_type_to_str(val.GetValueType()) + '\n')
1458        err.write('\t' + "Summary          -> " + str(val.GetSummary())        + '\n')
1459        err.write('\t' + "IsPointerType    -> " + str(val.TypeIsPointerType()) + '\n')
1460        err.write('\t' + "Location         -> " + val.GetLocation()            + '\n')
1461
1462    def DebugSBType(self, type):
1463        """Debug print a SBType object, if traceAlways is True."""
1464        if not traceAlways:
1465            return
1466
1467        err = sys.stderr
1468        err.write(type.GetName() + ":\n")
1469        err.write('\t' + "ByteSize        -> " + str(type.GetByteSize())     + '\n')
1470        err.write('\t' + "IsPointerType   -> " + str(type.IsPointerType())   + '\n')
1471        err.write('\t' + "IsReferenceType -> " + str(type.IsReferenceType()) + '\n')
1472
1473    def DebugPExpect(self, child):
1474        """Debug the spwaned pexpect object."""
1475        if not traceAlways:
1476            return
1477
1478        print child
1479
1480    @classmethod
1481    def RemoveTempFile(cls, file):
1482        if os.path.exists(file):
1483            os.remove(file)
1484